X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=apps%2Fca.c;h=4867f309c7a0645aa4c24d7083942ad15d52684b;hp=a6e6976f7f7f5caa8ea0f79d3c15f27d26b30233;hb=907a8f1e6ef1166c9089841e130b6312b2956c8b;hpb=437db75b943ba0f72eb27d49f660a6d69dfddf1b diff --git a/apps/ca.c b/apps/ca.c index a6e6976f7f..4867f309c7 100644 --- a/apps/ca.c +++ b/apps/ca.c @@ -80,7 +80,11 @@ #ifdef OPENSSL_SYS_WINDOWS #define strcasecmp _stricmp #else -#include +# ifdef NO_STRINGS_H + int strcasecmp(); +# else +# include +# endif /* NO_STRINGS_H */ #endif #ifndef W_OK @@ -90,7 +94,7 @@ # else # include # endif -# else +# elif !defined(OPENSSL_SYS_VXWORKS) # include # endif #endif @@ -238,7 +242,6 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, int verbose, X509_REQ *req, char *ext_sect, CONF *conf, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy); -static X509_NAME *do_subject(char *subject, int email_dn); static int do_revoke(X509 *x509, TXT_DB *db, int ext, char *extval); static int get_certificate_status(const char *ser_status, TXT_DB *db); static int do_updatedb(TXT_DB *db); @@ -571,6 +574,7 @@ bad: #else strncpy(buf[0],X509_get_default_cert_area(), sizeof(buf[0])-2-sizeof(CONFIG_FILE)); + buf[0][sizeof(buf[0])-2-sizeof(CONFIG_FILE)]='\0'; strcat(buf[0],"/"); #endif strcat(buf[0],CONFIG_FILE); @@ -590,6 +594,9 @@ bad: goto err; } + if (!load_config(bio_err, conf)) + goto err; + /* Lets get the config section we are using */ if (section == NULL) { @@ -692,7 +699,7 @@ bad: goto err; } } - pkey = load_key(bio_err, keyfile, keyform, key, e, + pkey = load_key(bio_err, keyfile, keyform, 0, key, e, "CA private key"); if (key) memset(key,0,strlen(key)); if (pkey == NULL) @@ -1151,9 +1158,14 @@ bad: } if (verbose) { - if ((f=BN_bn2hex(serial)) == NULL) goto err; - BIO_printf(bio_err,"next serial number is %s\n",f); - OPENSSL_free(f); + if (BN_is_zero(serial)) + BIO_printf(bio_err,"next serial number is 00\n"); + else + { + if ((f=BN_bn2hex(serial)) == NULL) goto err; + BIO_printf(bio_err,"next serial number is %s\n",f); + OPENSSL_free(f); + } } if ((attribs=NCONF_get_section(conf,policy)) == NULL) @@ -1274,6 +1286,7 @@ bad: BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk)); strncpy(buf[0],serialfile,BSIZE-4); + buf[0][BSIZE-4]='\0'; #ifdef OPENSSL_SYS_VMS strcat(buf[0],"-new"); @@ -1284,6 +1297,7 @@ bad: if (!save_serial(buf[0],serial)) goto err; strncpy(buf[1],dbfile,BSIZE-4); + buf[1][BSIZE-4]='\0'; #ifdef OPENSSL_SYS_VMS strcat(buf[1],"-new"); @@ -1314,6 +1328,7 @@ bad: p=(char *)x->cert_info->serialNumber->data; strncpy(buf[2],outdir,BSIZE-(j*2)-6); + buf[2][BSIZE-(j*2)-6]='\0'; #ifndef OPENSSL_SYS_VMS strcat(buf[2],"/"); @@ -1351,6 +1366,7 @@ bad: { /* Rename the database and the serial file */ strncpy(buf[2],serialfile,BSIZE-4); + buf[2][BSIZE-4]='\0'; #ifdef OPENSSL_SYS_VMS strcat(buf[2],"-old"); @@ -1379,6 +1395,7 @@ bad: } strncpy(buf[2],dbfile,BSIZE-4); + buf[2][BSIZE-4]='\0'; #ifdef OPENSSL_SYS_VMS strcat(buf[2],"-old"); @@ -1442,13 +1459,13 @@ bad: } if ((crldays == 0) && (crlhours == 0)) { - BIO_printf(bio_err,"cannot lookup how long until the next CRL is issuer\n"); + BIO_printf(bio_err,"cannot lookup how long until the next CRL is issued\n"); goto err; } if (verbose) BIO_printf(bio_err,"making CRL\n"); if ((crl=X509_CRL_new()) == NULL) goto err; - if (!X509_CRL_set_issuer_name(crl, X509_get_issuer_name(x509))) goto err; + if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) goto err; tmptm = ASN1_TIME_new(); if (!tmptm) goto err; @@ -1501,6 +1518,11 @@ bad: if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1(); else +#endif +#ifndef OPENSSL_NO_ECDSA + if (pkey->type == EVP_PKEY_EC) + dgst=EVP_ecdsa(); + else #endif dgst=EVP_md5(); } @@ -1546,6 +1568,7 @@ bad: X509_free(revcert); strncpy(buf[0],dbfile,BSIZE-4); + buf[0][BSIZE-4]='\0'; #ifndef OPENSSL_SYS_VMS strcat(buf[0],".new"); #else @@ -1560,11 +1583,16 @@ bad: j=TXT_DB_write(out,db); if (j <= 0) goto err; strncpy(buf[1],dbfile,BSIZE-4); + buf[1][BSIZE-4]='\0'; #ifndef OPENSSL_SYS_VMS strcat(buf[1],".old"); #else strcat(buf[1],"-old"); #endif + BIO_free(in); + in = NULL; + BIO_free(out); + out = NULL; if (rename(dbfile,buf[1]) < 0) { BIO_printf(bio_err,"unable to rename %s to %s\n", dbfile, buf[1]); @@ -1668,7 +1696,7 @@ static BIGNUM *load_serial(char *serialfile) ret=ASN1_INTEGER_to_BN(ai,NULL); if (ret == NULL) { - BIO_printf(bio_err,"error converting number from bin to BIGNUM"); + BIO_printf(bio_err,"error converting number from bin to BIGNUM\n"); goto err; } err: @@ -1859,7 +1887,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, if (subj) { - X509_NAME *n = do_subject(subj, email_dn); + X509_NAME *n = do_subject(subj, MBSTRING_ASC); if (!n) { @@ -1909,14 +1937,17 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n"); goto err; } - j=ASN1_PRINTABLE_type(str->data,str->length); - if ( ((j == V_ASN1_T61STRING) && - (str->type != V_ASN1_T61STRING)) || - ((j == V_ASN1_IA5STRING) && - (str->type == V_ASN1_PRINTABLESTRING))) + if ((str->type != V_ASN1_BMPSTRING) && (str->type != V_ASN1_UTF8STRING)) { - BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n"); - goto err; + j=ASN1_PRINTABLE_type(str->data,str->length); + if ( ((j == V_ASN1_T61STRING) && + (str->type != V_ASN1_T61STRING)) || + ((j == V_ASN1_IA5STRING) && + (str->type == V_ASN1_PRINTABLESTRING))) + { + BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n"); + goto err; + } } if (default_op) @@ -2060,7 +2091,7 @@ again2: goto err; } while((i = X509_NAME_get_index_by_NID(dn_subject, - NID_pkcs9_emailAddress, -1) >= 0)) + NID_pkcs9_emailAddress, -1)) >= 0) { tmpne = X509_NAME_get_entry(dn_subject, i); X509_NAME_delete_entry(dn_subject, i); @@ -2068,9 +2099,11 @@ again2: } } - row[DB_name]=X509_NAME_oneline(dn_subject,NULL,0); - row[DB_serial]=BN_bn2hex(serial); - if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) + if (BN_is_zero(serial)) + row[DB_serial]=BUF_strdup("00"); + else + row[DB_serial]=BN_bn2hex(serial); + if (row[DB_serial] == NULL) { BIO_printf(bio_err,"Memory allocation failure\n"); goto err; @@ -2267,6 +2300,16 @@ again2: EVP_PKEY_copy_parameters(pktmp,pkey); EVP_PKEY_free(pktmp); #endif +#ifndef OPENSSL_NO_ECDSA + if (pkey->type == EVP_PKEY_EC) + dgst = EVP_ecdsa(); + pktmp = X509_get_pubkey(ret); + if (EVP_PKEY_missing_parameters(pktmp) && + !EVP_PKEY_missing_parameters(pkey)) + EVP_PKEY_copy_parameters(pktmp, pkey); + EVP_PKEY_free(pktmp); +#endif + if (!X509_sign(ret,pkey,dgst)) goto err; @@ -2283,10 +2326,10 @@ again2: /* row[DB_serial] done already */ row[DB_file]=(char *)OPENSSL_malloc(8); - /* row[DB_name] done already */ + row[DB_name]=X509_NAME_oneline(X509_get_subject_name(ret),NULL,0); if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || - (row[DB_file] == NULL)) + (row[DB_file] == NULL) || (row[DB_name] == NULL)) { BIO_printf(bio_err,"Memory allocation failure\n"); goto err; @@ -2553,7 +2596,10 @@ static int do_revoke(X509 *x509, TXT_DB *db, int type, char *value) row[i]=NULL; row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0); bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL); - row[DB_serial]=BN_bn2hex(bn); + if (BN_is_zero(bn)) + row[DB_serial]=BUF_strdup("00"); + else + row[DB_serial]=BN_bn2hex(bn); BN_free(bn); if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) { @@ -2990,68 +3036,128 @@ int make_revoked(X509_REVOKED *rev, char *str) return ret; } -static X509_NAME *do_subject(char *subject, int email_dn) +/* + * subject is expected to be in the format /type0=value0/type1=value1/type2=... + * where characters may be escaped by \ + */ +X509_NAME *do_subject(char *subject, long chtype) { - X509_NAME *n = NULL; - - int i, nid, ne_num=0; - - char *ne_name = NULL; - char *ne_value = NULL; - - char *tmp = NULL; - char *p[2]; + size_t buflen = strlen(subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */ + char *buf = OPENSSL_malloc(buflen); + size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */ + char **ne_types = OPENSSL_malloc(max_ne * sizeof (char *)); + char **ne_values = OPENSSL_malloc(max_ne * sizeof (char *)); - char *str_list[256]; - - p[0] = ",/"; - p[1] = "="; + char *sp = subject, *bp = buf; + int i, ne_num = 0; - n = X509_NAME_new(); + X509_NAME *n = NULL; + int nid; - tmp = strtok(subject, p[0]); - while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list))) + if (!buf || !ne_types || !ne_values) { - char *token = tmp; + BIO_printf(bio_err, "malloc error\n"); + goto error; + } - while (token[0] == ' ') - token++; - str_list[ne_num] = token; + if (*subject != '/') + { + BIO_printf(bio_err, "Subject does not start with '/'.\n"); + goto error; + } + sp++; /* skip leading / */ - tmp = strtok(NULL, p[0]); + while (*sp) + { + /* collect type */ + ne_types[ne_num] = bp; + while (*sp) + { + if (*sp == '\\') /* is there anything to escape in the type...? */ + { + if (*++sp) + *bp++ = *sp++; + else + { + BIO_printf(bio_err, "escape character at end of string\n"); + goto error; + } + } + else if (*sp == '=') + { + sp++; + *bp++ = '\0'; + break; + } + else + *bp++ = *sp++; + } + if (!*sp) + { + BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num); + goto error; + } + ne_values[ne_num] = bp; + while (*sp) + { + if (*sp == '\\') + { + if (*++sp) + *bp++ = *sp++; + else + { + BIO_printf(bio_err, "escape character at end of string\n"); + goto error; + } + } + else if (*sp == '/') + { + sp++; + break; + } + else + *bp++ = *sp++; + } + *bp++ = '\0'; ne_num++; - } + } + + if (!(n = X509_NAME_new())) + goto error; for (i = 0; i < ne_num; i++) { - ne_name = strtok(str_list[i], p[1]); - ne_value = strtok(NULL, p[1]); - - if ((nid=OBJ_txt2nid(ne_name)) == NID_undef) + if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef) { - BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_name); + BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]); continue; } - if (ne_value == NULL) + if (!*ne_values[i]) { - BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_name); + BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]); continue; } - if ((nid == NID_pkcs9_emailAddress) && (email_dn == 0)) - continue; - - if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned char*)ne_value, -1,-1,0)) - { - X509_NAME_free(n); - return NULL; - } + if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,0)) + goto error; } + OPENSSL_free(ne_values); + OPENSSL_free(ne_types); + OPENSSL_free(buf); return n; - } +error: + X509_NAME_free(n); + if (ne_values) + OPENSSL_free(ne_values); + if (ne_types) + OPENSSL_free(ne_types); + if (buf) + OPENSSL_free(buf); + return NULL; +} int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str) {