⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simpleca.c

📁 simpleca 比起正式的CA来说功能简单
💻 C
📖 第 1 页 / 共 4 页
字号:
	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. */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -