Demo of use of errors in applications.
[openssl.git] / apps / ca.c
index e0349a765608510401f89b42080faf136479ef38..934970d9e45e9742972e8ff263c5c317cd25bdb1 100644 (file)
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -63,8 +63,6 @@
 #include <string.h>
 #include <ctype.h>
 #include <sys/types.h>
 #include <string.h>
 #include <ctype.h>
 #include <sys/types.h>
-#include <sys/stat.h>
-#include "apps.h"
 #include <openssl/conf.h>
 #include <openssl/bio.h>
 #include <openssl/err.h>
 #include <openssl/conf.h>
 #include <openssl/bio.h>
 #include <openssl/err.h>
 #include <openssl/objects.h>
 #include <openssl/ocsp.h>
 #include <openssl/pem.h>
 #include <openssl/objects.h>
 #include <openssl/ocsp.h>
 #include <openssl/pem.h>
-#include <openssl/engine.h>
 
 #ifndef W_OK
 
 #ifndef W_OK
-#  ifdef VMS
+#  ifdef OPENSSL_SYS_VMS
 #    if defined(__DECC)
 #      include <unistd.h>
 #    else
 #      include <unixlib.h>
 #    endif
 #    if defined(__DECC)
 #      include <unistd.h>
 #    else
 #      include <unixlib.h>
 #    endif
-#  else
+#  elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_NETWARE)
 #    include <sys/file.h>
 #  endif
 #endif
 
 #    include <sys/file.h>
 #  endif
 #endif
 
+#include "apps.h"
+
 #ifndef W_OK
 #  define F_OK 0
 #  define X_OK 1
 #ifndef W_OK
 #  define F_OK 0
 #  define X_OK 1
 
 #define ENV_DEFAULT_CA         "default_ca"
 
 
 #define ENV_DEFAULT_CA         "default_ca"
 
+#define STRING_MASK    "string_mask"
+#define UTF8_IN                        "utf8"
+
 #define ENV_DIR                        "dir"
 #define ENV_CERTS              "certs"
 #define ENV_CRL_DIR            "crl_dir"
 #define ENV_DIR                        "dir"
 #define ENV_CERTS              "certs"
 #define ENV_CRL_DIR            "crl_dir"
 #define ENV_NEW_CERTS_DIR      "new_certs_dir"
 #define ENV_CERTIFICATE        "certificate"
 #define ENV_SERIAL             "serial"
 #define ENV_NEW_CERTS_DIR      "new_certs_dir"
 #define ENV_CERTIFICATE        "certificate"
 #define ENV_SERIAL             "serial"
+#define ENV_CRLNUMBER          "crlnumber"
 #define ENV_CRL                        "crl"
 #define ENV_PRIVATE_KEY                "private_key"
 #define ENV_RANDFILE           "RANDFILE"
 #define ENV_CRL                        "crl"
 #define ENV_PRIVATE_KEY                "private_key"
 #define ENV_RANDFILE           "RANDFILE"
 #define ENV_DEFAULT_CRL_DAYS   "default_crl_days"
 #define ENV_DEFAULT_CRL_HOURS  "default_crl_hours"
 #define ENV_DEFAULT_MD         "default_md"
 #define ENV_DEFAULT_CRL_DAYS   "default_crl_days"
 #define ENV_DEFAULT_CRL_HOURS  "default_crl_hours"
 #define ENV_DEFAULT_MD         "default_md"
+#define ENV_DEFAULT_EMAIL_DN   "email_in_dn"
 #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_PRESERVE           "preserve"
 #define ENV_POLICY             "policy"
 #define ENV_EXTENSIONS         "x509_extensions"
 #define ENV_CRLEXT             "crl_extensions"
 #define ENV_MSIE_HACK          "msie_hack"
+#define ENV_NAMEOPT            "name_opt"
+#define ENV_CERTOPT            "cert_opt"
+#define ENV_EXTCOPY            "copy_extensions"
+#define ENV_UNIQUE_SUBJECT     "unique_subject"
 
 #define ENV_DATABASE           "database"
 
 
 #define ENV_DATABASE           "database"
 
-#define DB_type         0
-#define DB_exp_date     1
-#define DB_rev_date     2
-#define DB_serial       3       /* index - unique */
-#define DB_file         4       
-#define DB_name         5       /* index - unique for active */
-#define DB_NUMBER       6
-
-#define DB_TYPE_REV    'R'
-#define DB_TYPE_EXP    'E'
-#define DB_TYPE_VAL    'V'
-
 /* Additional revocation information types */
 
 #define REV_NONE               0       /* No addditional information */
 /* Additional revocation information types */
 
 #define REV_NONE               0       /* No addditional information */
 #define REV_KEY_COMPROMISE     3       /* Value is cert key compromise time */
 #define REV_CA_COMPROMISE      4       /* Value is CA key compromise time */
 
 #define REV_KEY_COMPROMISE     3       /* Value is cert key compromise time */
 #define REV_CA_COMPROMISE      4       /* Value is CA key compromise time */
 
-static char *ca_usage[]={
+static const char *ca_usage[]={
 "usage: ca args\n",
 "\n",
 "usage: ca args\n",
 "\n",
-" -verbose        - Talk alot while doing things\n",
+" -verbose        - Talk a lot while doing things\n",
 " -config file    - A config file\n",
 " -name arg       - The particular CA definition to use\n",
 " -gencrl         - Generate a new CRL\n",
 " -config file    - A config file\n",
 " -name arg       - The particular CA definition to use\n",
 " -gencrl         - Generate a new CRL\n",
@@ -167,6 +163,7 @@ static char *ca_usage[]={
 " -keyform arg    - private key file format (PEM or ENGINE)\n",
 " -key arg        - key to decode the private key if it is encrypted\n",
 " -cert file      - The CA certificate\n",
 " -keyform arg    - private key file format (PEM or ENGINE)\n",
 " -key arg        - key to decode the private key if it is encrypted\n",
 " -cert file      - The CA certificate\n",
+" -selfsign       - sign a certificate with the key associated with it\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",
@@ -174,13 +171,19 @@ 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",
+" -noemailDN      - Don't add the EMAIL field into certificate' subject\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",
 " -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",
+" -subj arg       - Use arg instead of request's subject\n",
+" -utf8           - input characters are UTF8 (default ASCII)\n",
+" -multivalue-rdn - enable support for multivalued RDNs\n",
 " -extensions ..  - Extension section (override value in config file)\n",
 " -extensions ..  - Extension section (override value in config file)\n",
-" -extfile file   - Configuration file with X509v3 extentions to add\n",
+" -extfile file   - Configuration file with X509v3 extensions to add\n",
 " -crlexts ..     - CRL extension section (override value in config file)\n",
 " -crlexts ..     - CRL extension section (override value in config file)\n",
+#ifndef OPENSSL_NO_ENGINE
 " -engine e       - use engine e, possibly a hardware device.\n",
 " -engine e       - use engine e, possibly a hardware device.\n",
+#endif
 " -status serial  - Shows certificate status given the serial number\n",
 " -updatedb       - Updates db for expired certificates\n",
 NULL
 " -status serial  - Shows certificate status given the serial number\n",
 " -updatedb       - Updates db for expired certificates\n",
 NULL
@@ -192,52 +195,51 @@ extern int EF_PROTECT_BELOW;
 extern int EF_ALIGNMENT;
 #endif
 
 extern int EF_ALIGNMENT;
 #endif
 
-static void lookup_fail(char *name,char *tag);
-static unsigned long index_serial_hash(const char **a);
-static int index_serial_cmp(const char **a, const char **b);
-static unsigned long index_name_hash(const char **a);
-static int index_name_qual(char **a);
-static int index_name_cmp(const char **a,const char **b);
-static BIGNUM *load_serial(char *serialfile);
-static int save_serial(char *serialfile, BIGNUM *serial);
+static void lookup_fail(const char *name, const char *tag);
 static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
 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 *conf,int verbose);
+                  const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts,
+                  STACK_OF(CONF_VALUE) *policy,CA_DB *db,
+                  BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate,
+                  char *enddate, long days, int batch, char *ext_sect, CONF *conf,
+                  int verbose, unsigned long certopt, unsigned long nameopt,
+                  int default_op, int ext_copy, int selfsign);
 static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
 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 *conf,int verbose);
+                       const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts,
+                       STACK_OF(CONF_VALUE) *policy,
+                       CA_DB *db, BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn,
+                       char *startdate, char *enddate, long days, int batch,
+                       char *ext_sect, CONF *conf,int verbose, unsigned long certopt,
+                       unsigned long nameopt, int default_op, int ext_copy,
+                       ENGINE *e);
 static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
 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 *conf,
-                               int verbose);
-static int fix_data(int nid, int *type);
+                        const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts,
+                        STACK_OF(CONF_VALUE) *policy,
+                        CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn, int email_dn,
+                        char *startdate, char *enddate, long days, char *ext_sect,
+                        CONF *conf, int verbose, unsigned long certopt, 
+                        unsigned long nameopt, int default_op, int ext_copy);
 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
-       STACK_OF(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, int ext, char *extval);
-static int get_certificate_status(const char *ser_status, TXT_DB *db);
-static int do_updatedb(TXT_DB *db);
-static int check_time_format(char *str);
+       STACK_OF(OPENSSL_STRING) *sigopts,
+       STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn,
+       int email_dn, char *startdate, char *enddate, long days, int batch,
+               int verbose, X509_REQ *req, char *ext_sect, CONF *conf,
+       unsigned long certopt, unsigned long nameopt, int default_op,
+       int ext_copy, int selfsign);
+static int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval);
+static int get_certificate_status(const char *ser_status, CA_DB *db);
+static int do_updatedb(CA_DB *db);
+static int check_time_format(const char *str);
 char *make_revocation_str(int rev_type, char *rev_arg);
 char *make_revocation_str(int rev_type, char *rev_arg);
-int make_revoked(X509_REVOKED *rev, char *str);
-static LHASH *conf=NULL;
-static LHASH *extconf=NULL;
+int make_revoked(X509_REVOKED *rev, const char *str);
+int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str);
+static CONF *conf=NULL;
+static CONF *extconf=NULL;
 static char *section=NULL;
 
 static int preserve=0;
 static int msie_hack=0;
 
 static char *section=NULL;
 
 static int preserve=0;
 static int msie_hack=0;
 
-static IMPLEMENT_LHASH_HASH_FN(index_serial_hash,const char **)
-static IMPLEMENT_LHASH_COMP_FN(index_serial_cmp,const char **)
-static IMPLEMENT_LHASH_HASH_FN(index_name_hash,const char **)
-static IMPLEMENT_LHASH_COMP_FN(index_name_cmp,const char **)
-
 
 int MAIN(int, char **);
 
 
 int MAIN(int, char **);
 
@@ -245,10 +247,13 @@ int MAIN(int argc, char **argv)
        {
        ENGINE *e = NULL;
        char *key=NULL,*passargin=NULL;
        {
        ENGINE *e = NULL;
        char *key=NULL,*passargin=NULL;
+       int create_ser = 0;
+       int free_key = 0;
        int total=0;
        int total_done=0;
        int badops=0;
        int ret=1;
        int total=0;
        int total_done=0;
        int badops=0;
        int ret=1;
+       int email_dn=1;
        int req=0;
        int verbose=0;
        int gencrl=0;
        int req=0;
        int verbose=0;
        int gencrl=0;
@@ -256,6 +261,7 @@ int MAIN(int argc, char **argv)
        int doupdatedb=0;
        long crldays=0;
        long crlhours=0;
        int doupdatedb=0;
        long crldays=0;
        long crlhours=0;
+       long crlsec=0;
        long errorline= -1;
        char *configfile=NULL;
        char *md=NULL;
        long errorline= -1;
        char *configfile=NULL;
        char *md=NULL;
@@ -272,37 +278,53 @@ int MAIN(int argc, char **argv)
        char *outfile=NULL;
        char *outdir=NULL;
        char *serialfile=NULL;
        char *outfile=NULL;
        char *outdir=NULL;
        char *serialfile=NULL;
+       char *crlnumberfile=NULL;
        char *extensions=NULL;
        char *extfile=NULL;
        char *extensions=NULL;
        char *extfile=NULL;
+       char *subj=NULL;
+       unsigned long chtype = MBSTRING_ASC;
+       int multirdn = 0;
+       char *tmp_email_dn=NULL;
        char *crl_ext=NULL;
        int rev_type = REV_NONE;
        char *rev_arg = NULL;
        BIGNUM *serial=NULL;
        char *crl_ext=NULL;
        int rev_type = REV_NONE;
        char *rev_arg = NULL;
        BIGNUM *serial=NULL;
+       BIGNUM *crlnumber=NULL;
        char *startdate=NULL;
        char *enddate=NULL;
        char *startdate=NULL;
        char *enddate=NULL;
-       int days=0;
+       long days=0;
        int batch=0;
        int notext=0;
        int batch=0;
        int notext=0;
-       X509 *x509=NULL;
+       unsigned long nameopt = 0, certopt = 0;
+       int default_op = 1;
+       int ext_copy = EXT_COPY_NONE;
+       int selfsign = 0;
+       X509 *x509=NULL, *x509p = NULL;
        X509 *x=NULL;
        BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
        char *dbfile=NULL;
        X509 *x=NULL;
        BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
        char *dbfile=NULL;
-       TXT_DB *db=NULL;
+       CA_DB *db=NULL;
        X509_CRL *crl=NULL;
        X509_CRL *crl=NULL;
-       X509_CRL_INFO *ci=NULL;
        X509_REVOKED *r=NULL;
        X509_REVOKED *r=NULL;
-       char **pp,*p,*f;
+       ASN1_TIME *tmptm;
+       ASN1_INTEGER *tmpser;
+       char *f;
+       const char *p;
+       char * const *pp;
        int i,j;
        int i,j;
-       long l;
        const EVP_MD *dgst=NULL;
        STACK_OF(CONF_VALUE) *attribs=NULL;
        STACK_OF(X509) *cert_sk=NULL;
        const EVP_MD *dgst=NULL;
        STACK_OF(CONF_VALUE) *attribs=NULL;
        STACK_OF(X509) *cert_sk=NULL;
-       BIO *hex=NULL;
+       STACK_OF(OPENSSL_STRING) *sigopts = NULL;
 #undef BSIZE
 #define BSIZE 256
        MS_STATIC char buf[3][BSIZE];
        char *randfile=NULL;
 #undef BSIZE
 #define BSIZE 256
        MS_STATIC char buf[3][BSIZE];
        char *randfile=NULL;
+#ifndef OPENSSL_NO_ENGINE
        char *engine = NULL;
        char *engine = NULL;
+#endif
+       char *tofree=NULL;
+       DB_ATTR db_attr;
 
 #ifdef EFENCE
 EF_PROTECT_FREE=1;
 
 #ifdef EFENCE
 EF_PROTECT_FREE=1;
@@ -338,6 +360,18 @@ EF_ALIGNMENT=0;
                        if (--argc < 1) goto bad;
                        section= *(++argv);
                        }
                        if (--argc < 1) goto bad;
                        section= *(++argv);
                        }
+               else if (strcmp(*argv,"-subj") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       subj= *(++argv);
+                       /* preserve=1; */
+                       }
+               else if (strcmp(*argv,"-utf8") == 0)
+                       chtype = MBSTRING_UTF8;
+               else if (strcmp(*argv,"-create_serial") == 0)
+                       create_ser = 1;
+               else if (strcmp(*argv,"-multivalue-rdn") == 0)
+                       multirdn=1;
                else if (strcmp(*argv,"-startdate") == 0)
                        {
                        if (--argc < 1) goto bad;
                else if (strcmp(*argv,"-startdate") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -388,6 +422,8 @@ EF_ALIGNMENT=0;
                        if (--argc < 1) goto bad;
                        certfile= *(++argv);
                        }
                        if (--argc < 1) goto bad;
                        certfile= *(++argv);
                        }
+               else if (strcmp(*argv,"-selfsign") == 0)
+                       selfsign=1;
                else if (strcmp(*argv,"-in") == 0)
                        {
                        if (--argc < 1) goto bad;
                else if (strcmp(*argv,"-in") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -404,12 +440,23 @@ EF_ALIGNMENT=0;
                        if (--argc < 1) goto bad;
                        outdir= *(++argv);
                        }
                        if (--argc < 1) goto bad;
                        outdir= *(++argv);
                        }
+               else if (strcmp(*argv,"-sigopt") == 0)
+                       {
+                       if (--argc < 1)
+                               goto bad;
+                       if (!sigopts)
+                               sigopts = sk_OPENSSL_STRING_new_null();
+                       if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
+                               goto bad;
+                       }
                else if (strcmp(*argv,"-notext") == 0)
                        notext=1;
                else if (strcmp(*argv,"-batch") == 0)
                        batch=1;
                else if (strcmp(*argv,"-preserveDN") == 0)
                        preserve=1;
                else if (strcmp(*argv,"-notext") == 0)
                        notext=1;
                else if (strcmp(*argv,"-batch") == 0)
                        batch=1;
                else if (strcmp(*argv,"-preserveDN") == 0)
                        preserve=1;
+               else if (strcmp(*argv,"-noemailDN") == 0)
+                       email_dn=0;
                else if (strcmp(*argv,"-gencrl") == 0)
                        gencrl=1;
                else if (strcmp(*argv,"-msie_hack") == 0)
                else if (strcmp(*argv,"-gencrl") == 0)
                        gencrl=1;
                else if (strcmp(*argv,"-msie_hack") == 0)
@@ -424,6 +471,11 @@ EF_ALIGNMENT=0;
                        if (--argc < 1) goto bad;
                        crlhours= atol(*(++argv));
                        }
                        if (--argc < 1) goto bad;
                        crlhours= atol(*(++argv));
                        }
+               else if (strcmp(*argv,"-crlsec") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       crlsec = atol(*(++argv));
+                       }
                else if (strcmp(*argv,"-infiles") == 0)
                        {
                        argc--;
                else if (strcmp(*argv,"-infiles") == 0)
                        {
                        argc--;
@@ -449,6 +501,12 @@ EF_ALIGNMENT=0;
                        infile= *(++argv);
                        dorevoke=1;
                        }
                        infile= *(++argv);
                        dorevoke=1;
                        }
+               else if (strcmp(*argv,"-valid") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       infile= *(++argv);
+                       dorevoke=2;
+                       }
                else if (strcmp(*argv,"-extensions") == 0)
                        {
                        if (--argc < 1) goto bad;
                else if (strcmp(*argv,"-extensions") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -497,11 +555,13 @@ EF_ALIGNMENT=0;
                        rev_arg = *(++argv);
                        rev_type = REV_CA_COMPROMISE;
                        }
                        rev_arg = *(++argv);
                        rev_type = REV_CA_COMPROMISE;
                        }
+#ifndef OPENSSL_NO_ENGINE
                else if (strcmp(*argv,"-engine") == 0)
                        {
                        if (--argc < 1) goto bad;
                        engine= *(++argv);
                        }
                else if (strcmp(*argv,"-engine") == 0)
                        {
                        if (--argc < 1) goto bad;
                        engine= *(++argv);
                        }
+#endif
                else
                        {
 bad:
                else
                        {
 bad:
@@ -515,51 +575,41 @@ bad:
 
        if (badops)
                {
 
        if (badops)
                {
-               for (pp=ca_usage; (*pp != NULL); pp++)
-                       BIO_printf(bio_err,"%s",*pp);
+               const char **pp2;
+
+               for (pp2=ca_usage; (*pp2 != NULL); pp2++)
+                       BIO_printf(bio_err,"%s",*pp2);
                goto err;
                }
 
        ERR_load_crypto_strings();
 
                goto err;
                }
 
        ERR_load_crypto_strings();
 
-       if (engine != NULL)
-               {
-               if ((e = ENGINE_by_id(engine)) == NULL)
-                       {
-                       BIO_printf(bio_err,"invalid engine \"%s\"\n",
-                               engine);
-                       goto err;
-                       }
-               if (!ENGINE_set_default(e, ENGINE_METHOD_ALL))
-                       {
-                       BIO_printf(bio_err,"can't use that engine\n");
-                       goto err;
-                       }
-               BIO_printf(bio_err,"engine \"%s\" set.\n", engine);
-               /* Free our "structural" reference. */
-               ENGINE_free(e);
-               }
-
        /*****************************************************************/
        /*****************************************************************/
+       tofree=NULL;
        if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
        if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
        if (configfile == NULL)
                {
        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));
+               const char *s=X509_get_default_cert_area();
+               size_t len;
+
+#ifdef OPENSSL_SYS_VMS
+               len = strlen(s)+sizeof(CONFIG_FILE);
+               tofree=OPENSSL_malloc(len);
+               strcpy(tofree,s);
 #else
 #else
-               strncpy(buf[0],X509_get_default_cert_area(),
-                       sizeof(buf[0])-2-sizeof(CONFIG_FILE));
-               strcat(buf[0],"/");
+               len = strlen(s)+sizeof(CONFIG_FILE)+1;
+               tofree=OPENSSL_malloc(len);
+               BUF_strlcpy(tofree,s,len);
+               BUF_strlcat(tofree,"/",len);
 #endif
 #endif
-               strcat(buf[0],CONFIG_FILE);
-               configfile=buf[0];
+               BUF_strlcat(tofree,CONFIG_FILE,len);
+               configfile=tofree;
                }
 
        BIO_printf(bio_err,"Using configuration from %s\n",configfile);
                }
 
        BIO_printf(bio_err,"Using configuration from %s\n",configfile);
-       if ((conf=CONF_load(NULL,configfile,&errorline)) == NULL)
+       conf = NCONF_new(NULL);
+       if (NCONF_load(conf,configfile,&errorline) <= 0)
                {
                if (errorline <= 0)
                        BIO_printf(bio_err,"error loading the config file '%s'\n",
                {
                if (errorline <= 0)
                        BIO_printf(bio_err,"error loading the config file '%s'\n",
@@ -569,11 +619,23 @@ bad:
                                ,errorline,configfile);
                goto err;
                }
                                ,errorline,configfile);
                goto err;
                }
+       if(tofree)
+               {
+               OPENSSL_free(tofree);
+               tofree = NULL;
+               }
+
+       if (!load_config(bio_err, conf))
+               goto err;
+
+#ifndef OPENSSL_NO_ENGINE
+       e = setup_engine(bio_err, engine, 0);
+#endif
 
        /* Lets get the config section we are using */
        if (section == NULL)
                {
 
        /* Lets get the config section we are using */
        if (section == NULL)
                {
-               section=CONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
+               section=NCONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
                if (section == NULL)
                        {
                        lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
                if (section == NULL)
                        {
                        lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
@@ -583,7 +645,7 @@ bad:
 
        if (conf != NULL)
                {
 
        if (conf != NULL)
                {
-               p=CONF_get_string(conf,NULL,"oid_file");
+               p=NCONF_get_string(conf,NULL,"oid_file");
                if (p == NULL)
                        ERR_clear_error();
                if (p != NULL)
                if (p == NULL)
                        ERR_clear_error();
                if (p != NULL)
@@ -612,10 +674,47 @@ bad:
                        }
                }
 
                        }
                }
 
-       randfile = CONF_get_string(conf, BASE_SECTION, "RANDFILE");
+       randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
        if (randfile == NULL)
                ERR_clear_error();
        app_RAND_load_file(randfile, bio_err, 0);
        if (randfile == NULL)
                ERR_clear_error();
        app_RAND_load_file(randfile, bio_err, 0);
+
+       f = NCONF_get_string(conf, section, STRING_MASK);
+       if (!f)
+               ERR_clear_error();
+
+       if(f && !ASN1_STRING_set_default_mask_asc(f)) {
+               BIO_printf(bio_err, "Invalid global string mask setting %s\n", f);
+               goto err;
+       }
+
+       if (chtype != MBSTRING_UTF8){
+               f = NCONF_get_string(conf, section, UTF8_IN);
+               if (!f)
+                       ERR_clear_error();
+               else if (!strcmp(f, "yes"))
+                       chtype = MBSTRING_UTF8;
+       }
+
+       db_attr.unique_subject = 1;
+       p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT);
+       if (p)
+               {
+#ifdef RL_DEBUG
+               BIO_printf(bio_err, "DEBUG: unique_subject = \"%s\"\n", p);
+#endif
+               db_attr.unique_subject = parse_yesno(p,1);
+               }
+       else
+               ERR_clear_error();
+#ifdef RL_DEBUG
+       if (!p)
+               BIO_printf(bio_err, "DEBUG: unique_subject undefined\n", p);
+#endif
+#ifdef RL_DEBUG
+       BIO_printf(bio_err, "DEBUG: configured unique_subject is %d\n",
+               db_attr.unique_subject);
+#endif
        
        in=BIO_new(BIO_s_file());
        out=BIO_new(BIO_s_file());
        
        in=BIO_new(BIO_s_file());
        out=BIO_new(BIO_s_file());
@@ -631,29 +730,15 @@ bad:
        /* report status of cert with serial number given on command line */
        if (ser_status)
        {
        /* report status of cert with serial number given on command line */
        if (ser_status)
        {
-               if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL)
+               if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
                        {
                        lookup_fail(section,ENV_DATABASE);
                        goto err;
                        }
                        {
                        lookup_fail(section,ENV_DATABASE);
                        goto err;
                        }
-               if (BIO_read_filename(in,dbfile) <= 0)
-                       {
-                       perror(dbfile);
-                       BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
-                       goto err;
-                       }
-               db=TXT_DB_read(in,DB_NUMBER);
+               db = load_index(dbfile,&db_attr);
                if (db == NULL) goto err;
 
                if (db == NULL) goto err;
 
-               if (!TXT_DB_create_index(db, DB_serial, NULL,
-                                       LHASH_HASH_FN(index_serial_hash),
-                                       LHASH_COMP_FN(index_serial_cmp)))
-                       {
-                       BIO_printf(bio_err,
-                         "error creating serial number index:(%ld,%ld,%ld)\n",
-                                               db->error,db->arg1,db->arg2);
-                       goto err;
-                       }
+               if (!index_index(db)) goto err;
 
                if (get_certificate_status(ser_status,db) != 1)
                        BIO_printf(bio_err,"Error verifying serial %s!\n",
 
                if (get_certificate_status(ser_status,db) != 1)
                        BIO_printf(bio_err,"Error verifying serial %s!\n",
@@ -662,101 +747,121 @@ bad:
        }
 
        /*****************************************************************/
        }
 
        /*****************************************************************/
-       /* we definitely need a public key, so let's get it */
+       /* we definitely need a private key, so let's get it */
 
 
-       if ((keyfile == NULL) && ((keyfile=CONF_get_string(conf,
+       if ((keyfile == NULL) && ((keyfile=NCONF_get_string(conf,
                section,ENV_PRIVATE_KEY)) == NULL))
                {
                lookup_fail(section,ENV_PRIVATE_KEY);
                goto err;
                }
                section,ENV_PRIVATE_KEY)) == NULL))
                {
                lookup_fail(section,ENV_PRIVATE_KEY);
                goto err;
                }
-       if (!key && !app_passwd(bio_err, passargin, NULL, &key, NULL))
-               {
-               BIO_printf(bio_err,"Error getting password\n");
-               goto err;
-               }
-       if (keyform == FORMAT_ENGINE)
-               {
-               if (!e)
-                       {
-                       BIO_printf(bio_err,"no engine specified\n");
-                       goto err;
-                       }
-               pkey = ENGINE_load_private_key(e, keyfile, key);
-               }
-       else if (keyform == FORMAT_PEM)
+       if (!key)
                {
                {
-               if (BIO_read_filename(in,keyfile) <= 0)
+               free_key = 1;
+               if (!app_passwd(bio_err, passargin, NULL, &key, NULL))
                        {
                        {
-                       perror(keyfile);
-                       BIO_printf(bio_err,"trying to load CA private key\n");
+                       BIO_printf(bio_err,"Error getting password\n");
                        goto err;
                        }
                        goto err;
                        }
-               pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,key);
-               }
-       else
-               {
-               BIO_printf(bio_err,"bad input format specified for key file\n");
-               goto err;
                }
                }
-       if (key) memset(key,0,strlen(key));
+       pkey = load_key(bio_err, keyfile, keyform, 0, key, e, 
+               "CA private key");
+       if (key) OPENSSL_cleanse(key,strlen(key));
        if (pkey == NULL)
                {
        if (pkey == NULL)
                {
-               BIO_printf(bio_err,"unable to load CA private key\n");
+               /* load_key() has already printed an appropriate message */
                goto err;
                }
 
        /*****************************************************************/
        /* we need a certificate */
                goto err;
                }
 
        /*****************************************************************/
        /* we need a certificate */
-       if ((certfile == NULL) && ((certfile=CONF_get_string(conf,
-               section,ENV_CERTIFICATE)) == NULL))
-               {
-               lookup_fail(section,ENV_CERTIFICATE);
-               goto err;
-               }
-        if (BIO_read_filename(in,certfile) <= 0)
-               {
-               perror(certfile);
-               BIO_printf(bio_err,"trying to load CA certificate\n");
-               goto err;
-               }
-       x509=PEM_read_bio_X509(in,NULL,NULL,NULL);
-       if (x509 == NULL)
+       if (!selfsign || spkac_file || ss_cert_file || gencrl)
                {
                {
-               BIO_printf(bio_err,"unable to load CA certificate\n");
-               goto err;
-               }
+               if ((certfile == NULL)
+                       && ((certfile=NCONF_get_string(conf,
+                                    section,ENV_CERTIFICATE)) == NULL))
+                       {
+                       lookup_fail(section,ENV_CERTIFICATE);
+                       goto err;
+                       }
+               x509=load_cert(bio_err, certfile, FORMAT_PEM, NULL, e,
+                       "CA certificate");
+               if (x509 == NULL)
+                       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;
+               if (!X509_check_private_key(x509,pkey))
+                       {
+                       BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
+                       goto err;
+                       }
                }
                }
+       if (!selfsign) x509p = x509;
 
 
-       f=CONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
+       f=NCONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
        if (f == NULL)
                ERR_clear_error();
        if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
                preserve=1;
        if (f == NULL)
                ERR_clear_error();
        if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
                preserve=1;
-       f=CONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
+       f=NCONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
        if (f == NULL)
                ERR_clear_error();
        if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
                msie_hack=1;
 
        if (f == NULL)
                ERR_clear_error();
        if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
                msie_hack=1;
 
+       f=NCONF_get_string(conf,section,ENV_NAMEOPT);
+
+       if (f)
+               {
+               if (!set_name_ex(&nameopt, f))
+                       {
+                       BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f);
+                       goto err;
+                       }
+               default_op = 0;
+               }
+       else
+               ERR_clear_error();
+
+       f=NCONF_get_string(conf,section,ENV_CERTOPT);
+
+       if (f)
+               {
+               if (!set_cert_ex(&certopt, f))
+                       {
+                       BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f);
+                       goto err;
+                       }
+               default_op = 0;
+               }
+       else
+               ERR_clear_error();
+
+       f=NCONF_get_string(conf,section,ENV_EXTCOPY);
+
+       if (f)
+               {
+               if (!set_ext_copy(&ext_copy, f))
+                       {
+                       BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f);
+                       goto err;
+                       }
+               }
+       else
+               ERR_clear_error();
+
        /*****************************************************************/
        /* lookup where to write new certificates */
        if ((outdir == NULL) && (req))
                {
        /*****************************************************************/
        /* lookup where to write new certificates */
        if ((outdir == NULL) && (req))
                {
-               struct stat sb;
 
 
-               if ((outdir=CONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
+               if ((outdir=NCONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
                        == NULL)
                        {
                        BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
                        goto err;
                        }
                        == NULL)
                        {
                        BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
                        goto err;
                        }
-#ifndef VMS /* outdir is a directory spec, but access() for VMS demands a
+#ifndef OPENSSL_SYS_VMS
+           /* outdir is a directory spec, but access() for VMS demands a
               filename.  In any case, stat(), below, will catch the problem
               if outdir is not a directory spec, and the fopen() or open()
               will catch an error if there is no write access.
               filename.  In any case, stat(), below, will catch the problem
               if outdir is not a directory spec, and the fopen() or open()
               will catch an error if there is no write access.
@@ -765,51 +870,41 @@ bad:
               C routines to convert the directory syntax to Unixly, and give
               that to access().  However, time's too short to do that just
               now.
               C routines to convert the directory syntax to Unixly, and give
               that to access().  However, time's too short to do that just
               now.
-            */
+           */
+#ifndef _WIN32
                if (access(outdir,R_OK|W_OK|X_OK) != 0)
                if (access(outdir,R_OK|W_OK|X_OK) != 0)
+#else
+               if (_access(outdir,R_OK|W_OK|X_OK) != 0)
+#endif
                        {
                        BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
                        perror(outdir);
                        goto err;
                        }
 
                        {
                        BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
                        perror(outdir);
                        goto err;
                        }
 
-               if (stat(outdir,&sb) != 0)
-                       {
-                       BIO_printf(bio_err,"unable to stat(%s)\n",outdir);
-                       perror(outdir);
-                       goto err;
-                       }
-#ifdef S_IFDIR
-               if (!(sb.st_mode & S_IFDIR))
+               if (app_isdir(outdir)<=0)
                        {
                        BIO_printf(bio_err,"%s need to be a directory\n",outdir);
                        perror(outdir);
                        goto err;
                        }
                        {
                        BIO_printf(bio_err,"%s need to be a directory\n",outdir);
                        perror(outdir);
                        goto err;
                        }
-#endif
 #endif
                }
 
        /*****************************************************************/
        /* we need to load the database file */
 #endif
                }
 
        /*****************************************************************/
        /* we need to load the database file */
-       if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL)
+       if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
                {
                lookup_fail(section,ENV_DATABASE);
                goto err;
                }
                {
                lookup_fail(section,ENV_DATABASE);
                goto err;
                }
-       if (BIO_read_filename(in,dbfile) <= 0)
-               {
-               perror(dbfile);
-               BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
-               goto err;
-               }
-       db=TXT_DB_read(in,DB_NUMBER);
+       db = load_index(dbfile, &db_attr);
        if (db == NULL) goto err;
 
        /* Lets check some fields */
        if (db == NULL) goto err;
 
        /* Lets check some fields */
-       for (i=0; i<sk_num(db->data); i++)
+       for (i=0; i<sk_OPENSSL_PSTRING_num(db->db->data); i++)
                {
                {
-               pp=(char **)sk_value(db->data,i);
+               pp=sk_OPENSSL_PSTRING_value(db->db->data,i);
                if ((pp[DB_type][0] != DB_TYPE_REV) &&
                        (pp[DB_rev_date][0] != '\0'))
                        {
                if ((pp[DB_type][0] != DB_TYPE_REV) &&
                        (pp[DB_rev_date][0] != '\0'))
                        {
@@ -822,13 +917,18 @@ bad:
                        BIO_printf(bio_err," in entry %d\n", i+1);
                        goto err;
                        }
                        BIO_printf(bio_err," in entry %d\n", i+1);
                        goto err;
                        }
-               if (!check_time_format(pp[DB_exp_date]))
+               if (!check_time_format((char *)pp[DB_exp_date]))
                        {
                        BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
                        goto err;
                        }
                p=pp[DB_serial];
                j=strlen(p);
                        {
                        BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
                        goto err;
                        }
                p=pp[DB_serial];
                j=strlen(p);
+               if (*p == '-')
+                       {
+                       p++;
+                       j--;
+                       }
                if ((j&1) || (j < 2))
                        {
                        BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
                if ((j&1) || (j < 2))
                        {
                        BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
@@ -849,34 +949,19 @@ bad:
        if (verbose)
                {
                BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
        if (verbose)
                {
                BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
-#ifdef VMS
+#ifdef OPENSSL_SYS_VMS
                {
                BIO *tmpbio = BIO_new(BIO_f_linebuffer());
                out = BIO_push(tmpbio, out);
                }
 #endif
                {
                BIO *tmpbio = BIO_new(BIO_f_linebuffer());
                out = BIO_push(tmpbio, out);
                }
 #endif
-               TXT_DB_write(out,db);
+               TXT_DB_write(out,db->db);
                BIO_printf(bio_err,"%d entries loaded from the database\n",
                BIO_printf(bio_err,"%d entries loaded from the database\n",
-                       db->data->num);
+                          sk_OPENSSL_PSTRING_num(db->db->data));
                BIO_printf(bio_err,"generating index\n");
                }
        
                BIO_printf(bio_err,"generating index\n");
                }
        
-       if (!TXT_DB_create_index(db, DB_serial, NULL,
-                       LHASH_HASH_FN(index_serial_hash),
-                       LHASH_COMP_FN(index_serial_cmp)))
-               {
-               BIO_printf(bio_err,"error creating serial number index:(%ld,%ld,%ld)\n",db->error,db->arg1,db->arg2);
-               goto err;
-               }
-
-       if (!TXT_DB_create_index(db, DB_name, index_name_qual,
-                       LHASH_HASH_FN(index_name_hash),
-                       LHASH_COMP_FN(index_name_cmp)))
-               {
-               BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
-                       db->error,db->arg1,db->arg2);
-               goto err;
-               }
+       if (!index_index(db)) goto err;
 
        /*****************************************************************/
        /* Update the db file for expired certificates */
 
        /*****************************************************************/
        /* Update the db file for expired certificates */
@@ -891,74 +976,29 @@ bad:
                        {
                        BIO_printf(bio_err,"Malloc failure\n");
                        goto err;
                        {
                        BIO_printf(bio_err,"Malloc failure\n");
                        goto err;
-                       }
+                       }
                else if (i == 0)
                else if (i == 0)
-                       {
+                       {
                        if (verbose) BIO_printf(bio_err,
                                        "No entries found to mark expired\n"); 
                        }
                else
                        {
                        if (verbose) BIO_printf(bio_err,
                                        "No entries found to mark expired\n"); 
                        }
                else
                        {
-                       out = BIO_new(BIO_s_file());
-                       if (out == NULL)
-                               {
-                               ERR_print_errors(bio_err);
-                               goto err;
-                               }
-
-                       j = BIO_snprintf(buf[0], sizeof buf[0], "%s.new", dbfile);
-                       if (j < 0 || j >= sizeof buf[0])
-                               {
-                               BIO_printf(bio_err, "file name too long\n");
-                               goto err;
-                               }
-                       if (BIO_write_filename(out,buf[0]) <= 0)
-                               {
-                               perror(dbfile);
-                               BIO_printf(bio_err,"unable to open '%s'\n",
-                                                                       dbfile);
-                               goto err;
-                               }
-                       j=TXT_DB_write(out,db);
-                       if (j <= 0) goto err;
-                       
-                       BIO_free(out);
-                       out = NULL;
-                       j = BIO_snprintf(buf[1], sizeof buf[1], "%s.old", dbfile);
-                       if (j < 0 || j >= sizeof buf[1])
-                               {
-                               BIO_printf(bio_err, "file name too long\n");
-                               goto err;
-                               }
-                       if (rename(dbfile,buf[1]) < 0)
-                               {
-                               BIO_printf(bio_err,
-                                               "unable to rename %s to %s\n",
-                                               dbfile, buf[1]);
-                               perror("reason");
-                               goto err;
-                               }
-                       if (rename(buf[0],dbfile) < 0)
-                               {
-                               BIO_printf(bio_err,
-                                               "unable to rename %s to %s\n",
-                                               buf[0],dbfile);
-                               perror("reason");
-                               rename(buf[1],dbfile);
-                               goto err;
-                               }
+                       if (!save_index(dbfile,"new",db)) goto err;
+                               
+                       if (!rotate_index(dbfile,"new","old")) goto err;
                                
                        if (verbose) BIO_printf(bio_err,
                                "Done. %d entries marked as expired\n",i); 
                        }
                                
                        if (verbose) BIO_printf(bio_err,
                                "Done. %d entries marked as expired\n",i); 
                        }
-                       goto err;
                }
 
        /*****************************************************************/
                }
 
        /*****************************************************************/
-       /* Read extentions config file                                   */
+       /* Read extensions config file                                   */
        if (extfile)
                {
        if (extfile)
                {
-               if (!(extconf=CONF_load(NULL,extfile,&errorline)))
+               extconf = NCONF_new(NULL);
+               if (NCONF_load(extconf,extfile,&errorline) <= 0)
                        {
                        if (errorline <= 0)
                                BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
                        {
                        if (errorline <= 0)
                                BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
@@ -971,12 +1011,12 @@ bad:
                        }
 
                if (verbose)
                        }
 
                if (verbose)
-                       BIO_printf(bio_err, "Succesfully loaded extensions file %s\n", extfile);
+                       BIO_printf(bio_err, "Successfully loaded extensions file %s\n", extfile);
 
                /* We can have sections in the ext file */
 
                /* We can have sections in the ext file */
-               if (!extensions && !(extensions = CONF_get_string(extconf, "default", "extensions")))
+               if (!extensions && !(extensions = NCONF_get_string(extconf, "default", "extensions")))
                        extensions = "default";
                        extensions = "default";
-                }
+               }
 
        /*****************************************************************/
        if (req || gencrl)
 
        /*****************************************************************/
        if (req || gencrl)
@@ -992,7 +1032,7 @@ bad:
                else
                        {
                        BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
                else
                        {
                        BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
-#ifdef VMS
+#ifdef OPENSSL_SYS_VMS
                        {
                        BIO *tmpbio = BIO_new(BIO_f_linebuffer());
                        Sout = BIO_push(tmpbio, Sout);
                        {
                        BIO *tmpbio = BIO_new(BIO_f_linebuffer());
                        Sout = BIO_push(tmpbio, Sout);
@@ -1001,23 +1041,42 @@ bad:
                        }
                }
 
                        }
                }
 
-       if (req)
+       if ((md == NULL) && ((md=NCONF_get_string(conf,
+               section,ENV_DEFAULT_MD)) == NULL))
+               {
+               lookup_fail(section,ENV_DEFAULT_MD);
+               goto err;
+               }
+
+       if (!strcmp(md, "default"))
                {
                {
-               if ((md == NULL) && ((md=CONF_get_string(conf,
-                       section,ENV_DEFAULT_MD)) == NULL))
+               int def_nid;
+               if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0)
                        {
                        {
-                       lookup_fail(section,ENV_DEFAULT_MD);
+                       BIO_puts(bio_err,"no default digest\n");
                        goto err;
                        }
                        goto err;
                        }
-               if ((dgst=EVP_get_digestbyname(md)) == NULL)
+               md = (char *)OBJ_nid2sn(def_nid);
+               }
+
+       if ((dgst=EVP_get_digestbyname(md)) == NULL)
+               {
+               BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
+               goto err;
+               }
+
+       if (req)
+               {
+               if ((email_dn == 1) && ((tmp_email_dn=NCONF_get_string(conf,
+                       section,ENV_DEFAULT_EMAIL_DN)) != NULL ))
                        {
                        {
-                       BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
-                       goto err;
+                       if(strcmp(tmp_email_dn,"no") == 0)
+                               email_dn=0;
                        }
                if (verbose)
                        BIO_printf(bio_err,"message digest is %s\n",
                                OBJ_nid2ln(dgst->type));
                        }
                if (verbose)
                        BIO_printf(bio_err,"message digest is %s\n",
                                OBJ_nid2ln(dgst->type));
-               if ((policy == NULL) && ((policy=CONF_get_string(conf,
+               if ((policy == NULL) && ((policy=NCONF_get_string(conf,
                        section,ENV_POLICY)) == NULL))
                        {
                        lookup_fail(section,ENV_POLICY);
                        section,ENV_POLICY)) == NULL))
                        {
                        lookup_fail(section,ENV_POLICY);
@@ -1026,7 +1085,7 @@ bad:
                if (verbose)
                        BIO_printf(bio_err,"policy is %s\n",policy);
 
                if (verbose)
                        BIO_printf(bio_err,"policy is %s\n",policy);
 
-               if ((serialfile=CONF_get_string(conf,section,ENV_SERIAL))
+               if ((serialfile=NCONF_get_string(conf,section,ENV_SERIAL))
                        == NULL)
                        {
                        lookup_fail(section,ENV_SERIAL);
                        == NULL)
                        {
                        lookup_fail(section,ENV_SERIAL);
@@ -1039,7 +1098,7 @@ bad:
                         * in the main configuration file */
                        if (!extensions)
                                {
                         * in the main configuration file */
                        if (!extensions)
                                {
-                               extensions=CONF_get_string(conf,section,
+                               extensions=NCONF_get_string(conf,section,
                                                                ENV_EXTENSIONS);
                                if (!extensions)
                                        ERR_clear_error();
                                                                ENV_EXTENSIONS);
                                if (!extensions)
                                        ERR_clear_error();
@@ -1049,8 +1108,8 @@ bad:
                                /* Check syntax of file */
                                X509V3_CTX ctx;
                                X509V3_set_ctx_test(&ctx);
                                /* 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,
+                               X509V3_set_nconf(&ctx, conf);
+                               if (!X509V3_EXT_add_nconf(conf, &ctx, extensions,
                                                                NULL))
                                        {
                                        BIO_printf(bio_err,
                                                                NULL))
                                        {
                                        BIO_printf(bio_err,
@@ -1064,35 +1123,35 @@ bad:
 
                if (startdate == NULL)
                        {
 
                if (startdate == NULL)
                        {
-                       startdate=CONF_get_string(conf,section,
+                       startdate=NCONF_get_string(conf,section,
                                ENV_DEFAULT_STARTDATE);
                        if (startdate == NULL)
                                ERR_clear_error();
                        }
                                ENV_DEFAULT_STARTDATE);
                        if (startdate == NULL)
                                ERR_clear_error();
                        }
-               if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
+               if (startdate && !ASN1_TIME_set_string(NULL, startdate))
                        {
                        {
-                       BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
+                       BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
                        goto err;
                        }
                if (startdate == NULL) startdate="today";
 
                if (enddate == NULL)
                        {
                        goto err;
                        }
                if (startdate == NULL) startdate="today";
 
                if (enddate == NULL)
                        {
-                       enddate=CONF_get_string(conf,section,
+                       enddate=NCONF_get_string(conf,section,
                                ENV_DEFAULT_ENDDATE);
                        if (enddate == NULL)
                                ERR_clear_error();
                        }
                                ENV_DEFAULT_ENDDATE);
                        if (enddate == NULL)
                                ERR_clear_error();
                        }
-               if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
+               if (enddate && !ASN1_TIME_set_string(NULL, enddate))
                        {
                        {
-                       BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
+                       BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
                        goto err;
                        }
 
                if (days == 0)
                        {
                        goto err;
                        }
 
                if (days == 0)
                        {
-                       days=(int)CONF_get_number(conf,section,
-                               ENV_DEFAULT_DAYS);
+                       if(!NCONF_get_number(conf,section, ENV_DEFAULT_DAYS, &days))
+                               days = 0;
                        }
                if (!enddate && (days == 0))
                        {
                        }
                if (!enddate && (days == 0))
                        {
@@ -1100,19 +1159,24 @@ bad:
                        goto err;
                        }
 
                        goto err;
                        }
 
-               if ((serial=load_serial(serialfile)) == NULL)
+               if ((serial=load_serial(serialfile, create_ser, NULL)) == NULL)
                        {
                        BIO_printf(bio_err,"error while loading serial number\n");
                        goto err;
                        }
                if (verbose)
                        {
                        {
                        BIO_printf(bio_err,"error while loading serial number\n");
                        goto err;
                        }
                if (verbose)
                        {
-                       if ((f=BN_bn2hex(serial)) == NULL) goto err;
-                       BIO_printf(bio_err,"next serial number is %s\n",f);
-                       OPENSSL_free(f);
+                       if (BN_is_zero(serial))
+                               BIO_printf(bio_err,"next serial number is 00\n");
+                       else
+                               {
+                               if ((f=BN_bn2hex(serial)) == NULL) goto err;
+                               BIO_printf(bio_err,"next serial number is %s\n",f);
+                               OPENSSL_free(f);
+                               }
                        }
 
                        }
 
-               if ((attribs=CONF_get_section(conf,policy)) == NULL)
+               if ((attribs=NCONF_get_section(conf,policy)) == NULL)
                        {
                        BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
                        goto err;
                        {
                        BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
                        goto err;
@@ -1126,9 +1190,10 @@ bad:
                if (spkac_file != NULL)
                        {
                        total++;
                if (spkac_file != NULL)
                        {
                        total++;
-                       j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
-                               serial,startdate,enddate, days,extensions,conf,
-                               verbose);
+                       j=certify_spkac(&x,spkac_file,pkey,x509,dgst,sigopts,
+                               attribs,db, serial,subj,chtype,multirdn,
+                               email_dn,startdate,enddate,days,extensions,
+                               conf,verbose,certopt,nameopt,default_op,ext_copy);
                        if (j < 0) goto err;
                        if (j > 0)
                                {
                        if (j < 0) goto err;
                        if (j > 0)
                                {
@@ -1150,9 +1215,11 @@ bad:
                if (ss_cert_file != NULL)
                        {
                        total++;
                if (ss_cert_file != NULL)
                        {
                        total++;
-                       j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
-                               db,serial,startdate,enddate,days,batch,
-                               extensions,conf,verbose);
+                       j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,sigopts,
+                               attribs,
+                               db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
+                               extensions,conf,verbose, certopt, nameopt,
+                               default_op, ext_copy, e);
                        if (j < 0) goto err;
                        if (j > 0)
                                {
                        if (j < 0) goto err;
                        if (j > 0)
                                {
@@ -1169,9 +1236,10 @@ bad:
                if (infile != NULL)
                        {
                        total++;
                if (infile != NULL)
                        {
                        total++;
-                       j=certify(&x,infile,pkey,x509,dgst,attribs,db,
-                               serial,startdate,enddate,days,batch,
-                               extensions,conf,verbose);
+                       j=certify(&x,infile,pkey,x509p,dgst,sigopts, attribs,db,
+                               serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
+                               extensions,conf,verbose, certopt, nameopt,
+                               default_op, ext_copy, selfsign);
                        if (j < 0) goto err;
                        if (j > 0)
                                {
                        if (j < 0) goto err;
                        if (j > 0)
                                {
@@ -1188,9 +1256,10 @@ bad:
                for (i=0; i<argc; i++)
                        {
                        total++;
                for (i=0; i<argc; i++)
                        {
                        total++;
-                       j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
-                               serial,startdate,enddate,days,batch,
-                               extensions,conf,verbose);
+                       j=certify(&x,argv[i],pkey,x509p,dgst,sigopts,attribs,db,
+                               serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
+                               extensions,conf,verbose, certopt, nameopt,
+                               default_op, ext_copy, selfsign);
                        if (j < 0) goto err;
                        if (j > 0)
                                {
                        if (j < 0) goto err;
                        if (j > 0)
                                {
@@ -1215,7 +1284,12 @@ bad:
                                BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
                                (void)BIO_flush(bio_err);
                                buf[0][0]='\0';
                                BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
                                (void)BIO_flush(bio_err);
                                buf[0][0]='\0';
-                               fgets(buf[0],10,stdin);
+                               if (!fgets(buf[0],10,stdin))
+                                       {
+                                       BIO_printf(bio_err,"CERTIFICATION CANCELED: I/O error\n"); 
+                                       ret=0;
+                                       goto err;
+                                       }
                                if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
                                        {
                                        BIO_printf(bio_err,"CERTIFICATION CANCELED\n"); 
                                if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
                                        {
                                        BIO_printf(bio_err,"CERTIFICATION CANCELED\n"); 
@@ -1226,32 +1300,9 @@ bad:
 
                        BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
 
 
                        BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
 
-                       strncpy(buf[0],serialfile,BSIZE-4);
-
-#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 (!save_serial(serialfile,"new",serial,NULL)) goto err;
 
 
-                       if (BIO_write_filename(out,buf[1]) <= 0)
-                               {
-                               perror(dbfile);
-                               BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
-                               goto err;
-                               }
-                       l=TXT_DB_write(out,db);
-                       if (l <= 0) goto err;
+                       if (!save_index(dbfile, "new", db)) goto err;
                        }
        
                if (verbose)
                        }
        
                if (verbose)
@@ -1259,25 +1310,35 @@ bad:
                for (i=0; i<sk_X509_num(cert_sk); i++)
                        {
                        int k;
                for (i=0; i<sk_X509_num(cert_sk); i++)
                        {
                        int k;
-                       unsigned char *n;
+                       char *n;
 
                        x=sk_X509_value(cert_sk,i);
 
                        j=x->cert_info->serialNumber->length;
 
                        x=sk_X509_value(cert_sk,i);
 
                        j=x->cert_info->serialNumber->length;
-                       p=(char *)x->cert_info->serialNumber->data;
+                       p=(const char *)x->cert_info->serialNumber->data;
                        
                        
-                       strncpy(buf[2],outdir,BSIZE-(j*2)-6);
+                       if(strlen(outdir) >= (size_t)(j ? BSIZE-j*2-6 : BSIZE-8))
+                               {
+                               BIO_printf(bio_err,"certificate file name too long\n");
+                               goto err;
+                               }
 
 
-#ifndef VMS
-                       strcat(buf[2],"/");
+                       strcpy(buf[2],outdir);
+
+#ifndef OPENSSL_SYS_VMS
+                       BUF_strlcat(buf[2],"/",sizeof(buf[2]));
 #endif
 
 #endif
 
-                       n=(unsigned char *)&(buf[2][strlen(buf[2])]);
+                       n=(char *)&(buf[2][strlen(buf[2])]);
                        if (j > 0)
                                {
                                for (k=0; k<j; k++)
                                        {
                        if (j > 0)
                                {
                                for (k=0; k<j; k++)
                                        {
-                                       sprintf((char *)n,"%02X",(unsigned char)*(p++));
+                                       if (n >= &(buf[2][sizeof(buf[2])]))
+                                               break;
+                                       BIO_snprintf(n,
+                                                    &buf[2][0] + sizeof(buf[2]) - n,
+                                                    "%02X",(unsigned char)*(p++));
                                        n+=2;
                                        }
                                }
                                        n+=2;
                                        }
                                }
@@ -1303,57 +1364,10 @@ bad:
                if (sk_X509_num(cert_sk))
                        {
                        /* Rename the database and the serial file */
                if (sk_X509_num(cert_sk))
                        {
                        /* 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_all(out);
-                       in=NULL;
-                       out=NULL;
-                       if (rename(serialfile,buf[2]) < 0)
-                               {
-                               BIO_printf(bio_err,"unable to rename %s to %s\n",
-                                       serialfile,buf[2]);
-                               perror("reason");
-                               goto err;
-                               }
-                       if (rename(buf[0],serialfile) < 0)
-                               {
-                               BIO_printf(bio_err,"unable to rename %s to %s\n",
-                                       buf[0],serialfile);
-                               perror("reason");
-                               rename(buf[2],serialfile);
-                               goto err;
-                               }
-
-                       strncpy(buf[2],dbfile,BSIZE-4);
+                       if (!rotate_serial(serialfile,"new","old")) goto err;
 
 
-#ifdef VMS
-                       strcat(buf[2],"-old");
-#else
-                       strcat(buf[2],".old");
-#endif
+                       if (!rotate_index(dbfile,"new","old")) goto err;
 
 
-                       if (rename(dbfile,buf[2]) < 0)
-                               {
-                               BIO_printf(bio_err,"unable to rename %s to %s\n",
-                                       dbfile,buf[2]);
-                               perror("reason");
-                               goto err;
-                               }
-                       if (rename(buf[1],dbfile) < 0)
-                               {
-                               BIO_printf(bio_err,"unable to rename %s to %s\n",
-                                       buf[1],dbfile);
-                               perror("reason");
-                               rename(buf[2],dbfile);
-                               goto err;
-                               }
                        BIO_printf(bio_err,"Data Base Updated\n");
                        }
                }
                        BIO_printf(bio_err,"Data Base Updated\n");
                        }
                }
@@ -1364,7 +1378,7 @@ bad:
                int crl_v2 = 0;
                if (!crl_ext)
                        {
                int crl_v2 = 0;
                if (!crl_ext)
                        {
-                       crl_ext=CONF_get_string(conf,section,ENV_CRLEXT);
+                       crl_ext=NCONF_get_string(conf,section,ENV_CRLEXT);
                        if (!crl_ext)
                                ERR_clear_error();
                        }
                        if (!crl_ext)
                                ERR_clear_error();
                        }
@@ -1373,8 +1387,8 @@ bad:
                        /* Check syntax of file */
                        X509V3_CTX ctx;
                        X509V3_set_ctx_test(&ctx);
                        /* 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))
+                       X509V3_set_nconf(&ctx, conf);
+                       if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL))
                                {
                                BIO_printf(bio_err,
                                 "Error Loading CRL extension section %s\n",
                                {
                                BIO_printf(bio_err,
                                 "Error Loading CRL extension section %s\n",
@@ -1383,103 +1397,122 @@ bad:
                                goto err;
                                }
                        }
                                goto err;
                                }
                        }
-               if ((hex=BIO_new(BIO_s_mem())) == NULL) goto err;
 
 
-               if (!crldays && !crlhours)
+               if ((crlnumberfile=NCONF_get_string(conf,section,ENV_CRLNUMBER))
+                       != NULL)
+                       if ((crlnumber=load_serial(crlnumberfile,0,NULL)) == NULL)
+                               {
+                               BIO_printf(bio_err,"error while loading CRL number\n");
+                               goto err;
+                               }
+
+               if (!crldays && !crlhours && !crlsec)
                        {
                        {
-                       crldays=CONF_get_number(conf,section,
-                               ENV_DEFAULT_CRL_DAYS);
-                       crlhours=CONF_get_number(conf,section,
-                               ENV_DEFAULT_CRL_HOURS);
+                       if (!NCONF_get_number(conf,section,
+                               ENV_DEFAULT_CRL_DAYS, &crldays))
+                               crldays = 0;
+                       if (!NCONF_get_number(conf,section,
+                               ENV_DEFAULT_CRL_HOURS, &crlhours))
+                               crlhours = 0;
+                       ERR_clear_error();
                        }
                        }
-               if ((crldays == 0) && (crlhours == 0))
+               if ((crldays == 0) && (crlhours == 0) && (crlsec == 0))
                        {
                        {
-                       BIO_printf(bio_err,"cannot lookup how long until the next CRL is issuer\n");
+                       BIO_printf(bio_err,"cannot lookup how long until the next CRL is issued\n");
                        goto err;
                        }
 
                if (verbose) BIO_printf(bio_err,"making CRL\n");
                if ((crl=X509_CRL_new()) == NULL) goto err;
                        goto err;
                        }
 
                if (verbose) BIO_printf(bio_err,"making CRL\n");
                if ((crl=X509_CRL_new()) == NULL) goto err;
-               ci=crl->crl;
-               X509_NAME_free(ci->issuer);
-               ci->issuer=X509_NAME_dup(x509->cert_info->subject);
-               if (ci->issuer == NULL) goto err;
+               if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) goto err;
+
+               tmptm = ASN1_TIME_new();
+               if (!tmptm) goto err;
+               X509_gmtime_adj(tmptm,0);
+               X509_CRL_set_lastUpdate(crl, tmptm);    
+               if (!X509_time_adj_ex(tmptm, crldays, crlhours*60*60 + crlsec,
+                       NULL))
+                       {
+                       BIO_puts(bio_err, "error setting CRL nextUpdate\n");
+                       goto err;
+                       }
+               X509_CRL_set_nextUpdate(crl, tmptm);    
 
 
-               X509_gmtime_adj(ci->lastUpdate,0);
-               if (ci->nextUpdate == NULL)
-                       ci->nextUpdate=ASN1_UTCTIME_new();
-               X509_gmtime_adj(ci->nextUpdate,(crldays*24+crlhours)*60*60);
+               ASN1_TIME_free(tmptm);
 
 
-               for (i=0; i<sk_num(db->data); i++)
+               for (i=0; i<sk_OPENSSL_PSTRING_num(db->db->data); i++)
                        {
                        {
-                       pp=(char **)sk_value(db->data,i);
+                       pp=sk_OPENSSL_PSTRING_value(db->db->data,i);
                        if (pp[DB_type][0] == DB_TYPE_REV)
                                {
                                if ((r=X509_REVOKED_new()) == NULL) goto err;
                                j = make_revoked(r, pp[DB_rev_date]);
                                if (!j) goto err;
                                if (j == 2) crl_v2 = 1;
                        if (pp[DB_type][0] == DB_TYPE_REV)
                                {
                                if ((r=X509_REVOKED_new()) == NULL) goto err;
                                j = make_revoked(r, pp[DB_rev_date]);
                                if (!j) goto err;
                                if (j == 2) crl_v2 = 1;
-                               (void)BIO_reset(hex);
-                               if (!BIO_puts(hex,pp[DB_serial]))
+                               if (!BN_hex2bn(&serial, pp[DB_serial]))
                                        goto err;
                                        goto err;
-                               if (!a2i_ASN1_INTEGER(hex,r->serialNumber,
-                                       buf[0],BSIZE)) goto err;
-
+                               tmpser = BN_to_ASN1_INTEGER(serial, NULL);
+                               BN_free(serial);
+                               serial = NULL;
+                               if (!tmpser)
+                                       goto err;
+                               X509_REVOKED_set_serialNumber(r, tmpser);
+                               ASN1_INTEGER_free(tmpser);
                                X509_CRL_add0_revoked(crl,r);
                                }
                        }
                                X509_CRL_add0_revoked(crl,r);
                                }
                        }
+
                /* sort the data so it will be written in serial
                 * number order */
                /* sort the data so it will be written in serial
                 * number order */
-               sk_X509_REVOKED_sort(ci->revoked);
-               for (i=0; i<sk_X509_REVOKED_num(ci->revoked); i++)
-                       {
-                       r=sk_X509_REVOKED_value(ci->revoked,i);
-                       r->sequence=i;
-                       }
+               X509_CRL_sort(crl);
 
                /* we now have a CRL */
                if (verbose) BIO_printf(bio_err,"signing CRL\n");
 
                /* we now have a CRL */
                if (verbose) BIO_printf(bio_err,"signing CRL\n");
-               if (md != NULL)
-                       {
-                       if ((dgst=EVP_get_digestbyname(md)) == NULL)
-                               {
-                               BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
-                               goto err;
-                               }
-                       }
-               else
-                       {
-#ifndef NO_DSA
-                       if (pkey->type == EVP_PKEY_DSA) 
-                               dgst=EVP_dss1();
-                       else
-#endif
-                               dgst=EVP_md5();
-                       }
 
                /* Add any extensions asked for */
 
 
                /* Add any extensions asked for */
 
-               if (crl_ext)
+               if (crl_ext || crlnumberfile != NULL)
                        {
                        X509V3_CTX crlctx;
                        {
                        X509V3_CTX crlctx;
-                       if (ci->version == NULL)
-                               if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
                        X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
                        X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
-                       X509V3_set_conf_lhash(&crlctx, conf);
+                       X509V3_set_nconf(&crlctx, conf);
 
 
-                       if (!X509V3_EXT_CRL_add_conf(conf, &crlctx,
-                               crl_ext, crl)) goto err;
+                       if (crl_ext)
+                               if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx,
+                                       crl_ext, crl)) goto err;
+                       if (crlnumberfile != NULL)
+                               {
+                               tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL);
+                               if (!tmpser) goto err;
+                               X509_CRL_add1_ext_i2d(crl,NID_crl_number,tmpser,0,0);
+                               ASN1_INTEGER_free(tmpser);
+                               crl_v2 = 1;
+                               if (!BN_add_word(crlnumber,1)) goto err;
+                               }
                        }
                if (crl_ext || crl_v2)
                        {
                        }
                if (crl_ext || crl_v2)
                        {
-                       if (ci->version == NULL)
-                               if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
-                       ASN1_INTEGER_set(ci->version,1); /* version 2 CRL */
+                       if (!X509_CRL_set_version(crl, 1))
+                               goto err; /* version 2 CRL */
+                       }
+
+               
+               if (crlnumberfile != NULL)      /* we have a CRL number that need updating */
+                       if (!save_serial(crlnumberfile,"new",crlnumber,NULL)) goto err;
+
+               if (crlnumber)
+                       {
+                       BN_free(crlnumber);
+                       crlnumber = NULL;
                        }
 
                        }
 
-               if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
+               if (!do_X509_CRL_sign(bio_err,crl,pkey,dgst,sigopts)) goto err;
 
                PEM_write_bio_X509_CRL(Sout,crl);
 
                PEM_write_bio_X509_CRL(Sout,crl);
+
+               if (crlnumberfile != NULL)      /* Rename the crlnumber file */
+                       if (!rotate_serial(crlnumberfile,"new","old")) goto err;
+
                }
        /*****************************************************************/
        if (dorevoke)
                }
        /*****************************************************************/
        if (dorevoke)
@@ -1492,180 +1525,68 @@ bad:
                else
                        {
                        X509 *revcert;
                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);
+                       revcert=load_cert(bio_err, infile, FORMAT_PEM,
+                               NULL, e, infile);
                        if (revcert == NULL)
                        if (revcert == NULL)
-                               {
-                               BIO_printf(bio_err,"unable to load '%s' certificate\n",infile);
                                goto err;
                                goto err;
-                               }
+                       if (dorevoke == 2)
+                               rev_type = -1;
                        j=do_revoke(revcert,db, rev_type, rev_arg);
                        if (j <= 0) goto err;
                        X509_free(revcert);
 
                        j=do_revoke(revcert,db, rev_type, rev_arg);
                        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;
-                               }
+                       if (!save_index(dbfile, "new", db)) goto err;
+
+                       if (!rotate_index(dbfile, "new", "old")) goto err;
+
                        BIO_printf(bio_err,"Data Base Updated\n"); 
                        }
                }
        /*****************************************************************/
        ret=0;
 err:
                        BIO_printf(bio_err,"Data Base Updated\n"); 
                        }
                }
        /*****************************************************************/
        ret=0;
 err:
-       BIO_free(hex);
+       if(tofree)
+               OPENSSL_free(tofree);
        BIO_free_all(Cout);
        BIO_free_all(Sout);
        BIO_free_all(out);
        BIO_free_all(Cout);
        BIO_free_all(Sout);
        BIO_free_all(out);
-       BIO_free(in);
+       BIO_free_all(in);
 
 
-       sk_X509_pop_free(cert_sk,X509_free);
+       if (cert_sk)
+               sk_X509_pop_free(cert_sk,X509_free);
 
        if (ret) ERR_print_errors(bio_err);
        app_RAND_write_file(randfile, bio_err);
 
        if (ret) ERR_print_errors(bio_err);
        app_RAND_write_file(randfile, bio_err);
+       if (free_key && key)
+               OPENSSL_free(key);
        BN_free(serial);
        BN_free(serial);
-       TXT_DB_free(db);
+       BN_free(crlnumber);
+       free_index(db);
+       if (sigopts)
+               sk_OPENSSL_STRING_free(sigopts);
        EVP_PKEY_free(pkey);
        EVP_PKEY_free(pkey);
-       X509_free(x509);
+       if (x509) X509_free(x509);
        X509_CRL_free(crl);
        X509_CRL_free(crl);
-       CONF_free(conf);
+       NCONF_free(conf);
+       NCONF_free(extconf);
        OBJ_cleanup();
        OBJ_cleanup();
-       EXIT(ret);
+       apps_shutdown();
+       OPENSSL_EXIT(ret);
        }
 
        }
 
-static void lookup_fail(char *name, char *tag)
+static void lookup_fail(const char *name, const char *tag)
        {
        BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
        }
 
        {
        BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
        }
 
-static unsigned long index_serial_hash(const char **a)
-       {
-       const char *n;
-
-       n=a[DB_serial];
-       while (*n == '0') n++;
-       return(lh_strhash(n));
-       }
-
-static int index_serial_cmp(const char **a, const char **b)
-       {
-       const char *aa,*bb;
-
-       for (aa=a[DB_serial]; *aa == '0'; aa++);
-       for (bb=b[DB_serial]; *bb == '0'; bb++);
-       return(strcmp(aa,bb));
-       }
-
-static unsigned long index_name_hash(const char **a)
-       { return(lh_strhash(a[DB_name])); }
-
-static int index_name_qual(char **a)
-       { return(a[0][0] == 'V'); }
-
-static int index_name_cmp(const char **a, const char **b)
-       { return(strcmp(a[DB_name],
-            b[DB_name])); }
-
-static BIGNUM *load_serial(char *serialfile)
-       {
-       BIO *in=NULL;
-       BIGNUM *ret=NULL;
-       MS_STATIC char buf[1024];
-       ASN1_INTEGER *ai=NULL;
-
-       if ((in=BIO_new(BIO_s_file())) == NULL)
-               {
-               ERR_print_errors(bio_err);
-               goto err;
-               }
-
-       if (BIO_read_filename(in,serialfile) <= 0)
-               {
-               perror(serialfile);
-               goto err;
-               }
-       ai=ASN1_INTEGER_new();
-       if (ai == NULL) goto err;
-       if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
-               {
-               BIO_printf(bio_err,"unable to load number from %s\n",
-                       serialfile);
-               goto err;
-               }
-       ret=ASN1_INTEGER_to_BN(ai,NULL);
-       if (ret == NULL)
-               {
-               BIO_printf(bio_err,"error converting number from bin to BIGNUM");
-               goto err;
-               }
-err:
-       if (in != NULL) BIO_free(in);
-       if (ai != NULL) ASN1_INTEGER_free(ai);
-       return(ret);
-       }
-
-static int save_serial(char *serialfile, BIGNUM *serial)
-       {
-       BIO *out;
-       int ret=0;
-       ASN1_INTEGER *ai=NULL;
-
-       out=BIO_new(BIO_s_file());
-       if (out == NULL)
-               {
-               ERR_print_errors(bio_err);
-               goto err;
-               }
-       if (BIO_write_filename(out,serialfile) <= 0)
-               {
-               perror(serialfile);
-               goto err;
-               }
-
-       if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
-               {
-               BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
-               goto err;
-               }
-       i2a_ASN1_INTEGER(out,ai);
-       BIO_puts(out,"\n");
-       ret=1;
-err:
-       if (out != NULL) BIO_free_all(out);
-       if (ai != NULL) ASN1_INTEGER_free(ai);
-       return(ret);
-       }
-
 static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
 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)
+            const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+            STACK_OF(CONF_VALUE) *policy, CA_DB *db,
+            BIGNUM *serial, char *subj,unsigned long chtype, int multirdn,
+            int email_dn, char *startdate, char *enddate,
+            long days, int batch, char *ext_sect, CONF *lconf, int verbose,
+            unsigned long certopt, unsigned long nameopt, int default_op,
+            int ext_copy, int selfsign)
        {
        X509_REQ *req=NULL;
        BIO *in=NULL;
        {
        X509_REQ *req=NULL;
        BIO *in=NULL;
@@ -1690,6 +1611,12 @@ static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
 
        BIO_printf(bio_err,"Check that the request matches the signature\n");
 
 
        BIO_printf(bio_err,"Check that the request matches the signature\n");
 
+       if (selfsign && !X509_REQ_check_private_key(req,pkey))
+               {
+               BIO_printf(bio_err,"Certificate request and CA private key do not match\n");
+               ok=0;
+               goto err;
+               }
        if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
                {
                BIO_printf(bio_err,"error unpacking public key\n");
        if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
                {
                BIO_printf(bio_err,"error unpacking public key\n");
@@ -1712,8 +1639,10 @@ static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
        else
                BIO_printf(bio_err,"Signature ok\n");
 
        else
                BIO_printf(bio_err,"Signature ok\n");
 
-       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate, enddate,
-               days,batch,verbose,req,ext_sect,lconf);
+       ok=do_body(xret,pkey,x509,dgst,sigopts, policy,db,serial,subj,chtype,
+               multirdn, email_dn,
+               startdate,enddate,days,batch,verbose,req,ext_sect,lconf,
+               certopt, nameopt, default_op, ext_copy, selfsign);
 
 err:
        if (req != NULL) X509_REQ_free(req);
 
 err:
        if (req != NULL) X509_REQ_free(req);
@@ -1722,28 +1651,20 @@ err:
        }
 
 static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
        }
 
 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)
+            const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+            STACK_OF(CONF_VALUE) *policy, CA_DB *db,
+            BIGNUM *serial, char *subj, unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate,
+            long days, int batch, char *ext_sect, CONF *lconf, int verbose,
+            unsigned long certopt, unsigned long nameopt, int default_op,
+            int ext_copy, ENGINE *e)
        {
        X509 *req=NULL;
        X509_REQ *rreq=NULL;
        {
        X509 *req=NULL;
        X509_REQ *rreq=NULL;
-       BIO *in=NULL;
        EVP_PKEY *pktmp=NULL;
        int ok= -1,i;
 
        EVP_PKEY *pktmp=NULL;
        int ok= -1,i;
 
-       in=BIO_new(BIO_s_file());
-
-       if (BIO_read_filename(in,infile) <= 0)
-               {
-               perror(infile);
-               goto err;
-               }
-       if ((req=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
-               {
-               BIO_printf(bio_err,"Error reading self signed certificate in %s\n",infile);
+       if ((req=load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL)
                goto err;
                goto err;
-               }
        if (verbose)
                X509_print(bio_err,req);
 
        if (verbose)
                X509_print(bio_err,req);
 
@@ -1774,22 +1695,26 @@ static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
        if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
                goto err;
 
        if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
                goto err;
 
-       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,days,
-               batch,verbose,rreq,ext_sect,lconf);
+       ok=do_body(xret,pkey,x509,dgst,sigopts,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,
+               days,batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op,
+               ext_copy, 0);
 
 err:
        if (rreq != NULL) X509_REQ_free(rreq);
        if (req != NULL) X509_free(req);
 
 err:
        if (rreq != NULL) X509_REQ_free(rreq);
        if (req != NULL) X509_free(req);
-       if (in != NULL) BIO_free(in);
        return(ok);
        }
 
 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
        return(ok);
        }
 
 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)
+            STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy,
+             CA_DB *db, BIGNUM *serial, char *subj,
+            unsigned long chtype, int multirdn,
+            int email_dn, char *startdate, char *enddate, long days, int batch,
+            int verbose, X509_REQ *req, char *ext_sect, CONF *lconf,
+            unsigned long certopt, unsigned long nameopt, int default_op,
+            int ext_copy, int selfsign)
        {
        {
-       X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
+       X509_NAME *name=NULL,*CAname=NULL,*subject=NULL, *dn_subject=NULL;
        ASN1_UTCTIME *tm,*tmptm;
        ASN1_STRING *str,*str2;
        ASN1_OBJECT *obj;
        ASN1_UTCTIME *tm,*tmptm;
        ASN1_STRING *str,*str2;
        ASN1_OBJECT *obj;
@@ -1799,10 +1724,12 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
        X509_NAME_ENTRY *tne,*push;
        EVP_PKEY *pktmp;
        int ok= -1,i,j,last,nid;
        X509_NAME_ENTRY *tne,*push;
        EVP_PKEY *pktmp;
        int ok= -1,i,j,last,nid;
-       char *p;
+       const char *p;
        CONF_VALUE *cv;
        CONF_VALUE *cv;
-       char *row[DB_NUMBER],**rrow,**irow=NULL;
-       char buf[25],*pbuf;
+       OPENSSL_STRING row[DB_NUMBER];
+       OPENSSL_STRING *irow=NULL;
+       OPENSSL_STRING *rrow=NULL;
+       char buf[25];
 
        tmptm=ASN1_UTCTIME_new();
        if (tmptm == NULL)
 
        tmptm=ASN1_UTCTIME_new();
        if (tmptm == NULL)
@@ -1814,20 +1741,29 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
        for (i=0; i<DB_NUMBER; i++)
                row[i]=NULL;
 
        for (i=0; i<DB_NUMBER; i++)
                row[i]=NULL;
 
-       BIO_printf(bio_err,"The Subjects Distinguished Name is as follows\n");
+       if (subj)
+               {
+               X509_NAME *n = parse_name(subj, chtype, multirdn);
+
+               if (!n)
+                       {
+                       ERR_print_errors(bio_err);
+                       goto err;
+                       }
+               X509_REQ_set_subject_name(req,n);
+               req->req_info->enc.modified = 1;
+               X509_NAME_free(n);
+               }
+
+       if (default_op)
+               BIO_printf(bio_err,"The Subject's Distinguished Name is as follows\n");
+
        name=X509_REQ_get_subject_name(req);
        for (i=0; i<X509_NAME_entry_count(name); i++)
                {
        name=X509_REQ_get_subject_name(req);
        for (i=0; i<X509_NAME_entry_count(name); i++)
                {
-               ne=(X509_NAME_ENTRY *)X509_NAME_get_entry(name,i);
-               obj=X509_NAME_ENTRY_get_object(ne);
-               j=i2a_ASN1_OBJECT(bio_err,obj);
+               ne= X509_NAME_get_entry(name,i);
                str=X509_NAME_ENTRY_get_data(ne);
                str=X509_NAME_ENTRY_get_data(ne);
-               pbuf=buf;
-               for (j=22-j; j>0; j--)
-                       *(pbuf++)=' ';
-               *(pbuf++)=':';
-               *(pbuf++)='\0';
-               BIO_puts(bio_err,buf);
+               obj=X509_NAME_ENTRY_get_object(ne);
 
                if (msie_hack)
                        {
 
                if (msie_hack)
                        {
@@ -1846,16 +1782,9 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
                                str->type=V_ASN1_IA5STRING;
                        }
 
                                str->type=V_ASN1_IA5STRING;
                        }
 
-               if (str->type == V_ASN1_PRINTABLESTRING)
-                       BIO_printf(bio_err,"PRINTABLE:'");
-               else if (str->type == V_ASN1_T61STRING)
-                       BIO_printf(bio_err,"T61STRING:'");
-               else if (str->type == V_ASN1_IA5STRING)
-                       BIO_printf(bio_err,"IA5STRING:'");
-               else if (str->type == V_ASN1_UNIVERSALSTRING)
-                       BIO_printf(bio_err,"UNIVERSALSTRING:'");
-               else
-                       BIO_printf(bio_err,"ASN.1 %2d:'",str->type);
+               /* If no EMAIL is wanted in the subject */
+               if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn))
+                       continue;
 
                /* check some things */
                if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
 
                /* check some things */
                if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
@@ -1864,29 +1793,21 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
                        BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
                        goto err;
                        }
                        BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
                        goto err;
                        }
-               j=ASN1_PRINTABLE_type(str->data,str->length);
-               if (    ((j == V_ASN1_T61STRING) &&
-                        (str->type != V_ASN1_T61STRING)) ||
-                       ((j == V_ASN1_IA5STRING) &&
-                        (str->type == V_ASN1_PRINTABLESTRING)))
+               if ((str->type != V_ASN1_BMPSTRING) && (str->type != V_ASN1_UTF8STRING))
                        {
                        {
-                       BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
-                       goto err;
-                       }
-                       
-               p=(char *)str->data;
-               for (j=str->length; j>0; j--)
-                       {
-                       if ((*p >= ' ') && (*p <= '~'))
-                               BIO_printf(bio_err,"%c",*p);
-                       else if (*p & 0x80)
-                               BIO_printf(bio_err,"\\0x%02X",*p);
-                       else if ((unsigned char)*p == 0xf7)
-                               BIO_printf(bio_err,"^?");
-                       else    BIO_printf(bio_err,"^%c",*p+'@');
-                       p++;
+                       j=ASN1_PRINTABLE_type(str->data,str->length);
+                       if (    ((j == V_ASN1_T61STRING) &&
+                                (str->type != V_ASN1_T61STRING)) ||
+                               ((j == V_ASN1_IA5STRING) &&
+                                (str->type == V_ASN1_PRINTABLESTRING)))
+                               {
+                               BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
+                               goto err;
+                               }
                        }
                        }
-               BIO_printf(bio_err,"'\n");
+
+               if (default_op)
+                       old_entry_print(bio_err, obj, str);
                }
 
        /* Ok, now we check the 'policy' stuff. */
                }
 
        /* Ok, now we check the 'policy' stuff. */
@@ -1897,7 +1818,10 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
                }
 
        /* take a copy of the issuer name before we mess with it. */
                }
 
        /* take a copy of the issuer name before we mess with it. */
-       CAname=X509_NAME_dup(x509->cert_info->subject);
+       if (selfsign)
+               CAname=X509_NAME_dup(name);
+       else
+               CAname=X509_NAME_dup(x509->cert_info->subject);
        if (CAname == NULL) goto err;
        str=str2=NULL;
 
        if (CAname == NULL) goto err;
        str=str2=NULL;
 
@@ -2001,30 +1925,64 @@ again2:
        if (preserve)
                {
                X509_NAME_free(subject);
        if (preserve)
                {
                X509_NAME_free(subject);
-               subject=X509_NAME_dup(X509_REQ_get_subject_name(req));
+               /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */
+               subject=X509_NAME_dup(name);
                if (subject == NULL) goto err;
                }
 
        if (verbose)
                BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
 
                if (subject == NULL) goto err;
                }
 
        if (verbose)
                BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
 
-       row[DB_name]=X509_NAME_oneline(subject,NULL,0);
-       row[DB_serial]=BN_bn2hex(serial);
-       if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
+       /* Build the correct Subject if no e-mail is wanted in the subject */
+       /* and add it later on because of the method extensions are added (altName) */
+        
+       if (email_dn)
+               dn_subject = subject;
+       else
+               {
+               X509_NAME_ENTRY *tmpne;
+               /* Its best to dup the subject DN and then delete any email
+                * addresses because this retains its structure.
+                */
+               if (!(dn_subject = X509_NAME_dup(subject)))
+                       {
+                       BIO_printf(bio_err,"Memory allocation failure\n");
+                       goto err;
+                       }
+               while((i = X509_NAME_get_index_by_NID(dn_subject,
+                                       NID_pkcs9_emailAddress, -1)) >= 0)
+                       {
+                       tmpne = X509_NAME_get_entry(dn_subject, i);
+                       X509_NAME_delete_entry(dn_subject, i);
+                       X509_NAME_ENTRY_free(tmpne);
+                       }
+               }
+
+       if (BN_is_zero(serial))
+               row[DB_serial]=BUF_strdup("00");
+       else
+               row[DB_serial]=BN_bn2hex(serial);
+       if (row[DB_serial] == NULL)
                {
                BIO_printf(bio_err,"Memory allocation failure\n");
                goto err;
                }
 
                {
                BIO_printf(bio_err,"Memory allocation failure\n");
                goto err;
                }
 
-       rrow=TXT_DB_get_by_index(db,DB_name,row);
-       if (rrow != NULL)
+       if (db->attributes.unique_subject)
                {
                {
-               BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n",
-                       row[DB_name]);
+               OPENSSL_STRING *crow=row;
+
+               rrow=TXT_DB_get_by_index(db->db,DB_name,crow);
+               if (rrow != NULL)
+                       {
+                       BIO_printf(bio_err,
+                               "ERROR:There is already a certificate for %s\n",
+                               row[DB_name]);
+                       }
                }
                }
-       else
+       if (rrow == NULL)
                {
                {
-               rrow=TXT_DB_get_by_index(db,DB_serial,row);
+               rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
                if (rrow != NULL)
                        {
                        BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
                if (rrow != NULL)
                        {
                        BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
@@ -2072,26 +2030,35 @@ again2:
 
 #ifdef X509_V3
        /* Make it an X509 v3 certificate. */
 
 #ifdef X509_V3
        /* Make it an X509 v3 certificate. */
-       if (!X509_set_version(x509,2)) goto err;
+       if (!X509_set_version(ret,2)) goto err;
 #endif
 
        if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
                goto err;
 #endif
 
        if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
                goto err;
-       if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
-               goto err;
+       if (selfsign)
+               {
+               if (!X509_set_issuer_name(ret,subject))
+                       goto err;
+               }
+       else
+               {
+               if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
+                       goto err;
+               }
 
 
-       BIO_printf(bio_err,"Certificate is to be certified until ");
        if (strcmp(startdate,"today") == 0)
                X509_gmtime_adj(X509_get_notBefore(ret),0);
        if (strcmp(startdate,"today") == 0)
                X509_gmtime_adj(X509_get_notBefore(ret),0);
-       else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
+       else ASN1_TIME_set_string(X509_get_notBefore(ret),startdate);
 
        if (enddate == NULL)
 
        if (enddate == NULL)
-               X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
-       else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
-
-       ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
-       if (days) BIO_printf(bio_err," (%d days)",days);
-       BIO_printf(bio_err, "\n");
+               X509_time_adj_ex(X509_get_notAfter(ret),days, 0, NULL);
+       else
+               {
+               int tdays;
+               ASN1_TIME_set_string(X509_get_notAfter(ret),enddate);
+               ASN1_TIME_diff(&tdays, NULL, NULL, X509_get_notAfter(ret));
+               days = tdays;
+               }
 
        if (!X509_set_subject_name(ret,subject)) goto err;
 
 
        if (!X509_set_subject_name(ret,subject)) goto err;
 
@@ -2118,7 +2085,10 @@ again2:
                ci->extensions = NULL;
 
                /* Initialize the context structure */
                ci->extensions = NULL;
 
                /* Initialize the context structure */
-               X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
+               if (selfsign)
+                       X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0);
+               else
+                       X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
 
                if (extconf)
                        {
 
                if (extconf)
                        {
@@ -2126,13 +2096,13 @@ again2:
                                BIO_printf(bio_err, "Extra configuration file found\n");
  
                        /* Use the extconf configuration db LHASH */
                                BIO_printf(bio_err, "Extra configuration file found\n");
  
                        /* Use the extconf configuration db LHASH */
-                       X509V3_set_conf_lhash(&ctx, extconf);
+                       X509V3_set_nconf(&ctx, extconf);
  
                        /* Test the structure (needed?) */
                        /* X509V3_set_ctx_test(&ctx); */
 
                        /* Adds exts contained in the configuration file */
  
                        /* Test the structure (needed?) */
                        /* X509V3_set_ctx_test(&ctx); */
 
                        /* Adds exts contained in the configuration file */
-                       if (!X509V3_EXT_add_conf(extconf, &ctx, ext_sect,ret))
+                       if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect,ret))
                                {
                                BIO_printf(bio_err,
                                    "ERROR: adding extensions in section %s\n",
                                {
                                BIO_printf(bio_err,
                                    "ERROR: adding extensions in section %s\n",
@@ -2146,9 +2116,9 @@ again2:
                else if (ext_sect)
                        {
                        /* We found extensions to be set from config file */
                else if (ext_sect)
                        {
                        /* We found extensions to be set from config file */
-                       X509V3_set_conf_lhash(&ctx, lconf);
+                       X509V3_set_nconf(&ctx, lconf);
 
 
-                       if(!X509V3_EXT_add_conf(lconf, &ctx, ext_sect, ret))
+                       if(!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret))
                                {
                                BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
                                ERR_print_errors(bio_err);
                                {
                                BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
                                ERR_print_errors(bio_err);
@@ -2160,13 +2130,46 @@ again2:
                        }
                }
 
                        }
                }
 
+       /* Copy extensions from request (if any) */
+
+       if (!copy_extensions(ret, req, ext_copy))
+               {
+               BIO_printf(bio_err, "ERROR: adding extensions from request\n");
+               ERR_print_errors(bio_err);
+               goto err;
+               }
+
+       /* Set the right value for the noemailDN option */
+       if( email_dn == 0 )
+               {
+               if (!X509_set_subject_name(ret,dn_subject)) goto err;
+               }
+
+       if (!default_op)
+               {
+               BIO_printf(bio_err, "Certificate Details:\n");
+               /* Never print signature details because signature not present */
+               certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
+               X509_print_ex(bio_err, ret, nameopt, certopt); 
+               }
+
+       BIO_printf(bio_err,"Certificate is to be certified until ");
+       ASN1_TIME_print(bio_err,X509_get_notAfter(ret));
+       if (days) BIO_printf(bio_err," (%ld days)",days);
+       BIO_printf(bio_err, "\n");
 
        if (!batch)
                {
 
        if (!batch)
                {
+
                BIO_printf(bio_err,"Sign the certificate? [y/n]:");
                (void)BIO_flush(bio_err);
                buf[0]='\0';
                BIO_printf(bio_err,"Sign the certificate? [y/n]:");
                (void)BIO_flush(bio_err);
                buf[0]='\0';
-               fgets(buf,sizeof(buf)-1,stdin);
+               if (!fgets(buf,sizeof(buf)-1,stdin))
+                       {
+                       BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n");
+                       ok=0;
+                       goto err;
+                       }
                if (!((buf[0] == 'y') || (buf[0] == 'Y')))
                        {
                        BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
                if (!((buf[0] == 'y') || (buf[0] == 'Y')))
                        {
                        BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
@@ -2175,17 +2178,13 @@ again2:
                        }
                }
 
                        }
                }
 
-
-#ifndef NO_DSA
-       if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
        pktmp=X509_get_pubkey(ret);
        if (EVP_PKEY_missing_parameters(pktmp) &&
                !EVP_PKEY_missing_parameters(pkey))
                EVP_PKEY_copy_parameters(pktmp,pkey);
        EVP_PKEY_free(pktmp);
        pktmp=X509_get_pubkey(ret);
        if (EVP_PKEY_missing_parameters(pktmp) &&
                !EVP_PKEY_missing_parameters(pkey))
                EVP_PKEY_copy_parameters(pktmp,pkey);
        EVP_PKEY_free(pktmp);
-#endif
 
 
-       if (!X509_sign(ret,pkey,dgst))
+       if (!do_X509_sign(bio_err, ret,pkey,dgst, sigopts))
                goto err;
 
        /* We now just add it to the database */
                goto err;
 
        /* We now just add it to the database */
@@ -2200,15 +2199,15 @@ again2:
 
        /* row[DB_serial] done already */
        row[DB_file]=(char *)OPENSSL_malloc(8);
 
        /* row[DB_serial] done already */
        row[DB_file]=(char *)OPENSSL_malloc(8);
-       /* row[DB_name] done already */
+       row[DB_name]=X509_NAME_oneline(X509_get_subject_name(ret),NULL,0);
 
        if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
 
        if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
-               (row[DB_file] == NULL))
+               (row[DB_file] == NULL) || (row[DB_name] == NULL))
                {
                BIO_printf(bio_err,"Memory allocation failure\n");
                goto err;
                }
                {
                BIO_printf(bio_err,"Memory allocation failure\n");
                goto err;
                }
-       strcpy(row[DB_file],"unknown");
+       BUF_strlcpy(row[DB_file],"unknown",8);
        row[DB_type][0]='V';
        row[DB_type][1]='\0';
 
        row[DB_type][0]='V';
        row[DB_type][1]='\0';
 
@@ -2225,10 +2224,10 @@ again2:
                }
        irow[DB_NUMBER]=NULL;
 
                }
        irow[DB_NUMBER]=NULL;
 
-       if (!TXT_DB_insert(db,irow))
+       if (!TXT_DB_insert(db->db,irow))
                {
                BIO_printf(bio_err,"failed to update database\n");
                {
                BIO_printf(bio_err,"failed to update database\n");
-               BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
+               BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error);
                goto err;
                }
        ok=1;
                goto err;
                }
        ok=1;
@@ -2240,6 +2239,8 @@ err:
                X509_NAME_free(CAname);
        if (subject != NULL)
                X509_NAME_free(subject);
                X509_NAME_free(CAname);
        if (subject != NULL)
                X509_NAME_free(subject);
+       if ((dn_subject != NULL) && !email_dn)
+               X509_NAME_free(dn_subject);
        if (tmptm != NULL)
                ASN1_UTCTIME_free(tmptm);
        if (ok <= 0)
        if (tmptm != NULL)
                ASN1_UTCTIME_free(tmptm);
        if (ok <= 0)
@@ -2277,12 +2278,14 @@ static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
        }
 
 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
        }
 
 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)
+            const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+            STACK_OF(CONF_VALUE) *policy, CA_DB *db,
+            BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate,
+            long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt,
+            unsigned long nameopt, int default_op, int ext_copy)
        {
        STACK_OF(CONF_VALUE) *sk=NULL;
        {
        STACK_OF(CONF_VALUE) *sk=NULL;
-       LHASH *parms=NULL;
+       LHASH_OF(CONF_VALUE) *parms=NULL;
        X509_REQ *req=NULL;
        CONF_VALUE *cv=NULL;
        NETSCAPE_SPKI *spki = NULL;
        X509_REQ *req=NULL;
        CONF_VALUE *cv=NULL;
        NETSCAPE_SPKI *spki = NULL;
@@ -2369,20 +2372,9 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
                        continue;
                        }
 
                        continue;
                        }
 
-               j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
-               if (fix_data(nid, &j) == 0)
-                       {
-                       BIO_printf(bio_err,
-                               "invalid characters in string %s\n",buf);
-                       goto err;
-                       }
-
-               if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
-                       (unsigned char *)buf,
-                       strlen(buf))) == NULL)
+               if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
+                               (unsigned char *)buf, -1, -1, 0))
                        goto err;
                        goto err;
-
-               if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
                }
        if (spki == NULL)
                {
                }
        if (spki == NULL)
                {
@@ -2413,8 +2405,9 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
 
        X509_REQ_set_pubkey(req,pktmp);
        EVP_PKEY_free(pktmp);
 
        X509_REQ_set_pubkey(req,pktmp);
        EVP_PKEY_free(pktmp);
-       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,
-                  days,1,verbose,req,ext_sect,lconf);
+       ok=do_body(xret,pkey,x509,dgst,sigopts,policy,db,serial,subj,chtype,
+                  multirdn,email_dn,startdate,enddate, days,1,verbose,req,
+                  ext_sect,lconf, certopt, nameopt, default_op, ext_copy, 0);
 err:
        if (req != NULL) X509_REQ_free(req);
        if (parms != NULL) CONF_free(parms);
 err:
        if (req != NULL) X509_REQ_free(req);
        if (parms != NULL) CONF_free(parms);
@@ -2424,32 +2417,12 @@ err:
        return(ok);
        }
 
        return(ok);
        }
 
-static int fix_data(int nid, int *type)
-       {
-       if (nid == NID_pkcs9_emailAddress)
-               *type=V_ASN1_IA5STRING;
-       if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
-               *type=V_ASN1_T61STRING;
-       if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
-               *type=V_ASN1_T61STRING;
-       if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
-               return(0);
-       if (nid == NID_pkcs9_unstructuredName)
-               *type=V_ASN1_IA5STRING;
-       return(1);
-       }
-
-static int check_time_format(char *str)
+static int check_time_format(const 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 ASN1_TIME_set_string(NULL, str);
        }
 
        }
 
-static int do_revoke(X509 *x509, TXT_DB *db, int type, char *value)
+static int do_revoke(X509 *x509, CA_DB *db, int type, char *value)
        {
        ASN1_UTCTIME *tm=NULL;
        char *row[DB_NUMBER],**rrow,**irow;
        {
        ASN1_UTCTIME *tm=NULL;
        char *row[DB_NUMBER],**rrow,**irow;
@@ -2461,7 +2434,12 @@ static int do_revoke(X509 *x509, TXT_DB *db, int type, char *value)
                row[i]=NULL;
        row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
        bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
                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);
+       if (!bn)
+               goto err;
+       if (BN_is_zero(bn))
+               row[DB_serial]=BUF_strdup("00");
+       else
+               row[DB_serial]=BN_bn2hex(bn);
        BN_free(bn);
        if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
                {
        BN_free(bn);
        if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
                {
@@ -2471,10 +2449,10 @@ static int do_revoke(X509 *x509, TXT_DB *db, int type, char *value)
        /* We have to lookup by serial number because name lookup
         * skips revoked certs
         */
        /* We have to lookup by serial number because name lookup
         * skips revoked certs
         */
-       rrow=TXT_DB_get_by_index(db,DB_serial,row);
+       rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
        if (rrow == NULL)
                {
        if (rrow == NULL)
                {
-               BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]);
+               BIO_printf(bio_err,"Adding Entry with serial number %s to DB for %s\n", row[DB_serial], row[DB_name]);
 
                /* We now just add it to the database */
                row[DB_type]=(char *)OPENSSL_malloc(2);
 
                /* We now just add it to the database */
                row[DB_type]=(char *)OPENSSL_malloc(2);
@@ -2497,7 +2475,7 @@ static int do_revoke(X509 *x509, TXT_DB *db, int type, char *value)
                        BIO_printf(bio_err,"Memory allocation failure\n");
                        goto err;
                        }
                        BIO_printf(bio_err,"Memory allocation failure\n");
                        goto err;
                        }
-               strcpy(row[DB_file],"unknown");
+               BUF_strlcpy(row[DB_file],"unknown",8);
                row[DB_type][0]='V';
                row[DB_type][1]='\0';
 
                row[DB_type][0]='V';
                row[DB_type][1]='\0';
 
@@ -2514,25 +2492,34 @@ static int do_revoke(X509 *x509, TXT_DB *db, int type, char *value)
                        }
                irow[DB_NUMBER]=NULL;
 
                        }
                irow[DB_NUMBER]=NULL;
 
-               if (!TXT_DB_insert(db,irow))
+               if (!TXT_DB_insert(db->db,irow))
                        {
                        BIO_printf(bio_err,"failed to update database\n");
                        {
                        BIO_printf(bio_err,"failed to update database\n");
-                       BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
+                       BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error);
                        goto err;
                        }
 
                /* Revoke Certificate */
                        goto err;
                        }
 
                /* Revoke Certificate */
-               ok = do_revoke(x509,db, type, value);
+               if (type == -1)
+                       ok = 1;
+               else
+                       ok = do_revoke(x509,db, type, value);
 
                goto err;
 
                }
 
                goto err;
 
                }
-       else if (index_name_cmp((const char **)row,(const char **)rrow))
+       else if (index_name_cmp_noconst(row, rrow))
                {
                BIO_printf(bio_err,"ERROR:name does not match %s\n",
                           row[DB_name]);
                goto err;
                }
                {
                BIO_printf(bio_err,"ERROR:name does not match %s\n",
                           row[DB_name]);
                goto err;
                }
+       else if (type == -1)
+               {
+               BIO_printf(bio_err,"ERROR:Already present, 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",
        else if (rrow[DB_type][0]=='R')
                {
                BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
@@ -2562,7 +2549,7 @@ err:
        return(ok);
        }
 
        return(ok);
        }
 
-static int get_certificate_status(const char *serial, TXT_DB *db)
+static int get_certificate_status(const char *serial, CA_DB *db)
        {
        char *row[DB_NUMBER],**rrow;
        int ok=-1,i;
        {
        char *row[DB_NUMBER],**rrow;
        int ok=-1,i;
@@ -2597,13 +2584,13 @@ static int get_certificate_status(const char *serial, TXT_DB *db)
                        
        /* Make it Upper Case */
        for (i=0; row[DB_serial][i] != '\0'; i++)
                        
        /* Make it Upper Case */
        for (i=0; row[DB_serial][i] != '\0'; i++)
-               row[DB_serial][i] = toupper(row[DB_serial][i]);
+               row[DB_serial][i] = toupper((unsigned char)row[DB_serial][i]);
        
 
        ok=1;
 
        /* Search for the certificate */
        
 
        ok=1;
 
        /* Search for the certificate */
-       rrow=TXT_DB_get_by_index(db,DB_serial,row);
+       rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
        if (rrow == NULL)
                {
                BIO_printf(bio_err,"Serial %s not present in db.\n",
        if (rrow == NULL)
                {
                BIO_printf(bio_err,"Serial %s not present in db.\n",
@@ -2650,7 +2637,7 @@ err:
        return(ok);
        }
 
        return(ok);
        }
 
-static int do_updatedb (TXT_DB *db)
+static int do_updatedb (CA_DB *db)
        {
        ASN1_UTCTIME    *a_tm = NULL;
        int i, cnt = 0;
        {
        ASN1_UTCTIME    *a_tm = NULL;
        int i, cnt = 0;
@@ -2676,9 +2663,9 @@ static int do_updatedb (TXT_DB *db)
        else
                a_y2k = 0;
 
        else
                a_y2k = 0;
 
-       for (i = 0; i < sk_num(db->data); i++)
+       for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
                {
                {
-               rrow = (char **) sk_value(db->data, i);
+               rrow = sk_OPENSSL_PSTRING_value(db->db->data, i);
 
                if (rrow[DB_type][0] == 'V')
                        {
 
                if (rrow[DB_type][0] == 'V')
                        {
@@ -2722,7 +2709,7 @@ err:
        return (cnt);
        }
 
        return (cnt);
        }
 
-static char *crl_reasons[] = {
+static const char *crl_reasons[] = {
        /* CRL reason strings */
        "unspecified",
        "keyCompromise",
        /* CRL reason strings */
        "unspecified",
        "keyCompromise",
@@ -2750,7 +2737,8 @@ static char *crl_reasons[] = {
 
 char *make_revocation_str(int rev_type, char *rev_arg)
        {
 
 char *make_revocation_str(int rev_type, char *rev_arg)
        {
-       char *reason = NULL, *other = NULL, *str;
+       char *other = NULL, *str;
+       const char *reason = NULL;
        ASN1_OBJECT *otmp;
        ASN1_UTCTIME *revtm = NULL;
        int i;
        ASN1_OBJECT *otmp;
        ASN1_UTCTIME *revtm = NULL;
        int i;
@@ -2821,16 +2809,16 @@ char *make_revocation_str(int rev_type, char *rev_arg)
 
        if (!str) return NULL;
 
 
        if (!str) return NULL;
 
-       strcpy(str, (char *)revtm->data);
+       BUF_strlcpy(str, (char *)revtm->data, i);
        if (reason)
                {
        if (reason)
                {
-               strcat(str, ",");
-               strcat(str, reason);
+               BUF_strlcat(str, ",", i);
+               BUF_strlcat(str, reason, i);
                }
        if (other)
                {
                }
        if (other)
                {
-               strcat(str, ",");
-               strcat(str, other);
+               BUF_strlcat(str, ",", i);
+               BUF_strlcat(str, other, i);
                }
        ASN1_UTCTIME_free(revtm);
        return str;
                }
        ASN1_UTCTIME_free(revtm);
        return str;
@@ -2843,15 +2831,109 @@ char *make_revocation_str(int rev_type, char *rev_arg)
  * 2 OK and some extensions added (i.e. V2 CRL)
  */
 
  * 2 OK and some extensions added (i.e. V2 CRL)
  */
 
-int make_revoked(X509_REVOKED *rev, char *str)
+
+int make_revoked(X509_REVOKED *rev, const char *str)
        {
        char *tmp = NULL;
        {
        char *tmp = NULL;
-       char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
        int reason_code = -1;
        int i, ret = 0;
        ASN1_OBJECT *hold = NULL;
        ASN1_GENERALIZEDTIME *comp_time = NULL;
        ASN1_ENUMERATED *rtmp = NULL;
        int reason_code = -1;
        int i, ret = 0;
        ASN1_OBJECT *hold = NULL;
        ASN1_GENERALIZEDTIME *comp_time = NULL;
        ASN1_ENUMERATED *rtmp = NULL;
+
+       ASN1_TIME *revDate = NULL;
+
+       i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str);
+
+       if (i == 0)
+               goto err;
+
+       if (rev && !X509_REVOKED_set_revocationDate(rev, revDate))
+               goto err;
+
+       if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
+               {
+               rtmp = ASN1_ENUMERATED_new();
+               if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
+                       goto err;
+               if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
+                       goto err;
+               }
+
+       if (rev && comp_time)
+               {
+               if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
+                       goto err;
+               }
+       if (rev && hold)
+               {
+               if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
+                       goto err;
+               }
+
+       if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
+               ret = 2;
+       else ret = 1;
+
+       err:
+
+       if (tmp) OPENSSL_free(tmp);
+       ASN1_OBJECT_free(hold);
+       ASN1_GENERALIZEDTIME_free(comp_time);
+       ASN1_ENUMERATED_free(rtmp);
+       ASN1_TIME_free(revDate);
+
+       return ret;
+       }
+
+int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
+       {
+       char buf[25],*pbuf, *p;
+       int j;
+       j=i2a_ASN1_OBJECT(bp,obj);
+       pbuf=buf;
+       for (j=22-j; j>0; j--)
+               *(pbuf++)=' ';
+       *(pbuf++)=':';
+       *(pbuf++)='\0';
+       BIO_puts(bp,buf);
+
+       if (str->type == V_ASN1_PRINTABLESTRING)
+               BIO_printf(bp,"PRINTABLE:'");
+       else if (str->type == V_ASN1_T61STRING)
+               BIO_printf(bp,"T61STRING:'");
+       else if (str->type == V_ASN1_IA5STRING)
+               BIO_printf(bp,"IA5STRING:'");
+       else if (str->type == V_ASN1_UNIVERSALSTRING)
+               BIO_printf(bp,"UNIVERSALSTRING:'");
+       else
+               BIO_printf(bp,"ASN.1 %2d:'",str->type);
+                       
+       p=(char *)str->data;
+       for (j=str->length; j>0; j--)
+               {
+               if ((*p >= ' ') && (*p <= '~'))
+                       BIO_printf(bp,"%c",*p);
+               else if (*p & 0x80)
+                       BIO_printf(bp,"\\0x%02X",*p);
+               else if ((unsigned char)*p == 0xf7)
+                       BIO_printf(bp,"^?");
+               else    BIO_printf(bp,"^%c",*p+'@');
+               p++;
+               }
+       BIO_printf(bp,"'\n");
+       return 1;
+       }
+
+int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, const char *str)
+       {
+       char *tmp = NULL;
+       char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
+       int reason_code = -1;
+       int ret = 0;
+       unsigned int i;
+       ASN1_OBJECT *hold = NULL;
+       ASN1_GENERALIZEDTIME *comp_time = NULL;
        tmp = BUF_strdup(str);
 
        p = strchr(tmp, ',');
        tmp = BUF_strdup(str);
 
        p = strchr(tmp, ',');
@@ -2871,10 +2953,14 @@ int make_revoked(X509_REVOKED *rev, char *str)
                        }
                }
 
                        }
                }
 
-       if (rev && !ASN1_UTCTIME_set_string(rev->revocationDate, rtime_str))
+       if (prevtm)
                {
                {
-               BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
-               goto err;
+               *prevtm = ASN1_UTCTIME_new();
+               if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str))
+                       {
+                       BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
+                       goto err;
+                       }
                }
        if (reason_str)
                {
                }
        if (reason_str)
                {
@@ -2909,6 +2995,7 @@ int make_revoked(X509_REVOKED *rev, char *str)
                                BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
                                goto err;
                                }
                                BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
                                goto err;
                                }
+                       if (phold) *phold = hold;
                        }
                else if ((reason_code == 9) || (reason_code == 10))
                        {
                        }
                else if ((reason_code == 9) || (reason_code == 10))
                        {
@@ -2930,36 +3017,17 @@ int make_revoked(X509_REVOKED *rev, char *str)
                        }
                }
 
                        }
                }
 
-       if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
-               {
-               rtmp = ASN1_ENUMERATED_new();
-               if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
-                       goto err;
-               if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
-                       goto err;
-               }
+       if (preason) *preason = reason_code;
+       if (pinvtm) *pinvtm = comp_time;
+       else ASN1_GENERALIZEDTIME_free(comp_time);
 
 
-       if (rev && comp_time)
-               {
-               if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
-                       goto err;
-               }
-       if (rev && hold)
-               {
-               if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
-                       goto err;
-               }
-
-       if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
-               ret = 2;
-       else ret = 1;
+       ret = 1;
 
        err:
 
        if (tmp) OPENSSL_free(tmp);
 
        err:
 
        if (tmp) OPENSSL_free(tmp);
-       ASN1_OBJECT_free(hold);
-       ASN1_GENERALIZEDTIME_free(comp_time);
-       ASN1_ENUMERATED_free(rtmp);
+       if (!phold) ASN1_OBJECT_free(hold);
+       if (!pinvtm) ASN1_GENERALIZEDTIME_free(comp_time);
 
        return ret;
        }
 
        return ret;
        }