Fix to the -revoke option in ca. It was leaking memory, crashing and just
[openssl.git] / apps / ca.c
index a5848366cfe6649987b8c7099b0c39ab29ffb2ac..93f992b2f412185998d7b56a6a24ac8221639524 100644 (file)
--- a/apps/ca.c
+++ b/apps/ca.c
 #include <sys/types.h>
 #include <sys/stat.h>
 #include "apps.h"
-#include "bio.h"
-#include "err.h"
-#include "bn.h"
-#include "txt_db.h"
-#include "evp.h"
-#include "x509.h"
-#include "objects.h"
-#include "pem.h"
-#include "conf.h"
+#include <openssl/conf.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/bn.h>
+#include <openssl/txt_db.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/objects.h>
+#include <openssl/pem.h>
 
 #ifndef W_OK
-#include <sys/file.h>
+#  ifdef VMS
+#    if defined(__DECC)
+#      include <unistd.h>
+#    else
+#      include <unixlib.h>
+#    endif
+#  else
+#    include <sys/file.h>
+#  endif
+#endif
+
+#ifndef W_OK
+#  define F_OK 0
+#  define X_OK 1
+#  define W_OK 2
+#  define R_OK 4
 #endif
 
 #undef PROG
 #define PROG ca_main
 
 #define BASE_SECTION   "ca"
-#define CONFIG_FILE "lib/ssleay.cnf"
+#define CONFIG_FILE "openssl.cnf"
 
 #define ENV_DEFAULT_CA         "default_ca"
 
 #define ENV_RANDFILE           "RANDFILE"
 #define ENV_DEFAULT_DAYS       "default_days"
 #define ENV_DEFAULT_STARTDATE  "default_startdate"
+#define ENV_DEFAULT_ENDDATE    "default_enddate"
 #define ENV_DEFAULT_CRL_DAYS   "default_crl_days"
 #define ENV_DEFAULT_CRL_HOURS  "default_crl_hours"
 #define ENV_DEFAULT_MD         "default_md"
 #define ENV_PRESERVE           "preserve"
 #define ENV_POLICY             "policy"
 #define ENV_EXTENSIONS         "x509_extensions"
+#define ENV_CRLEXT             "crl_extensions"
 #define ENV_MSIE_HACK          "msie_hack"
 
 #define ENV_DATABASE           "database"
@@ -129,12 +147,14 @@ static char *ca_usage[]={
 " -gencrl         - Generate a new CRL\n",
 " -crldays days   - Days is when the next CRL is due\n",
 " -crlhours hours - Hours is when the next CRL is due\n",
+" -startdate YYMMDDHHMMSSZ  - certificate validity notBefore\n",
+" -enddate YYMMDDHHMMSSZ    - certificate validity notAfter (overrides -days)\n",
 " -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",
 " -key arg        - key to decode the private key if it is encrypted\n",
-" -cert           - The CA certificate\n",
+" -cert file      - The CA certificate\n",
 " -in file        - The input PEM encoded certificate request(s)\n",
 " -out file       - Where to put the output file(s)\n",
 " -outdir dir     - Where to put output certificates\n",
@@ -142,8 +162,11 @@ static char *ca_usage[]={
 " -spkac file     - File contains DN and signed public key and challenge\n",
 " -ss_cert file   - File contains a self signed cert to sign\n",
 " -preserveDN     - Don't re-order the DN\n",
-" -batch         - Don't ask questions\n",
-" -msie_hack     - msie modifications to handle all thos universal strings\n",
+" -batch          - Don't ask questions\n",
+" -msie_hack      - msie modifications to handle all those universal strings\n",
+" -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",
 NULL
 };
 
@@ -153,10 +176,9 @@ extern int EF_PROTECT_BELOW;
 extern int EF_ALIGNMENT;
 #endif
 
-#ifndef NOPROTO
-static STACK *load_extensions(char *section);
+static int add_oid_section(LHASH *conf);
 static void lookup_fail(char *name,char *tag);
-static int MS_CALLBACK key_callback(char *buf,int len,int verify);
+static int MS_CALLBACK key_callback(char *buf,int len,int verify,void *u);
 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);
@@ -165,50 +187,35 @@ static int index_name_cmp(char **a,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,
-       EVP_MD *dgst,STACK *policy,TXT_DB *db,BIGNUM *serial,char *startdate,
-       int days, int batch, STACK *extensions,int verbose);
+                  const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,TXT_DB *db,
+                  BIGNUM *serial, char *startdate,char *enddate, int days,
+                  int batch, char *ext_sect, LHASH *conf,int verbose);
 static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
-       EVP_MD *dgst,STACK *policy,TXT_DB *db,BIGNUM *serial,char *startdate,
-       int days,int batch,STACK *extensions,int verbose);
+                       const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
+                       TXT_DB *db, BIGNUM *serial,char *startdate,
+                       char *enddate, int days, int batch, char *ext_sect,
+                       LHASH *conf,int verbose);
 static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
-       EVP_MD *dgst,STACK *policy,TXT_DB *db,BIGNUM *serial,char *startdate,
-       int days,STACK *extensions,int verbose);
+                        const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
+                        TXT_DB *db, BIGNUM *serial,char *startdate,
+                        char *enddate, int days, char *ext_sect,LHASH *conf,
+                               int verbose);
 static int fix_data(int nid, int *type);
 static void write_new_certificate(BIO *bp, X509 *x, int output_der);
-static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, EVP_MD *dgst,
-       STACK *policy, TXT_DB *db, BIGNUM *serial, char *startdate,
-       int days, int batch, int verbose, X509_REQ *req, STACK *extensions);
+static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
+       STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
+       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 check_time_format(char *str);
-#else
-static STACK *load_extensions();
-static void lookup_fail();
-static int MS_CALLBACK key_callback();
-static unsigned long index_serial_hash();
-static int index_serial_cmp();
-static unsigned long index_name_hash();
-static int index_name_qual();
-static int index_name_cmp();
-static int fix_data();
-static BIGNUM *load_serial();
-static int save_serial();
-static int certify();
-static int certify_cert();
-static int certify_spkac();
-static void write_new_certificate();
-static int do_body();
-static int check_time_format();
-#endif
-
-static LHASH *conf;
+static LHASH *conf=NULL;
 static char *key=NULL;
 static char *section=NULL;
 
 static int preserve=0;
 static int msie_hack=0;
 
-int MAIN(argc, argv)
-int argc;
-char **argv;
+int MAIN(int argc, char **argv)
        {
        int total=0;
        int total_done=0;
@@ -217,6 +224,7 @@ char **argv;
        int req=0;
        int verbose=0;
        int gencrl=0;
+       int dorevoke=0;
        long crldays=0;
        long crlhours=0;
        long errorline= -1;
@@ -234,8 +242,10 @@ char **argv;
        char *outdir=NULL;
        char *serialfile=NULL;
        char *extensions=NULL;
+       char *crl_ext=NULL;
        BIGNUM *serial=NULL;
        char *startdate=NULL;
+       char *enddate=NULL;
        int days=0;
        int batch=0;
        X509 *x509=NULL;
@@ -249,14 +259,14 @@ char **argv;
        char **pp,*p,*f;
        int i,j;
        long l;
-       EVP_MD *dgst=NULL;
-       STACK *attribs=NULL;
-       STACK *extensions_sk=NULL;
+       const EVP_MD *dgst=NULL;
+       STACK_OF(CONF_VALUE) *attribs=NULL;
        STACK *cert_sk=NULL;
        BIO *hex=NULL;
 #undef BSIZE
 #define BSIZE 256
        MS_STATIC char buf[3][BSIZE];
+       char *randfile;
 
 #ifdef EFENCE
 EF_PROTECT_FREE=1;
@@ -266,9 +276,14 @@ EF_ALIGNMENT=0;
 
        apps_startup();
 
-       X509v3_add_netscape_extensions();
+       conf = NULL;
+       key = NULL;
+       section = NULL;
+
+       X509V3_add_standard_extensions();
 
        preserve=0;
+       msie_hack=0;
        if (bio_err == NULL)
                if ((bio_err=BIO_new(BIO_s_file())) != NULL)
                        BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
@@ -294,6 +309,11 @@ EF_ALIGNMENT=0;
                        if (--argc < 1) goto bad;
                        startdate= *(++argv);
                        }
+               else if (strcmp(*argv,"-enddate") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       enddate= *(++argv);
+                       }
                else if (strcmp(*argv,"-days") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -377,6 +397,22 @@ EF_ALIGNMENT=0;
                        spkac_file = *(++argv);
                        req=1;
                        }
+               else if (strcmp(*argv,"-revoke") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       infile= *(++argv);
+                       dorevoke=1;
+                       }
+               else if (strcmp(*argv,"-extensions") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       extensions= *(++argv);
+                       }
+               else if (strcmp(*argv,"-crlexts") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       crl_ext= *(++argv);
+                       }
                else
                        {
 bad:
@@ -398,12 +434,19 @@ bad:
        ERR_load_crypto_strings();
 
        /*****************************************************************/
+       if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
+       if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
        if (configfile == NULL)
                {
                /* We will just use 'buf[0]' as a temporary buffer.  */
+#ifdef VMS
+               strncpy(buf[0],X509_get_default_cert_area(),
+                       sizeof(buf[0])-1-sizeof(CONFIG_FILE));
+#else
                strncpy(buf[0],X509_get_default_cert_area(),
                        sizeof(buf[0])-2-sizeof(CONFIG_FILE));
                strcat(buf[0],"/");
+#endif
                strcat(buf[0],CONFIG_FILE);
                configfile=buf[0];
                }
@@ -431,6 +474,38 @@ bad:
                        }
                }
 
+       if (conf != NULL)
+               {
+               p=CONF_get_string(conf,NULL,"oid_file");
+               if (p != NULL)
+                       {
+                       BIO *oid_bio;
+
+                       oid_bio=BIO_new_file(p,"r");
+                       if (oid_bio == NULL) 
+                               {
+                               /*
+                               BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
+                               ERR_print_errors(bio_err);
+                               */
+                               ERR_clear_error();
+                               }
+                       else
+                               {
+                               OBJ_create_objects(oid_bio);
+                               BIO_free(oid_bio);
+                               }
+                       }
+               if(!add_oid_section(conf)) 
+                       {
+                       ERR_print_errors(bio_err);
+                       goto err;
+                       }
+               }
+
+       randfile = CONF_get_string(conf, BASE_SECTION, "RANDFILE");
+       app_RAND_load_file(randfile, bio_err, 0);
+       
        in=BIO_new(BIO_s_file());
        out=BIO_new(BIO_s_file());
        Sout=BIO_new(BIO_s_file());
@@ -457,10 +532,10 @@ bad:
                goto err;
                }
        if (key == NULL)
-               pkey=PEM_read_bio_PrivateKey(in,NULL,NULL);
+               pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,NULL);
        else
                {
-               pkey=PEM_read_bio_PrivateKey(in,NULL,key_callback);
+               pkey=PEM_read_bio_PrivateKey(in,NULL,key_callback,NULL);
                memset(key,0,strlen(key));
                }
        if (pkey == NULL)
@@ -483,13 +558,19 @@ bad:
                BIO_printf(bio_err,"trying to load CA certificate\n");
                goto err;
                }
-       x509=PEM_read_bio_X509(in,NULL,NULL);
+       x509=PEM_read_bio_X509(in,NULL,NULL,NULL);
        if (x509 == NULL)
                {
                BIO_printf(bio_err,"unable to load CA certificate\n");
                goto err;
                }
 
+       if (!X509_check_private_key(x509,pkey))
+               {
+               BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
+               goto err;
+               }
+
        f=CONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
        if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
                preserve=1;
@@ -509,7 +590,12 @@ 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
                if (access(outdir,R_OK|W_OK|X_OK) != 0)
+#endif
                        {
                        BIO_printf(bio_err,"I am unable to acces the %s directory\n",outdir);
                        perror(outdir);
@@ -522,12 +608,14 @@ bad:
                        perror(outdir);
                        goto err;
                        }
+#ifdef S_IFDIR
                if (!(sb.st_mode & S_IFDIR))
                        {
                        BIO_printf(bio_err,"%s need to be a directory\n",outdir);
                        perror(outdir);
                        goto err;
                        }
+#endif
                }
 
        /*****************************************************************/
@@ -537,7 +625,7 @@ bad:
                lookup_fail(section,ENV_DATABASE);
                goto err;
                }
-        if (BIO_read_filename(in,dbfile) <= 0)
+       if (BIO_read_filename(in,dbfile) <= 0)
                {
                perror(dbfile);
                BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
@@ -553,13 +641,13 @@ bad:
                if ((pp[DB_type][0] != DB_TYPE_REV) &&
                        (pp[DB_rev_date][0] != '\0'))
                        {
-                       BIO_printf(bio_err,"entry %d: not, revoked yet has a revokation date\n",i+1);
+                       BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
                        goto err;
                        }
                if ((pp[DB_type][0] == DB_TYPE_REV) &&
                        !check_time_format(pp[DB_rev_date]))
                        {
-                       BIO_printf(bio_err,"entry %d: invalid revokation date\n",
+                       BIO_printf(bio_err,"entry %d: invalid revocation date\n",
                                i+1);
                        goto err;
                        }
@@ -658,28 +746,43 @@ bad:
                        lookup_fail(section,ENV_SERIAL);
                        goto err;
                        }
-
-               if ((extensions=CONF_get_string(conf,section,ENV_EXTENSIONS))
-                       != NULL)
-                       {
-                       if ((extensions_sk=load_extensions(extensions)) == NULL)
+               if(!extensions)
+                       extensions=CONF_get_string(conf,section,ENV_EXTENSIONS);
+               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)) {
+                               BIO_printf(bio_err,
+                                "Error Loading extension section %s\n",
+                                                                extensions);
+                               ret = 1;
                                goto err;
                        }
+               }
 
                if (startdate == NULL)
                        {
-                       startdate=(char *)CONF_get_string(conf,section,
+                       startdate=CONF_get_string(conf,section,
                                ENV_DEFAULT_STARTDATE);
-                       if (startdate == NULL)
-                               startdate="today";
-                       else
-                               {
-                               if (!ASN1_UTCTIME_set_string(NULL,startdate))
-                                       {
-                                       BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSS\n");
-                                       goto err;
-                                       }
-                               }
+                       }
+               if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
+                       {
+                       BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
+                       goto err;
+                       }
+               if (startdate == NULL) startdate="today";
+
+               if (enddate == NULL)
+                       {
+                       enddate=CONF_get_string(conf,section,
+                               ENV_DEFAULT_ENDDATE);
+                       }
+               if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
+                       {
+                       BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
+                       goto err;
                        }
 
                if (days == 0)
@@ -687,7 +790,7 @@ bad:
                        days=(int)CONF_get_number(conf,section,
                                ENV_DEFAULT_DAYS);
                        }
-               if (days == 0)
+               if (!enddate && (days == 0))
                        {
                        BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
                        goto err;
@@ -700,7 +803,7 @@ bad:
                        }
                if (verbose)
                        {
-                       if ((f=BN_bn2ascii(serial)) == NULL) goto err;
+                       if ((f=BN_bn2hex(serial)) == NULL) goto err;
                        BIO_printf(bio_err,"next serial number is %s\n",f);
                        Free(f);
                        }
@@ -720,7 +823,8 @@ bad:
                        {
                        total++;
                        j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
-                               serial,startdate,days,extensions_sk,verbose);
+                               serial,startdate,enddate, days,extensions,conf,
+                               verbose);
                        if (j < 0) goto err;
                        if (j > 0)
                                {
@@ -743,8 +847,8 @@ bad:
                        {
                        total++;
                        j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
-                               db,serial,startdate,days,batch,
-                               extensions_sk,verbose);
+                               db,serial,startdate,enddate,days,batch,
+                               extensions,conf,verbose);
                        if (j < 0) goto err;
                        if (j > 0)
                                {
@@ -762,8 +866,8 @@ bad:
                        {
                        total++;
                        j=certify(&x,infile,pkey,x509,dgst,attribs,db,
-                               serial,startdate,days,batch,
-                               extensions_sk,verbose);
+                               serial,startdate,enddate,days,batch,
+                               extensions,conf,verbose);
                        if (j < 0) goto err;
                        if (j > 0)
                                {
@@ -781,8 +885,8 @@ bad:
                        {
                        total++;
                        j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
-                               serial,startdate,days,batch,
-                               extensions_sk,verbose);
+                               serial,startdate,enddate,days,batch,
+                               extensions,conf,verbose);
                        if (j < 0) goto err;
                        if (j > 0)
                                {
@@ -805,7 +909,7 @@ bad:
                        if (!batch)
                                {
                                BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
-                               BIO_flush(bio_err);
+                               (void)BIO_flush(bio_err);
                                buf[0][0]='\0';
                                fgets(buf[0],10,stdin);
                                if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
@@ -819,12 +923,23 @@ bad:
                        BIO_printf(bio_err,"Write out database with %d new entries\n",sk_num(cert_sk));
 
                        strncpy(buf[0],serialfile,BSIZE-4);
+
+#ifdef VMS
+                       strcat(buf[0],"-new");
+#else
                        strcat(buf[0],".new");
+#endif
 
                        if (!save_serial(buf[0],serial)) goto err;
 
                        strncpy(buf[1],dbfile,BSIZE-4);
+
+#ifdef VMS
+                       strcat(buf[1],"-new");
+#else
                        strcat(buf[1],".new");
+#endif
+
                        if (BIO_write_filename(out,buf[1]) <= 0)
                                {
                                perror(dbfile);
@@ -848,7 +963,11 @@ bad:
                        p=(char *)x->cert_info->serialNumber->data;
                        
                        strncpy(buf[2],outdir,BSIZE-(j*2)-6);
+
+#ifndef VMS
                        strcat(buf[2],"/");
+#endif
+
                        n=(unsigned char *)&(buf[2][strlen(buf[2])]);
                        if (j > 0)
                                {
@@ -881,7 +1000,13 @@ bad:
                        {
                        /* Rename the database and the serial file */
                        strncpy(buf[2],serialfile,BSIZE-4);
+
+#ifdef VMS
+                       strcat(buf[2],"-old");
+#else
                        strcat(buf[2],".old");
+#endif
+
                        BIO_free(in);
                        BIO_free(out);
                        in=NULL;
@@ -903,7 +1028,13 @@ bad:
                                }
 
                        strncpy(buf[2],dbfile,BSIZE-4);
+
+#ifdef VMS
+                       strcat(buf[2],"-old");
+#else
                        strcat(buf[2],".old");
+#endif
+
                        if (rename(dbfile,buf[2]) < 0)
                                {
                                BIO_printf(bio_err,"unabel to rename %s to %s\n",
@@ -926,6 +1057,20 @@ bad:
        /*****************************************************************/
        if (gencrl)
                {
+               if(!crl_ext) crl_ext=CONF_get_string(conf,section,ENV_CRLEXT);
+               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)) {
+                               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)
@@ -965,25 +1110,25 @@ bad:
                                        strlen(pp[DB_rev_date]));
                                /* strcpy(r->revocationDate,pp[DB_rev_date]);*/
 
-                               BIO_reset(hex);
+                               (void)BIO_reset(hex);
                                if (!BIO_puts(hex,pp[DB_serial]))
                                        goto err;
                                if (!a2i_ASN1_INTEGER(hex,r->serialNumber,
                                        buf[0],BSIZE)) goto err;
 
-                               sk_push(ci->revoked,(char *)r);
+                               sk_X509_REVOKED_push(ci->revoked,r);
                                }
                        }
                /* sort the data so it will be written in serial
                 * number order */
-               sk_find(ci->revoked,NULL);
-               for (i=0; i<sk_num(ci->revoked); i++)
+               sk_X509_REVOKED_sort(ci->revoked);
+               for (i=0; i<sk_X509_REVOKED_num(ci->revoked); i++)
                        {
-                       r=(X509_REVOKED *)sk_value(ci->revoked,i);
+                       r=sk_X509_REVOKED_value(ci->revoked,i);
                        r->sequence=i;
                        }
 
-               /* we how have a CRL */
+               /* we now have a CRL */
                if (verbose) BIO_printf(bio_err,"signing CRL\n");
                if (md != NULL)
                        {
@@ -994,45 +1139,118 @@ bad:
                                }
                        }
                else
+                   {
+#ifndef NO_DSA
+                   if (pkey->type == EVP_PKEY_DSA) 
+                       dgst=EVP_dss1();
+                   else
+#endif
                        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(!X509V3_EXT_CRL_add_conf(conf, &crlctx,
+                                                crl_ext, crl)) goto err;
+               }
+
                if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
 
                PEM_write_bio_X509_CRL(Sout,crl);
                }
        /*****************************************************************/
+       if (dorevoke)
+               {
+               if (infile == NULL) 
+                       {
+                       BIO_printf(bio_err,"no input files\n");
+                       goto err;
+                       }
+               else
+                       {
+                       X509 *revcert;
+                       if (BIO_read_filename(in,infile) <= 0)
+                               {
+                               perror(infile);
+                               BIO_printf(bio_err,"error trying to load '%s' certificate\n",infile);
+                               goto err;
+                               }
+                       revcert=PEM_read_bio_X509(in,NULL,NULL,NULL);
+                       if (revcert == NULL)
+                               {
+                               BIO_printf(bio_err,"unable to load '%s' certificate\n",infile);
+                               goto err;
+                               }
+                       j=do_revoke(revcert,db);
+                       if (j <= 0) goto err;
+                       X509_free(revcert);
+
+                       strncpy(buf[0],dbfile,BSIZE-4);
+                       strcat(buf[0],".new");
+                       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;
+                       strncpy(buf[1],dbfile,BSIZE-4);
+                       strcat(buf[1],".old");
+                       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;
+                               }
+                       BIO_printf(bio_err,"Data Base Updated\n"); 
+                       }
+               }
+       /*****************************************************************/
        ret=0;
 err:
-       if (hex != NULL) BIO_free(hex);
-       if (Cout != NULL) BIO_free(Cout);
-       if (Sout != NULL) BIO_free(Sout);
-       if (out != NULL) BIO_free(out);
-       if (in != NULL) BIO_free(in);
+       BIO_free(hex);
+       BIO_free(Cout);
+       BIO_free(Sout);
+       BIO_free(out);
+       BIO_free(in);
 
-       if (cert_sk != NULL) sk_pop_free(cert_sk,X509_free);
-       if (extensions_sk != NULL)
-               sk_pop_free(extensions_sk,X509_EXTENSION_free);
+       sk_pop_free(cert_sk,X509_free);
 
        if (ret) ERR_print_errors(bio_err);
-       if (serial != NULL) BN_free(serial);
-       if (db != NULL) TXT_DB_free(db);
-       if (pkey != NULL) EVP_PKEY_free(pkey);
-       if (x509 != NULL) X509_free(x509);
-       if (crl != NULL) X509_CRL_free(crl);
-       if (conf != NULL) CONF_free(conf);
-       X509v3_cleanup_extensions();
+       app_RAND_write_file(randfile, bio_err);
+       BN_free(serial);
+       TXT_DB_free(db);
+       EVP_PKEY_free(pkey);
+       X509_free(x509);
+       X509_CRL_free(crl);
+       CONF_free(conf);
+       X509V3_EXT_cleanup();
+       OBJ_cleanup();
        EXIT(ret);
        }
 
-static void lookup_fail(name,tag)
-char *name;
-char *tag;
+static void lookup_fail(char *name, char *tag)
        {
        BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
        }
 
-static int MS_CALLBACK key_callback(buf,len,verify)
-char *buf;
-int len,verify;
+static int MS_CALLBACK key_callback(char *buf, int len, int verify, void *u)
        {
        int i;
 
@@ -1043,8 +1261,7 @@ int len,verify;
        return(i);
        }
 
-static unsigned long index_serial_hash(a)
-char **a;
+static unsigned long index_serial_hash(char **a)
        {
        char *n;
 
@@ -1053,9 +1270,7 @@ char **a;
        return(lh_strhash(n));
        }
 
-static int index_serial_cmp(a,b)
-char **a;
-char **b;
+static int index_serial_cmp(char **a, char **b)
        {
        char *aa,*bb;
 
@@ -1064,21 +1279,17 @@ char **b;
        return(strcmp(aa,bb));
        }
 
-static unsigned long index_name_hash(a)
-char **a;
+static unsigned long index_name_hash(char **a)
        { return(lh_strhash(a[DB_name])); }
 
-static int index_name_qual(a)
-char **a;
+static int index_name_qual(char **a)
        { return(a[0][0] == 'V'); }
 
-static int index_name_cmp(a,b)
-char **a;
-char **b;
-       { return(strcmp(a[DB_name],b[DB_name])); }
+static int index_name_cmp(char **a, char **b)
+       { return(strcmp(a[DB_name],
+            b[DB_name])); }
 
-static BIGNUM *load_serial(serialfile)
-char *serialfile;
+static BIGNUM *load_serial(char *serialfile)
        {
        BIO *in=NULL;
        BIGNUM *ret=NULL;
@@ -1116,9 +1327,7 @@ err:
        return(ret);
        }
 
-static int save_serial(serialfile,serial)
-char *serialfile;
-BIGNUM *serial;
+static int save_serial(char *serialfile, BIGNUM *serial)
        {
        BIO *out;
        int ret=0;
@@ -1150,21 +1359,10 @@ err:
        return(ret);
        }
 
-static int certify(xret,infile,pkey,x509,dgst,policy,db,serial,startdate,days,
-       batch,extensions,verbose)
-X509 **xret;
-char *infile;
-EVP_PKEY *pkey;
-X509 *x509;
-EVP_MD *dgst;
-STACK *policy;
-TXT_DB *db;
-BIGNUM *serial;
-char *startdate;
-int days;
-int batch;
-STACK *extensions;
-int verbose;
+static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
+            const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
+            BIGNUM *serial, char *startdate, char *enddate, int days,
+            int batch, char *ext_sect, LHASH *lconf, int verbose)
        {
        X509_REQ *req=NULL;
        BIO *in=NULL;
@@ -1178,7 +1376,7 @@ int verbose;
                perror(infile);
                goto err;
                }
-       if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL)) == NULL)
+       if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
                {
                BIO_printf(bio_err,"Error reading certificate request in %s\n",
                        infile);
@@ -1195,6 +1393,7 @@ int verbose;
                goto err;
                }
        i=X509_REQ_verify(req,pktmp);
+       EVP_PKEY_free(pktmp);
        if (i < 0)
                {
                ok=0;
@@ -1210,8 +1409,8 @@ int verbose;
        else
                BIO_printf(bio_err,"Signature ok\n");
 
-       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,
-               days,batch,verbose,req,extensions);
+       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate, enddate,
+               days,batch,verbose,req,ext_sect,lconf);
 
 err:
        if (req != NULL) X509_REQ_free(req);
@@ -1219,21 +1418,10 @@ err:
        return(ok);
        }
 
-static int certify_cert(xret,infile,pkey,x509,dgst,policy,db,serial,startdate,
-       days, batch,extensions,verbose)
-X509 **xret;
-char *infile;
-EVP_PKEY *pkey;
-X509 *x509;
-EVP_MD *dgst;
-STACK *policy;
-TXT_DB *db;
-BIGNUM *serial;
-char *startdate;
-int days;
-int batch;
-STACK *extensions;
-int verbose;
+static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
+            const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
+            BIGNUM *serial, char *startdate, char *enddate, int days,
+            int batch, char *ext_sect, LHASH *lconf, int verbose)
        {
        X509 *req=NULL;
        X509_REQ *rreq=NULL;
@@ -1248,7 +1436,7 @@ int verbose;
                perror(infile);
                goto err;
                }
-       if ((req=PEM_read_bio_X509(in,NULL,NULL)) == NULL)
+       if ((req=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
                {
                BIO_printf(bio_err,"Error reading self signed certificate in %s\n",infile);
                goto err;
@@ -1264,6 +1452,7 @@ int verbose;
                goto err;
                }
        i=X509_verify(req,pktmp);
+       EVP_PKEY_free(pktmp);
        if (i < 0)
                {
                ok=0;
@@ -1273,7 +1462,7 @@ int verbose;
        if (i == 0)
                {
                ok=0;
-               BIO_printf(bio_err,"Signature did not match the certificate request\n");
+               BIO_printf(bio_err,"Signature did not match the certificate\n");
                goto err;
                }
        else
@@ -1282,8 +1471,8 @@ int verbose;
        if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
                goto err;
 
-       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,days,
-               batch,verbose,rreq,extensions);
+       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,days,
+               batch,verbose,rreq,ext_sect,lconf);
 
 err:
        if (rreq != NULL) X509_REQ_free(rreq);
@@ -1292,21 +1481,10 @@ err:
        return(ok);
        }
 
-static int do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,days,
-       batch,verbose,req, extensions)
-X509 **xret;
-EVP_PKEY *pkey;
-X509 *x509;
-EVP_MD *dgst;
-STACK *policy;
-TXT_DB *db;
-BIGNUM *serial;
-char *startdate;
-int days;
-int batch;
-int verbose;
-X509_REQ *req;
-STACK *extensions;
+static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
+            STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
+            char *startdate, char *enddate, int days, int batch, int verbose,
+            X509_REQ *req, char *ext_sect, LHASH *lconf)
        {
        X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
        ASN1_UTCTIME *tm,*tmptm;
@@ -1316,7 +1494,6 @@ STACK *extensions;
        X509_CINF *ci;
        X509_NAME_ENTRY *ne;
        X509_NAME_ENTRY *tne,*push;
-       X509_EXTENSION *ex=NULL;
        EVP_PKEY *pktmp;
        int ok= -1,i,j,last,nid;
        char *p;
@@ -1421,9 +1598,9 @@ STACK *extensions;
        if (CAname == NULL) goto err;
        str=str2=NULL;
 
-       for (i=0; i<sk_num(policy); i++)
+       for (i=0; i<sk_CONF_VALUE_num(policy); i++)
                {
-               cv=(CONF_VALUE *)sk_value(policy,i); /* get the object id */
+               cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
                if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
                        {
                        BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
@@ -1506,8 +1683,7 @@ again2:
 
                        if (push != NULL)
                                {
-                               if (!X509_NAME_add_entry(subject,push,
-                                       X509_NAME_entry_count(subject),0))
+                               if (!X509_NAME_add_entry(subject,push, -1, 0))
                                        {
                                        if (push != NULL)
                                                X509_NAME_ENTRY_free(push);
@@ -1530,7 +1706,7 @@ again2:
                BIO_printf(bio_err,"The subject name apears to be ok, checking data base for clashes\n");
 
        row[DB_name]=X509_NAME_oneline(subject,NULL,0);
-       row[DB_serial]=BN_bn2ascii(serial);
+       row[DB_serial]=BN_bn2hex(serial);
        if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
                {
                BIO_printf(bio_err,"Malloc failure\n");
@@ -1566,7 +1742,7 @@ again2:
                        p="Valid";
                else
                        p="\ninvalid type, Data base error\n";
-               BIO_printf(bio_err,"Type          :%s\n",p);;
+               BIO_printf(bio_err,"Type          :%s\n",p);;
                if (rrow[DB_type][0] == 'R')
                        {
                        p=rrow[DB_exp_date]; if (p == NULL) p="undef";
@@ -1603,26 +1779,28 @@ again2:
 
        BIO_printf(bio_err,"Certificate is to be certified until ");
        if (strcmp(startdate,"today") == 0)
-               {
                X509_gmtime_adj(X509_get_notBefore(ret),0);
+       else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
+
+       if (enddate == NULL)
                X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
-               }
-       else
-               {
-               /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
-               ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
-               }
+       else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
+
        ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
-       BIO_printf(bio_err," (%d days)\n",days);
+       if(days) BIO_printf(bio_err," (%d days)",days);
+       BIO_printf(bio_err, "\n");
 
        if (!X509_set_subject_name(ret,subject)) goto err;
 
        pktmp=X509_REQ_get_pubkey(req);
-       if (!X509_set_pubkey(ret,pktmp)) goto err;
+       i = X509_set_pubkey(ret,pktmp);
+       EVP_PKEY_free(pktmp);
+       if (!i) goto err;
 
        /* Lets add the extensions, if there are any */
-       if ((extensions != NULL) && (sk_num(extensions) > 0))
+       if (ext_sect)
                {
+               X509V3_CTX ctx;
                if (ci->version == NULL)
                        if ((ci->version=ASN1_INTEGER_new()) == NULL)
                                goto err;
@@ -1631,26 +1809,23 @@ again2:
                /* Free the current entries if any, there should not
                 * be any I belive */
                if (ci->extensions != NULL)
-                       sk_pop_free(ci->extensions,X509_EXTENSION_free);
+                       sk_X509_EXTENSION_pop_free(ci->extensions,
+                                                  X509_EXTENSION_free);
 
-               if ((ci->extensions=sk_new_null()) == NULL)
-                       goto err;
+               ci->extensions = NULL;
+
+               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;
 
-               /* Lets 'copy' in the new ones */
-               for (i=0; i<sk_num(extensions); i++)
-                       {
-                       ex=X509_EXTENSION_dup((X509_EXTENSION *)
-                               sk_value(extensions,i));
-                       if (ex == NULL) goto err;
-                       if (!sk_push(ci->extensions,(char *)ex)) goto err;
-                       }
                }
 
 
        if (!batch)
                {
                BIO_printf(bio_err,"Sign the certificate? [y/n]:");
-               BIO_flush(bio_err);
+               (void)BIO_flush(bio_err);
                buf[0]='\0';
                fgets(buf,sizeof(buf)-1,stdin);
                if (!((buf[0] == 'y') || (buf[0] == 'Y')))
@@ -1661,11 +1836,14 @@ again2:
                        }
                }
 
+
 #ifndef NO_DSA
-        pktmp=X509_get_pubkey(ret);
-        if (EVP_PKEY_missing_parameters(pktmp) &&
+       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
 
        if (!X509_sign(ret,pkey,dgst))
@@ -1723,6 +1901,8 @@ err:
                X509_NAME_free(CAname);
        if (subject != NULL)
                X509_NAME_free(subject);
+       if (tmptm != NULL)
+               ASN1_UTCTIME_free(tmptm);
        if (ok <= 0)
                {
                if (ret != NULL) X509_free(ret);
@@ -1733,10 +1913,7 @@ err:
        return(ok);
        }
 
-static void write_new_certificate(bp,x, output_der)
-BIO *bp;
-X509 *x;
-int output_der;
+static void write_new_certificate(BIO *bp, X509 *x, int output_der)
        {
        char *f;
        char buf[256];
@@ -1762,27 +1939,16 @@ int output_der;
        BIO_puts(bp,"\n");
        }
 
-static int certify_spkac(xret,infile,pkey,x509,dgst,policy,db,serial,
-       startdate,days,extensions,verbose)
-X509 **xret;
-char *infile;
-EVP_PKEY *pkey;
-X509 *x509;
-EVP_MD *dgst;
-STACK *policy;
-TXT_DB *db;
-BIGNUM *serial;
-char *startdate;
-int days;
-STACK *extensions;
-int verbose;
+static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
+            const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
+            BIGNUM *serial, char *startdate, char *enddate, int days,
+            char *ext_sect, LHASH *lconf, int verbose)
        {
-       STACK *sk=NULL;
+       STACK_OF(CONF_VALUE) *sk=NULL;
        LHASH *parms=NULL;
        X509_REQ *req=NULL;
        CONF_VALUE *cv=NULL;
        NETSCAPE_SPKI *spki = NULL;
-       unsigned char *spki_der = NULL,*p;
        X509_REQ_INFO *ri;
        char *type,*buf;
        EVP_PKEY *pktmp=NULL;
@@ -1806,7 +1972,7 @@ int verbose;
                }
 
        sk=CONF_get_section(parms, "default");
-       if (sk_num(sk) == 0)
+       if (sk_CONF_VALUE_num(sk) == 0)
                {
                BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
                CONF_free(parms);
@@ -1835,35 +2001,26 @@ int verbose;
 
        for (i = 0; ; i++)
                {
-               if ((int)sk_num(sk) <= i) break;
+               if (sk_CONF_VALUE_num(sk) <= i) break;
 
-               cv=(CONF_VALUE *)sk_value(sk,i);
+               cv=sk_CONF_VALUE_value(sk,i);
                type=cv->name;
-               buf=cv->value;
+               /* 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;
+               }
 
+               buf=cv->value;
                if ((nid=OBJ_txt2nid(type)) == NID_undef)
                        {
                        if (strcmp(type, "SPKAC") == 0)
                                {
-                               spki_der=(unsigned char *)Malloc(
-                                       strlen(cv->value)+1);
-                               if (spki_der == NULL)
-                                       {
-                                       BIO_printf(bio_err,"Malloc failure\n");
-                                       goto err;
-                                       }
-                               j = EVP_DecodeBlock(spki_der, (unsigned char *)cv->value,
-                                       strlen(cv->value));
-                               if (j <= 0)
-                                       {
-                                       BIO_printf(bio_err, "Can't b64 decode SPKAC structure\n");
-                                       goto err;
-                                       }
-
-                               p=spki_der;
-                               spki = d2i_NETSCAPE_SPKI(&spki, &p, j);
-                               Free(spki_der);
-                               spki_der = NULL;
+                               spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
                                if (spki == NULL)
                                        {
                                        BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
@@ -1887,8 +2044,7 @@ int verbose;
                        strlen(buf))) == NULL)
                        goto err;
 
-               if (!X509_NAME_add_entry(n,ne,X509_NAME_entry_count(n),0))
-                       goto err;
+               if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
                }
        if (spki == NULL)
                {
@@ -1903,7 +2059,7 @@ int verbose;
 
        BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
 
-       if ((pktmp=X509_PUBKEY_get(spki->spkac->pubkey)) == NULL)
+       if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
                {
                BIO_printf(bio_err,"error unpacking SPKAC public key\n");
                goto err;
@@ -1918,21 +2074,19 @@ int verbose;
        BIO_printf(bio_err,"Signature ok\n");
 
        X509_REQ_set_pubkey(req,pktmp);
-       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,
-               days,1,verbose,req,extensions);
+       EVP_PKEY_free(pktmp);
+       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,
+                  days,1,verbose,req,ext_sect,lconf);
 err:
        if (req != NULL) X509_REQ_free(req);
        if (parms != NULL) CONF_free(parms);
-       if (spki_der != NULL) Free(spki_der);
        if (spki != NULL) NETSCAPE_SPKI_free(spki);
        if (ne != NULL) X509_NAME_ENTRY_free(ne);
 
        return(ok);
        }
 
-static int fix_data(nid,type)
-int nid;
-int *type;
+static int fix_data(int nid, int *type)
        {
        if (nid == NID_pkcs9_emailAddress)
                *type=V_ASN1_IA5STRING;
@@ -1947,110 +2101,146 @@ int *type;
        return(1);
        }
 
-
-static STACK *load_extensions(sec)
-char *sec;
+static int check_time_format(char *str)
        {
-       STACK *ext;
-       STACK *ret=NULL;
-       CONF_VALUE *cv;
-       ASN1_OCTET_STRING *str=NULL;
-       ASN1_STRING *tmp=NULL;
-       X509_EXTENSION *x;
-       BIO *mem=NULL;
-       BUF_MEM *buf=NULL;
-       int i,nid,len;
-       unsigned char *ptr;
-       int pack_type;
-       int data_type;
+       ASN1_UTCTIME tm;
 
-       if ((ext=CONF_get_section(conf,sec)) == NULL)
-               {
-               BIO_printf(bio_err,"unable to find extension section called '%s'\n",sec);
-               return(NULL);
+       tm.data=(unsigned char *)str;
+       tm.length=strlen(str);
+       tm.type=V_ASN1_UTCTIME;
+       return(ASN1_UTCTIME_check(&tm));
+       }
+
+static int add_oid_section(LHASH *hconf)
+{      
+       char *p;
+       STACK_OF(CONF_VALUE) *sktmp;
+       CONF_VALUE *cnf;
+       int i;
+       if(!(p=CONF_get_string(hconf,NULL,"oid_section"))) return 1;
+       if(!(sktmp = CONF_get_section(hconf, p))) {
+               BIO_printf(bio_err, "problem loading oid section %s\n", p);
+               return 0;
+       }
+       for(i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
+               cnf = sk_CONF_VALUE_value(sktmp, i);
+               if(OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
+                       BIO_printf(bio_err, "problem creating object %s=%s\n",
+                                                        cnf->name, cnf->value);
+                       return 0;
                }
+       }
+       return 1;
+}
 
-       if ((ret=sk_new_null()) == NULL) return(NULL);
+static int do_revoke(X509 *x509, TXT_DB *db)
+{
+       ASN1_UTCTIME *tm=NULL, *revtm=NULL;
+       char *row[DB_NUMBER],**rrow,**irow;
+       BIGNUM *bn = NULL;
+       int ok=-1,i;
 
-       for (i=0; i<sk_num(ext); i++)
+       for (i=0; i<DB_NUMBER; i++)
+               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);
+       BN_free(bn);
+       if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
                {
-               cv=(CONF_VALUE *)sk_value(ext,i); /* get the object id */
-               if ((nid=OBJ_txt2nid(cv->name)) == NID_undef)
+               BIO_printf(bio_err,"Malloc failure\n");
+               goto err;
+               }
+       /* We have to lookup by serial number because name lookup
+        * skips revoked certs
+        */
+       rrow=TXT_DB_get_by_index(db,DB_serial,row);
+       if (rrow == NULL)
+               {
+               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);
+
+               tm=X509_get_notAfter(x509);
+               row[DB_exp_date]=(char *)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_name] done already */
+
+               if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
+                       (row[DB_file] == NULL))
                        {
-                       BIO_printf(bio_err,"%s:unknown object type in section, '%s'\n",sec,cv->name);
+                       BIO_printf(bio_err,"Malloc failure\n");
                        goto err;
                        }
+               strcpy(row[DB_file],"unknown");
+               row[DB_type][0]='V';
+               row[DB_type][1]='\0';
 
-               pack_type=X509v3_pack_type_by_NID(nid);
-               data_type=X509v3_data_type_by_NID(nid);
-
-               /* pack up the input bytes */
-               ptr=(unsigned char *)cv->value;
-               len=strlen((char *)ptr);
-               if ((len > 2) && (cv->value[0] == '0') &&
-                       (cv->value[1] == 'x'))
+               if ((irow=(char **)Malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
                        {
-                       if (data_type == V_ASN1_UNDEF)
-                               {
-                               BIO_printf(bio_err,"data type for extension %s is unknown\n",cv->name);
-                               goto err;
-                               }
-                       if (mem == NULL)
-                               if ((mem=BIO_new(BIO_s_mem())) == NULL)
-                                       goto err;
-                       if (((buf=BUF_MEM_new()) == NULL) ||
-                               !BUF_MEM_grow(buf,128))
-                               goto err;
-                       if ((tmp=ASN1_STRING_new()) == NULL) goto err;
+                       BIO_printf(bio_err,"Malloc failure\n");
+                       goto err;
+                       }
 
-                       BIO_reset(mem);
-                       BIO_write(mem,(char *)&(ptr[2]),len-2);
-                       if (!a2i_ASN1_STRING(mem,tmp,buf->data,buf->max))
-                               goto err;
-                       len=tmp->length;
-                       ptr=tmp->data;
+               for (i=0; i<DB_NUMBER; i++)
+                       {
+                       irow[i]=row[i];
+                       row[i]=NULL;
                        }
+               irow[DB_NUMBER]=NULL;
 
-               switch (pack_type)
+               if (!TXT_DB_insert(db,irow))
                        {
-               case X509_EXT_PACK_STRING:
-                       if ((str=X509v3_pack_string(&str,
-                               data_type,ptr,len)) == NULL)
-                               goto err;
-                       break;
-               case X509_EXT_PACK_UNKNOWN:
-               default:
-                       BIO_printf(bio_err,"Don't know how to pack extension %s\n",cv->name);
+                       BIO_printf(bio_err,"failed to update database\n");
+                       BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
                        goto err;
-                       break;
                        }
 
-               if ((x=X509_EXTENSION_create_by_NID(NULL,nid,0,str)) == NULL)
-                       goto err;
-               sk_push(ret,(char *)x);
-               }
+               /* Revoke Certificate */
+               ok = do_revoke(x509,db);
 
-       if (0)
+               goto err;
+
+               }
+       else if (index_name_cmp(row,rrow))
+               {
+               BIO_printf(bio_err,"ERROR:name does not match %s\n",
+                          row[DB_name]);
+               goto err;
+               }
+       else if (rrow[DB_type][0]=='R')
+               {
+               BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
+                          row[DB_serial]);
+               goto err;
+               }
+       else
                {
+               BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
+               revtm = ASN1_UTCTIME_new();
+               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);
+               memcpy(rrow[DB_rev_date],revtm->data,revtm->length);
+               rrow[DB_rev_date][revtm->length]='\0';
+               ASN1_UTCTIME_free(revtm);
+               }
+       ok=1;
 err:
-               if (ret != NULL) sk_pop_free(ret,X509_EXTENSION_free);
-               ret=NULL;
+       for (i=0; i<DB_NUMBER; i++)
+               {
+               if (row[i] != NULL) 
+                       Free(row[i]);
                }
-       if (str != NULL) ASN1_OCTET_STRING_free(str);
-       if (tmp != NULL) ASN1_STRING_free(tmp);
-       if (buf != NULL) BUF_MEM_free(buf);
-       if (mem != NULL) BIO_free(mem);
-       return(ret);
-       }
-
-static int check_time_format(str)
-char *str;
-       {
-       ASN1_UTCTIME tm;
-
-       tm.data=(unsigned char *)str;
-       tm.length=strlen(str);
-       tm.type=V_ASN1_UTCTIME;
-       return(ASN1_UTCTIME_check(&tm));
-       }
+       return(ok);
+}