?? simpleca.c
字號(hào):
val |= usagetable[i].code; flag = TRUE; } } if(!flag) { fprintf(stderr, "ERROR: Unknown key usage %s.\n", ptr->item); exit(EXIT_FAILURE); } } /* If there are no defined key uses, let cryptlib do its defaults */ /* It is an error to try to set usages to 0 in cryptlib */ if(val) { res = cryptSetAttribute(cert, CRYPT_CERTINFO_KEYUSAGE, val); if(res) die("Could not set normal key usage field."); } else { warn("No key usages set, using defaults."); }}/* Given a certificate and list of strings, set the extended key usage fields on the certificate. */void set_ext_key_usage(CRYPT_CERTIFICATE cert, struct stringlist *usage){ int i, flag; int val, res; struct stringlist *ptr; val = 0; for(ptr = usage; ptr; ptr=ptr->next) { flag = FALSE; for(i=0; i<NUM_EXTUSAGE; i++) { if(strcasecmp(ptr->item, extusagetable[i].txt)==0) { res = cryptSetAttribute(cert, extusagetable[i].code, CRYPT_UNUSED); if(res) { /* already set maybe, ignore */ } flag = TRUE; } } if(!flag) { fprintf(stderr, "ERROR: Unknown extended key usage %s.\n", ptr->item); exit(EXIT_FAILURE); } }}/* Given an 8 byte string containing a binary serial number, return a textual representation of the serial number in hex.*/char *sn_to_string(unsigned char *sn){ char buffer[MAXBUF]; /*Print each byte as a 0-padded, 2 character hex value. */ snprintf(buffer, MAXBUF, "%02x%02x%02x%02x%02x%02x%02x%02x", sn[0], sn[1], sn[2], sn[3], sn[4], sn[5], sn[6], sn[7]); return strdup(buffer);}char *get_raw_dn(CRYPT_CERTIFICATE cert){ int res, length; char buffer[MAXBUF]; res=cryptGetAttributeString(cert, CRYPT_CERTINFO_DN, buffer, &length); if(res) die("Could not get subject distinguished name."); buffer[length]=0; return strdup(buffer);}char *get_dn(CRYPT_CERTIFICATE cert){ return strdup(prettify_subject(get_raw_dn(cert)));}/* Given a string of 4 bytes representing an IP address, return text string of that ip address */char *expand_ip(char *str){ char buffer[MAXBUF]; snprintf(buffer, MAXBUF, "%d.%d.%d.%d", *((unsigned char *)(str+0)), *((unsigned char *)(str+1)), *((unsigned char *)(str+2)), *((unsigned char *)(str+3))); return strdup(buffer);}/* Retrieve the general name (alt name) of a given certificate in text form */char *get_gn(CRYPT_CERTIFICATE cert){ int i, res, length, putcomma; char buffer[MAXBUF]; char *result; putcomma = 0; result = ""; res=cryptGetAttributeString(cert, CRYPT_CERTINFO_DN, buffer, &length); if(!res) { buffer[length]=0; if(putcomma) result = string_cat(result, ", "); else putcomma=1; result = string_cat(result, prettify_subject(buffer)); } for(i=0; i<NUM_SUBJ_ALT_ATTR; i++) { res=cryptGetAttributeString(cert, subjalttable[i].code, buffer, &length); if(!res) { buffer[length]=0; if(putcomma) result = string_cat(result, ", "); else putcomma=1; /* Handle IP addresses specially */ result = string_cat(result, subjalttable[i].txt); result = string_cat(result, ":"); if(subjalttable[i].code==CRYPT_CERTINFO_IPADDRESS) result = string_cat(result, expand_ip(buffer)); else result = string_cat(result, buffer); } } return result;}/* Given a request and a cert, transfer over anything in the subj-alt of the request to the cert, ignoring errors (for duplicate content)*/void transfer_altname(CRYPT_CERTIFICATE req, CRYPT_CERTIFICATE cert){ char buffer[MAXBUF]; int res, length, i; for(i=0; i<NUM_SUBJ_ALT_ATTR; i++) { res = cryptGetAttributeString(req, subjalttable[i].code, buffer, &length); if(!res) { res = cryptSetAttributeString(cert, subjalttable[i].code, buffer, length); if(res) { printf("WARNING: Could not set attribute %s.\n", subjalttable[i].txt); } } } return;}/* Given data set in global variables, create a certificate from a certificate request. */void create_cert(void){ CRYPT_CERTIFICATE req, cert; CRYPT_KEYSET keyset; CRYPT_CONTEXT privkey; char *txt; int res; if(!keyfile) die("Private key file for CA must be set."); if(!inputfile) die("No certificate request file specified."); req = import_cert(inputfile); res = cryptCheckCert(req, CRYPT_UNUSED); if(res) die("Imported certificate request did not pass a consistency check."); res = cryptKeysetOpen(&keyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, keyfile, CRYPT_KEYOPT_READONLY); if(res) die("Opening private key file failed."); if(password==NULL) { password = get_pass("Password for CA's private key: "); } res = cryptGetPrivateKey(keyset, &privkey, CRYPT_KEYID_NAME, "private", password); if(res) die("Could not retrieve private key from private key file."); res=cryptCreateCert(&cert, CRYPT_UNUSED, CRYPT_CERTTYPE_CERTIFICATE); if(res) die("Creation of blank certificate failed."); /* printf("use_request_info_subj = %d, _alt = %d\n", use_request_info_subj, use_request_info_alt); */ /* If we have a subject or altname to set, just use the key from the request */ res=cryptSetAttribute(cert, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, req); if(res) die("Could not add public key from certificate request to certificate."); /* Set the subject DN (transferring from request as necessary) */ /* The way the transfer from the request works is that we get the raw cryptlib data for the dn, then possibly pass this on to set_cert_dn as appropriate. The last argument to set_cert_dn will get prepended to the final dn. This is good, since usually the request will have a CN and then the repository will add stuff like O or C. */ if(subject_declared) if(use_request_info_subj) set_cert_dn(cert, subject, get_raw_dn(req)); else set_cert_dn(cert, subject, ""); else set_cert_dn(cert, subject, get_raw_dn(req)); /* Set gn, then transfer old gn from request if necessary */ if(subject_alt_declared) set_cert_gn(cert, subject_alt); if(use_request_info_alt) transfer_altname(req, cert); set_cert_valid_times(cert, validfrom, validto); set_key_usage(cert, usage); set_ext_key_usage(cert, ext_usage); res=cryptSignCert(cert, privkey); if(res) printf("Signing error %d\n", res); if(res) die("Signing certificate failed."); txt=export_cert(cert); /* The case when outputfile is STDOUT is special. We write the data to stdout in that case. */ if(strcmp(outputfile, "STDOUT")==0) { printf("%s\n", txt); } else { save_carefully(txt, outputfile); } if(cert_dup_dir) { char buffer[MAXBUF]; snprintf(buffer, MAXBUF, "%s/%s", cert_dup_dir, outputfile); save_carefully(txt, buffer); } res = cryptDestroyCert(req); if(res) die("Could not free certificate request."); res = cryptDestroyContext(privkey); if(res) die("Could not free private key."); res = cryptKeysetClose(keyset); if(res) die("Could not close private key file."); res = cryptDestroyCert(cert); if(res) die("Could not free certificate.");}/* Calculate the length of a list of strings. */int stringlist_length(struct stringlist *lst){ if(lst==NULL) return 0; return 1 + stringlist_length(lst->next);}/* Given a CRL, a filename, and a date, revoke the certificate in the filename on the given date. */void revoke_it(CRYPT_CERTIFICATE cert, char *filename, char *date){ CRYPT_CERTIFICATE victim; int ndate, res; char buffer[4]; if(entirely_spaces(filename)) return; victim = import_cert(filename); ndate = process_date(date); memcpy(buffer, &ndate, 4); res = cryptSetAttribute(cert, CRYPT_CERTINFO_CERTIFICATE, victim); if(res) { fprintf(stderr, "WARNING: Could not add %s to CRL (may be a duplicate entry).\n", filename); } else { res = cryptSetAttributeString(cert, CRYPT_CERTINFO_REVOCATIONDATE, buffer, 4); if(res) die("Could not set revocation date for a certificate in the CRL."); } res=cryptDestroyCert(victim); if(res) die("Could not free revoked certificate.");}/* Given a CRL and a name that may or may not include a date, revoke the named certificate in the CRL. */void try_to_revoke(CRYPT_CERTIFICATE cert, char *name){ char *filename, *date, *t; t = strchr(name, '\t'); if(t==NULL) { filename = name; date = ""; } else { *t = 0; date = t+1; filename = name; } revoke_it(cert, filename, date);}/*Perl-style chomp*/char *chomp(char *txt){ int l; char *res; res = strdup(txt); l = strlen(res) - 1; if(res[l] == '\n') res[l] = 0; return res;}/* Given a CRL and a file, read entries in the file and add them to the CRL. */void add_certificates(CRYPT_CERTIFICATE cert, char *file){ FILE *fp; char buffer[MAXBUF]; char *f; fp=fopen(file, "rt"); if(!fp) { fprintf(stderr, "ERROR: Could not open %s for reading revoked certificates.\n", file); exit(EXIT_FAILURE); } while(!(feof(fp))) { fgets(buffer, MAXBUF, fp); f=chomp(buffer); try_to_revoke(cert, f); } fclose(fp);}/* Given data in global variables, create a CRL. */void create_crl(void){ CRYPT_CERTIFICATE cert; CRYPT_KEYSET keyset; CRYPT_CONTEXT privkey; char *txt; int res; if(!keyfile) die("Private key file for CA must be set."); if(!inputfile) die("No revocation list specified."); res = cryptKeysetOpen(&keyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, keyfile, CRYPT_KEYOPT_READONLY); if(res) die("Opening private key file failed."); if(password==NULL) { password = get_pass("Password for CA private key: "); } res = cryptGetPrivateKey(keyset, &privkey, CRYPT_KEYID_NAME, "private", password); if(res) die("Could not retrieve private key from private key file."); res=cryptCreateCert(&cert, CRYPT_UNUSED, CRYPT_CERTTYPE_CRL); if(res) die("Creation of blank certificate revocation list failed."); set_crl_next_update(cert, crl_next_update); add_certificates(cert, inputfile); res=cryptSignCert(cert, privkey); if(res) die("Signing certificate failed."); txt=export_cert(cert); if(strcmp(outputfile, "STDOUT")==0) { printf("%s\n", txt); } else { save_carefully(txt, outputfile); } if(cert_dup_dir) { char buffer[MAXBUF]; snprintf(buffer, MAXBUF, "%s/%s", cert_dup_dir, outputfile); save_carefully(txt, buffer); } res = cryptDestroyContext(privkey); if(res) die("Could not free private key."); res = cryptKeysetClose(keyset); if(res) die("Could not close private key file."); res = cryptDestroyCert(cert); if(res) die("Could not free certificate.");}/* Given data set in global variables (and data that is entered when prompted), create a new CA certificate and update the information about the private key so it can sign certificates.*/void create_new_ca(void){ FILE *fp; int res; char *txt; char *crlfile; CRYPT_KEYSET keyset; CRYPT_CONTEXT privkey; CRYPT_CERTIFICATE cert; if(!outputfile) die("Must specify output file."); fp=fopen(outputfile, "rt"); if(fp) { fclose(fp); die("Output file already exists."); } if(!keyfile) { keyfile = prompt("Name of file for the key pair to be written to: "); } if(strcmp(keyfile, "")==0) die("No filename entered."); fp=fopen(keyfile, "rt"); if(fp) { die("File already exists."); } else { /* Create the keyfile */ res = cryptKeysetOpen(&keyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, keyfile, CRYPT_KEYOPT_CREATE); if(res) die("Creating keyfile failed."); /* Just use RSA, less complicated for user. */ res = cryptCreateContext(&privkey, CRYPT_UNUSED, CRYPT_ALGO_RSA); if(res) die("Creating private key context failed."); /* cryptlib requires all keys to have labels, we always use "private" for private keys. */ res = cryptSetAttributeString(privkey, CRYPT_CTXINFO_LABEL, "private", 7); if(res) die("Setting label for private key failed."); if(keysize<=0) { txt = prompt("Key size in bits (<RETURN> for 1024): "); keysize = atoi(txt); } if(keysize<=0) { warn("No keysize specified, using 1024 bits."); keysize = 1024; } res = cryptSetAttribute(privkey, CRYPT_CTXINFO_KEYSIZE, keysize/8); if(res) die("Setting key size failed."); res = cryptGenerateKey(privkey); if(res) die("Generation of private key failed."); if(password==NULL) { password = get_pass("Password for the key being created: "); } res = cryptAddPrivateKey(keyset, privkey, password); if(res) die("Adding private key to keyfile failed."); } if(stringlist_length(subject) == 0) { txt = prompt("CA name: "); if(strlen(txt)==0) die("CA name cannot be empty."); stringlist_append(&subject, string_cat("cn:", txt)); } res=cryptCreateCert(&cert, CRYPT_UNUSED, CRYPT_CERTTYPE_CERTIFICATE); if(res) die("Creation of blank certificate failed."); res=cryptSetAttribute(cert, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, privkey); if(res) die("Could not add key to certificate."); res=cryptSetAttribute(cert, CRYPT_CERTINFO_CA, 1); if(res) die("Could not set CA attribute of certificate."); res=cryptSetAttribute(cert, CRYPT_CERTINFO_SELFSIGNED, 1); if(res) die("Could not set selfsigned attribute of certificate."); set_cert_dn(cert, subject, ""); set_cert_gn(cert, subject_alt); set_cert_valid_times(cert, validfrom, validto); /* Let cryptlib handle CA's key usages since CA is a special case. The user probably wants the key usages to apply to keys certified by the CA. */ /* set_key_usage(cert, usage); */ /* set_ext_key_usage(cert, ext_usage); */ /* Finally get the CRLDP and set it if it's there */ if(crldp) { res=cryptSetAttribute(cert, CRYPT_CERTINFO_CURRENT_FIELD, CRYPT_CERTINFO_CRLDIST_FULLNAME); if(res) die("Could not move to CRLDP extension."); res=cryptSetAttributeString(cert, CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, crldp, strlen(crldp)); if(res) die("Could not set CRLDP in certificate."); } res=cryptSignCert(cert, privkey); if(res) die("Signing certificate failed."); res=cryptAddPublicKey(keyset, cert); if(res) die("Could not add CA certificate to CA private key store."); txt=export_cert(cert); if(strcmp(outputfile, "STDOUT")==0) { printf("%s\n", txt); } else { save_carefully(txt, outputfile); } if(cert_dup_dir) { char buffer[MAXBUF]; snprintf(buffer, MAXBUF, "%s/%s", cert_dup_dir, outputfile); save_carefully(txt, buffer); } /* Create initial blank CRL */ if(1) { /* Write a blank CRL */ res = cryptDestroyCert(cert); if(res) die("Could not free certificate."); res = cryptDestroyContext(privkey); if(res) die("Could not free private key."); res = cryptKeysetClose(keyset); if(res) die("Could not close private key file."); res = cryptKeysetOpen(&keyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, keyfile, CRYPT_KEYOPT_READONLY); if(res) die("Opening private key file failed."); res = cryptGetPrivateKey(keyset, &privkey, CRYPT_KEYID_NAME, "private", password); if(res) die("Could not retrieve private key from private key file."); if(!inputfile) crlfile = prompt("Name of file for the empty CRL to be written to: "); else crlfile = prompt("Name of file for the initial CRL to be written to: "); res=cryptCreateCert(&cert, CRYPT_UNUSED, CRYPT_CERTTYPE_CRL); if(res) die("Creation of blank certificate revocation list failed."); set_crl_next_update(cert, crl_next_update); if(inputfile) add_certificates(cert, inputfile); res=cryptSignCert(cert, privkey); if(res) die("Signing certificate failed."); txt=export_cert(cert); if(strcmp(crlfile, "STDOUT")==0) { printf("%s\n", txt); } else { save_carefully(txt, crlfile); } if(cert_dup_dir) { char buffer[MAXBUF]; snprintf(buffer, MAXBUF, "%s/%s", cert_dup_dir, crlfile); save_carefully(txt, buffer); } }}/* Generate a string of a list of strings with semicolons between entries. */char *semicolon_list(struct stringlist *lst){ char tmp[MAXBUF]; char *res; if(lst==NULL) return ""; if(lst && lst->next) { snprintf(tmp, MAXBUF, "%s;", lst->item); res = semicolon_list(lst->next); return string_cat(tmp, res); } snprintf(tmp, MAXBUF, "%s", lst->item); return(strdup(tmp));}/* Print a list of strings with semicolons between entries. */
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -