?? simpleca.c
字號:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <ctype.h>#include <sys/types.h>#include <cryptlib.h>#define DEFAULT_CONFIG_FILE "/etc/simpleca.conf"#define MIN_PASSWORD_LENGTH 2#ifdef WIN32#define strcasecmp stricmp#define snprintf _snprintf#define DEFAULT_CONFIG_FILE "C:\\simpleca.conf"#else#include <strings.h>#include <unistd.h>#endif#define FALSE 0#define TRUE (!FALSE)/* The maximum size of a single text line */#define MAXBUF 1024/* The maximum size of a single certificate */#define BIGMAXBUF 65500#define ACTION_NONE 0#define ACTION_VIEW 1#define ACTION_CREATEKEYS 2#define ACTION_CREATECA 3#define ACTION_CREATEREQUEST 4#define ACTION_CREATECERT 5#define ACTION_CREATECRL 6#define ACTION_VALUES 7/* How much extra to pad cryptlib's response on cert sizes to eliminate segfaults */#define FUDGE_FACTOR 10#define VERSION "$Date: 2004/03/12 01:22:02 $ $Revision: 1.24 $\n"/*#define SET_FAUX_BLANK_SUBJECT *//*Memory management note:This program allocates but never frees memory toprevent errors. This program is only designed forshort term use and doesn't use much memory, sothis should never be a problem and should helpeliminate memory bugs.*//* A stringlist is a standard linked-list of strings. */struct stringlist { char *item; struct stringlist *next;};/* A txtcodepair is a pair of a string for a label and an integer representing a cryptlib field for the label.*/struct txtcodepair { char *txt; int code;};/* This table holds abbreviations for fields of the subject and the corresponding name of the field in cryptlib.*/#define NUM_SUBJ_ALT_ATTR 3struct txtcodepair subjalttable[] = { { "email", CRYPT_CERTINFO_RFC822NAME }, { "dns", CRYPT_CERTINFO_DNSNAME }, { "ip", CRYPT_CERTINFO_IPADDRESS },};/* This table holds abbreviations for key usage names, and the corresponding field name in cryptlib.*/#define NUM_USAGE 9struct txtcodepair usagetable[] = { { "digitalSignature", CRYPT_KEYUSAGE_DIGITALSIGNATURE }, { "nonRepudiation", CRYPT_KEYUSAGE_NONREPUDIATION }, { "keyEncipherment", CRYPT_KEYUSAGE_KEYENCIPHERMENT }, { "dataEncipherment", CRYPT_KEYUSAGE_DATAENCIPHERMENT }, { "keyAgreement", CRYPT_KEYUSAGE_KEYAGREEMENT }, { "keyCertSign", CRYPT_KEYUSAGE_KEYCERTSIGN }, { "cRLSign", CRYPT_KEYUSAGE_CRLSIGN }, { "encipherOnly", CRYPT_KEYUSAGE_ENCIPHERONLY }, { "decipherOnly", CRYPT_KEYUSAGE_DECIPHERONLY },};/* This table defines extended key usages and the cryptlib field name. These are also allowed in the key usage field.*/#define NUM_EXTUSAGE 17struct txtcodepair extusagetable[] = { { "codeSigning", CRYPT_CERTINFO_EXTKEY_CODESIGNING}, { "directoryService", CRYPT_CERTINFO_EXTKEY_DIRECTORYSERVICE}, { "emailProtection", CRYPT_CERTINFO_EXTKEY_EMAILPROTECTION}, { "ipsecEndSystem", CRYPT_CERTINFO_EXTKEY_IPSECENDSYSTEM}, { "ipsecTunnel", CRYPT_CERTINFO_EXTKEY_IPSECTUNNEL}, { "ipsecUser", CRYPT_CERTINFO_EXTKEY_IPSECUSER}, { "msCertTrustListSigning", CRYPT_CERTINFO_EXTKEY_MS_CERTTRUSTLISTSIGNING}, { "msTimestampSigning", CRYPT_CERTINFO_EXTKEY_MS_TIMESTAMPSIGNING}, { "msEncryptedFilesystem", CRYPT_CERTINFO_EXTKEY_MS_ENCRYPTEDFILESYSTEM}, { "msIndividualCodeSigning", CRYPT_CERTINFO_EXTKEY_MS_INDIVIDUALCODESIGNING}, { "msCommercialCodeSigning", CRYPT_CERTINFO_EXTKEY_MS_COMMERCIALCODESIGNING}, { "msServerGatedCrypto", CRYPT_CERTINFO_EXTKEY_MS_SERVERGATEDCRYPTO}, { "nsServerGatedCrypto", CRYPT_CERTINFO_EXTKEY_NS_SERVERGATEDCRYPTO}, { "vsServerGatedCryptoCa", CRYPT_CERTINFO_EXTKEY_VS_SERVERGATEDCRYPTO_CA}, { "serverAuth", CRYPT_CERTINFO_EXTKEY_SERVERAUTH}, { "clientAuth", CRYPT_CERTINFO_EXTKEY_CLIENTAUTH}, { "timestamping", CRYPT_CERTINFO_EXTKEY_TIMESTAMPING}, };/* Global variables */struct stringlist *subject;struct stringlist *subject_alt;struct stringlist *usage;struct stringlist *ext_usage;int validfrom;int validto;int crl_next_update;char *inputfile;char *outputfile;char *keyfile;int keysize;char *password;int action;int show_values;char *cert_dup_dir;char *crldp;int use_request_info_subj;int use_request_info_alt;int subject_declared;int subject_alt_declared;/* Set default values for global variables */void set_defaults(void) { subject = NULL; usage = NULL; validfrom = time(NULL); /* The validto date is the current time +5 years */ validto = validfrom + 60*60*24*365*5; /* Unless otherwise overridden, the crl-next-update time is +1day */ crl_next_update = validfrom + 60*60*24; inputfile = NULL; outputfile = NULL; keyfile = NULL; keysize = 0; password = NULL; action = ACTION_NONE; show_values = 0; cert_dup_dir = NULL; crldp = NULL; use_request_info_subj = FALSE; use_request_info_alt = FALSE; subject_declared = FALSE; subject_alt_declared = FALSE;}/* Print an error message then stop. */void die(char *err){ fprintf(stderr, "ERROR: %s\n", err); exit(EXIT_FAILURE);}/* Print a warning message, then continue. */void warn(char *warn){ fprintf(stderr, "WARNING: %s\n", warn);}/* Given two strings, create a new string that is the concatenation of both and return it.*/char *string_cat(char *left, char *right){ char *res; res = (char *)malloc(strlen(left)+strlen(right)+1); strcpy(res, left); strcat(res, right); return res;}/* Convert an integer into 4 bytes */char *int_to_chars(int x){ char *result; result = (char *)calloc(1,5); strncpy(result, (char *)&x, 4); result[4]=0; return result;}/* Determine if a string is entirely space characters. */int entirely_spaces(char *txt){ while(*txt && isspace(*txt)) txt++; if(*txt == 0) return TRUE; return FALSE;}/* Determine if a string is a comment (starts with #). */int comment(char *txt){ while(*txt && isspace(*txt)) txt++; if(*txt == '#') return TRUE; return FALSE;}/*Print a list of strings (for debugging purposes).Prints everything on one line, each string has [] around it,period at end with newline.*/void printlist(struct stringlist *lst){ if(lst==NULL) { printf("Empty\n"); } else { while(lst) { printf("[%s] ", lst->item); lst = lst->next; } printf(".\n"); }}/* Given a reference to a variable holding a list of strings, and a second list of strings, append the second list to the first list and set the referenced variable to the result. The first variable must be passed by reference to allow it to be modified; this means that the first argument will be a pointer to a pointer to a list node.*/void stringlist_extend(struct stringlist **lst1, struct stringlist *lst2){ struct stringlist *ptr; if(*lst1==NULL) { *lst1 = lst2; return; } for(ptr = *lst1; ptr && ptr->next; ptr = ptr->next) {}; ptr->next = lst2;}/* Given a reference to a variable holding a list of strings, and a second string, append the string to the list of strings. The first variable must be passed by reference to allow the value of the variable to be modified by the function. */void stringlist_append(struct stringlist **lst, char *item){ struct stringlist *t; struct stringlist *temp; temp = (struct stringlist *)malloc(sizeof(struct stringlist)); temp->item = strdup(item); temp->next = NULL; if(*lst == NULL) { *lst = temp; return; } t = *lst; while(t->next) t=t->next; t->next = temp;}/* Given a reference to a variable holding a list of strings, reverse the list to which the variable refers. The argument must be passed by reference so that the value of the variable may be changed by the function.*/void stringlist_reverse(struct stringlist **lst){ char *tmp; struct stringlist *l; if(*lst == NULL) return; l = *lst; tmp = l->item; l=l->next; stringlist_reverse(&l); stringlist_append(&l, tmp); *lst = l;}/* Break a string into a list of strings at the semicolons. *//* This function is the helper subroutine for the full function. This function takes a partial result reference and the rest of the string to process, finds a semicolon, adds the string to the partial results, and recursively calls itself. */void separate_semicolons_sub(struct stringlist **results, char *rest){ int i, flag; char buffer[MAXBUF]; /* No more text means we are done, return the accumulated answer */ if(*rest==0) return; /* Ignore spaces at start of string */ while(*rest==' ') rest++; flag = FALSE; for(i=0; i<strlen(rest); i++) if(rest[i] == ';') { flag = TRUE; break; } if(flag) { memcpy(buffer, rest, i); buffer[i]=0; rest += i; rest++; stringlist_append(results, buffer); separate_semicolons_sub(results, rest); return; } else { stringlist_append(results, rest); return; }}/* Given a string, return a list of strings that represents breaking the string at the semicolons. The semicolons do not appear anywhere in the result. */struct stringlist *separate_semicolons(char *line){ struct stringlist *val; val = NULL; separate_semicolons_sub(&val, line); return val;}/* Given a reference to a variable holding a list of strings and a string, interpret the string as a semicolon list and either replace the old value of the variable or add entries to it. Entries are added if the line starts with +, otherwise they are replaced.*/int process_semicolonlist(struct stringlist **var, char *line){ if(line[0] == '+') { struct stringlist *newvals; line++; newvals = separate_semicolons(line); stringlist_extend(var, newvals); return TRUE; } else { *var = separate_semicolons(line); } return FALSE;}/* Given a string representing a date, return the date as number of seconds since 1970. Date may be like 5y, 2m, 100d (y=years, m=months, d=days, h=hours) or like 20031223, (yyyymmddhhmmss) with hh,mm,ss optional. Omitted elements are set to 0 in date.*/int process_date(char *txt){ int curtime; int pos, val; char last; char buffer[MAXBUF]; struct tm tminfo; curtime = time(NULL); if(*txt==0) return curtime; if(strlen(txt)==0) return curtime; pos = strlen(txt)-1; last = txt[pos]; if(last == 'h' || last == 'd' || last == 'm' || last == 'y') { memcpy(buffer, txt, pos); buffer[pos]=0; val=atoi(buffer); if(last == 'h') return curtime + 60*60*val; if(last == 'd') return curtime + 60*60*24*val; if(last == 'm') return curtime + 60*60*24*30*val; if(last == 'y') return curtime + 60*60*24*365*val; return curtime; } memset(&tminfo, 0, sizeof(tminfo)); tminfo.tm_sec = 0; tminfo.tm_min = 0; tminfo.tm_hour = 0; tminfo.tm_mday = 0; tminfo.tm_mon = 0; tminfo.tm_year = 0; tminfo.tm_isdst = -1; if(strlen(txt)>=4) { memcpy(buffer, txt+0, 4); buffer[4]=0; tminfo.tm_year = atoi(buffer)-1900; } if(strlen(txt)>=6) { memcpy(buffer, txt+4, 2); buffer[2]=0; tminfo.tm_mon = atoi(buffer)-1; } if(strlen(txt)>=8) { memcpy(buffer, txt+6, 2); buffer[2]=0; tminfo.tm_mday = atoi(buffer); } if(strlen(txt)>=10) { memcpy(buffer, txt+8, 2); buffer[2]=0; tminfo.tm_hour = atoi(buffer); } if(strlen(txt)>=12) { memcpy(buffer, txt+10, 2); buffer[2]=0; tminfo.tm_min = atoi(buffer); } if(strlen(txt)>=14) { memcpy(buffer, txt+12, 2); buffer[2]=0; tminfo.tm_sec = atoi(buffer); } val = mktime(&tminfo); if(val < 0) { fprintf(stderr, "ERROR: String \"%s\" is not a legal date.\n", txt); exit(EXIT_FAILURE); } return val;}/* Forward declaration for mutual recursion between process_file and process_line. */void process_file(char *filename);/* Make sure there is not already an action to perform. */void check_no_action(void){ if(!(action == ACTION_NONE)) { die("Already performing an action."); }}/* Print version information. */void print_version_info(void){ printf("SimpleCA\n"); printf(VERSION);}/* Print help text. */void print_help_text(void){ printf("LEGAL OPTIONS\n"); printf("config = filename\n"); printf("subj = [+]field:val;field:val\n"); printf("subj-alt = [+]field:val;field:val\n"); printf("key-usage = [+]use;use;use\n"); printf("ext-key-usage = [+]use;use;use\n"); printf("key-size = n\n"); printf("password = txt\n"); printf("start-date = n[y|m|d|h] | yyyymmdd[hh[mm[ss]]]\n"); printf("end-date = n[y|m|d|h] | yyyymmdd[hh[mm[ss]]]\n"); printf("crl-next-update = n[y|m|d|h] | yyyymmdd[hh[mm[ss]]]\n"); printf("view = filename\n"); printf("priv-key = filename\n"); printf("crl-contents = filename\n"); printf("crldp = url\n"); printf("request = filename\n"); printf("cert-dup-dir = directory\n"); printf("create-new-ca = filename\n"); printf("create-keys = filename\n"); printf("create-request = filename\n"); printf("create-cert = filename\n"); printf("create-crl = filename\n"); printf("show-values\n"); printf("values\n"); printf("help\n");}/* Given a pair of strings left=right, process them. This will normally just set some global variable and return. */void process_pair(char *left, char *right){ int app; if(strcmp(left, "config")==0) { process_file(right); return; } if(strcmp(left, "subj")==0) { app = process_semicolonlist(&subject, right); subject_declared = TRUE; if(app) use_request_info_subj = TRUE; return; } if(strcmp(left, "subj-alt")==0) { app = process_semicolonlist(&subject_alt, right); subject_alt_declared = TRUE; if(app) use_request_info_alt = TRUE; return; } if(strcmp(left, "key-usage")==0) { process_semicolonlist(&usage, right); return;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -