X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=apps%2Fca.c;h=1e70de9a6ae1d71455b23d4c00ed5ad32231dc41;hp=8696b4157147ef54794fa49e09bfeb8d90f4e842;hb=ec5add8784a2ffacd3391daae7937e04225da9da;hpb=657e60fa00ddde3618600d6306be913214d30457 diff --git a/apps/ca.c b/apps/ca.c index 8696b41571..1e70de9a6a 100644 --- a/apps/ca.c +++ b/apps/ca.c @@ -74,6 +74,7 @@ #include #include #include +#include #ifndef W_OK # ifdef VMS @@ -152,7 +153,8 @@ static char *ca_usage[]={ " -days arg - number of days to certify the certificate for\n", " -md arg - md to use, one of md2, md5, sha or sha1\n", " -policy arg - The CA 'policy' to support\n", -" -keyfile arg - PEM private key file\n", +" -keyfile arg - private key file\n", +" -keyform arg - private key file format (PEM or ENGINE)\n", " -key arg - key to decode the private key if it is encrypted\n", " -cert file - The CA certificate\n", " -in file - The input PEM encoded certificate request(s)\n", @@ -167,6 +169,7 @@ static char *ca_usage[]={ " -revoke file - Revoke a certificate (given in file)\n", " -extensions .. - Extension section (override value in config file)\n", " -crlexts .. - CRL extension section (override value in config file)\n", +" -engine e - use engine e, possibly a hardware device.\n", NULL }; @@ -176,13 +179,12 @@ extern int EF_PROTECT_BELOW; extern int EF_ALIGNMENT; #endif -static int add_oid_section(LHASH *conf); static void lookup_fail(char *name,char *tag); -static unsigned long index_serial_hash(char **a); -static int index_serial_cmp(char **a, char **b); -static unsigned long index_name_hash(char **a); +static unsigned long index_serial_hash(const char **a); +static int index_serial_cmp(const char **a, const char **b); +static unsigned long index_name_hash(const char **a); static int index_name_qual(char **a); -static int index_name_cmp(char **a,char **b); +static int index_name_cmp(const char **a,const char **b); static BIGNUM *load_serial(char *serialfile); static int save_serial(char *serialfile, BIGNUM *serial); static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509, @@ -213,9 +215,18 @@ static char *section=NULL; static int preserve=0; static int msie_hack=0; +static IMPLEMENT_LHASH_HASH_FN(index_serial_hash,const char **) +static IMPLEMENT_LHASH_COMP_FN(index_serial_cmp,const char **) +static IMPLEMENT_LHASH_HASH_FN(index_name_hash,const char **) +static IMPLEMENT_LHASH_COMP_FN(index_name_cmp,const char **) + + +int MAIN(int, char **); + int MAIN(int argc, char **argv) { - char *key=NULL; + ENGINE *e = NULL; + char *key=NULL,*passargin=NULL; int total=0; int total_done=0; int badops=0; @@ -232,6 +243,7 @@ int MAIN(int argc, char **argv) char *policy=NULL; char *keyfile=NULL; char *certfile=NULL; + int keyform=FORMAT_PEM; char *infile=NULL; char *spkac_file=NULL; char *ss_cert_file=NULL; @@ -261,12 +273,13 @@ int MAIN(int argc, char **argv) long l; const EVP_MD *dgst=NULL; STACK_OF(CONF_VALUE) *attribs=NULL; - STACK *cert_sk=NULL; + STACK_OF(X509) *cert_sk=NULL; BIO *hex=NULL; #undef BSIZE #define BSIZE 256 MS_STATIC char buf[3][BSIZE]; char *randfile=NULL; + char *engine = NULL; #ifdef EFENCE EF_PROTECT_FREE=1; @@ -332,6 +345,16 @@ EF_ALIGNMENT=0; if (--argc < 1) goto bad; keyfile= *(++argv); } + else if (strcmp(*argv,"-keyform") == 0) + { + if (--argc < 1) goto bad; + keyform=str2fmt(*(++argv)); + } + else if (strcmp(*argv,"-passin") == 0) + { + if (--argc < 1) goto bad; + passargin= *(++argv); + } else if (strcmp(*argv,"-key") == 0) { if (--argc < 1) goto bad; @@ -413,6 +436,11 @@ EF_ALIGNMENT=0; if (--argc < 1) goto bad; crl_ext= *(++argv); } + else if (strcmp(*argv,"-engine") == 0) + { + if (--argc < 1) goto bad; + engine= *(++argv); + } else { bad: @@ -433,6 +461,24 @@ bad: ERR_load_crypto_strings(); + if (engine != NULL) + { + if((e = ENGINE_by_id(engine)) == NULL) + { + BIO_printf(bio_err,"invalid engine \"%s\"\n", + engine); + goto err; + } + if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) + { + BIO_printf(bio_err,"can't use that engine\n"); + goto err; + } + BIO_printf(bio_err,"engine \"%s\" set.\n", engine); + /* Free our "structural" reference. */ + ENGINE_free(e); + } + /*****************************************************************/ if (configfile == NULL) configfile = getenv("OPENSSL_CONF"); if (configfile == NULL) configfile = getenv("SSLEAY_CONF"); @@ -477,6 +523,8 @@ bad: if (conf != NULL) { p=CONF_get_string(conf,NULL,"oid_file"); + if (p == NULL) + ERR_clear_error(); if (p != NULL) { BIO *oid_bio; @@ -496,7 +544,7 @@ bad: BIO_free(oid_bio); } } - if(!add_oid_section(conf)) + if(!add_oid_section(bio_err,conf)) { ERR_print_errors(bio_err); goto err; @@ -504,6 +552,8 @@ bad: } randfile = CONF_get_string(conf, BASE_SECTION, "RANDFILE"); + if (randfile == NULL) + ERR_clear_error(); app_RAND_load_file(randfile, bio_err, 0); in=BIO_new(BIO_s_file()); @@ -525,14 +575,36 @@ bad: lookup_fail(section,ENV_PRIVATE_KEY); goto err; } - if (BIO_read_filename(in,keyfile) <= 0) + if(!key && !app_passwd(bio_err, passargin, NULL, &key, NULL)) + { + BIO_printf(bio_err,"Error getting password\n"); + goto err; + } + if (keyform == FORMAT_ENGINE) + { + if (!e) + { + BIO_printf(bio_err,"no engine specified\n"); + goto err; + } + pkey = ENGINE_load_private_key(e, keyfile, key); + } + else if (keyform == FORMAT_PEM) { - perror(keyfile); - BIO_printf(bio_err,"trying to load CA private key\n"); + if (BIO_read_filename(in,keyfile) <= 0) + { + perror(keyfile); + BIO_printf(bio_err,"trying to load CA private key\n"); + goto err; + } + pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,key); + } + else + { + BIO_printf(bio_err,"bad input format specified for key file\n"); goto err; } - pkey=PEM_read_bio_PrivateKey(in,NULL,PEM_cb,key); - if(key) memset(key,0,strlen(key)); + if(key) memset(key,0,strlen(key)); if (pkey == NULL) { BIO_printf(bio_err,"unable to load CA private key\n"); @@ -567,9 +639,13 @@ bad: } f=CONF_get_string(conf,BASE_SECTION,ENV_PRESERVE); + if (f == NULL) + ERR_clear_error(); if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) preserve=1; f=CONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK); + if (f == NULL) + ERR_clear_error(); if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) msie_hack=1; @@ -585,12 +661,17 @@ bad: BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n"); goto err; } -#ifdef VMS - /* For technical reasons, VMS misbehaves with X_OK */ - if (access(outdir,R_OK|W_OK) != 0) -#else +#ifndef VMS /* outdir is a directory spec, but access() for VMS demands a + filename. In any case, stat(), below, will catch the problem + if outdir is not a directory spec, and the fopen() or open() + will catch an error if there is no write access. + + Presumably, this problem could also be solved by using the DEC + C routines to convert the directory syntax to Unixly, and give + that to access(). However, time's too short to do that just + now. + */ if (access(outdir,R_OK|W_OK|X_OK) != 0) -#endif { BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir); perror(outdir); @@ -610,6 +691,7 @@ bad: perror(outdir); goto err; } +#endif #endif } @@ -673,21 +755,29 @@ bad: if (verbose) { BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */ +#ifdef VMS + { + BIO *tmpbio = BIO_new(BIO_f_linebuffer()); + out = BIO_push(tmpbio, out); + } +#endif TXT_DB_write(out,db); BIO_printf(bio_err,"%d entries loaded from the database\n", db->data->num); BIO_printf(bio_err,"generating index\n"); } - if (!TXT_DB_create_index(db,DB_serial,NULL,index_serial_hash, - index_serial_cmp)) + if (!TXT_DB_create_index(db, DB_serial, NULL, + LHASH_HASH_FN(index_serial_hash), + LHASH_COMP_FN(index_serial_cmp))) { BIO_printf(bio_err,"error creating serial number index:(%ld,%ld,%ld)\n",db->error,db->arg1,db->arg2); goto err; } - if (!TXT_DB_create_index(db,DB_name,index_name_qual,index_name_hash, - index_name_cmp)) + if (!TXT_DB_create_index(db, DB_name, index_name_qual, + LHASH_HASH_FN(index_name_hash), + LHASH_COMP_FN(index_name_cmp))) { BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n", db->error,db->arg1,db->arg2); @@ -707,7 +797,15 @@ bad: } } else + { BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT); +#ifdef VMS + { + BIO *tmpbio = BIO_new(BIO_f_linebuffer()); + Sout = BIO_push(tmpbio, Sout); + } +#endif + } } if (req) @@ -741,26 +839,34 @@ bad: lookup_fail(section,ENV_SERIAL); goto err; } - if(!extensions) + if (!extensions) + { extensions=CONF_get_string(conf,section,ENV_EXTENSIONS); - if(extensions) { + if (!extensions) + ERR_clear_error(); + } + if (extensions) + { /* Check syntax of file */ X509V3_CTX ctx; X509V3_set_ctx_test(&ctx); X509V3_set_conf_lhash(&ctx, conf); - if(!X509V3_EXT_add_conf(conf, &ctx, extensions, NULL)) { + if (!X509V3_EXT_add_conf(conf, &ctx, extensions, NULL)) + { BIO_printf(bio_err, "Error Loading extension section %s\n", extensions); ret = 1; goto err; + } } - } if (startdate == NULL) { startdate=CONF_get_string(conf,section, ENV_DEFAULT_STARTDATE); + if (startdate == NULL) + ERR_clear_error(); } if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate)) { @@ -773,6 +879,8 @@ bad: { enddate=CONF_get_string(conf,section, ENV_DEFAULT_ENDDATE); + if (enddate == NULL) + ERR_clear_error(); } if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate)) { @@ -800,7 +908,7 @@ bad: { if ((f=BN_bn2hex(serial)) == NULL) goto err; BIO_printf(bio_err,"next serial number is %s\n",f); - Free(f); + OPENSSL_free(f); } if ((attribs=CONF_get_section(conf,policy)) == NULL) @@ -809,9 +917,9 @@ bad: goto err; } - if ((cert_sk=sk_new_null()) == NULL) + if ((cert_sk=sk_X509_new_null()) == NULL) { - BIO_printf(bio_err,"Malloc failure\n"); + BIO_printf(bio_err,"Memory allocation failure\n"); goto err; } if (spkac_file != NULL) @@ -826,9 +934,9 @@ bad: total_done++; BIO_printf(bio_err,"\n"); if (!BN_add_word(serial,1)) goto err; - if (!sk_push(cert_sk,(char *)x)) + if (!sk_X509_push(cert_sk,x)) { - BIO_printf(bio_err,"Malloc failure\n"); + BIO_printf(bio_err,"Memory allocation failure\n"); goto err; } if (outfile) @@ -850,9 +958,9 @@ bad: total_done++; BIO_printf(bio_err,"\n"); if (!BN_add_word(serial,1)) goto err; - if (!sk_push(cert_sk,(char *)x)) + if (!sk_X509_push(cert_sk,x)) { - BIO_printf(bio_err,"Malloc failure\n"); + BIO_printf(bio_err,"Memory allocation failure\n"); goto err; } } @@ -869,9 +977,9 @@ bad: total_done++; BIO_printf(bio_err,"\n"); if (!BN_add_word(serial,1)) goto err; - if (!sk_push(cert_sk,(char *)x)) + if (!sk_X509_push(cert_sk,x)) { - BIO_printf(bio_err,"Malloc failure\n"); + BIO_printf(bio_err,"Memory allocation failure\n"); goto err; } } @@ -888,9 +996,9 @@ bad: total_done++; BIO_printf(bio_err,"\n"); if (!BN_add_word(serial,1)) goto err; - if (!sk_push(cert_sk,(char *)x)) + if (!sk_X509_push(cert_sk,x)) { - BIO_printf(bio_err,"Malloc failure\n"); + BIO_printf(bio_err,"Memory allocation failure\n"); goto err; } } @@ -899,7 +1007,7 @@ bad: * and a data base and serial number that need * updating */ - if (sk_num(cert_sk) > 0) + if (sk_X509_num(cert_sk) > 0) { if (!batch) { @@ -915,7 +1023,7 @@ bad: } } - BIO_printf(bio_err,"Write out database with %d new entries\n",sk_num(cert_sk)); + BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk)); strncpy(buf[0],serialfile,BSIZE-4); @@ -947,12 +1055,12 @@ bad: if (verbose) BIO_printf(bio_err,"writing new certificates\n"); - for (i=0; icert_info->serialNumber->length; p=(char *)x->cert_info->serialNumber->data; @@ -991,7 +1099,7 @@ bad: write_new_certificate(Sout,x, output_der, notext); } - if (sk_num(cert_sk)) + if (sk_X509_num(cert_sk)) { /* Rename the database and the serial file */ strncpy(buf[2],serialfile,BSIZE-4); @@ -1003,7 +1111,7 @@ bad: #endif BIO_free(in); - BIO_free(out); + BIO_free_all(out); in=NULL; out=NULL; if (rename(serialfile,buf[2]) < 0) @@ -1052,20 +1160,27 @@ bad: /*****************************************************************/ if (gencrl) { - if(!crl_ext) crl_ext=CONF_get_string(conf,section,ENV_CRLEXT); - if(crl_ext) { + if (!crl_ext) + { + crl_ext=CONF_get_string(conf,section,ENV_CRLEXT); + if (!crl_ext) + ERR_clear_error(); + } + if (crl_ext) + { /* Check syntax of file */ X509V3_CTX ctx; X509V3_set_ctx_test(&ctx); X509V3_set_conf_lhash(&ctx, conf); - if(!X509V3_EXT_add_conf(conf, &ctx, crl_ext, NULL)) { + if(!X509V3_EXT_add_conf(conf, &ctx, crl_ext, NULL)) + { BIO_printf(bio_err, "Error Loading CRL extension section %s\n", crl_ext); ret = 1; goto err; + } } - } if ((hex=BIO_new(BIO_s_mem())) == NULL) goto err; if (!crldays && !crlhours) @@ -1111,7 +1226,7 @@ bad: if (!a2i_ASN1_INTEGER(hex,r->serialNumber, buf[0],BSIZE)) goto err; - sk_X509_REVOKED_push(ci->revoked,r); + X509_CRL_add0_revoked(crl,r); } } /* sort the data so it will be written in serial @@ -1220,12 +1335,12 @@ bad: ret=0; err: BIO_free(hex); - BIO_free(Cout); - BIO_free(Sout); - BIO_free(out); + BIO_free_all(Cout); + BIO_free_all(Sout); + BIO_free_all(out); BIO_free(in); - sk_pop_free(cert_sk,X509_free); + sk_X509_pop_free(cert_sk,X509_free); if (ret) ERR_print_errors(bio_err); app_RAND_write_file(randfile, bio_err); @@ -1244,31 +1359,31 @@ static void lookup_fail(char *name, char *tag) BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag); } -static unsigned long index_serial_hash(char **a) +static unsigned long index_serial_hash(const char **a) { - char *n; + const char *n; n=a[DB_serial]; while (*n == '0') n++; return(lh_strhash(n)); } -static int index_serial_cmp(char **a, char **b) +static int index_serial_cmp(const char **a, const char **b) { - char *aa,*bb; + const char *aa,*bb; for (aa=a[DB_serial]; *aa == '0'; aa++); for (bb=b[DB_serial]; *bb == '0'; bb++); return(strcmp(aa,bb)); } -static unsigned long index_name_hash(char **a) +static unsigned long index_name_hash(const char **a) { return(lh_strhash(a[DB_name])); } static int index_name_qual(char **a) { return(a[0][0] == 'V'); } -static int index_name_cmp(char **a, char **b) +static int index_name_cmp(const char **a, const char **b) { return(strcmp(a[DB_name], b[DB_name])); } @@ -1337,7 +1452,7 @@ static int save_serial(char *serialfile, BIGNUM *serial) BIO_puts(out,"\n"); ret=1; err: - if (out != NULL) BIO_free(out); + if (out != NULL) BIO_free_all(out); if (ai != NULL) ASN1_INTEGER_free(ai); return(ret); } @@ -1572,7 +1687,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, /* Ok, now we check the 'policy' stuff. */ if ((subject=X509_NAME_new()) == NULL) { - BIO_printf(bio_err,"Malloc failure\n"); + BIO_printf(bio_err,"Memory allocation failure\n"); goto err; } @@ -1654,7 +1769,7 @@ again2: } if (j < 0) { - BIO_printf(bio_err,"The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n",cv->name,((str == NULL)?"NULL":(char *)str->data),((str2 == NULL)?"NULL":(char *)str2->data)); + BIO_printf(bio_err,"The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n",cv->name,((str2 == NULL)?"NULL":(char *)str2->data),((str == NULL)?"NULL":(char *)str->data)); goto err; } } @@ -1670,7 +1785,7 @@ again2: { if (push != NULL) X509_NAME_ENTRY_free(push); - BIO_printf(bio_err,"Malloc failure\n"); + BIO_printf(bio_err,"Memory allocation failure\n"); goto err; } } @@ -1692,7 +1807,7 @@ again2: row[DB_serial]=BN_bn2hex(serial); if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) { - BIO_printf(bio_err,"Malloc failure\n"); + BIO_printf(bio_err,"Memory allocation failure\n"); goto err; } @@ -1833,32 +1948,32 @@ again2: goto err; /* We now just add it to the database */ - row[DB_type]=(char *)Malloc(2); + row[DB_type]=(char *)OPENSSL_malloc(2); tm=X509_get_notAfter(ret); - row[DB_exp_date]=(char *)Malloc(tm->length+1); + row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1); memcpy(row[DB_exp_date],tm->data,tm->length); row[DB_exp_date][tm->length]='\0'; row[DB_rev_date]=NULL; /* row[DB_serial] done already */ - row[DB_file]=(char *)Malloc(8); + row[DB_file]=(char *)OPENSSL_malloc(8); /* row[DB_name] done already */ if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || (row[DB_file] == NULL)) { - BIO_printf(bio_err,"Malloc failure\n"); + BIO_printf(bio_err,"Memory allocation failure\n"); goto err; } strcpy(row[DB_file],"unknown"); row[DB_type][0]='V'; row[DB_type][1]='\0'; - if ((irow=(char **)Malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL) + if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL) { - BIO_printf(bio_err,"Malloc failure\n"); + BIO_printf(bio_err,"Memory allocation failure\n"); goto err; } @@ -1878,7 +1993,7 @@ again2: ok=1; err: for (i=0; ivalue, cnf->name, cnf->name) == NID_undef) { - BIO_printf(bio_err, "problem creating object %s=%s\n", - cnf->name, cnf->value); - return 0; - } - } - return 1; -} - static int do_revoke(X509 *x509, TXT_DB *db) { ASN1_UTCTIME *tm=NULL, *revtm=NULL; @@ -2129,7 +2222,7 @@ static int do_revoke(X509 *x509, TXT_DB *db) BN_free(bn); if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) { - BIO_printf(bio_err,"Malloc failure\n"); + BIO_printf(bio_err,"Memory allocation failure\n"); goto err; } /* We have to lookup by serial number because name lookup @@ -2141,33 +2234,33 @@ static int do_revoke(X509 *x509, TXT_DB *db) BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]); /* We now just add it to the database */ - row[DB_type]=(char *)Malloc(2); + row[DB_type]=(char *)OPENSSL_malloc(2); tm=X509_get_notAfter(x509); - row[DB_exp_date]=(char *)Malloc(tm->length+1); + row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1); memcpy(row[DB_exp_date],tm->data,tm->length); row[DB_exp_date][tm->length]='\0'; row[DB_rev_date]=NULL; /* row[DB_serial] done already */ - row[DB_file]=(char *)Malloc(8); + row[DB_file]=(char *)OPENSSL_malloc(8); /* row[DB_name] done already */ if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || (row[DB_file] == NULL)) { - BIO_printf(bio_err,"Malloc failure\n"); + BIO_printf(bio_err,"Memory allocation failure\n"); goto err; } strcpy(row[DB_file],"unknown"); row[DB_type][0]='V'; row[DB_type][1]='\0'; - if ((irow=(char **)Malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL) + if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL) { - BIO_printf(bio_err,"Malloc failure\n"); + BIO_printf(bio_err,"Memory allocation failure\n"); goto err; } @@ -2191,7 +2284,7 @@ static int do_revoke(X509 *x509, TXT_DB *db) goto err; } - else if (index_name_cmp(row,rrow)) + else if (index_name_cmp((const char **)row,(const char **)rrow)) { BIO_printf(bio_err,"ERROR:name does not match %s\n", row[DB_name]); @@ -2210,7 +2303,7 @@ static int do_revoke(X509 *x509, TXT_DB *db) revtm=X509_gmtime_adj(revtm,0); rrow[DB_type][0]='R'; rrow[DB_type][1]='\0'; - rrow[DB_rev_date]=(char *)Malloc(revtm->length+1); + rrow[DB_rev_date]=(char *)OPENSSL_malloc(revtm->length+1); memcpy(rrow[DB_rev_date],revtm->data,revtm->length); rrow[DB_rev_date][revtm->length]='\0'; ASN1_UTCTIME_free(revtm); @@ -2220,7 +2313,7 @@ err: for (i=0; i