From: Bodo Möller Date: Fri, 12 Jan 2001 14:50:44 +0000 (+0000) Subject: New 'openssl ca -status ' and 'openssl ca -updatedb' X-Git-Tag: OpenSSL_0_9_6a-beta1~81^2~34 X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff_plain;h=c67cdb50d2ef09c917c96d8a7e8a65d698ed9b8c;hp=af5473c45a61add4928a4373503a2e080cd4f8d8 New 'openssl ca -status ' and 'openssl ca -updatedb' commands. Submitted by: Massimiliano Pala --- diff --git a/CHANGES b/CHANGES index 0213d865db..0970f62b42 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,13 @@ Changes between 0.9.6 and 0.9.7 [xx XXX 2000] + *) New subcommands for 'openssl ca': + 'openssl ca -status ' prints the status of the cert with + the given serial number (according to the index file). + 'openssl ca -updatedb' updates the expiry status of certificates + in the index file. + [Massimiliano Pala ] + *) New '-newreq-nodes' command option to CA.pl. This is like '-newreq', but calls 'openssl req' with the '-nodes' option so that the resulting key is not encrypted. diff --git a/apps/ca.c b/apps/ca.c index 1e70de9a6a..2ac0db74d6 100644 --- a/apps/ca.c +++ b/apps/ca.c @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include "apps.h" @@ -170,6 +171,8 @@ static char *ca_usage[]={ " -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", +" -status serial - Shows certificate status given the serial number\n", +" -updatedb - Updates db for expired certificates\n", NULL }; @@ -208,6 +211,8 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, char *startdate, char *enddate, int days, int batch, int verbose, X509_REQ *req, char *ext_sect, LHASH *conf); static int do_revoke(X509 *x509, TXT_DB *db); +static int get_certificate_status(const char *ser_status, TXT_DB *db); +static int do_updatedb(TXT_DB *db); static int check_time_format(char *str); static LHASH *conf=NULL; static char *section=NULL; @@ -235,6 +240,7 @@ int MAIN(int argc, char **argv) int verbose=0; int gencrl=0; int dorevoke=0; + int doupdatedb=0; long crldays=0; long crlhours=0; long errorline= -1; @@ -247,6 +253,7 @@ int MAIN(int argc, char **argv) char *infile=NULL; char *spkac_file=NULL; char *ss_cert_file=NULL; + char *ser_status=NULL; EVP_PKEY *pkey=NULL; int output_der = 0; char *outfile=NULL; @@ -431,6 +438,15 @@ EF_ALIGNMENT=0; if (--argc < 1) goto bad; extensions= *(++argv); } + else if (strcmp(*argv,"-status") == 0) + { + if (--argc < 1) goto bad; + ser_status= *(++argv); + } + else if (strcmp(*argv,"-updatedb") == 0) + { + doupdatedb=1; + } else if (strcmp(*argv,"-crlexts") == 0) { if (--argc < 1) goto bad; @@ -463,13 +479,13 @@ bad: if (engine != NULL) { - if((e = ENGINE_by_id(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)) + if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { BIO_printf(bio_err,"can't use that engine\n"); goto err; @@ -544,7 +560,7 @@ bad: BIO_free(oid_bio); } } - if(!add_oid_section(bio_err,conf)) + if (!add_oid_section(bio_err,conf)) { ERR_print_errors(bio_err); goto err; @@ -567,7 +583,41 @@ bad: } /*****************************************************************/ - /* we definitely need an public key, so lets get it */ + /* report status of cert with serial number given on command line */ + if (ser_status) + { + if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL) + { + lookup_fail(section,ENV_DATABASE); + goto err; + } + if (BIO_read_filename(in,dbfile) <= 0) + { + perror(dbfile); + BIO_printf(bio_err,"unable to open '%s'\n",dbfile); + goto err; + } + db=TXT_DB_read(in,DB_NUMBER); + if (db == NULL) goto err; + + 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 (get_certificate_status(ser_status,db) != 1) + BIO_printf(bio_err,"Error verifying serial %s!\n", + ser_status); + goto err; + } + + /*****************************************************************/ + /* we definitely need a public key, so let's get it */ if ((keyfile == NULL) && ((keyfile=CONF_get_string(conf, section,ENV_PRIVATE_KEY)) == NULL)) @@ -575,7 +625,7 @@ bad: lookup_fail(section,ENV_PRIVATE_KEY); goto err; } - if(!key && !app_passwd(bio_err, passargin, NULL, &key, NULL)) + if (!key && !app_passwd(bio_err, passargin, NULL, &key, NULL)) { BIO_printf(bio_err,"Error getting password\n"); goto err; @@ -604,7 +654,7 @@ bad: BIO_printf(bio_err,"bad input format specified for key file\n"); goto err; } - 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"); @@ -784,6 +834,82 @@ bad: goto err; } + /*****************************************************************/ + /* Update the db file for expired certificates */ + if (doupdatedb) + { + if (verbose) + BIO_printf(bio_err, "Updating %s ...\n", + dbfile); + + i = do_updatedb(db); + if (i == -1) + { + BIO_printf(bio_err,"Malloc failure\n"); + goto err; + } + else if (i == 0) + { + if (verbose) BIO_printf(bio_err, + "No entries found to mark expired\n"); + } + else + { + out = BIO_new(BIO_s_file()); + if (out == NULL) + { + ERR_print_errors(bio_err); + goto err; + } + + j = BIO_snprintf(buf[0], sizeof buf[0], "%s.new", dbfile); + if (j < 0 || j >= sizeof buf[0]) + { + BIO_printf(bio_err, "file name too long\n"); + goto err; + } + if (BIO_write_filename(out,buf[0]) <= 0) + { + perror(dbfile); + BIO_printf(bio_err,"unable to open '%s'\n", + dbfile); + goto err; + } + j=TXT_DB_write(out,db); + if (j <= 0) goto err; + + BIO_free(out); + out = NULL; + j = BIO_snprintf(buf[1], sizeof buf[1], "%s.old", dbfile); + if (j < 0 || j >= sizeof buf[1]) + { + BIO_printf(bio_err, "file name too long\n"); + goto err; + } + if (rename(dbfile,buf[1]) < 0) + { + BIO_printf(bio_err, + "unable to rename %s to %s\n", + dbfile, buf[1]); + perror("reason"); + goto err; + } + if (rename(buf[0],dbfile) < 0) + { + BIO_printf(bio_err, + "unable to rename %s to %s\n", + buf[0],dbfile); + perror("reason"); + rename(buf[1],dbfile); + goto err; + } + + if (verbose) BIO_printf(bio_err, + "Done. %d entries marked as expired\n",i); + } + goto err; + } + /*****************************************************************/ if (req || gencrl) { @@ -1172,7 +1298,7 @@ bad: 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", @@ -1249,28 +1375,29 @@ bad: } } else - { + { #ifndef NO_DSA - if (pkey->type == EVP_PKEY_DSA) - dgst=EVP_dss1(); - else + if (pkey->type == EVP_PKEY_DSA) + dgst=EVP_dss1(); + else #endif - dgst=EVP_md5(); - } + dgst=EVP_md5(); + } /* Add any extensions asked for */ - if(crl_ext) { - X509V3_CTX crlctx; - if (ci->version == NULL) - if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err; - ASN1_INTEGER_set(ci->version,1); /* version 2 CRL */ - X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0); - X509V3_set_conf_lhash(&crlctx, conf); + if (crl_ext) + { + X509V3_CTX crlctx; + if (ci->version == NULL) + if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err; + ASN1_INTEGER_set(ci->version,1); /* version 2 CRL */ + X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0); + X509V3_set_conf_lhash(&crlctx, conf); - if(!X509V3_EXT_CRL_add_conf(conf, &crlctx, - crl_ext, crl)) goto err; - } + if (!X509V3_EXT_CRL_add_conf(conf, &crlctx, + crl_ext, crl)) goto err; + } if (!X509_CRL_sign(crl,pkey,dgst)) goto err; @@ -1885,7 +2012,7 @@ again2: else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate); ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret)); - if(days) BIO_printf(bio_err," (%d days)",days); + if (days) BIO_printf(bio_err," (%d days)",days); BIO_printf(bio_err, "\n"); if (!X509_set_subject_name(ret,subject)) goto err; @@ -1915,7 +2042,7 @@ again2: X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0); X509V3_set_conf_lhash(&ctx, lconf); - if(!X509V3_EXT_add_conf(lconf, &ctx, ext_sect, ret)) goto err; + if (!X509V3_EXT_add_conf(lconf, &ctx, ext_sect, ret)) goto err; } @@ -2031,7 +2158,7 @@ static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext) i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber); BIO_puts(bp,"\n\n"); #endif - if(!notext)X509_print(bp,x); + if (!notext)X509_print(bp,x); PEM_write_bio_X509(bp,x); } @@ -2104,12 +2231,13 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, /* Skip past any leading X. X: X, etc to allow for * multiple instances */ - for(buf = cv->name; *buf ; buf++) - if ((*buf == ':') || (*buf == ',') || (*buf == '.')) { - buf++; - if(*buf) type = buf; - break; - } + for (buf = cv->name; *buf ; buf++) + if ((*buf == ':') || (*buf == ',') || (*buf == '.')) + { + buf++; + if (*buf) type = buf; + break; + } buf=cv->value; if ((nid=OBJ_txt2nid(type)) == NID_undef) @@ -2208,7 +2336,7 @@ static int check_time_format(char *str) } static int do_revoke(X509 *x509, TXT_DB *db) -{ + { ASN1_UTCTIME *tm=NULL, *revtm=NULL; char *row[DB_NUMBER],**rrow,**irow; BIGNUM *bn = NULL; @@ -2316,5 +2444,163 @@ err: OPENSSL_free(row[i]); } return(ok); -} + } + +static int get_certificate_status(const char *serial, TXT_DB *db) + { + unsigned char *row[DB_NUMBER],**rrow; + int ok=-1,i; + + /* Free Resources */ + for (i=0; i= 2000 */ + char **rrow, *a_tm_s; + + a_tm = ASN1_UTCTIME_new(); + + /* get actual time and make a string */ + a_tm = X509_gmtime_adj(a_tm, 0); + a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1); + if (a_tm_s == NULL) + { + cnt = -1; + goto err; + } + + memcpy(a_tm_s, a_tm->data, a_tm->length); + a_tm_s[a_tm->length] = '\0'; + + if (strncmp(a_tm_s, "49", 2) <= 0) + a_y2k = 1; + else + a_y2k = 0; + for (i = 0; i < sk_num(db->data); i++) + { + rrow = (char **) sk_value(db->data, i); + + if (rrow[DB_type][0] == 'V') + { + /* ignore entries that are not valid */ + if (strncmp(rrow[DB_exp_date], "49", 2) <= 0) + db_y2k = 1; + else + db_y2k = 0; + + if (db_y2k == a_y2k) + { + /* all on the same y2k side */ + if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0) + { + rrow[DB_type][0] = 'E'; + rrow[DB_type][1] = '\0'; + cnt++; + + BIO_printf(bio_err, "%s=Expired\n", + rrow[DB_serial]); + } + } + else if (db_y2k < a_y2k) + { + rrow[DB_type][0] = 'E'; + rrow[DB_type][1] = '\0'; + cnt++; + + BIO_printf(bio_err, "%s=Expired\n", + rrow[DB_serial]); + } + + } + } + +err: + + ASN1_UTCTIME_free(a_tm); + OPENSSL_free(a_tm_s); + + return (cnt); + }