Add `openssl ca -revoke <certfile>' facility which revokes a certificate
[openssl.git] / apps / ca.c
index 21592412ba64d78176be0cdfa7882f34cbff3fde..6c060ce02e246e322af581f74351c99f779bc515 100644 (file)
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -70,6 +70,7 @@
 #include "txt_db.h"
 #include "evp.h"
 #include "x509.h"
 #include "txt_db.h"
 #include "evp.h"
 #include "x509.h"
+#include "x509v3.h"
 #include "objects.h"
 #include "pem.h"
 #include "conf.h"
 #include "objects.h"
 #include "pem.h"
 #include "conf.h"
@@ -82,7 +83,7 @@
 #define PROG ca_main
 
 #define BASE_SECTION   "ca"
 #define PROG ca_main
 
 #define BASE_SECTION   "ca"
-#define CONFIG_FILE "lib/ssleay.cnf"
+#define CONFIG_FILE "lib/openssl.cnf"
 
 #define ENV_DEFAULT_CA         "default_ca"
 
 
 #define ENV_DEFAULT_CA         "default_ca"
 
 #define ENV_PRESERVE           "preserve"
 #define ENV_POLICY             "policy"
 #define ENV_EXTENSIONS         "x509_extensions"
 #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"
 #define ENV_MSIE_HACK          "msie_hack"
 
 #define ENV_DATABASE           "database"
@@ -134,7 +136,7 @@ static char *ca_usage[]={
 " -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",
 " -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",
 " -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 +144,9 @@ 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",
 " -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",
 NULL
 };
 
 NULL
 };
 
@@ -154,7 +157,7 @@ extern int EF_ALIGNMENT;
 #endif
 
 #ifndef NOPROTO
 #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 unsigned long index_serial_hash(char **a);
 static void lookup_fail(char *name,char *tag);
 static int MS_CALLBACK key_callback(char *buf,int len,int verify);
 static unsigned long index_serial_hash(char **a);
@@ -166,21 +169,23 @@ 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,
 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);
+       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,
 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);
+       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,
 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);
+       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,
 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);
+       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 int check_time_format(char *str);
 #else
-static STACK *load_extensions();
+static int add_oid_section();
 static void lookup_fail();
 static int MS_CALLBACK key_callback();
 static unsigned long index_serial_hash();
 static void lookup_fail();
 static int MS_CALLBACK key_callback();
 static unsigned long index_serial_hash();
@@ -196,6 +201,7 @@ static int certify_cert();
 static int certify_spkac();
 static void write_new_certificate();
 static int do_body();
 static int certify_spkac();
 static void write_new_certificate();
 static int do_body();
+static int do_revoke();
 static int check_time_format();
 #endif
 
 static int check_time_format();
 #endif
 
@@ -217,6 +223,7 @@ char **argv;
        int req=0;
        int verbose=0;
        int gencrl=0;
        int req=0;
        int verbose=0;
        int gencrl=0;
+       int revoke=0;
        long crldays=0;
        long crlhours=0;
        long errorline= -1;
        long crldays=0;
        long crlhours=0;
        long errorline= -1;
@@ -234,6 +241,7 @@ char **argv;
        char *outdir=NULL;
        char *serialfile=NULL;
        char *extensions=NULL;
        char *outdir=NULL;
        char *serialfile=NULL;
        char *extensions=NULL;
+       char *crl_ext=NULL;
        BIGNUM *serial=NULL;
        char *startdate=NULL;
        int days=0;
        BIGNUM *serial=NULL;
        char *startdate=NULL;
        int days=0;
@@ -251,7 +259,6 @@ char **argv;
        long l;
        EVP_MD *dgst=NULL;
        STACK *attribs=NULL;
        long l;
        EVP_MD *dgst=NULL;
        STACK *attribs=NULL;
-       STACK *extensions_sk=NULL;
        STACK *cert_sk=NULL;
        BIO *hex=NULL;
 #undef BSIZE
        STACK *cert_sk=NULL;
        BIO *hex=NULL;
 #undef BSIZE
@@ -266,7 +273,7 @@ EF_ALIGNMENT=0;
 
        apps_startup();
 
 
        apps_startup();
 
-       X509v3_add_netscape_extensions();
+       X509V3_add_standard_extensions();
 
        preserve=0;
        if (bio_err == NULL)
 
        preserve=0;
        if (bio_err == NULL)
@@ -377,6 +384,12 @@ EF_ALIGNMENT=0;
                        spkac_file = *(++argv);
                        req=1;
                        }
                        spkac_file = *(++argv);
                        req=1;
                        }
+               else if (strcmp(*argv,"-revoke") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       infile= *(++argv);
+                       revoke=1;
+                       }
                else
                        {
 bad:
                else
                        {
 bad:
@@ -445,6 +458,7 @@ bad:
                                BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
                                ERR_print_errors(bio_err);
                                */
                                BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
                                ERR_print_errors(bio_err);
                                */
+                               ERR_clear_error();
                                }
                        else
                                {
                                }
                        else
                                {
@@ -453,6 +467,10 @@ bad:
                                }
                        }
                }
                                }
                        }
                }
+               if(!add_oid_section(conf)) {
+                       ERR_print_errors(bio_err);
+                       goto err;
+               }
 
        in=BIO_new(BIO_s_file());
        out=BIO_new(BIO_s_file());
 
        in=BIO_new(BIO_s_file());
        out=BIO_new(BIO_s_file());
@@ -582,13 +600,13 @@ bad:
                if ((pp[DB_type][0] != DB_TYPE_REV) &&
                        (pp[DB_rev_date][0] != '\0'))
                        {
                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]))
                        {
                        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;
                        }
                                i+1);
                        goto err;
                        }
@@ -688,12 +706,17 @@ bad:
                        goto err;
                        }
 
                        goto err;
                        }
 
-               if ((extensions=CONF_get_string(conf,section,ENV_EXTENSIONS))
-                       != NULL)
-                       {
-                       if ((extensions_sk=load_extensions(extensions)) == NULL)
+               extensions=CONF_get_string(conf,section,ENV_EXTENSIONS);
+               if(extensions) {
+                       /* Check syntax of file */
+                       if(!X509V3_EXT_check_conf(conf, extensions)) {
+                               BIO_printf(bio_err,
+                                "Error Loading extension section %s\n",
+                                                                extensions);
+                               ret = 1;
                                goto err;
                        }
                                goto err;
                        }
+               }
 
                if (startdate == NULL)
                        {
 
                if (startdate == NULL)
                        {
@@ -749,7 +772,7 @@ bad:
                        {
                        total++;
                        j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
                        {
                        total++;
                        j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
-                               serial,startdate,days,extensions_sk,verbose);
+                               serial,startdate,days,extensions,conf,verbose);
                        if (j < 0) goto err;
                        if (j > 0)
                                {
                        if (j < 0) goto err;
                        if (j > 0)
                                {
@@ -773,7 +796,7 @@ bad:
                        total++;
                        j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
                                db,serial,startdate,days,batch,
                        total++;
                        j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
                                db,serial,startdate,days,batch,
-                               extensions_sk,verbose);
+                               extensions,conf,verbose);
                        if (j < 0) goto err;
                        if (j > 0)
                                {
                        if (j < 0) goto err;
                        if (j > 0)
                                {
@@ -792,7 +815,7 @@ bad:
                        total++;
                        j=certify(&x,infile,pkey,x509,dgst,attribs,db,
                                serial,startdate,days,batch,
                        total++;
                        j=certify(&x,infile,pkey,x509,dgst,attribs,db,
                                serial,startdate,days,batch,
-                               extensions_sk,verbose);
+                               extensions,conf,verbose);
                        if (j < 0) goto err;
                        if (j > 0)
                                {
                        if (j < 0) goto err;
                        if (j > 0)
                                {
@@ -811,7 +834,7 @@ bad:
                        total++;
                        j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
                                serial,startdate,days,batch,
                        total++;
                        j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
                                serial,startdate,days,batch,
-                               extensions_sk,verbose);
+                               extensions,conf,verbose);
                        if (j < 0) goto err;
                        if (j > 0)
                                {
                        if (j < 0) goto err;
                        if (j > 0)
                                {
@@ -955,6 +978,17 @@ bad:
        /*****************************************************************/
        if (gencrl)
                {
        /*****************************************************************/
        if (gencrl)
                {
+               crl_ext=CONF_get_string(conf,section,ENV_CRLEXT);
+               if(crl_ext) {
+                       /* Check syntax of file */
+                       if(!X509V3_EXT_check_conf(conf, crl_ext)) {
+                               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)
                if ((hex=BIO_new(BIO_s_mem())) == NULL) goto err;
 
                if (!crldays && !crlhours)
@@ -1023,36 +1057,119 @@ bad:
                                }
                        }
                else
                                }
                        }
                else
-                       dgst=EVP_md5();
+                   {
 #ifndef NO_DSA
 #ifndef NO_DSA
-               if (pkey->type == EVP_PKEY_DSA) 
-                   dgst = EVP_dss1() ;
+                   if (pkey->type == EVP_PKEY_DSA) 
+                       dgst=EVP_dss1();
+                   else
 #endif
 #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 */
+                   crlctx.crl = crl;
+                   crlctx.issuer_cert = x509;
+                   crlctx.subject_cert = NULL;
+                   crlctx.subject_req = NULL;
+                   crlctx.flags = 0;
+
+                   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 (!X509_CRL_sign(crl,pkey,dgst)) goto err;
 
                PEM_write_bio_X509_CRL(Sout,crl);
                }
        /*****************************************************************/
+       if (revoke)
+               {
+               in=BIO_new(BIO_s_file());
+               out=BIO_new(BIO_s_file());
+               if ((in == NULL) || (out == NULL))
+                       {
+                       ERR_print_errors(bio_err);
+                       goto err;
+                       }
+               if (infile == NULL) 
+                       {
+                       BIO_printf(bio_err,"no input files\n");
+                       goto err;
+                       }
+               else
+                       {
+                       if (BIO_read_filename(in,infile) <= 0)
+                               {
+                               perror(infile);
+                               BIO_printf(bio_err,"error trying to load '%s' certificate\n",infile);
+                               goto err;
+                               }
+                       x509=PEM_read_bio_X509(in,NULL,NULL);
+                       if (x509 == NULL)
+                               {
+                               BIO_printf(bio_err,"unable to load '%s' certificate\n",infile);
+                               goto err;
+                               }
+                       j=do_revoke(x509,db);
+
+                       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;
+                       BIO_free(in);
+                       BIO_free(out);
+                       in=NULL;
+                       out=NULL;
+                       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:
        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 (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();
+       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);
        }
 
        EXIT(ret);
        }
 
@@ -1184,7 +1301,7 @@ err:
        }
 
 static int certify(xret,infile,pkey,x509,dgst,policy,db,serial,startdate,days,
        }
 
 static int certify(xret,infile,pkey,x509,dgst,policy,db,serial,startdate,days,
-       batch,extensions,verbose)
+                  batch,ext_sect,lconf,verbose)
 X509 **xret;
 char *infile;
 EVP_PKEY *pkey;
 X509 **xret;
 char *infile;
 EVP_PKEY *pkey;
@@ -1196,7 +1313,8 @@ BIGNUM *serial;
 char *startdate;
 int days;
 int batch;
 char *startdate;
 int days;
 int batch;
-STACK *extensions;
+char *ext_sect;
+LHASH *lconf;
 int verbose;
        {
        X509_REQ *req=NULL;
 int verbose;
        {
        X509_REQ *req=NULL;
@@ -1228,6 +1346,7 @@ int verbose;
                goto err;
                }
        i=X509_REQ_verify(req,pktmp);
                goto err;
                }
        i=X509_REQ_verify(req,pktmp);
+       EVP_PKEY_free(pktmp);
        if (i < 0)
                {
                ok=0;
        if (i < 0)
                {
                ok=0;
@@ -1244,7 +1363,7 @@ int verbose;
                BIO_printf(bio_err,"Signature ok\n");
 
        ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,
                BIO_printf(bio_err,"Signature ok\n");
 
        ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,
-               days,batch,verbose,req,extensions);
+               days,batch,verbose,req,ext_sect,lconf);
 
 err:
        if (req != NULL) X509_REQ_free(req);
 
 err:
        if (req != NULL) X509_REQ_free(req);
@@ -1253,7 +1372,7 @@ err:
        }
 
 static int certify_cert(xret,infile,pkey,x509,dgst,policy,db,serial,startdate,
        }
 
 static int certify_cert(xret,infile,pkey,x509,dgst,policy,db,serial,startdate,
-       days, batch,extensions,verbose)
+                       days,batch,ext_sect,lconf,verbose)
 X509 **xret;
 char *infile;
 EVP_PKEY *pkey;
 X509 **xret;
 char *infile;
 EVP_PKEY *pkey;
@@ -1265,7 +1384,8 @@ BIGNUM *serial;
 char *startdate;
 int days;
 int batch;
 char *startdate;
 int days;
 int batch;
-STACK *extensions;
+char *ext_sect;
+LHASH *lconf;
 int verbose;
        {
        X509 *req=NULL;
 int verbose;
        {
        X509 *req=NULL;
@@ -1297,6 +1417,7 @@ int verbose;
                goto err;
                }
        i=X509_verify(req,pktmp);
                goto err;
                }
        i=X509_verify(req,pktmp);
+       EVP_PKEY_free(pktmp);
        if (i < 0)
                {
                ok=0;
        if (i < 0)
                {
                ok=0;
@@ -1316,7 +1437,7 @@ int verbose;
                goto err;
 
        ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,days,
                goto err;
 
        ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,days,
-               batch,verbose,rreq,extensions);
+               batch,verbose,rreq,ext_sect,lconf);
 
 err:
        if (rreq != NULL) X509_REQ_free(rreq);
 
 err:
        if (rreq != NULL) X509_REQ_free(rreq);
@@ -1326,7 +1447,7 @@ err:
        }
 
 static int do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,days,
        }
 
 static int do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,days,
-       batch,verbose,req, extensions)
+                  batch,verbose,req,ext_sect,lconf)
 X509 **xret;
 EVP_PKEY *pkey;
 X509 *x509;
 X509 **xret;
 EVP_PKEY *pkey;
 X509 *x509;
@@ -1339,7 +1460,8 @@ int days;
 int batch;
 int verbose;
 X509_REQ *req;
 int batch;
 int verbose;
 X509_REQ *req;
-STACK *extensions;
+char *ext_sect;
+LHASH *lconf;
        {
        X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
        ASN1_UTCTIME *tm,*tmptm;
        {
        X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
        ASN1_UTCTIME *tm,*tmptm;
@@ -1349,7 +1471,6 @@ STACK *extensions;
        X509_CINF *ci;
        X509_NAME_ENTRY *ne;
        X509_NAME_ENTRY *tne,*push;
        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;
        EVP_PKEY *pktmp;
        int ok= -1,i,j,last,nid;
        char *p;
@@ -1651,11 +1772,14 @@ again2:
        if (!X509_set_subject_name(ret,subject)) goto err;
 
        pktmp=X509_REQ_get_pubkey(req);
        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 */
 
        /* 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;
                if (ci->version == NULL)
                        if ((ci->version=ASN1_INTEGER_new()) == NULL)
                                goto err;
@@ -1666,17 +1790,16 @@ again2:
                if (ci->extensions != NULL)
                        sk_pop_free(ci->extensions,X509_EXTENSION_free);
 
                if (ci->extensions != NULL)
                        sk_pop_free(ci->extensions,X509_EXTENSION_free);
 
-               if ((ci->extensions=sk_new_null()) == NULL)
-                       goto err;
+               ci->extensions = NULL;
+
+               ctx.subject_cert = ret;
+               ctx.issuer_cert = x509;
+               ctx.subject_req = req;
+               ctx.crl = NULL;
+               ctx.flags = 0;
+
+               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;
-                       }
                }
 
 
                }
 
 
@@ -1701,6 +1824,7 @@ again2:
         if (EVP_PKEY_missing_parameters(pktmp) &&
                !EVP_PKEY_missing_parameters(pkey))
                EVP_PKEY_copy_parameters(pktmp,pkey);
         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))
 #endif
 
        if (!X509_sign(ret,pkey,dgst))
@@ -1798,7 +1922,7 @@ int output_der;
        }
 
 static int certify_spkac(xret,infile,pkey,x509,dgst,policy,db,serial,
        }
 
 static int certify_spkac(xret,infile,pkey,x509,dgst,policy,db,serial,
-       startdate,days,extensions,verbose)
+                        startdate,days,ext_sect,lconf,verbose)
 X509 **xret;
 char *infile;
 EVP_PKEY *pkey;
 X509 **xret;
 char *infile;
 EVP_PKEY *pkey;
@@ -1809,7 +1933,8 @@ TXT_DB *db;
 BIGNUM *serial;
 char *startdate;
 int days;
 BIGNUM *serial;
 char *startdate;
 int days;
-STACK *extensions;
+char *ext_sect;
+LHASH *lconf;
 int verbose;
        {
        STACK *sk=NULL;
 int verbose;
        {
        STACK *sk=NULL;
@@ -1953,8 +2078,9 @@ int verbose;
        BIO_printf(bio_err,"Signature ok\n");
 
        X509_REQ_set_pubkey(req,pktmp);
        BIO_printf(bio_err,"Signature ok\n");
 
        X509_REQ_set_pubkey(req,pktmp);
+       EVP_PKEY_free(pktmp);
        ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,
        ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,
-               days,1,verbose,req,extensions);
+                  days,1,verbose,req,ext_sect,lconf);
 err:
        if (req != NULL) X509_REQ_free(req);
        if (parms != NULL) CONF_free(parms);
 err:
        if (req != NULL) X509_REQ_free(req);
        if (parms != NULL) CONF_free(parms);
@@ -1982,102 +2108,6 @@ int *type;
        return(1);
        }
 
        return(1);
        }
 
-
-static STACK *load_extensions(sec)
-char *sec;
-       {
-       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;
-
-       if ((ext=CONF_get_section(conf,sec)) == NULL)
-               {
-               BIO_printf(bio_err,"unable to find extension section called '%s'\n",sec);
-               return(NULL);
-               }
-
-       if ((ret=sk_new_null()) == NULL) return(NULL);
-
-       for (i=0; i<sk_num(ext); i++)
-               {
-               cv=(CONF_VALUE *)sk_value(ext,i); /* get the object id */
-               if ((nid=OBJ_txt2nid(cv->name)) == NID_undef)
-                       {
-                       BIO_printf(bio_err,"%s:unknown object type in section, '%s'\n",sec,cv->name);
-                       goto err;
-                       }
-
-               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 (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_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;
-                       }
-
-               switch (pack_type)
-                       {
-               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);
-                       goto err;
-                       /* break; */
-                       }
-
-               if ((x=X509_EXTENSION_create_by_NID(NULL,nid,0,str)) == NULL)
-                       goto err;
-               sk_push(ret,(char *)x);
-               }
-
-       if (0)
-               {
-err:
-               if (ret != NULL) sk_pop_free(ret,X509_EXTENSION_free);
-               ret=NULL;
-               }
-       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;
        {
 static int check_time_format(str)
 char *str;
        {
@@ -2089,3 +2119,133 @@ char *str;
        return(ASN1_UTCTIME_check(&tm));
        }
 
        return(ASN1_UTCTIME_check(&tm));
        }
 
+static int add_oid_section(hconf)
+LHASH *hconf;
+{      
+       char *p;
+       STACK *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_num(sktmp); i++) {
+               cnf = (CONF_VALUE *)sk_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;
+}
+
+static int do_revoke(x509,db)
+X509 *x509;
+TXT_DB *db;
+{
+        ASN1_UTCTIME *tm=NULL;
+        char *row[DB_NUMBER],**rrow,**irow;
+        int ok=-1,i;
+
+        for (i=0; i<DB_NUMBER; i++)
+                row[i]=NULL;
+        row[DB_name]=X509_NAME_oneline(x509->cert_info->subject,NULL,0);
+        row[DB_serial]=BN_bn2hex(ASN1_INTEGER_to_BN(x509->cert_info->serialNumber,NULL));
+        if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
+                {
+                BIO_printf(bio_err,"Malloc failure\n");
+                goto err;
+                }
+        rrow=TXT_DB_get_by_index(db,DB_name,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,"Malloc 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)
+                        {
+                        BIO_printf(bio_err,"Malloc failure\n");
+                        goto err;
+                        }
+
+                for (i=0; i<DB_NUMBER; i++)
+                        {
+                        irow[i]=row[i];
+                        row[i]=NULL;
+                        }
+                irow[DB_NUMBER]=NULL;
+
+                if (!TXT_DB_insert(db,irow))
+                        {
+                        BIO_printf(bio_err,"failed to update database\n");
+                        BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
+                        goto err;
+                        }
+
+                /* Revoke Certificate */
+                do_revoke(x509,db);
+
+                ok=1;
+                goto err;
+
+                }
+        else if (index_serial_cmp(row,rrow))
+                {
+                BIO_printf(bio_err,"ERROR:no same serial number %s\n",
+                           row[DB_serial]);
+                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]);
+                tm=X509_gmtime_adj(tm,0);
+                rrow[DB_type][0]='R';
+                rrow[DB_type][1]='\0';
+                rrow[DB_rev_date]=(char *)Malloc(tm->length+1);
+                memcpy(rrow[DB_rev_date],tm->data,tm->length);
+                rrow[DB_rev_date][tm->length]='\0';
+                }
+        ok=1;
+err:
+        for (i=0; i<DB_NUMBER; i++)
+                {
+                if (row[i] != NULL) 
+                        Free(row[i]);
+                }
+        ASN1_UTCTIME_free(tm);
+        return(ok);
+}
+