diff options
Diffstat (limited to 'apps/ca.c')
-rw-r--r-- | apps/ca.c | 214 |
1 files changed, 115 insertions, 99 deletions
diff --git a/apps/ca.c b/apps/ca.c index 651c5a648afc..2a83d1936e4c 100644 --- a/apps/ca.c +++ b/apps/ca.c @@ -63,7 +63,6 @@ #include <string.h> #include <ctype.h> #include <sys/types.h> -#include <sys/stat.h> #include <openssl/conf.h> #include <openssl/bio.h> #include <openssl/err.h> @@ -83,7 +82,7 @@ # else # include <unixlib.h> # endif -# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_NETWARE) && !defined(__TANDEM) +# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_NETWARE) # include <sys/file.h> # endif #endif @@ -198,26 +197,30 @@ extern int EF_ALIGNMENT; static void lookup_fail(const char *name, const char *tag); static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509, - const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,CA_DB *db, + const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy,CA_DB *db, BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate, long days, int batch, char *ext_sect, CONF *conf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy, int selfsign); static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509, - const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy, + const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate, long days, int batch, char *ext_sect, CONF *conf,int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy, ENGINE *e); static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509, - const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy, + const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate, long days, char *ext_sect, CONF *conf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy); static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext); static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, + STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate, long days, int batch, int verbose, X509_REQ *req, char *ext_sect, CONF *conf, @@ -258,6 +261,7 @@ int MAIN(int argc, char **argv) int doupdatedb=0; long crldays=0; long crlhours=0; + long crlsec=0; long errorline= -1; char *configfile=NULL; char *md=NULL; @@ -305,11 +309,13 @@ int MAIN(int argc, char **argv) ASN1_TIME *tmptm; ASN1_INTEGER *tmpser; char *f; - const char *p, **pp; + const char *p; + char * const *pp; int i,j; const EVP_MD *dgst=NULL; STACK_OF(CONF_VALUE) *attribs=NULL; STACK_OF(X509) *cert_sk=NULL; + STACK_OF(OPENSSL_STRING) *sigopts = NULL; #undef BSIZE #define BSIZE 256 MS_STATIC char buf[3][BSIZE]; @@ -434,6 +440,15 @@ EF_ALIGNMENT=0; if (--argc < 1) goto bad; outdir= *(++argv); } + else if (strcmp(*argv,"-sigopt") == 0) + { + if (--argc < 1) + goto bad; + if (!sigopts) + sigopts = sk_OPENSSL_STRING_new_null(); + if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv))) + goto bad; + } else if (strcmp(*argv,"-notext") == 0) notext=1; else if (strcmp(*argv,"-batch") == 0) @@ -456,6 +471,11 @@ EF_ALIGNMENT=0; if (--argc < 1) goto bad; crlhours= atol(*(++argv)); } + else if (strcmp(*argv,"-crlsec") == 0) + { + if (--argc < 1) goto bad; + crlsec = atol(*(++argv)); + } else if (strcmp(*argv,"-infiles") == 0) { argc--; @@ -549,8 +569,10 @@ bad: if (badops) { - for (pp=ca_usage; (*pp != NULL); pp++) - BIO_printf(bio_err,"%s",*pp); + const char **pp2; + + for (pp2=ca_usage; (*pp2 != NULL); pp2++) + BIO_printf(bio_err,"%s",*pp2); goto err; } @@ -825,7 +847,6 @@ bad: /* lookup where to write new certificates */ if ((outdir == NULL) && (req)) { - struct stat sb; if ((outdir=NCONF_get_string(conf,section,ENV_NEW_CERTS_DIR)) == NULL) @@ -844,28 +865,24 @@ bad: that to access(). However, time's too short to do that just now. */ +#ifndef _WIN32 if (access(outdir,R_OK|W_OK|X_OK) != 0) +#else + 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); goto err; } - if (stat(outdir,&sb) != 0) - { - BIO_printf(bio_err,"unable to stat(%s)\n",outdir); - perror(outdir); - goto err; - } -#ifdef S_ISDIR - if (!S_ISDIR(sb.st_mode)) + if (app_isdir(outdir)<=0) { BIO_printf(bio_err,"%s need to be a directory\n",outdir); perror(outdir); goto err; } #endif -#endif } /*****************************************************************/ @@ -879,9 +896,9 @@ bad: if (db == NULL) goto err; /* Lets check some fields */ - for (i=0; i<sk_num(db->db->data); i++) + for (i=0; i<sk_OPENSSL_PSTRING_num(db->db->data); i++) { - pp=(const char **)sk_value(db->db->data,i); + pp=sk_OPENSSL_PSTRING_value(db->db->data,i); if ((pp[DB_type][0] != DB_TYPE_REV) && (pp[DB_rev_date][0] != '\0')) { @@ -894,7 +911,7 @@ bad: BIO_printf(bio_err," in entry %d\n", i+1); goto err; } - if (!check_time_format(pp[DB_exp_date])) + if (!check_time_format((char *)pp[DB_exp_date])) { BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1); goto err; @@ -934,7 +951,7 @@ bad: #endif TXT_DB_write(out,db->db); BIO_printf(bio_err,"%d entries loaded from the database\n", - db->db->data->num); + sk_OPENSSL_PSTRING_num(db->db->data)); BIO_printf(bio_err,"generating index\n"); } @@ -1025,6 +1042,17 @@ bad: goto err; } + if (!strcmp(md, "default")) + { + int def_nid; + if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0) + { + BIO_puts(bio_err,"no default digest\n"); + goto err; + } + md = (char *)OBJ_nid2sn(def_nid); + } + if ((dgst=EVP_get_digestbyname(md)) == NULL) { BIO_printf(bio_err,"%s is an unsupported message digest type\n",md); @@ -1094,9 +1122,9 @@ bad: if (startdate == NULL) ERR_clear_error(); } - if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate)) + if (startdate && !ASN1_TIME_set_string(NULL, startdate)) { - BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n"); + BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n"); goto err; } if (startdate == NULL) startdate="today"; @@ -1108,9 +1136,9 @@ bad: if (enddate == NULL) ERR_clear_error(); } - if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate)) + if (enddate && !ASN1_TIME_set_string(NULL, enddate)) { - BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n"); + BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n"); goto err; } @@ -1156,8 +1184,9 @@ bad: if (spkac_file != NULL) { total++; - j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db, - serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,extensions, + j=certify_spkac(&x,spkac_file,pkey,x509,dgst,sigopts, + attribs,db, serial,subj,chtype,multirdn, + email_dn,startdate,enddate,days,extensions, conf,verbose,certopt,nameopt,default_op,ext_copy); if (j < 0) goto err; if (j > 0) @@ -1180,7 +1209,8 @@ bad: if (ss_cert_file != NULL) { total++; - j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs, + j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,sigopts, + attribs, db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch, extensions,conf,verbose, certopt, nameopt, default_op, ext_copy, e); @@ -1200,7 +1230,7 @@ bad: if (infile != NULL) { total++; - j=certify(&x,infile,pkey,x509p,dgst,attribs,db, + j=certify(&x,infile,pkey,x509p,dgst,sigopts, attribs,db, serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch, extensions,conf,verbose, certopt, nameopt, default_op, ext_copy, selfsign); @@ -1220,7 +1250,7 @@ bad: for (i=0; i<argc; i++) { total++; - j=certify(&x,argv[i],pkey,x509p,dgst,attribs,db, + j=certify(&x,argv[i],pkey,x509p,dgst,sigopts,attribs,db, serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch, extensions,conf,verbose, certopt, nameopt, default_op, ext_copy, selfsign); @@ -1370,7 +1400,7 @@ bad: goto err; } - if (!crldays && !crlhours) + if (!crldays && !crlhours && !crlsec) { if (!NCONF_get_number(conf,section, ENV_DEFAULT_CRL_DAYS, &crldays)) @@ -1379,7 +1409,7 @@ bad: ENV_DEFAULT_CRL_HOURS, &crlhours)) crlhours = 0; } - if ((crldays == 0) && (crlhours == 0)) + if ((crldays == 0) && (crlhours == 0) && (crlsec == 0)) { BIO_printf(bio_err,"cannot lookup how long until the next CRL is issued\n"); goto err; @@ -1393,14 +1423,19 @@ bad: if (!tmptm) goto err; X509_gmtime_adj(tmptm,0); X509_CRL_set_lastUpdate(crl, tmptm); - X509_gmtime_adj(tmptm,(crldays*24+crlhours)*60*60); + if (!X509_time_adj_ex(tmptm, crldays, crlhours*60*60 + crlsec, + NULL)) + { + BIO_puts(bio_err, "error setting CRL nextUpdate\n"); + goto err; + } X509_CRL_set_nextUpdate(crl, tmptm); ASN1_TIME_free(tmptm); - for (i=0; i<sk_num(db->db->data); i++) + for (i=0; i<sk_OPENSSL_PSTRING_num(db->db->data); i++) { - pp=(const char **)sk_value(db->db->data,i); + pp=sk_OPENSSL_PSTRING_value(db->db->data,i); if (pp[DB_type][0] == DB_TYPE_REV) { if ((r=X509_REVOKED_new()) == NULL) goto err; @@ -1426,15 +1461,6 @@ bad: /* we now have a CRL */ if (verbose) BIO_printf(bio_err,"signing CRL\n"); -#ifndef OPENSSL_NO_DSA - if (pkey->type == EVP_PKEY_DSA) - dgst=EVP_dss1(); - else -#endif -#ifndef OPENSSL_NO_ECDSA - if (pkey->type == EVP_PKEY_EC) - dgst=EVP_ecdsa(); -#endif /* Add any extensions asked for */ @@ -1467,7 +1493,13 @@ bad: if (crlnumberfile != NULL) /* we have a CRL number that need updating */ if (!save_serial(crlnumberfile,"new",crlnumber,NULL)) goto err; - if (!X509_CRL_sign(crl,pkey,dgst)) goto err; + if (crlnumber) + { + BN_free(crlnumber); + crlnumber = NULL; + } + + if (!do_X509_CRL_sign(bio_err,crl,pkey,dgst,sigopts)) goto err; PEM_write_bio_X509_CRL(Sout,crl); @@ -1519,7 +1551,10 @@ err: if (free_key && key) OPENSSL_free(key); BN_free(serial); + BN_free(crlnumber); free_index(db); + if (sigopts) + sk_OPENSSL_STRING_free(sigopts); EVP_PKEY_free(pkey); if (x509) X509_free(x509); X509_CRL_free(crl); @@ -1536,8 +1571,10 @@ static void lookup_fail(const char *name, const char *tag) } static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, - const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate, + const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, + BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, + int email_dn, char *startdate, char *enddate, long days, int batch, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy, int selfsign) @@ -1593,7 +1630,8 @@ static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, else BIO_printf(bio_err,"Signature ok\n"); - ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn, email_dn, + ok=do_body(xret,pkey,x509,dgst,sigopts, policy,db,serial,subj,chtype, + multirdn, email_dn, startdate,enddate,days,batch,verbose,req,ext_sect,lconf, certopt, nameopt, default_op, ext_copy, selfsign); @@ -1604,7 +1642,8 @@ err: } static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, - const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db, + const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj, unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate, long days, int batch, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, @@ -1647,7 +1686,7 @@ static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL) goto err; - ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate, + ok=do_body(xret,pkey,x509,dgst,sigopts,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate, days,batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op, ext_copy, 0); @@ -1658,7 +1697,8 @@ err: } static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, - STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj, + STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, + CA_DB *db, BIGNUM *serial, char *subj, unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate, long days, int batch, int verbose, X509_REQ *req, char *ext_sect, CONF *lconf, @@ -1677,7 +1717,9 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, int ok= -1,i,j,last,nid; const char *p; CONF_VALUE *cv; - char *row[DB_NUMBER],**rrow=NULL,**irow=NULL; + OPENSSL_STRING row[DB_NUMBER]; + OPENSSL_STRING *irow=NULL; + OPENSSL_STRING *rrow=NULL; char buf[25]; tmptm=ASN1_UTCTIME_new(); @@ -1919,7 +1961,9 @@ again2: if (db->attributes.unique_subject) { - rrow=TXT_DB_get_by_index(db->db,DB_name,row); + OPENSSL_STRING *crow=row; + + rrow=TXT_DB_get_by_index(db->db,DB_name,crow); if (rrow != NULL) { BIO_printf(bio_err, @@ -1995,11 +2039,11 @@ again2: if (strcmp(startdate,"today") == 0) X509_gmtime_adj(X509_get_notBefore(ret),0); - else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate); + else ASN1_TIME_set_string(X509_get_notBefore(ret),startdate); if (enddate == NULL) - X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days); - else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate); + X509_time_adj_ex(X509_get_notAfter(ret),days, 0, NULL); + else ASN1_TIME_set_string(X509_get_notAfter(ret),enddate); if (!X509_set_subject_name(ret,subject)) goto err; @@ -2119,27 +2163,13 @@ again2: } } - -#ifndef OPENSSL_NO_DSA - if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1(); 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 -#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)) + if (!do_X509_sign(bio_err, ret,pkey,dgst, sigopts)) goto err; /* We now just add it to the database */ @@ -2233,13 +2263,14 @@ static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext) } static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, - const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db, + const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate, long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy) { STACK_OF(CONF_VALUE) *sk=NULL; - LHASH *parms=NULL; + LHASH_OF(CONF_VALUE) *parms=NULL; X509_REQ *req=NULL; CONF_VALUE *cv=NULL; NETSCAPE_SPKI *spki = NULL; @@ -2359,9 +2390,9 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, X509_REQ_set_pubkey(req,pktmp); EVP_PKEY_free(pktmp); - ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate, - days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op, - ext_copy, 0); + ok=do_body(xret,pkey,x509,dgst,sigopts,policy,db,serial,subj,chtype, + multirdn,email_dn,startdate,enddate, days,1,verbose,req, + ext_sect,lconf, certopt, nameopt, default_op, ext_copy, 0); err: if (req != NULL) X509_REQ_free(req); if (parms != NULL) CONF_free(parms); @@ -2373,15 +2404,7 @@ err: static int check_time_format(const char *str) { - ASN1_TIME tm; - - tm.data=(unsigned char *)str; - tm.length=strlen(str); - tm.type=V_ASN1_UTCTIME; - if (ASN1_TIME_check(&tm)) - return 1; - tm.type=V_ASN1_GENERALIZEDTIME; - return ASN1_TIME_check(&tm); + return ASN1_TIME_set_string(NULL, str); } static int do_revoke(X509 *x509, CA_DB *db, int type, char *value) @@ -2396,6 +2419,8 @@ static int do_revoke(X509 *x509, CA_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); + if (!bn) + goto err; if (BN_is_zero(bn)) row[DB_serial]=BUF_strdup("00"); else @@ -2465,7 +2490,7 @@ static int do_revoke(X509 *x509, CA_DB *db, int type, char *value) goto err; } - else if (index_name_cmp((const char **)row,(const char **)rrow)) + else if (index_name_cmp_noconst(row, rrow)) { BIO_printf(bio_err,"ERROR:name does not match %s\n", row[DB_name]); @@ -2535,7 +2560,7 @@ static int get_certificate_status(const char *serial, CA_DB *db) /* Make it Upper Case */ for (i=0; row[DB_serial][i] != '\0'; i++) - row[DB_serial][i] = toupper(row[DB_serial][i]); + row[DB_serial][i] = toupper((unsigned char)row[DB_serial][i]); ok=1; @@ -2614,9 +2639,9 @@ static int do_updatedb (CA_DB *db) else a_y2k = 0; - for (i = 0; i < sk_num(db->db->data); i++) + for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { - rrow = (char **) sk_value(db->db->data, i); + rrow = sk_OPENSSL_PSTRING_value(db->db->data, i); if (rrow[DB_type][0] == 'V') { @@ -2863,22 +2888,13 @@ int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str) p=(char *)str->data; for (j=str->length; j>0; j--) { -#ifdef CHARSET_EBCDIC - if ((*p >= 0x20) && (*p <= 0x7e)) - BIO_printf(bp,"%c",os_toebcdic[*p]); -#else if ((*p >= ' ') && (*p <= '~')) BIO_printf(bp,"%c",*p); -#endif else if (*p & 0x80) BIO_printf(bp,"\\0x%02X",*p); else if ((unsigned char)*p == 0xf7) BIO_printf(bp,"^?"); -#ifdef CHARSET_EBCDIC - else BIO_printf(bp,"^%c",os_toebcdic[*p+0x40]); -#else else BIO_printf(bp,"^%c",*p+'@'); -#endif p++; } BIO_printf(bp,"'\n"); |