Reset the version number of the issuer certificate? I believe this
[oweals/openssl.git] / apps / ca.c
1 /* apps/ca.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 /* The PPKI stuff has been donated by Jeff Barber <jeffb@issl.atl.hp.com> */
60
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <ctype.h>
65 #include <sys/types.h>
66 #include <sys/stat.h>
67 #include <openssl/conf.h>
68 #include <openssl/bio.h>
69 #include <openssl/err.h>
70 #include <openssl/bn.h>
71 #include <openssl/txt_db.h>
72 #include <openssl/evp.h>
73 #include <openssl/x509.h>
74 #include <openssl/x509v3.h>
75 #include <openssl/objects.h>
76 #include <openssl/ocsp.h>
77 #include <openssl/pem.h>
78
79 #ifdef OPENSSL_SYS_WINDOWS
80 #define strcasecmp _stricmp
81 #else
82 #  ifdef NO_STRINGS_H
83     int strcasecmp();
84 #  else
85 #    include <strings.h>
86 #  endif /* NO_STRINGS_H */
87 #endif
88
89 #ifndef W_OK
90 #  ifdef OPENSSL_SYS_VMS
91 #    if defined(__DECC)
92 #      include <unistd.h>
93 #    else
94 #      include <unixlib.h>
95 #    endif
96 #  elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS)
97 #    include <sys/file.h>
98 #  endif
99 #endif
100
101 #include "apps.h"
102
103 #ifndef W_OK
104 #  define F_OK 0
105 #  define X_OK 1
106 #  define W_OK 2
107 #  define R_OK 4
108 #endif
109
110 #undef PROG
111 #define PROG ca_main
112
113 #define BASE_SECTION    "ca"
114 #define CONFIG_FILE "openssl.cnf"
115
116 #define ENV_DEFAULT_CA          "default_ca"
117
118 #define ENV_DIR                 "dir"
119 #define ENV_CERTS               "certs"
120 #define ENV_CRL_DIR             "crl_dir"
121 #define ENV_CA_DB               "CA_DB"
122 #define ENV_NEW_CERTS_DIR       "new_certs_dir"
123 #define ENV_CERTIFICATE         "certificate"
124 #define ENV_SERIAL              "serial"
125 #define ENV_CRL                 "crl"
126 #define ENV_PRIVATE_KEY         "private_key"
127 #define ENV_RANDFILE            "RANDFILE"
128 #define ENV_DEFAULT_DAYS        "default_days"
129 #define ENV_DEFAULT_STARTDATE   "default_startdate"
130 #define ENV_DEFAULT_ENDDATE     "default_enddate"
131 #define ENV_DEFAULT_CRL_DAYS    "default_crl_days"
132 #define ENV_DEFAULT_CRL_HOURS   "default_crl_hours"
133 #define ENV_DEFAULT_MD          "default_md"
134 #define ENV_DEFAULT_EMAIL_DN    "email_in_dn"
135 #define ENV_PRESERVE            "preserve"
136 #define ENV_POLICY              "policy"
137 #define ENV_EXTENSIONS          "x509_extensions"
138 #define ENV_CRLEXT              "crl_extensions"
139 #define ENV_MSIE_HACK           "msie_hack"
140 #define ENV_NAMEOPT             "name_opt"
141 #define ENV_CERTOPT             "cert_opt"
142 #define ENV_EXTCOPY             "copy_extensions"
143
144 #define ENV_DATABASE            "database"
145
146 #define DB_type         0
147 #define DB_exp_date     1
148 #define DB_rev_date     2
149 #define DB_serial       3       /* index - unique */
150 #define DB_file         4       
151 #define DB_name         5       /* index - unique for active */
152 #define DB_NUMBER       6
153
154 #define DB_TYPE_REV     'R'
155 #define DB_TYPE_EXP     'E'
156 #define DB_TYPE_VAL     'V'
157
158 /* Additional revocation information types */
159
160 #define REV_NONE                0       /* No addditional information */
161 #define REV_CRL_REASON          1       /* Value is CRL reason code */
162 #define REV_HOLD                2       /* Value is hold instruction */
163 #define REV_KEY_COMPROMISE      3       /* Value is cert key compromise time */
164 #define REV_CA_COMPROMISE       4       /* Value is CA key compromise time */
165
166 static char *ca_usage[]={
167 "usage: ca args\n",
168 "\n",
169 " -verbose        - Talk alot while doing things\n",
170 " -config file    - A config file\n",
171 " -name arg       - The particular CA definition to use\n",
172 " -gencrl         - Generate a new CRL\n",
173 " -crldays days   - Days is when the next CRL is due\n",
174 " -crlhours hours - Hours is when the next CRL is due\n",
175 " -startdate YYMMDDHHMMSSZ  - certificate validity notBefore\n",
176 " -enddate YYMMDDHHMMSSZ    - certificate validity notAfter (overrides -days)\n",
177 " -days arg       - number of days to certify the certificate for\n",
178 " -md arg         - md to use, one of md2, md5, sha or sha1\n",
179 " -policy arg     - The CA 'policy' to support\n",
180 " -keyfile arg    - private key file\n",
181 " -keyform arg    - private key file format (PEM or ENGINE)\n",
182 " -key arg        - key to decode the private key if it is encrypted\n",
183 " -cert file      - The CA certificate\n",
184 " -in file        - The input PEM encoded certificate request(s)\n",
185 " -out file       - Where to put the output file(s)\n",
186 " -outdir dir     - Where to put output certificates\n",
187 " -infiles ....   - The last argument, requests to process\n",
188 " -spkac file     - File contains DN and signed public key and challenge\n",
189 " -ss_cert file   - File contains a self signed cert to sign\n",
190 " -preserveDN     - Don't re-order the DN\n",
191 " -noemailDN      - Don't add the EMAIL field into certificate' subject\n",
192 " -batch          - Don't ask questions\n",
193 " -msie_hack      - msie modifications to handle all those universal strings\n",
194 " -revoke file    - Revoke a certificate (given in file)\n",
195 " -subj arg       - Use arg instead of request's subject\n",
196 " -extensions ..  - Extension section (override value in config file)\n",
197 " -extfile file   - Configuration file with X509v3 extentions to add\n",
198 " -crlexts ..     - CRL extension section (override value in config file)\n",
199 #ifndef OPENSSL_NO_ENGINE
200 " -engine e       - use engine e, possibly a hardware device.\n",
201 #endif
202 " -status serial  - Shows certificate status given the serial number\n",
203 " -updatedb       - Updates db for expired certificates\n",
204 NULL
205 };
206
207 #ifdef EFENCE
208 extern int EF_PROTECT_FREE;
209 extern int EF_PROTECT_BELOW;
210 extern int EF_ALIGNMENT;
211 #endif
212
213 static void lookup_fail(char *name,char *tag);
214 static unsigned long index_serial_hash(const char **a);
215 static int index_serial_cmp(const char **a, const char **b);
216 static unsigned long index_name_hash(const char **a);
217 static int index_name_qual(char **a);
218 static int index_name_cmp(const char **a,const char **b);
219 static BIGNUM *load_serial(char *serialfile);
220 static int save_serial(char *serialfile, BIGNUM *serial);
221 static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
222                    const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,TXT_DB *db,
223                    BIGNUM *serial, char *subj, int email_dn, char *startdate,
224                    char *enddate, long days, int batch, char *ext_sect, CONF *conf,
225                    int verbose, unsigned long certopt, unsigned long nameopt,
226                    int default_op, int ext_copy);
227 static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
228                         const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
229                         TXT_DB *db, BIGNUM *serial, char *subj, int email_dn,
230                         char *startdate, char *enddate, long days, int batch,
231                         char *ext_sect, CONF *conf,int verbose, unsigned long certopt,
232                         unsigned long nameopt, int default_op, int ext_copy,
233                         ENGINE *e);
234 static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
235                          const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
236                          TXT_DB *db, BIGNUM *serial,char *subj, int email_dn,
237                          char *startdate, char *enddate, long days, char *ext_sect,
238                          CONF *conf, int verbose, unsigned long certopt, 
239                          unsigned long nameopt, int default_op, int ext_copy);
240 static int fix_data(int nid, int *type);
241 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
242 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
243         STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,char *subj,
244         int email_dn, char *startdate, char *enddate, long days, int batch,
245         int verbose, X509_REQ *req, char *ext_sect, CONF *conf,
246         unsigned long certopt, unsigned long nameopt, int default_op,
247         int ext_copy);
248 static int do_revoke(X509 *x509, TXT_DB *db, int ext, char *extval);
249 static int get_certificate_status(const char *ser_status, TXT_DB *db);
250 static int do_updatedb(TXT_DB *db);
251 static int check_time_format(char *str);
252 char *make_revocation_str(int rev_type, char *rev_arg);
253 int make_revoked(X509_REVOKED *rev, char *str);
254 int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str);
255 static CONF *conf=NULL;
256 static CONF *extconf=NULL;
257 static char *section=NULL;
258
259 static int preserve=0;
260 static int msie_hack=0;
261
262 static IMPLEMENT_LHASH_HASH_FN(index_serial_hash,const char **)
263 static IMPLEMENT_LHASH_COMP_FN(index_serial_cmp,const char **)
264 static IMPLEMENT_LHASH_HASH_FN(index_name_hash,const char **)
265 static IMPLEMENT_LHASH_COMP_FN(index_name_cmp,const char **)
266
267
268 int MAIN(int, char **);
269
270 int MAIN(int argc, char **argv)
271         {
272         ENGINE *e = NULL;
273         char *key=NULL,*passargin=NULL;
274         int free_key = 0;
275         int total=0;
276         int total_done=0;
277         int badops=0;
278         int ret=1;
279         int email_dn=1;
280         int req=0;
281         int verbose=0;
282         int gencrl=0;
283         int dorevoke=0;
284         int doupdatedb=0;
285         long crldays=0;
286         long crlhours=0;
287         long errorline= -1;
288         char *configfile=NULL;
289         char *md=NULL;
290         char *policy=NULL;
291         char *keyfile=NULL;
292         char *certfile=NULL;
293         int keyform=FORMAT_PEM;
294         char *infile=NULL;
295         char *spkac_file=NULL;
296         char *ss_cert_file=NULL;
297         char *ser_status=NULL;
298         EVP_PKEY *pkey=NULL;
299         int output_der = 0;
300         char *outfile=NULL;
301         char *outdir=NULL;
302         char *serialfile=NULL;
303         char *extensions=NULL;
304         char *extfile=NULL;
305         char *subj=NULL;
306         char *tmp_email_dn=NULL;
307         char *crl_ext=NULL;
308         int rev_type = REV_NONE;
309         char *rev_arg = NULL;
310         BIGNUM *serial=NULL;
311         char *startdate=NULL;
312         char *enddate=NULL;
313         long days=0;
314         int batch=0;
315         int notext=0;
316         unsigned long nameopt = 0, certopt = 0;
317         int default_op = 1;
318         int ext_copy = EXT_COPY_NONE;
319         X509 *x509=NULL;
320         X509 *x=NULL;
321         BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
322         char *dbfile=NULL;
323         TXT_DB *db=NULL;
324         X509_CRL *crl=NULL;
325         X509_REVOKED *r=NULL;
326         ASN1_TIME *tmptm;
327         ASN1_INTEGER *tmpser;
328         char **pp,*p,*f;
329         int i,j;
330         long l;
331         const EVP_MD *dgst=NULL;
332         STACK_OF(CONF_VALUE) *attribs=NULL;
333         STACK_OF(X509) *cert_sk=NULL;
334 #undef BSIZE
335 #define BSIZE 256
336         MS_STATIC char buf[3][BSIZE];
337         char *randfile=NULL;
338 #ifndef OPENSSL_NO_ENGINE
339         char *engine = NULL;
340 #endif
341         char *tofree=NULL;
342
343 #ifdef EFENCE
344 EF_PROTECT_FREE=1;
345 EF_PROTECT_BELOW=1;
346 EF_ALIGNMENT=0;
347 #endif
348
349         apps_startup();
350
351         conf = NULL;
352         key = NULL;
353         section = NULL;
354
355         preserve=0;
356         msie_hack=0;
357         if (bio_err == NULL)
358                 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
359                         BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
360
361         argc--;
362         argv++;
363         while (argc >= 1)
364                 {
365                 if      (strcmp(*argv,"-verbose") == 0)
366                         verbose=1;
367                 else if (strcmp(*argv,"-config") == 0)
368                         {
369                         if (--argc < 1) goto bad;
370                         configfile= *(++argv);
371                         }
372                 else if (strcmp(*argv,"-name") == 0)
373                         {
374                         if (--argc < 1) goto bad;
375                         section= *(++argv);
376                         }
377                 else if (strcmp(*argv,"-subj") == 0)
378                         {
379                         if (--argc < 1) goto bad;
380                         subj= *(++argv);
381                         /* preserve=1; */
382                         }
383                 else if (strcmp(*argv,"-startdate") == 0)
384                         {
385                         if (--argc < 1) goto bad;
386                         startdate= *(++argv);
387                         }
388                 else if (strcmp(*argv,"-enddate") == 0)
389                         {
390                         if (--argc < 1) goto bad;
391                         enddate= *(++argv);
392                         }
393                 else if (strcmp(*argv,"-days") == 0)
394                         {
395                         if (--argc < 1) goto bad;
396                         days=atoi(*(++argv));
397                         }
398                 else if (strcmp(*argv,"-md") == 0)
399                         {
400                         if (--argc < 1) goto bad;
401                         md= *(++argv);
402                         }
403                 else if (strcmp(*argv,"-policy") == 0)
404                         {
405                         if (--argc < 1) goto bad;
406                         policy= *(++argv);
407                         }
408                 else if (strcmp(*argv,"-keyfile") == 0)
409                         {
410                         if (--argc < 1) goto bad;
411                         keyfile= *(++argv);
412                         }
413                 else if (strcmp(*argv,"-keyform") == 0)
414                         {
415                         if (--argc < 1) goto bad;
416                         keyform=str2fmt(*(++argv));
417                         }
418                 else if (strcmp(*argv,"-passin") == 0)
419                         {
420                         if (--argc < 1) goto bad;
421                         passargin= *(++argv);
422                         }
423                 else if (strcmp(*argv,"-key") == 0)
424                         {
425                         if (--argc < 1) goto bad;
426                         key= *(++argv);
427                         }
428                 else if (strcmp(*argv,"-cert") == 0)
429                         {
430                         if (--argc < 1) goto bad;
431                         certfile= *(++argv);
432                         }
433                 else if (strcmp(*argv,"-in") == 0)
434                         {
435                         if (--argc < 1) goto bad;
436                         infile= *(++argv);
437                         req=1;
438                         }
439                 else if (strcmp(*argv,"-out") == 0)
440                         {
441                         if (--argc < 1) goto bad;
442                         outfile= *(++argv);
443                         }
444                 else if (strcmp(*argv,"-outdir") == 0)
445                         {
446                         if (--argc < 1) goto bad;
447                         outdir= *(++argv);
448                         }
449                 else if (strcmp(*argv,"-notext") == 0)
450                         notext=1;
451                 else if (strcmp(*argv,"-batch") == 0)
452                         batch=1;
453                 else if (strcmp(*argv,"-preserveDN") == 0)
454                         preserve=1;
455                 else if (strcmp(*argv,"-noemailDN") == 0)
456                         email_dn=0;
457                 else if (strcmp(*argv,"-gencrl") == 0)
458                         gencrl=1;
459                 else if (strcmp(*argv,"-msie_hack") == 0)
460                         msie_hack=1;
461                 else if (strcmp(*argv,"-crldays") == 0)
462                         {
463                         if (--argc < 1) goto bad;
464                         crldays= atol(*(++argv));
465                         }
466                 else if (strcmp(*argv,"-crlhours") == 0)
467                         {
468                         if (--argc < 1) goto bad;
469                         crlhours= atol(*(++argv));
470                         }
471                 else if (strcmp(*argv,"-infiles") == 0)
472                         {
473                         argc--;
474                         argv++;
475                         req=1;
476                         break;
477                         }
478                 else if (strcmp(*argv, "-ss_cert") == 0)
479                         {
480                         if (--argc < 1) goto bad;
481                         ss_cert_file = *(++argv);
482                         req=1;
483                         }
484                 else if (strcmp(*argv, "-spkac") == 0)
485                         {
486                         if (--argc < 1) goto bad;
487                         spkac_file = *(++argv);
488                         req=1;
489                         }
490                 else if (strcmp(*argv,"-revoke") == 0)
491                         {
492                         if (--argc < 1) goto bad;
493                         infile= *(++argv);
494                         dorevoke=1;
495                         }
496                 else if (strcmp(*argv,"-extensions") == 0)
497                         {
498                         if (--argc < 1) goto bad;
499                         extensions= *(++argv);
500                         }
501                 else if (strcmp(*argv,"-extfile") == 0)
502                         {
503                         if (--argc < 1) goto bad;
504                         extfile= *(++argv);
505                         }
506                 else if (strcmp(*argv,"-status") == 0)
507                         {
508                         if (--argc < 1) goto bad;
509                         ser_status= *(++argv);
510                         }
511                 else if (strcmp(*argv,"-updatedb") == 0)
512                         {
513                         doupdatedb=1;
514                         }
515                 else if (strcmp(*argv,"-crlexts") == 0)
516                         {
517                         if (--argc < 1) goto bad;
518                         crl_ext= *(++argv);
519                         }
520                 else if (strcmp(*argv,"-crl_reason") == 0)
521                         {
522                         if (--argc < 1) goto bad;
523                         rev_arg = *(++argv);
524                         rev_type = REV_CRL_REASON;
525                         }
526                 else if (strcmp(*argv,"-crl_hold") == 0)
527                         {
528                         if (--argc < 1) goto bad;
529                         rev_arg = *(++argv);
530                         rev_type = REV_HOLD;
531                         }
532                 else if (strcmp(*argv,"-crl_compromise") == 0)
533                         {
534                         if (--argc < 1) goto bad;
535                         rev_arg = *(++argv);
536                         rev_type = REV_KEY_COMPROMISE;
537                         }
538                 else if (strcmp(*argv,"-crl_CA_compromise") == 0)
539                         {
540                         if (--argc < 1) goto bad;
541                         rev_arg = *(++argv);
542                         rev_type = REV_CA_COMPROMISE;
543                         }
544 #ifndef OPENSSL_NO_ENGINE
545                 else if (strcmp(*argv,"-engine") == 0)
546                         {
547                         if (--argc < 1) goto bad;
548                         engine= *(++argv);
549                         }
550 #endif
551                 else
552                         {
553 bad:
554                         BIO_printf(bio_err,"unknown option %s\n",*argv);
555                         badops=1;
556                         break;
557                         }
558                 argc--;
559                 argv++;
560                 }
561
562         if (badops)
563                 {
564                 for (pp=ca_usage; (*pp != NULL); pp++)
565                         BIO_printf(bio_err,"%s",*pp);
566                 goto err;
567                 }
568
569         ERR_load_crypto_strings();
570
571 #ifndef OPENSSL_NO_ENGINE
572         e = setup_engine(bio_err, engine, 0);
573 #endif
574
575         /*****************************************************************/
576         tofree=NULL;
577         if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
578         if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
579         if (configfile == NULL)
580                 {
581                 const char *s=X509_get_default_cert_area();
582
583 #ifdef OPENSSL_SYS_VMS
584                 tofree=OPENSSL_malloc(strlen(s)+sizeof(CONFIG_FILE));
585                 strcpy(tofree,s);
586 #else
587                 tofree=OPENSSL_malloc(strlen(s)+sizeof(CONFIG_FILE)+1);
588                 strcpy(tofree,s);
589                 strcat(tofree,"/");
590 #endif
591                 strcat(tofree,CONFIG_FILE);
592                 configfile=tofree;
593                 }
594
595         BIO_printf(bio_err,"Using configuration from %s\n",configfile);
596         conf = NCONF_new(NULL);
597         if (NCONF_load(conf,configfile,&errorline) <= 0)
598                 {
599                 if (errorline <= 0)
600                         BIO_printf(bio_err,"error loading the config file '%s'\n",
601                                 configfile);
602                 else
603                         BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
604                                 ,errorline,configfile);
605                 goto err;
606                 }
607         if(tofree)
608                 {
609                 OPENSSL_free(tofree);
610                 tofree = NULL;
611                 }
612
613         if (!load_config(bio_err, conf))
614                 goto err;
615
616         /* Lets get the config section we are using */
617         if (section == NULL)
618                 {
619                 section=NCONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
620                 if (section == NULL)
621                         {
622                         lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
623                         goto err;
624                         }
625                 }
626
627         if (conf != NULL)
628                 {
629                 p=NCONF_get_string(conf,NULL,"oid_file");
630                 if (p == NULL)
631                         ERR_clear_error();
632                 if (p != NULL)
633                         {
634                         BIO *oid_bio;
635
636                         oid_bio=BIO_new_file(p,"r");
637                         if (oid_bio == NULL) 
638                                 {
639                                 /*
640                                 BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
641                                 ERR_print_errors(bio_err);
642                                 */
643                                 ERR_clear_error();
644                                 }
645                         else
646                                 {
647                                 OBJ_create_objects(oid_bio);
648                                 BIO_free(oid_bio);
649                                 }
650                         }
651                 if (!add_oid_section(bio_err,conf)) 
652                         {
653                         ERR_print_errors(bio_err);
654                         goto err;
655                         }
656                 }
657
658         randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
659         if (randfile == NULL)
660                 ERR_clear_error();
661         app_RAND_load_file(randfile, bio_err, 0);
662         
663         in=BIO_new(BIO_s_file());
664         out=BIO_new(BIO_s_file());
665         Sout=BIO_new(BIO_s_file());
666         Cout=BIO_new(BIO_s_file());
667         if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL))
668                 {
669                 ERR_print_errors(bio_err);
670                 goto err;
671                 }
672
673         /*****************************************************************/
674         /* report status of cert with serial number given on command line */
675         if (ser_status)
676         {
677                 if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
678                         {
679                         lookup_fail(section,ENV_DATABASE);
680                         goto err;
681                         }
682                 if (BIO_read_filename(in,dbfile) <= 0)
683                         {
684                         perror(dbfile);
685                         BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
686                         goto err;
687                         }
688                 db=TXT_DB_read(in,DB_NUMBER);
689                 if (db == NULL) goto err;
690
691                 if (!make_serial_index(db))
692                         goto err;
693
694                 if (get_certificate_status(ser_status,db) != 1)
695                         BIO_printf(bio_err,"Error verifying serial %s!\n",
696                                  ser_status);
697                 goto err;
698         }
699
700         /*****************************************************************/
701         /* we definitely need a public key, so let's get it */
702
703         if ((keyfile == NULL) && ((keyfile=NCONF_get_string(conf,
704                 section,ENV_PRIVATE_KEY)) == NULL))
705                 {
706                 lookup_fail(section,ENV_PRIVATE_KEY);
707                 goto err;
708                 }
709         if (!key)
710                 {
711                 free_key = 1;
712                 if (!app_passwd(bio_err, passargin, NULL, &key, NULL))
713                         {
714                         BIO_printf(bio_err,"Error getting password\n");
715                         goto err;
716                         }
717                 }
718         pkey = load_key(bio_err, keyfile, keyform, 0, key, e, 
719                 "CA private key");
720         if (key) OPENSSL_cleanse(key,strlen(key));
721         if (pkey == NULL)
722                 {
723                 /* load_key() has already printed an appropriate message */
724                 goto err;
725                 }
726
727         /*****************************************************************/
728         /* we need a certificate */
729         if ((certfile == NULL) && ((certfile=NCONF_get_string(conf,
730                 section,ENV_CERTIFICATE)) == NULL))
731                 {
732                 lookup_fail(section,ENV_CERTIFICATE);
733                 goto err;
734                 }
735         x509=load_cert(bio_err, certfile, FORMAT_PEM, NULL, e,
736                 "CA certificate");
737         if (x509 == NULL)
738                 goto err;
739
740         if (!X509_check_private_key(x509,pkey))
741                 {
742                 BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
743                 goto err;
744                 }
745
746         f=NCONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
747         if (f == NULL)
748                 ERR_clear_error();
749         if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
750                 preserve=1;
751         f=NCONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
752         if (f == NULL)
753                 ERR_clear_error();
754         if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
755                 msie_hack=1;
756
757         f=NCONF_get_string(conf,section,ENV_NAMEOPT);
758
759         if (f)
760                 {
761                 if (!set_name_ex(&nameopt, f))
762                         {
763                         BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f);
764                         goto err;
765                         }
766                 default_op = 0;
767                 }
768         else
769                 ERR_clear_error();
770
771         f=NCONF_get_string(conf,section,ENV_CERTOPT);
772
773         if (f)
774                 {
775                 if (!set_cert_ex(&certopt, f))
776                         {
777                         BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f);
778                         goto err;
779                         }
780                 default_op = 0;
781                 }
782         else
783                 ERR_clear_error();
784
785         f=NCONF_get_string(conf,section,ENV_EXTCOPY);
786
787         if (f)
788                 {
789                 if (!set_ext_copy(&ext_copy, f))
790                         {
791                         BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f);
792                         goto err;
793                         }
794                 }
795         else
796                 ERR_clear_error();
797
798         /*****************************************************************/
799         /* lookup where to write new certificates */
800         if ((outdir == NULL) && (req))
801                 {
802                 struct stat sb;
803
804                 if ((outdir=NCONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
805                         == NULL)
806                         {
807                         BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
808                         goto err;
809                         }
810 #ifndef OPENSSL_SYS_VMS
811             /* outdir is a directory spec, but access() for VMS demands a
812                filename.  In any case, stat(), below, will catch the problem
813                if outdir is not a directory spec, and the fopen() or open()
814                will catch an error if there is no write access.
815
816                Presumably, this problem could also be solved by using the DEC
817                C routines to convert the directory syntax to Unixly, and give
818                that to access().  However, time's too short to do that just
819                now.
820             */
821                 if (access(outdir,R_OK|W_OK|X_OK) != 0)
822                         {
823                         BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
824                         perror(outdir);
825                         goto err;
826                         }
827
828                 if (stat(outdir,&sb) != 0)
829                         {
830                         BIO_printf(bio_err,"unable to stat(%s)\n",outdir);
831                         perror(outdir);
832                         goto err;
833                         }
834 #ifdef S_IFDIR
835                 if (!(sb.st_mode & S_IFDIR))
836                         {
837                         BIO_printf(bio_err,"%s need to be a directory\n",outdir);
838                         perror(outdir);
839                         goto err;
840                         }
841 #endif
842 #endif
843                 }
844
845         /*****************************************************************/
846         /* we need to load the database file */
847         if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
848                 {
849                 lookup_fail(section,ENV_DATABASE);
850                 goto err;
851                 }
852         if (BIO_read_filename(in,dbfile) <= 0)
853                 {
854                 perror(dbfile);
855                 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
856                 goto err;
857                 }
858         db=TXT_DB_read(in,DB_NUMBER);
859         if (db == NULL) goto err;
860
861         /* Lets check some fields */
862         for (i=0; i<sk_num(db->data); i++)
863                 {
864                 pp=(char **)sk_value(db->data,i);
865                 if ((pp[DB_type][0] != DB_TYPE_REV) &&
866                         (pp[DB_rev_date][0] != '\0'))
867                         {
868                         BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
869                         goto err;
870                         }
871                 if ((pp[DB_type][0] == DB_TYPE_REV) &&
872                         !make_revoked(NULL, pp[DB_rev_date]))
873                         {
874                         BIO_printf(bio_err," in entry %d\n", i+1);
875                         goto err;
876                         }
877                 if (!check_time_format(pp[DB_exp_date]))
878                         {
879                         BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
880                         goto err;
881                         }
882                 p=pp[DB_serial];
883                 j=strlen(p);
884                 if (*p == '-')
885                         {
886                         p++;
887                         j--;
888                         }
889                 if ((j&1) || (j < 2))
890                         {
891                         BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
892                         goto err;
893                         }
894                 while (*p)
895                         {
896                         if (!(  ((*p >= '0') && (*p <= '9')) ||
897                                 ((*p >= 'A') && (*p <= 'F')) ||
898                                 ((*p >= 'a') && (*p <= 'f')))  )
899                                 {
900                                 BIO_printf(bio_err,"entry %d: bad serial number characters, char pos %ld, char is '%c'\n",i+1,(long)(p-pp[DB_serial]),*p);
901                                 goto err;
902                                 }
903                         p++;
904                         }
905                 }
906         if (verbose)
907                 {
908                 BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
909 #ifdef OPENSSL_SYS_VMS
910                 {
911                 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
912                 out = BIO_push(tmpbio, out);
913                 }
914 #endif
915                 TXT_DB_write(out,db);
916                 BIO_printf(bio_err,"%d entries loaded from the database\n",
917                         db->data->num);
918                 BIO_printf(bio_err,"generating index\n");
919                 }
920         
921         if (!make_serial_index(db))
922                 goto err;
923
924         if (!TXT_DB_create_index(db, DB_name, index_name_qual,
925                         LHASH_HASH_FN(index_name_hash),
926                         LHASH_COMP_FN(index_name_cmp)))
927                 {
928                 BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
929                         db->error,db->arg1,db->arg2);
930                 goto err;
931                 }
932
933         /*****************************************************************/
934         /* Update the db file for expired certificates */
935         if (doupdatedb)
936                 {
937                 if (verbose)
938                         BIO_printf(bio_err, "Updating %s ...\n",
939                                                         dbfile);
940
941                 i = do_updatedb(db);
942                 if (i == -1)
943                         {
944                         BIO_printf(bio_err,"Malloc failure\n");
945                         goto err;
946                         }
947                 else if (i == 0)
948                         {
949                         if (verbose) BIO_printf(bio_err,
950                                         "No entries found to mark expired\n"); 
951                         }
952                 else
953                         {
954                         out = BIO_new(BIO_s_file());
955                         if (out == NULL)
956                                 {
957                                 ERR_print_errors(bio_err);
958                                 goto err;
959                                 }
960
961 #ifndef OPENSSL_SYS_VMS
962                         j = BIO_snprintf(buf[0], sizeof buf[0], "%s.new", dbfile);
963 #else
964                         j = BIO_snprintf(buf[0], sizeof buf[0], "%s-new", dbfile);
965 #endif
966                         if (j < 0 || j >= sizeof buf[0])
967                                 {
968                                 BIO_printf(bio_err, "file name too long\n");
969                                 goto err;
970                                 }
971                         if (BIO_write_filename(out,buf[0]) <= 0)
972                                 {
973                                 perror(dbfile);
974                                 BIO_printf(bio_err,"unable to open '%s'\n",
975                                                                         dbfile);
976                                 goto err;
977                                 }
978                         j=TXT_DB_write(out,db);
979                         if (j <= 0) goto err;
980                         
981                         BIO_free(out);
982                         out = NULL;
983 #ifndef OPENSSL_SYS_VMS
984                         j = BIO_snprintf(buf[1], sizeof buf[1], "%s.old", dbfile);
985 #else
986                         j = BIO_snprintf(buf[1], sizeof buf[1], "%s-old", dbfile);
987 #endif
988                         if (j < 0 || j >= sizeof buf[1])
989                                 {
990                                 BIO_printf(bio_err, "file name too long\n");
991                                 goto err;
992                                 }
993                         if (rename(dbfile,buf[1]) < 0)
994                                 {
995                                 BIO_printf(bio_err,
996                                                 "unable to rename %s to %s\n",
997                                                 dbfile, buf[1]);
998                                 perror("reason");
999                                 goto err;
1000                                 }
1001                         if (rename(buf[0],dbfile) < 0)
1002                                 {
1003                                 BIO_printf(bio_err,
1004                                                 "unable to rename %s to %s\n",
1005                                                 buf[0],dbfile);
1006                                 perror("reason");
1007                                 rename(buf[1],dbfile);
1008                                 goto err;
1009                                 }
1010                                 
1011                         if (verbose) BIO_printf(bio_err,
1012                                 "Done. %d entries marked as expired\n",i); 
1013                         }
1014                         goto err;
1015                 }
1016
1017         /*****************************************************************/
1018         /* Read extentions config file                                   */
1019         if (extfile)
1020                 {
1021                 extconf = NCONF_new(NULL);
1022                 if (NCONF_load(extconf,extfile,&errorline) <= 0)
1023                         {
1024                         if (errorline <= 0)
1025                                 BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
1026                                         extfile);
1027                         else
1028                                 BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n",
1029                                         errorline,extfile);
1030                         ret = 1;
1031                         goto err;
1032                         }
1033
1034                 if (verbose)
1035                         BIO_printf(bio_err, "Successfully loaded extensions file %s\n", extfile);
1036
1037                 /* We can have sections in the ext file */
1038                 if (!extensions && !(extensions = NCONF_get_string(extconf, "default", "extensions")))
1039                         extensions = "default";
1040                 }
1041
1042         /*****************************************************************/
1043         if (req || gencrl)
1044                 {
1045                 if (outfile != NULL)
1046                         {
1047                         if (BIO_write_filename(Sout,outfile) <= 0)
1048                                 {
1049                                 perror(outfile);
1050                                 goto err;
1051                                 }
1052                         }
1053                 else
1054                         {
1055                         BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
1056 #ifdef OPENSSL_SYS_VMS
1057                         {
1058                         BIO *tmpbio = BIO_new(BIO_f_linebuffer());
1059                         Sout = BIO_push(tmpbio, Sout);
1060                         }
1061 #endif
1062                         }
1063                 }
1064
1065         if (req)
1066                 {
1067                 if ((md == NULL) && ((md=NCONF_get_string(conf,
1068                         section,ENV_DEFAULT_MD)) == NULL))
1069                         {
1070                         lookup_fail(section,ENV_DEFAULT_MD);
1071                         goto err;
1072                         }
1073                 if ((email_dn == 1) && ((tmp_email_dn=NCONF_get_string(conf,
1074                         section,ENV_DEFAULT_EMAIL_DN)) != NULL ))
1075                         {
1076                         if(strcmp(tmp_email_dn,"no") == 0)
1077                                 email_dn=0;
1078                         }
1079                 if ((dgst=EVP_get_digestbyname(md)) == NULL)
1080                         {
1081                         BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1082                         goto err;
1083                         }
1084                 if (verbose)
1085                         BIO_printf(bio_err,"message digest is %s\n",
1086                                 OBJ_nid2ln(dgst->type));
1087                 if ((policy == NULL) && ((policy=NCONF_get_string(conf,
1088                         section,ENV_POLICY)) == NULL))
1089                         {
1090                         lookup_fail(section,ENV_POLICY);
1091                         goto err;
1092                         }
1093                 if (verbose)
1094                         BIO_printf(bio_err,"policy is %s\n",policy);
1095
1096                 if ((serialfile=NCONF_get_string(conf,section,ENV_SERIAL))
1097                         == NULL)
1098                         {
1099                         lookup_fail(section,ENV_SERIAL);
1100                         goto err;
1101                         }
1102
1103                 if (!extconf)
1104                         {
1105                         /* no '-extfile' option, so we look for extensions
1106                          * in the main configuration file */
1107                         if (!extensions)
1108                                 {
1109                                 extensions=NCONF_get_string(conf,section,
1110                                                                 ENV_EXTENSIONS);
1111                                 if (!extensions)
1112                                         ERR_clear_error();
1113                                 }
1114                         if (extensions)
1115                                 {
1116                                 /* Check syntax of file */
1117                                 X509V3_CTX ctx;
1118                                 X509V3_set_ctx_test(&ctx);
1119                                 X509V3_set_nconf(&ctx, conf);
1120                                 if (!X509V3_EXT_add_nconf(conf, &ctx, extensions,
1121                                                                 NULL))
1122                                         {
1123                                         BIO_printf(bio_err,
1124                                         "Error Loading extension section %s\n",
1125                                                                  extensions);
1126                                         ret = 1;
1127                                         goto err;
1128                                         }
1129                                 }
1130                         }
1131
1132                 if (startdate == NULL)
1133                         {
1134                         startdate=NCONF_get_string(conf,section,
1135                                 ENV_DEFAULT_STARTDATE);
1136                         if (startdate == NULL)
1137                                 ERR_clear_error();
1138                         }
1139                 if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
1140                         {
1141                         BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
1142                         goto err;
1143                         }
1144                 if (startdate == NULL) startdate="today";
1145
1146                 if (enddate == NULL)
1147                         {
1148                         enddate=NCONF_get_string(conf,section,
1149                                 ENV_DEFAULT_ENDDATE);
1150                         if (enddate == NULL)
1151                                 ERR_clear_error();
1152                         }
1153                 if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
1154                         {
1155                         BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
1156                         goto err;
1157                         }
1158
1159                 if (days == 0)
1160                         {
1161                         if(!NCONF_get_number(conf,section, ENV_DEFAULT_DAYS, &days))
1162                                 days = 0;
1163                         }
1164                 if (!enddate && (days == 0))
1165                         {
1166                         BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
1167                         goto err;
1168                         }
1169
1170                 if ((serial=load_serial(serialfile)) == NULL)
1171                         {
1172                         BIO_printf(bio_err,"error while loading serial number\n");
1173                         goto err;
1174                         }
1175                 if (verbose)
1176                         {
1177                         if (BN_is_zero(serial))
1178                                 BIO_printf(bio_err,"next serial number is 00\n");
1179                         else
1180                                 {
1181                                 if ((f=BN_bn2hex(serial)) == NULL) goto err;
1182                                 BIO_printf(bio_err,"next serial number is %s\n",f);
1183                                 OPENSSL_free(f);
1184                                 }
1185                         }
1186
1187                 if ((attribs=NCONF_get_section(conf,policy)) == NULL)
1188                         {
1189                         BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
1190                         goto err;
1191                         }
1192
1193                 if ((cert_sk=sk_X509_new_null()) == NULL)
1194                         {
1195                         BIO_printf(bio_err,"Memory allocation failure\n");
1196                         goto err;
1197                         }
1198                 if (spkac_file != NULL)
1199                         {
1200                         total++;
1201                         j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
1202                                 serial,subj,email_dn,startdate,enddate,days,extensions,
1203                                 conf,verbose,certopt,nameopt,default_op,ext_copy);
1204                         if (j < 0) goto err;
1205                         if (j > 0)
1206                                 {
1207                                 total_done++;
1208                                 BIO_printf(bio_err,"\n");
1209                                 if (!BN_add_word(serial,1)) goto err;
1210                                 if (!sk_X509_push(cert_sk,x))
1211                                         {
1212                                         BIO_printf(bio_err,"Memory allocation failure\n");
1213                                         goto err;
1214                                         }
1215                                 if (outfile)
1216                                         {
1217                                         output_der = 1;
1218                                         batch = 1;
1219                                         }
1220                                 }
1221                         }
1222                 if (ss_cert_file != NULL)
1223                         {
1224                         total++;
1225                         j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
1226                                 db,serial,subj,email_dn,startdate,enddate,days,batch,
1227                                 extensions,conf,verbose, certopt, nameopt,
1228                                 default_op, ext_copy, e);
1229                         if (j < 0) goto err;
1230                         if (j > 0)
1231                                 {
1232                                 total_done++;
1233                                 BIO_printf(bio_err,"\n");
1234                                 if (!BN_add_word(serial,1)) goto err;
1235                                 if (!sk_X509_push(cert_sk,x))
1236                                         {
1237                                         BIO_printf(bio_err,"Memory allocation failure\n");
1238                                         goto err;
1239                                         }
1240                                 }
1241                         }
1242                 if (infile != NULL)
1243                         {
1244                         total++;
1245                         j=certify(&x,infile,pkey,x509,dgst,attribs,db,
1246                                 serial,subj,email_dn,startdate,enddate,days,batch,
1247                                 extensions,conf,verbose, certopt, nameopt,
1248                                 default_op, ext_copy);
1249                         if (j < 0) goto err;
1250                         if (j > 0)
1251                                 {
1252                                 total_done++;
1253                                 BIO_printf(bio_err,"\n");
1254                                 if (!BN_add_word(serial,1)) goto err;
1255                                 if (!sk_X509_push(cert_sk,x))
1256                                         {
1257                                         BIO_printf(bio_err,"Memory allocation failure\n");
1258                                         goto err;
1259                                         }
1260                                 }
1261                         }
1262                 for (i=0; i<argc; i++)
1263                         {
1264                         total++;
1265                         j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
1266                                 serial,subj,email_dn,startdate,enddate,days,batch,
1267                                 extensions,conf,verbose, certopt, nameopt,
1268                                 default_op, ext_copy);
1269                         if (j < 0) goto err;
1270                         if (j > 0)
1271                                 {
1272                                 total_done++;
1273                                 BIO_printf(bio_err,"\n");
1274                                 if (!BN_add_word(serial,1)) goto err;
1275                                 if (!sk_X509_push(cert_sk,x))
1276                                         {
1277                                         BIO_printf(bio_err,"Memory allocation failure\n");
1278                                         goto err;
1279                                         }
1280                                 }
1281                         }       
1282                 /* we have a stack of newly certified certificates
1283                  * and a data base and serial number that need
1284                  * updating */
1285
1286                 if (sk_X509_num(cert_sk) > 0)
1287                         {
1288                         if (!batch)
1289                                 {
1290                                 BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
1291                                 (void)BIO_flush(bio_err);
1292                                 buf[0][0]='\0';
1293                                 fgets(buf[0],10,stdin);
1294                                 if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
1295                                         {
1296                                         BIO_printf(bio_err,"CERTIFICATION CANCELED\n"); 
1297                                         ret=0;
1298                                         goto err;
1299                                         }
1300                                 }
1301
1302                         BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
1303
1304                         if(strlen(serialfile) > BSIZE-5 || strlen(dbfile) > BSIZE-5)
1305                                 {
1306                                 BIO_printf(bio_err,"file name too long\n");
1307                                 goto err;
1308                                 }
1309
1310                         strcpy(buf[0],serialfile);
1311
1312 #ifdef OPENSSL_SYS_VMS
1313                         strcat(buf[0],"-new");
1314 #else
1315                         strcat(buf[0],".new");
1316 #endif
1317
1318                         if (!save_serial(buf[0],serial)) goto err;
1319
1320                         strcpy(buf[1],dbfile);
1321
1322 #ifdef OPENSSL_SYS_VMS
1323                         strcat(buf[1],"-new");
1324 #else
1325                         strcat(buf[1],".new");
1326 #endif
1327
1328                         if (BIO_write_filename(out,buf[1]) <= 0)
1329                                 {
1330                                 perror(dbfile);
1331                                 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1332                                 goto err;
1333                                 }
1334                         l=TXT_DB_write(out,db);
1335                         if (l <= 0) goto err;
1336                         }
1337         
1338                 if (verbose)
1339                         BIO_printf(bio_err,"writing new certificates\n");
1340                 for (i=0; i<sk_X509_num(cert_sk); i++)
1341                         {
1342                         int k;
1343                         unsigned char *n;
1344
1345                         x=sk_X509_value(cert_sk,i);
1346
1347                         j=x->cert_info->serialNumber->length;
1348                         p=(char *)x->cert_info->serialNumber->data;
1349                         
1350                         if(strlen(outdir) >= (size_t)(j ? BSIZE-j*2-6 : BSIZE-8))
1351                                 {
1352                                 BIO_printf(bio_err,"certificate file name too long\n");
1353                                 goto err;
1354                                 }
1355
1356                         strcpy(buf[2],outdir);
1357
1358 #ifndef OPENSSL_SYS_VMS
1359                         strcat(buf[2],"/");
1360 #endif
1361
1362                         n=(unsigned char *)&(buf[2][strlen(buf[2])]);
1363                         if (j > 0)
1364                                 {
1365                                 for (k=0; k<j; k++)
1366                                         {
1367                                         sprintf((char *)n,"%02X",(unsigned char)*(p++));
1368                                         n+=2;
1369                                         }
1370                                 }
1371                         else
1372                                 {
1373                                 *(n++)='0';
1374                                 *(n++)='0';
1375                                 }
1376                         *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
1377                         *n='\0';
1378                         if (verbose)
1379                                 BIO_printf(bio_err,"writing %s\n",buf[2]);
1380
1381                         if (BIO_write_filename(Cout,buf[2]) <= 0)
1382                                 {
1383                                 perror(buf[2]);
1384                                 goto err;
1385                                 }
1386                         write_new_certificate(Cout,x, 0, notext);
1387                         write_new_certificate(Sout,x, output_der, notext);
1388                         }
1389
1390                 if (sk_X509_num(cert_sk))
1391                         {
1392                         /* Rename the database and the serial file */
1393                         strncpy(buf[2],serialfile,BSIZE-4);
1394                         buf[2][BSIZE-4]='\0';
1395
1396 #ifdef OPENSSL_SYS_VMS
1397                         strcat(buf[2],"-old");
1398 #else
1399                         strcat(buf[2],".old");
1400 #endif
1401
1402                         BIO_free(in);
1403                         BIO_free_all(out);
1404                         in=NULL;
1405                         out=NULL;
1406                         if (rename(serialfile,buf[2]) < 0)
1407                                 {
1408                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1409                                         serialfile,buf[2]);
1410                                 perror("reason");
1411                                 goto err;
1412                                 }
1413                         if (rename(buf[0],serialfile) < 0)
1414                                 {
1415                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1416                                         buf[0],serialfile);
1417                                 perror("reason");
1418                                 rename(buf[2],serialfile);
1419                                 goto err;
1420                                 }
1421
1422                         strncpy(buf[2],dbfile,BSIZE-4);
1423                         buf[2][BSIZE-4]='\0';
1424
1425 #ifdef OPENSSL_SYS_VMS
1426                         strcat(buf[2],"-old");
1427 #else
1428                         strcat(buf[2],".old");
1429 #endif
1430
1431                         if (rename(dbfile,buf[2]) < 0)
1432                                 {
1433                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1434                                         dbfile,buf[2]);
1435                                 perror("reason");
1436                                 goto err;
1437                                 }
1438                         if (rename(buf[1],dbfile) < 0)
1439                                 {
1440                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1441                                         buf[1],dbfile);
1442                                 perror("reason");
1443                                 rename(buf[2],dbfile);
1444                                 goto err;
1445                                 }
1446                         BIO_printf(bio_err,"Data Base Updated\n");
1447                         }
1448                 }
1449         
1450         /*****************************************************************/
1451         if (gencrl)
1452                 {
1453                 int crl_v2 = 0;
1454                 if (!crl_ext)
1455                         {
1456                         crl_ext=NCONF_get_string(conf,section,ENV_CRLEXT);
1457                         if (!crl_ext)
1458                                 ERR_clear_error();
1459                         }
1460                 if (crl_ext)
1461                         {
1462                         /* Check syntax of file */
1463                         X509V3_CTX ctx;
1464                         X509V3_set_ctx_test(&ctx);
1465                         X509V3_set_nconf(&ctx, conf);
1466                         if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL))
1467                                 {
1468                                 BIO_printf(bio_err,
1469                                  "Error Loading CRL extension section %s\n",
1470                                                                  crl_ext);
1471                                 ret = 1;
1472                                 goto err;
1473                                 }
1474                         }
1475
1476                 if (!crldays && !crlhours)
1477                         {
1478                         if (!NCONF_get_number(conf,section,
1479                                 ENV_DEFAULT_CRL_DAYS, &crldays))
1480                                 crldays = 0;
1481                         if (!NCONF_get_number(conf,section,
1482                                 ENV_DEFAULT_CRL_HOURS, &crlhours))
1483                                 crlhours = 0;
1484                         }
1485                 if ((crldays == 0) && (crlhours == 0))
1486                         {
1487                         BIO_printf(bio_err,"cannot lookup how long until the next CRL is issued\n");
1488                         goto err;
1489                         }
1490
1491                 if (verbose) BIO_printf(bio_err,"making CRL\n");
1492                 if ((crl=X509_CRL_new()) == NULL) goto err;
1493                 if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) goto err;
1494
1495                 tmptm = ASN1_TIME_new();
1496                 if (!tmptm) goto err;
1497                 X509_gmtime_adj(tmptm,0);
1498                 X509_CRL_set_lastUpdate(crl, tmptm);    
1499                 X509_gmtime_adj(tmptm,(crldays*24+crlhours)*60*60);
1500                 X509_CRL_set_nextUpdate(crl, tmptm);    
1501
1502                 ASN1_TIME_free(tmptm);
1503
1504                 for (i=0; i<sk_num(db->data); i++)
1505                         {
1506                         pp=(char **)sk_value(db->data,i);
1507                         if (pp[DB_type][0] == DB_TYPE_REV)
1508                                 {
1509                                 if ((r=X509_REVOKED_new()) == NULL) goto err;
1510                                 j = make_revoked(r, pp[DB_rev_date]);
1511                                 if (!j) goto err;
1512                                 if (j == 2) crl_v2 = 1;
1513                                 if (!BN_hex2bn(&serial, pp[DB_serial]))
1514                                         goto err;
1515                                 tmpser = BN_to_ASN1_INTEGER(serial, NULL);
1516                                 BN_free(serial);
1517                                 serial = NULL;
1518                                 if (!tmpser)
1519                                         goto err;
1520                                 X509_REVOKED_set_serialNumber(r, tmpser);
1521                                 ASN1_INTEGER_free(tmpser);
1522                                 X509_CRL_add0_revoked(crl,r);
1523                                 }
1524                         }
1525
1526                 /* sort the data so it will be written in serial
1527                  * number order */
1528                 X509_CRL_sort(crl);
1529
1530                 /* we now have a CRL */
1531                 if (verbose) BIO_printf(bio_err,"signing CRL\n");
1532                 if (md != NULL)
1533                         {
1534                         if ((dgst=EVP_get_digestbyname(md)) == NULL)
1535                                 {
1536                                 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1537                                 goto err;
1538                                 }
1539                         }
1540                 else
1541                         {
1542 #ifndef OPENSSL_NO_DSA
1543                         if (pkey->type == EVP_PKEY_DSA) 
1544                                 dgst=EVP_dss1();
1545                         else
1546 #endif
1547                                 dgst=EVP_md5();
1548                         }
1549
1550                 /* Add any extensions asked for */
1551
1552                 if (crl_ext)
1553                         {
1554                         X509V3_CTX crlctx;
1555                         X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1556                         X509V3_set_nconf(&crlctx, conf);
1557
1558                         if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx,
1559                                 crl_ext, crl)) goto err;
1560                         }
1561                 if (crl_ext || crl_v2)
1562                         {
1563                         if (!X509_CRL_set_version(crl, 1))
1564                                 goto err; /* version 2 CRL */
1565                         }
1566
1567                 if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1568
1569                 PEM_write_bio_X509_CRL(Sout,crl);
1570                 }
1571         /*****************************************************************/
1572         if (dorevoke)
1573                 {
1574                 if (infile == NULL) 
1575                         {
1576                         BIO_printf(bio_err,"no input files\n");
1577                         goto err;
1578                         }
1579                 else
1580                         {
1581                         X509 *revcert;
1582                         revcert=load_cert(bio_err, infile, FORMAT_PEM,
1583                                 NULL, e, infile);
1584                         if (revcert == NULL)
1585                                 goto err;
1586                         j=do_revoke(revcert,db, rev_type, rev_arg);
1587                         if (j <= 0) goto err;
1588                         X509_free(revcert);
1589
1590                         if(strlen(dbfile) > BSIZE-5)
1591                                 {
1592                                 BIO_printf(bio_err,"filename too long\n");
1593                                 goto err;
1594                                 }
1595
1596                         strcpy(buf[0],dbfile);
1597 #ifndef OPENSSL_SYS_VMS
1598                         strcat(buf[0],".new");
1599 #else
1600                         strcat(buf[0],"-new");
1601 #endif
1602                         if (BIO_write_filename(out,buf[0]) <= 0)
1603                                 {
1604                                 perror(dbfile);
1605                                 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1606                                 goto err;
1607                                 }
1608                         j=TXT_DB_write(out,db);
1609                         if (j <= 0) goto err;
1610                         BIO_free_all(out);
1611                         out = NULL;
1612                         BIO_free_all(in);
1613                         in = NULL;
1614                         strncpy(buf[1],dbfile,BSIZE-4);
1615                         buf[1][BSIZE-4]='\0';
1616 #ifndef OPENSSL_SYS_VMS
1617                         strcat(buf[1],".old");
1618 #else
1619                         strcat(buf[1],"-old");
1620 #endif
1621                         if (rename(dbfile,buf[1]) < 0)
1622                                 {
1623                                 BIO_printf(bio_err,"unable to rename %s to %s\n", dbfile, buf[1]);
1624                                 perror("reason");
1625                                 goto err;
1626                                 }
1627                         if (rename(buf[0],dbfile) < 0)
1628                                 {
1629                                 BIO_printf(bio_err,"unable to rename %s to %s\n", buf[0],dbfile);
1630                                 perror("reason");
1631                                 rename(buf[1],dbfile);
1632                                 goto err;
1633                                 }
1634                         BIO_printf(bio_err,"Data Base Updated\n"); 
1635                         }
1636                 }
1637         /*****************************************************************/
1638         ret=0;
1639 err:
1640         if(tofree)
1641                 OPENSSL_free(tofree);
1642         BIO_free_all(Cout);
1643         BIO_free_all(Sout);
1644         BIO_free_all(out);
1645         BIO_free_all(in);
1646
1647         if (cert_sk)
1648                 sk_X509_pop_free(cert_sk,X509_free);
1649
1650         if (ret) ERR_print_errors(bio_err);
1651         app_RAND_write_file(randfile, bio_err);
1652         if (free_key && key)
1653                 OPENSSL_free(key);
1654         BN_free(serial);
1655         TXT_DB_free(db);
1656         EVP_PKEY_free(pkey);
1657         X509_free(x509);
1658         X509_CRL_free(crl);
1659         NCONF_free(conf);
1660         OBJ_cleanup();
1661         apps_shutdown();
1662         OPENSSL_EXIT(ret);
1663         }
1664
1665 static void lookup_fail(char *name, char *tag)
1666         {
1667         BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1668         }
1669
1670 static unsigned long index_serial_hash(const char **a)
1671         {
1672         const char *n;
1673
1674         n=a[DB_serial];
1675         while (*n == '0') n++;
1676         return(lh_strhash(n));
1677         }
1678
1679 static int index_serial_cmp(const char **a, const char **b)
1680         {
1681         const char *aa,*bb;
1682
1683         for (aa=a[DB_serial]; *aa == '0'; aa++);
1684         for (bb=b[DB_serial]; *bb == '0'; bb++);
1685         return(strcmp(aa,bb));
1686         }
1687
1688 static unsigned long index_name_hash(const char **a)
1689         { return(lh_strhash(a[DB_name])); }
1690
1691 static int index_name_qual(char **a)
1692         { return(a[0][0] == 'V'); }
1693
1694 static int index_name_cmp(const char **a, const char **b)
1695         { return(strcmp(a[DB_name],
1696              b[DB_name])); }
1697
1698 static BIGNUM *load_serial(char *serialfile)
1699         {
1700         BIO *in=NULL;
1701         BIGNUM *ret=NULL;
1702         MS_STATIC char buf[1024];
1703         ASN1_INTEGER *ai=NULL;
1704
1705         if ((in=BIO_new(BIO_s_file())) == NULL)
1706                 {
1707                 ERR_print_errors(bio_err);
1708                 goto err;
1709                 }
1710
1711         if (BIO_read_filename(in,serialfile) <= 0)
1712                 {
1713                 perror(serialfile);
1714                 goto err;
1715                 }
1716         ai=ASN1_INTEGER_new();
1717         if (ai == NULL) goto err;
1718         if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
1719                 {
1720                 BIO_printf(bio_err,"unable to load number from %s\n",
1721                         serialfile);
1722                 goto err;
1723                 }
1724         ret=ASN1_INTEGER_to_BN(ai,NULL);
1725         if (ret == NULL)
1726                 {
1727                 BIO_printf(bio_err,"error converting number from bin to BIGNUM\n");
1728                 goto err;
1729                 }
1730 err:
1731         if (in != NULL) BIO_free(in);
1732         if (ai != NULL) ASN1_INTEGER_free(ai);
1733         return(ret);
1734         }
1735
1736 static int save_serial(char *serialfile, BIGNUM *serial)
1737         {
1738         BIO *out;
1739         int ret=0;
1740         ASN1_INTEGER *ai=NULL;
1741
1742         out=BIO_new(BIO_s_file());
1743         if (out == NULL)
1744                 {
1745                 ERR_print_errors(bio_err);
1746                 goto err;
1747                 }
1748         if (BIO_write_filename(out,serialfile) <= 0)
1749                 {
1750                 perror(serialfile);
1751                 goto err;
1752                 }
1753
1754         if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
1755                 {
1756                 BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
1757                 goto err;
1758                 }
1759         i2a_ASN1_INTEGER(out,ai);
1760         BIO_puts(out,"\n");
1761         ret=1;
1762 err:
1763         if (out != NULL) BIO_free_all(out);
1764         if (ai != NULL) ASN1_INTEGER_free(ai);
1765         return(ret);
1766         }
1767
1768 static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1769              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1770              BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate,
1771              long days, int batch, char *ext_sect, CONF *lconf, int verbose,
1772              unsigned long certopt, unsigned long nameopt, int default_op,
1773              int ext_copy)
1774         {
1775         X509_REQ *req=NULL;
1776         BIO *in=NULL;
1777         EVP_PKEY *pktmp=NULL;
1778         int ok= -1,i;
1779
1780         in=BIO_new(BIO_s_file());
1781
1782         if (BIO_read_filename(in,infile) <= 0)
1783                 {
1784                 perror(infile);
1785                 goto err;
1786                 }
1787         if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
1788                 {
1789                 BIO_printf(bio_err,"Error reading certificate request in %s\n",
1790                         infile);
1791                 goto err;
1792                 }
1793         if (verbose)
1794                 X509_REQ_print(bio_err,req);
1795
1796         BIO_printf(bio_err,"Check that the request matches the signature\n");
1797
1798         if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
1799                 {
1800                 BIO_printf(bio_err,"error unpacking public key\n");
1801                 goto err;
1802                 }
1803         i=X509_REQ_verify(req,pktmp);
1804         EVP_PKEY_free(pktmp);
1805         if (i < 0)
1806                 {
1807                 ok=0;
1808                 BIO_printf(bio_err,"Signature verification problems....\n");
1809                 goto err;
1810                 }
1811         if (i == 0)
1812                 {
1813                 ok=0;
1814                 BIO_printf(bio_err,"Signature did not match the certificate request\n");
1815                 goto err;
1816                 }
1817         else
1818                 BIO_printf(bio_err,"Signature ok\n");
1819
1820         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj, email_dn,
1821                 startdate,enddate,days,batch,verbose,req,ext_sect,lconf,
1822                 certopt, nameopt, default_op, ext_copy);
1823
1824 err:
1825         if (req != NULL) X509_REQ_free(req);
1826         if (in != NULL) BIO_free(in);
1827         return(ok);
1828         }
1829
1830 static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1831              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1832              BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate,
1833              long days, int batch, char *ext_sect, CONF *lconf, int verbose,
1834              unsigned long certopt, unsigned long nameopt, int default_op,
1835              int ext_copy, ENGINE *e)
1836         {
1837         X509 *req=NULL;
1838         X509_REQ *rreq=NULL;
1839         EVP_PKEY *pktmp=NULL;
1840         int ok= -1,i;
1841
1842         if ((req=load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL)
1843                 goto err;
1844         if (verbose)
1845                 X509_print(bio_err,req);
1846
1847         BIO_printf(bio_err,"Check that the request matches the signature\n");
1848
1849         if ((pktmp=X509_get_pubkey(req)) == NULL)
1850                 {
1851                 BIO_printf(bio_err,"error unpacking public key\n");
1852                 goto err;
1853                 }
1854         i=X509_verify(req,pktmp);
1855         EVP_PKEY_free(pktmp);
1856         if (i < 0)
1857                 {
1858                 ok=0;
1859                 BIO_printf(bio_err,"Signature verification problems....\n");
1860                 goto err;
1861                 }
1862         if (i == 0)
1863                 {
1864                 ok=0;
1865                 BIO_printf(bio_err,"Signature did not match the certificate\n");
1866                 goto err;
1867                 }
1868         else
1869                 BIO_printf(bio_err,"Signature ok\n");
1870
1871         if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
1872                 goto err;
1873
1874         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,email_dn,startdate,enddate,
1875                 days,batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op,
1876                 ext_copy);
1877
1878 err:
1879         if (rreq != NULL) X509_REQ_free(rreq);
1880         if (req != NULL) X509_free(req);
1881         return(ok);
1882         }
1883
1884 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1885              STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial, char *subj,
1886              int email_dn, char *startdate, char *enddate, long days, int batch,
1887              int verbose, X509_REQ *req, char *ext_sect, CONF *lconf,
1888              unsigned long certopt, unsigned long nameopt, int default_op,
1889              int ext_copy)
1890         {
1891         X509_NAME *name=NULL,*CAname=NULL,*subject=NULL, *dn_subject=NULL;
1892         ASN1_UTCTIME *tm,*tmptm;
1893         ASN1_STRING *str,*str2;
1894         ASN1_OBJECT *obj;
1895         X509 *ret=NULL;
1896         X509_CINF *ci;
1897         X509_NAME_ENTRY *ne;
1898         X509_NAME_ENTRY *tne,*push;
1899         EVP_PKEY *pktmp;
1900         int ok= -1,i,j,last,nid;
1901         char *p;
1902         CONF_VALUE *cv;
1903         char *row[DB_NUMBER],**rrow,**irow=NULL;
1904         char buf[25];
1905
1906         tmptm=ASN1_UTCTIME_new();
1907         if (tmptm == NULL)
1908                 {
1909                 BIO_printf(bio_err,"malloc error\n");
1910                 return(0);
1911                 }
1912
1913         for (i=0; i<DB_NUMBER; i++)
1914                 row[i]=NULL;
1915
1916         if (subj)
1917                 {
1918                 X509_NAME *n = do_subject(subj, MBSTRING_ASC);
1919
1920                 if (!n)
1921                         {
1922                         ERR_print_errors(bio_err);
1923                         goto err;
1924                         }
1925                 X509_REQ_set_subject_name(req,n);
1926                 req->req_info->enc.modified = 1;
1927                 X509_NAME_free(n);
1928                 }
1929
1930         if (default_op)
1931                 BIO_printf(bio_err,"The Subject's Distinguished Name is as follows\n");
1932
1933         name=X509_REQ_get_subject_name(req);
1934         for (i=0; i<X509_NAME_entry_count(name); i++)
1935                 {
1936                 ne= X509_NAME_get_entry(name,i);
1937                 str=X509_NAME_ENTRY_get_data(ne);
1938                 obj=X509_NAME_ENTRY_get_object(ne);
1939
1940                 if (msie_hack)
1941                         {
1942                         /* assume all type should be strings */
1943                         nid=OBJ_obj2nid(ne->object);
1944
1945                         if (str->type == V_ASN1_UNIVERSALSTRING)
1946                                 ASN1_UNIVERSALSTRING_to_string(str);
1947
1948                         if ((str->type == V_ASN1_IA5STRING) &&
1949                                 (nid != NID_pkcs9_emailAddress))
1950                                 str->type=V_ASN1_T61STRING;
1951
1952                         if ((nid == NID_pkcs9_emailAddress) &&
1953                                 (str->type == V_ASN1_PRINTABLESTRING))
1954                                 str->type=V_ASN1_IA5STRING;
1955                         }
1956
1957                 /* If no EMAIL is wanted in the subject */
1958                 if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn))
1959                         continue;
1960
1961                 /* check some things */
1962                 if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1963                         (str->type != V_ASN1_IA5STRING))
1964                         {
1965                         BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
1966                         goto err;
1967                         }
1968                 if ((str->type != V_ASN1_BMPSTRING) && (str->type != V_ASN1_UTF8STRING))
1969                         {
1970                         j=ASN1_PRINTABLE_type(str->data,str->length);
1971                         if (    ((j == V_ASN1_T61STRING) &&
1972                                  (str->type != V_ASN1_T61STRING)) ||
1973                                 ((j == V_ASN1_IA5STRING) &&
1974                                  (str->type == V_ASN1_PRINTABLESTRING)))
1975                                 {
1976                                 BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1977                                 goto err;
1978                                 }
1979                         }
1980
1981                 if (default_op)
1982                         old_entry_print(bio_err, obj, str);
1983                 }
1984
1985         /* Ok, now we check the 'policy' stuff. */
1986         if ((subject=X509_NAME_new()) == NULL)
1987                 {
1988                 BIO_printf(bio_err,"Memory allocation failure\n");
1989                 goto err;
1990                 }
1991
1992         /* take a copy of the issuer name before we mess with it. */
1993         CAname=X509_NAME_dup(x509->cert_info->subject);
1994         if (CAname == NULL) goto err;
1995         str=str2=NULL;
1996
1997         for (i=0; i<sk_CONF_VALUE_num(policy); i++)
1998                 {
1999                 cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
2000                 if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
2001                         {
2002                         BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
2003                         goto err;
2004                         }
2005                 obj=OBJ_nid2obj(j);
2006
2007                 last= -1;
2008                 for (;;)
2009                         {
2010                         /* lookup the object in the supplied name list */
2011                         j=X509_NAME_get_index_by_OBJ(name,obj,last);
2012                         if (j < 0)
2013                                 {
2014                                 if (last != -1) break;
2015                                 tne=NULL;
2016                                 }
2017                         else
2018                                 {
2019                                 tne=X509_NAME_get_entry(name,j);
2020                                 }
2021                         last=j;
2022
2023                         /* depending on the 'policy', decide what to do. */
2024                         push=NULL;
2025                         if (strcmp(cv->value,"optional") == 0)
2026                                 {
2027                                 if (tne != NULL)
2028                                         push=tne;
2029                                 }
2030                         else if (strcmp(cv->value,"supplied") == 0)
2031                                 {
2032                                 if (tne == NULL)
2033                                         {
2034                                         BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
2035                                         goto err;
2036                                         }
2037                                 else
2038                                         push=tne;
2039                                 }
2040                         else if (strcmp(cv->value,"match") == 0)
2041                                 {
2042                                 int last2;
2043
2044                                 if (tne == NULL)
2045                                         {
2046                                         BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
2047                                         goto err;
2048                                         }
2049
2050                                 last2= -1;
2051
2052 again2:
2053                                 j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
2054                                 if ((j < 0) && (last2 == -1))
2055                                         {
2056                                         BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
2057                                         goto err;
2058                                         }
2059                                 if (j >= 0)
2060                                         {
2061                                         push=X509_NAME_get_entry(CAname,j);
2062                                         str=X509_NAME_ENTRY_get_data(tne);
2063                                         str2=X509_NAME_ENTRY_get_data(push);
2064                                         last2=j;
2065                                         if (ASN1_STRING_cmp(str,str2) != 0)
2066                                                 goto again2;
2067                                         }
2068                                 if (j < 0)
2069                                         {
2070                                         BIO_printf(bio_err,"The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n",cv->name,((str2 == NULL)?"NULL":(char *)str2->data),((str == NULL)?"NULL":(char *)str->data));
2071                                         goto err;
2072                                         }
2073                                 }
2074                         else
2075                                 {
2076                                 BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
2077                                 goto err;
2078                                 }
2079
2080                         if (push != NULL)
2081                                 {
2082                                 if (!X509_NAME_add_entry(subject,push, -1, 0))
2083                                         {
2084                                         if (push != NULL)
2085                                                 X509_NAME_ENTRY_free(push);
2086                                         BIO_printf(bio_err,"Memory allocation failure\n");
2087                                         goto err;
2088                                         }
2089                                 }
2090                         if (j < 0) break;
2091                         }
2092                 }
2093
2094         if (preserve)
2095                 {
2096                 X509_NAME_free(subject);
2097                 /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */
2098                 subject=X509_NAME_dup(name);
2099                 if (subject == NULL) goto err;
2100                 }
2101
2102         if (verbose)
2103                 BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
2104
2105         /* Build the correct Subject if no e-mail is wanted in the subject */
2106         /* and add it later on because of the method extensions are added (altName) */
2107          
2108         if (email_dn)
2109                 dn_subject = subject;
2110         else
2111                 {
2112                 X509_NAME_ENTRY *tmpne;
2113                 /* Its best to dup the subject DN and then delete any email
2114                  * addresses because this retains its structure.
2115                  */
2116                 if (!(dn_subject = X509_NAME_dup(subject)))
2117                         {
2118                         BIO_printf(bio_err,"Memory allocation failure\n");
2119                         goto err;
2120                         }
2121                 while((i = X509_NAME_get_index_by_NID(dn_subject,
2122                                         NID_pkcs9_emailAddress, -1)) >= 0)
2123                         {
2124                         tmpne = X509_NAME_get_entry(dn_subject, i);
2125                         X509_NAME_delete_entry(dn_subject, i);
2126                         X509_NAME_ENTRY_free(tmpne);
2127                         }
2128                 }
2129
2130         if (BN_is_zero(serial))
2131                 row[DB_serial]=BUF_strdup("00");
2132         else
2133                 row[DB_serial]=BN_bn2hex(serial);
2134         if (row[DB_serial] == NULL)
2135                 {
2136                 BIO_printf(bio_err,"Memory allocation failure\n");
2137                 goto err;
2138                 }
2139
2140         rrow=TXT_DB_get_by_index(db,DB_name,row);
2141         if (rrow != NULL)
2142                 {
2143                 BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n",
2144                         row[DB_name]);
2145                 }
2146         else
2147                 {
2148                 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2149                 if (rrow != NULL)
2150                         {
2151                         BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
2152                                 row[DB_serial]);
2153                         BIO_printf(bio_err,"      check the database/serial_file for corruption\n");
2154                         }
2155                 }
2156
2157         if (rrow != NULL)
2158                 {
2159                 BIO_printf(bio_err,
2160                         "The matching entry has the following details\n");
2161                 if (rrow[DB_type][0] == 'E')
2162                         p="Expired";
2163                 else if (rrow[DB_type][0] == 'R')
2164                         p="Revoked";
2165                 else if (rrow[DB_type][0] == 'V')
2166                         p="Valid";
2167                 else
2168                         p="\ninvalid type, Data base error\n";
2169                 BIO_printf(bio_err,"Type          :%s\n",p);;
2170                 if (rrow[DB_type][0] == 'R')
2171                         {
2172                         p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2173                         BIO_printf(bio_err,"Was revoked on:%s\n",p);
2174                         }
2175                 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2176                 BIO_printf(bio_err,"Expires on    :%s\n",p);
2177                 p=rrow[DB_serial]; if (p == NULL) p="undef";
2178                 BIO_printf(bio_err,"Serial Number :%s\n",p);
2179                 p=rrow[DB_file]; if (p == NULL) p="undef";
2180                 BIO_printf(bio_err,"File name     :%s\n",p);
2181                 p=rrow[DB_name]; if (p == NULL) p="undef";
2182                 BIO_printf(bio_err,"Subject Name  :%s\n",p);
2183                 ok= -1; /* This is now a 'bad' error. */
2184                 goto err;
2185                 }
2186
2187         /* We are now totally happy, lets make and sign the certificate */
2188         if (verbose)
2189                 BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
2190
2191         if ((ret=X509_new()) == NULL) goto err;
2192         ci=ret->cert_info;
2193
2194 #ifdef X509_V3
2195         /* Make it an X509 v3 certificate. */
2196         if (!X509_set_version(ret,2)) goto err;
2197 #endif
2198
2199         if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
2200                 goto err;
2201         if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
2202                 goto err;
2203
2204         if (strcmp(startdate,"today") == 0)
2205                 X509_gmtime_adj(X509_get_notBefore(ret),0);
2206         else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
2207
2208         if (enddate == NULL)
2209                 X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
2210         else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
2211
2212         if (!X509_set_subject_name(ret,subject)) goto err;
2213
2214         pktmp=X509_REQ_get_pubkey(req);
2215         i = X509_set_pubkey(ret,pktmp);
2216         EVP_PKEY_free(pktmp);
2217         if (!i) goto err;
2218
2219         /* Lets add the extensions, if there are any */
2220         if (ext_sect)
2221                 {
2222                 X509V3_CTX ctx;
2223                 if (ci->version == NULL)
2224                         if ((ci->version=ASN1_INTEGER_new()) == NULL)
2225                                 goto err;
2226                 ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
2227
2228                 /* Free the current entries if any, there should not
2229                  * be any I believe */
2230                 if (ci->extensions != NULL)
2231                         sk_X509_EXTENSION_pop_free(ci->extensions,
2232                                                    X509_EXTENSION_free);
2233
2234                 ci->extensions = NULL;
2235
2236                 /* Initialize the context structure */
2237                 X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
2238
2239                 if (extconf)
2240                         {
2241                         if (verbose)
2242                                 BIO_printf(bio_err, "Extra configuration file found\n");
2243  
2244                         /* Use the extconf configuration db LHASH */
2245                         X509V3_set_nconf(&ctx, extconf);
2246  
2247                         /* Test the structure (needed?) */
2248                         /* X509V3_set_ctx_test(&ctx); */
2249
2250                         /* Adds exts contained in the configuration file */
2251                         if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect,ret))
2252                                 {
2253                                 BIO_printf(bio_err,
2254                                     "ERROR: adding extensions in section %s\n",
2255                                                                 ext_sect);
2256                                 ERR_print_errors(bio_err);
2257                                 goto err;
2258                                 }
2259                         if (verbose)
2260                                 BIO_printf(bio_err, "Successfully added extensions from file.\n");
2261                         }
2262                 else if (ext_sect)
2263                         {
2264                         /* We found extensions to be set from config file */
2265                         X509V3_set_nconf(&ctx, lconf);
2266
2267                         if(!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret))
2268                                 {
2269                                 BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2270                                 ERR_print_errors(bio_err);
2271                                 goto err;
2272                                 }
2273
2274                         if (verbose) 
2275                                 BIO_printf(bio_err, "Successfully added extensions from config\n");
2276                         }
2277                 }
2278
2279         /* Copy extensions from request (if any) */
2280
2281         if (!copy_extensions(ret, req, ext_copy))
2282                 {
2283                 BIO_printf(bio_err, "ERROR: adding extensions from request\n");
2284                 ERR_print_errors(bio_err);
2285                 goto err;
2286                 }
2287
2288         /* Set the right value for the noemailDN option */
2289         if( email_dn == 0 )
2290                 {
2291                 if (!X509_set_subject_name(ret,dn_subject)) goto err;
2292                 }
2293
2294         if (!default_op)
2295                 {
2296                 BIO_printf(bio_err, "Certificate Details:\n");
2297                 /* Never print signature details because signature not present */
2298                 certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
2299                 X509_print_ex(bio_err, ret, nameopt, certopt); 
2300                 }
2301
2302         BIO_printf(bio_err,"Certificate is to be certified until ");
2303         ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
2304         if (days) BIO_printf(bio_err," (%d days)",days);
2305         BIO_printf(bio_err, "\n");
2306
2307         if (!batch)
2308                 {
2309
2310                 BIO_printf(bio_err,"Sign the certificate? [y/n]:");
2311                 (void)BIO_flush(bio_err);
2312                 buf[0]='\0';
2313                 fgets(buf,sizeof(buf)-1,stdin);
2314                 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
2315                         {
2316                         BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
2317                         ok=0;
2318                         goto err;
2319                         }
2320                 }
2321
2322
2323 #ifndef OPENSSL_NO_DSA
2324         if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
2325         pktmp=X509_get_pubkey(ret);
2326         if (EVP_PKEY_missing_parameters(pktmp) &&
2327                 !EVP_PKEY_missing_parameters(pkey))
2328                 EVP_PKEY_copy_parameters(pktmp,pkey);
2329         EVP_PKEY_free(pktmp);
2330 #endif
2331
2332         if (!X509_sign(ret,pkey,dgst))
2333                 goto err;
2334
2335         /* We now just add it to the database */
2336         row[DB_type]=(char *)OPENSSL_malloc(2);
2337
2338         tm=X509_get_notAfter(ret);
2339         row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2340         memcpy(row[DB_exp_date],tm->data,tm->length);
2341         row[DB_exp_date][tm->length]='\0';
2342
2343         row[DB_rev_date]=NULL;
2344
2345         /* row[DB_serial] done already */
2346         row[DB_file]=(char *)OPENSSL_malloc(8);
2347         row[DB_name]=X509_NAME_oneline(X509_get_subject_name(ret),NULL,0);
2348
2349         if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2350                 (row[DB_file] == NULL) || (row[DB_name] == NULL))
2351                 {
2352                 BIO_printf(bio_err,"Memory allocation failure\n");
2353                 goto err;
2354                 }
2355         strcpy(row[DB_file],"unknown");
2356         row[DB_type][0]='V';
2357         row[DB_type][1]='\0';
2358
2359         if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2360                 {
2361                 BIO_printf(bio_err,"Memory allocation failure\n");
2362                 goto err;
2363                 }
2364
2365         for (i=0; i<DB_NUMBER; i++)
2366                 {
2367                 irow[i]=row[i];
2368                 row[i]=NULL;
2369                 }
2370         irow[DB_NUMBER]=NULL;
2371
2372         if (!TXT_DB_insert(db,irow))
2373                 {
2374                 BIO_printf(bio_err,"failed to update database\n");
2375                 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2376                 goto err;
2377                 }
2378         ok=1;
2379 err:
2380         for (i=0; i<DB_NUMBER; i++)
2381                 if (row[i] != NULL) OPENSSL_free(row[i]);
2382
2383         if (CAname != NULL)
2384                 X509_NAME_free(CAname);
2385         if (subject != NULL)
2386                 X509_NAME_free(subject);
2387         if ((dn_subject != NULL) && !email_dn)
2388                 X509_NAME_free(dn_subject);
2389         if (tmptm != NULL)
2390                 ASN1_UTCTIME_free(tmptm);
2391         if (ok <= 0)
2392                 {
2393                 if (ret != NULL) X509_free(ret);
2394                 ret=NULL;
2395                 }
2396         else
2397                 *xret=ret;
2398         return(ok);
2399         }
2400
2401 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
2402         {
2403
2404         if (output_der)
2405                 {
2406                 (void)i2d_X509_bio(bp,x);
2407                 return;
2408                 }
2409 #if 0
2410         /* ??? Not needed since X509_print prints all this stuff anyway */
2411         f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
2412         BIO_printf(bp,"issuer :%s\n",f);
2413
2414         f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
2415         BIO_printf(bp,"subject:%s\n",f);
2416
2417         BIO_puts(bp,"serial :");
2418         i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
2419         BIO_puts(bp,"\n\n");
2420 #endif
2421         if (!notext)X509_print(bp,x);
2422         PEM_write_bio_X509(bp,x);
2423         }
2424
2425 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
2426              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
2427              BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate,
2428              long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt,
2429              unsigned long nameopt, int default_op, int ext_copy)
2430         {
2431         STACK_OF(CONF_VALUE) *sk=NULL;
2432         LHASH *parms=NULL;
2433         X509_REQ *req=NULL;
2434         CONF_VALUE *cv=NULL;
2435         NETSCAPE_SPKI *spki = NULL;
2436         X509_REQ_INFO *ri;
2437         char *type,*buf;
2438         EVP_PKEY *pktmp=NULL;
2439         X509_NAME *n=NULL;
2440         X509_NAME_ENTRY *ne=NULL;
2441         int ok= -1,i,j;
2442         long errline;
2443         int nid;
2444
2445         /*
2446          * Load input file into a hash table.  (This is just an easy
2447          * way to read and parse the file, then put it into a convenient
2448          * STACK format).
2449          */
2450         parms=CONF_load(NULL,infile,&errline);
2451         if (parms == NULL)
2452                 {
2453                 BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
2454                 ERR_print_errors(bio_err);
2455                 goto err;
2456                 }
2457
2458         sk=CONF_get_section(parms, "default");
2459         if (sk_CONF_VALUE_num(sk) == 0)
2460                 {
2461                 BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2462                 CONF_free(parms);
2463                 goto err;
2464                 }
2465
2466         /*
2467          * Now create a dummy X509 request structure.  We don't actually
2468          * have an X509 request, but we have many of the components
2469          * (a public key, various DN components).  The idea is that we
2470          * put these components into the right X509 request structure
2471          * and we can use the same code as if you had a real X509 request.
2472          */
2473         req=X509_REQ_new();
2474         if (req == NULL)
2475                 {
2476                 ERR_print_errors(bio_err);
2477                 goto err;
2478                 }
2479
2480         /*
2481          * Build up the subject name set.
2482          */
2483         ri=req->req_info;
2484         n = ri->subject;
2485
2486         for (i = 0; ; i++)
2487                 {
2488                 if (sk_CONF_VALUE_num(sk) <= i) break;
2489
2490                 cv=sk_CONF_VALUE_value(sk,i);
2491                 type=cv->name;
2492                 /* Skip past any leading X. X: X, etc to allow for
2493                  * multiple instances
2494                  */
2495                 for (buf = cv->name; *buf ; buf++)
2496                         if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2497                                 {
2498                                 buf++;
2499                                 if (*buf) type = buf;
2500                                 break;
2501                                 }
2502
2503                 buf=cv->value;
2504                 if ((nid=OBJ_txt2nid(type)) == NID_undef)
2505                         {
2506                         if (strcmp(type, "SPKAC") == 0)
2507                                 {
2508                                 spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2509                                 if (spki == NULL)
2510                                         {
2511                                         BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2512                                         ERR_print_errors(bio_err);
2513                                         goto err;
2514                                         }
2515                                 }
2516                         continue;
2517                         }
2518
2519                 /*
2520                 if ((nid == NID_pkcs9_emailAddress) && (email_dn == 0))
2521                         continue;
2522                 */
2523                 
2524                 j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
2525                 if (fix_data(nid, &j) == 0)
2526                         {
2527                         BIO_printf(bio_err,
2528                                 "invalid characters in string %s\n",buf);
2529                         goto err;
2530                         }
2531
2532                 if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
2533                         (unsigned char *)buf,
2534                         strlen(buf))) == NULL)
2535                         goto err;
2536
2537                 if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
2538                 }
2539         if (spki == NULL)
2540                 {
2541                 BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2542                         infile);
2543                 goto err;
2544                 }
2545
2546         /*
2547          * Now extract the key from the SPKI structure.
2548          */
2549
2550         BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2551
2552         if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
2553                 {
2554                 BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2555                 goto err;
2556                 }
2557
2558         j = NETSCAPE_SPKI_verify(spki, pktmp);
2559         if (j <= 0)
2560                 {
2561                 BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2562                 goto err;
2563                 }
2564         BIO_printf(bio_err,"Signature ok\n");
2565
2566         X509_REQ_set_pubkey(req,pktmp);
2567         EVP_PKEY_free(pktmp);
2568         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,email_dn,startdate,enddate,
2569                    days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op,
2570                         ext_copy);
2571 err:
2572         if (req != NULL) X509_REQ_free(req);
2573         if (parms != NULL) CONF_free(parms);
2574         if (spki != NULL) NETSCAPE_SPKI_free(spki);
2575         if (ne != NULL) X509_NAME_ENTRY_free(ne);
2576
2577         return(ok);
2578         }
2579
2580 static int fix_data(int nid, int *type)
2581         {
2582         if (nid == NID_pkcs9_emailAddress)
2583                 *type=V_ASN1_IA5STRING;
2584         if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
2585                 *type=V_ASN1_T61STRING;
2586         if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
2587                 *type=V_ASN1_T61STRING;
2588         if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
2589                 return(0);
2590         if (nid == NID_pkcs9_unstructuredName)
2591                 *type=V_ASN1_IA5STRING;
2592         return(1);
2593         }
2594
2595 static int check_time_format(char *str)
2596         {
2597         ASN1_UTCTIME tm;
2598
2599         tm.data=(unsigned char *)str;
2600         tm.length=strlen(str);
2601         tm.type=V_ASN1_UTCTIME;
2602         return(ASN1_UTCTIME_check(&tm));
2603         }
2604
2605 static int do_revoke(X509 *x509, TXT_DB *db, int type, char *value)
2606         {
2607         ASN1_UTCTIME *tm=NULL;
2608         char *row[DB_NUMBER],**rrow,**irow;
2609         char *rev_str = NULL;
2610         BIGNUM *bn = NULL;
2611         int ok=-1,i;
2612
2613         for (i=0; i<DB_NUMBER; i++)
2614                 row[i]=NULL;
2615         row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2616         bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2617         if (BN_is_zero(bn))
2618                 row[DB_serial]=BUF_strdup("00");
2619         else
2620                 row[DB_serial]=BN_bn2hex(bn);
2621         BN_free(bn);
2622         if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2623                 {
2624                 BIO_printf(bio_err,"Memory allocation failure\n");
2625                 goto err;
2626                 }
2627         /* We have to lookup by serial number because name lookup
2628          * skips revoked certs
2629          */
2630         rrow=TXT_DB_get_by_index(db,DB_serial,row);
2631         if (rrow == NULL)
2632                 {
2633                 BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]);
2634
2635                 /* We now just add it to the database */
2636                 row[DB_type]=(char *)OPENSSL_malloc(2);
2637
2638                 tm=X509_get_notAfter(x509);
2639                 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2640                 memcpy(row[DB_exp_date],tm->data,tm->length);
2641                 row[DB_exp_date][tm->length]='\0';
2642
2643                 row[DB_rev_date]=NULL;
2644
2645                 /* row[DB_serial] done already */
2646                 row[DB_file]=(char *)OPENSSL_malloc(8);
2647
2648                 /* row[DB_name] done already */
2649
2650                 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2651                         (row[DB_file] == NULL))
2652                         {
2653                         BIO_printf(bio_err,"Memory allocation failure\n");
2654                         goto err;
2655                         }
2656                 strcpy(row[DB_file],"unknown");
2657                 row[DB_type][0]='V';
2658                 row[DB_type][1]='\0';
2659
2660                 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2661                         {
2662                         BIO_printf(bio_err,"Memory allocation failure\n");
2663                         goto err;
2664                         }
2665
2666                 for (i=0; i<DB_NUMBER; i++)
2667                         {
2668                         irow[i]=row[i];
2669                         row[i]=NULL;
2670                         }
2671                 irow[DB_NUMBER]=NULL;
2672
2673                 if (!TXT_DB_insert(db,irow))
2674                         {
2675                         BIO_printf(bio_err,"failed to update database\n");
2676                         BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2677                         goto err;
2678                         }
2679
2680                 /* Revoke Certificate */
2681                 ok = do_revoke(x509,db, type, value);
2682
2683                 goto err;
2684
2685                 }
2686         else if (index_name_cmp((const char **)row,(const char **)rrow))
2687                 {
2688                 BIO_printf(bio_err,"ERROR:name does not match %s\n",
2689                            row[DB_name]);
2690                 goto err;
2691                 }
2692         else if (rrow[DB_type][0]=='R')
2693                 {
2694                 BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2695                            row[DB_serial]);
2696                 goto err;
2697                 }
2698         else
2699                 {
2700                 BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2701                 rev_str = make_revocation_str(type, value);
2702                 if (!rev_str)
2703                         {
2704                         BIO_printf(bio_err, "Error in revocation arguments\n");
2705                         goto err;
2706                         }
2707                 rrow[DB_type][0]='R';
2708                 rrow[DB_type][1]='\0';
2709                 rrow[DB_rev_date] = rev_str;
2710                 }
2711         ok=1;
2712 err:
2713         for (i=0; i<DB_NUMBER; i++)
2714                 {
2715                 if (row[i] != NULL) 
2716                         OPENSSL_free(row[i]);
2717                 }
2718         return(ok);
2719         }
2720
2721 static int get_certificate_status(const char *serial, TXT_DB *db)
2722         {
2723         char *row[DB_NUMBER],**rrow;
2724         int ok=-1,i;
2725
2726         /* Free Resources */
2727         for (i=0; i<DB_NUMBER; i++)
2728                 row[i]=NULL;
2729
2730         /* Malloc needed char spaces */
2731         row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2732         if (row[DB_serial] == NULL)
2733                 {
2734                 BIO_printf(bio_err,"Malloc failure\n");
2735                 goto err;
2736                 }
2737
2738         if (strlen(serial) % 2)
2739                 {
2740                 /* Set the first char to 0 */;
2741                 row[DB_serial][0]='0';
2742
2743                 /* Copy String from serial to row[DB_serial] */
2744                 memcpy(row[DB_serial]+1, serial, strlen(serial));
2745                 row[DB_serial][strlen(serial)+1]='\0';
2746                 }
2747         else
2748                 {
2749                 /* Copy String from serial to row[DB_serial] */
2750                 memcpy(row[DB_serial], serial, strlen(serial));
2751                 row[DB_serial][strlen(serial)]='\0';
2752                 }
2753                         
2754         /* Make it Upper Case */
2755         for (i=0; row[DB_serial][i] != '\0'; i++)
2756                 row[DB_serial][i] = toupper(row[DB_serial][i]);
2757         
2758
2759         ok=1;
2760
2761         /* Search for the certificate */
2762         rrow=TXT_DB_get_by_index(db,DB_serial,row);
2763         if (rrow == NULL)
2764                 {
2765                 BIO_printf(bio_err,"Serial %s not present in db.\n",
2766                                  row[DB_serial]);
2767                 ok=-1;
2768                 goto err;
2769                 }
2770         else if (rrow[DB_type][0]=='V')
2771                 {
2772                 BIO_printf(bio_err,"%s=Valid (%c)\n",
2773                         row[DB_serial], rrow[DB_type][0]);
2774                 goto err;
2775                 }
2776         else if (rrow[DB_type][0]=='R')
2777                 {
2778                 BIO_printf(bio_err,"%s=Revoked (%c)\n",
2779                         row[DB_serial], rrow[DB_type][0]);
2780                 goto err;
2781                 }
2782         else if (rrow[DB_type][0]=='E')
2783                 {
2784                 BIO_printf(bio_err,"%s=Expired (%c)\n",
2785                         row[DB_serial], rrow[DB_type][0]);
2786                 goto err;
2787                 }
2788         else if (rrow[DB_type][0]=='S')
2789                 {
2790                 BIO_printf(bio_err,"%s=Suspended (%c)\n",
2791                         row[DB_serial], rrow[DB_type][0]);
2792                 goto err;
2793                 }
2794         else
2795                 {
2796                 BIO_printf(bio_err,"%s=Unknown (%c).\n",
2797                         row[DB_serial], rrow[DB_type][0]);
2798                 ok=-1;
2799                 }
2800 err:
2801         for (i=0; i<DB_NUMBER; i++)
2802                 {
2803                 if (row[i] != NULL)
2804                         OPENSSL_free(row[i]);
2805                 }
2806         return(ok);
2807         }
2808
2809 static int do_updatedb (TXT_DB *db)
2810         {
2811         ASN1_UTCTIME    *a_tm = NULL;
2812         int i, cnt = 0;
2813         int db_y2k, a_y2k;  /* flags = 1 if y >= 2000 */ 
2814         char **rrow, *a_tm_s;
2815
2816         a_tm = ASN1_UTCTIME_new();
2817
2818         /* get actual time and make a string */
2819         a_tm = X509_gmtime_adj(a_tm, 0);
2820         a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2821         if (a_tm_s == NULL)
2822                 {
2823                 cnt = -1;
2824                 goto err;
2825                 }
2826
2827         memcpy(a_tm_s, a_tm->data, a_tm->length);
2828         a_tm_s[a_tm->length] = '\0';
2829
2830         if (strncmp(a_tm_s, "49", 2) <= 0)
2831                 a_y2k = 1;
2832         else
2833                 a_y2k = 0;
2834
2835         for (i = 0; i < sk_num(db->data); i++)
2836                 {
2837                 rrow = (char **) sk_value(db->data, i);
2838
2839                 if (rrow[DB_type][0] == 'V')
2840                         {
2841                         /* ignore entries that are not valid */
2842                         if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2843                                 db_y2k = 1;
2844                         else
2845                                 db_y2k = 0;
2846
2847                         if (db_y2k == a_y2k)
2848                                 {
2849                                 /* all on the same y2k side */
2850                                 if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2851                                         {
2852                                         rrow[DB_type][0]  = 'E';
2853                                         rrow[DB_type][1]  = '\0';
2854                                         cnt++;
2855
2856                                         BIO_printf(bio_err, "%s=Expired\n",
2857                                                         rrow[DB_serial]);
2858                                         }
2859                                 }
2860                         else if (db_y2k < a_y2k)
2861                                 {
2862                                 rrow[DB_type][0]  = 'E';
2863                                 rrow[DB_type][1]  = '\0';
2864                                 cnt++;
2865
2866                                 BIO_printf(bio_err, "%s=Expired\n",
2867                                                         rrow[DB_serial]);
2868                                 }
2869
2870                         }
2871                 }
2872
2873 err:
2874
2875         ASN1_UTCTIME_free(a_tm);
2876         OPENSSL_free(a_tm_s);
2877
2878         return (cnt);
2879         }
2880
2881 static char *crl_reasons[] = {
2882         /* CRL reason strings */
2883         "unspecified",
2884         "keyCompromise",
2885         "CACompromise",
2886         "affiliationChanged",
2887         "superseded", 
2888         "cessationOfOperation",
2889         "certificateHold",
2890         "removeFromCRL",
2891         /* Additional pseudo reasons */
2892         "holdInstruction",
2893         "keyTime",
2894         "CAkeyTime"
2895 };
2896
2897 #define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2898
2899 /* Given revocation information convert to a DB string.
2900  * The format of the string is:
2901  * revtime[,reason,extra]. Where 'revtime' is the
2902  * revocation time (the current time). 'reason' is the
2903  * optional CRL reason and 'extra' is any additional
2904  * argument
2905  */
2906
2907 char *make_revocation_str(int rev_type, char *rev_arg)
2908         {
2909         char *reason = NULL, *other = NULL, *str;
2910         ASN1_OBJECT *otmp;
2911         ASN1_UTCTIME *revtm = NULL;
2912         int i;
2913         switch (rev_type)
2914                 {
2915         case REV_NONE:
2916                 break;
2917
2918         case REV_CRL_REASON:
2919                 for (i = 0; i < 8; i++)
2920                         {
2921                         if (!strcasecmp(rev_arg, crl_reasons[i]))
2922                                 {
2923                                 reason = crl_reasons[i];
2924                                 break;
2925                                 }
2926                         }
2927                 if (reason == NULL)
2928                         {
2929                         BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2930                         return NULL;
2931                         }
2932                 break;
2933
2934         case REV_HOLD:
2935                 /* Argument is an OID */
2936
2937                 otmp = OBJ_txt2obj(rev_arg, 0);
2938                 ASN1_OBJECT_free(otmp);
2939
2940                 if (otmp == NULL)
2941                         {
2942                         BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2943                         return NULL;
2944                         }
2945
2946                 reason = "holdInstruction";
2947                 other = rev_arg;
2948                 break;
2949                 
2950         case REV_KEY_COMPROMISE:
2951         case REV_CA_COMPROMISE:
2952
2953                 /* Argument is the key compromise time  */
2954                 if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg))
2955                         {       
2956                         BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg);
2957                         return NULL;
2958                         }
2959                 other = rev_arg;
2960                 if (rev_type == REV_KEY_COMPROMISE)
2961                         reason = "keyTime";
2962                 else 
2963                         reason = "CAkeyTime";
2964
2965                 break;
2966
2967                 }
2968
2969         revtm = X509_gmtime_adj(NULL, 0);
2970
2971         i = revtm->length + 1;
2972
2973         if (reason) i += strlen(reason) + 1;
2974         if (other) i += strlen(other) + 1;
2975
2976         str = OPENSSL_malloc(i);
2977
2978         if (!str) return NULL;
2979
2980         strcpy(str, (char *)revtm->data);
2981         if (reason)
2982                 {
2983                 strcat(str, ",");
2984                 strcat(str, reason);
2985                 }
2986         if (other)
2987                 {
2988                 strcat(str, ",");
2989                 strcat(str, other);
2990                 }
2991         ASN1_UTCTIME_free(revtm);
2992         return str;
2993         }
2994
2995 /* Convert revocation field to X509_REVOKED entry 
2996  * return code:
2997  * 0 error
2998  * 1 OK
2999  * 2 OK and some extensions added (i.e. V2 CRL)
3000  */
3001
3002
3003 int make_revoked(X509_REVOKED *rev, char *str)
3004         {
3005         char *tmp = NULL;
3006         int reason_code = -1;
3007         int i, ret = 0;
3008         ASN1_OBJECT *hold = NULL;
3009         ASN1_GENERALIZEDTIME *comp_time = NULL;
3010         ASN1_ENUMERATED *rtmp = NULL;
3011
3012         ASN1_TIME *revDate = NULL;
3013
3014         i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str);
3015
3016         if (i == 0)
3017                 goto err;
3018
3019         if (rev && !X509_REVOKED_set_revocationDate(rev, revDate))
3020                 goto err;
3021
3022         if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
3023                 {
3024                 rtmp = ASN1_ENUMERATED_new();
3025                 if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
3026                         goto err;
3027                 if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
3028                         goto err;
3029                 }
3030
3031         if (rev && comp_time)
3032                 {
3033                 if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
3034                         goto err;
3035                 }
3036         if (rev && hold)
3037                 {
3038                 if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
3039                         goto err;
3040                 }
3041
3042         if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
3043                 ret = 2;
3044         else ret = 1;
3045
3046         err:
3047
3048         if (tmp) OPENSSL_free(tmp);
3049         ASN1_OBJECT_free(hold);
3050         ASN1_GENERALIZEDTIME_free(comp_time);
3051         ASN1_ENUMERATED_free(rtmp);
3052         ASN1_TIME_free(revDate);
3053
3054         return ret;
3055         }
3056
3057 /*
3058  * subject is expected to be in the format /type0=value0/type1=value1/type2=...
3059  * where characters may be escaped by \
3060  */
3061 X509_NAME *do_subject(char *subject, long chtype)
3062         {
3063         size_t buflen = strlen(subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */
3064         char *buf = OPENSSL_malloc(buflen);
3065         size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
3066         char **ne_types = OPENSSL_malloc(max_ne * sizeof (char *));
3067         char **ne_values = OPENSSL_malloc(max_ne * sizeof (char *));
3068
3069         char *sp = subject, *bp = buf;
3070         int i, ne_num = 0;
3071
3072         X509_NAME *n = NULL;
3073         int nid;
3074
3075         if (!buf || !ne_types || !ne_values)
3076         {
3077                 BIO_printf(bio_err, "malloc error\n");
3078                 goto error;
3079         }
3080
3081         if (*subject != '/')
3082         {
3083                 BIO_printf(bio_err, "Subject does not start with '/'.\n");
3084                 goto error;
3085         }
3086         sp++; /* skip leading / */
3087
3088         while (*sp)
3089                 {
3090                 /* collect type */
3091                 ne_types[ne_num] = bp;
3092                 while (*sp)
3093                         {
3094                         if (*sp == '\\') /* is there anything to escape in the type...? */
3095                                 {
3096                                 if (*++sp)
3097                                         *bp++ = *sp++;
3098                                 else
3099                                         {
3100                                         BIO_printf(bio_err, "escape character at end of string\n");
3101                                         goto error;
3102                                         }
3103                                 }
3104                         else if (*sp == '=')
3105                                 {
3106                                 sp++;
3107                                 *bp++ = '\0';
3108                                 break;
3109                                 }
3110                         else
3111                                 *bp++ = *sp++;
3112                         }
3113                 if (!*sp)
3114                         {
3115                         BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num);
3116                         goto error;
3117                         }
3118                 ne_values[ne_num] = bp;
3119                 while (*sp)
3120                         {
3121                         if (*sp == '\\')
3122                                 {
3123                                 if (*++sp)
3124                                         *bp++ = *sp++;
3125                                 else
3126                                         {
3127                                         BIO_printf(bio_err, "escape character at end of string\n");
3128                                         goto error;
3129                                         }
3130                                 }
3131                         else if (*sp == '/')
3132                                 {
3133                                 sp++;
3134                                 break;
3135                                 }
3136                         else
3137                                 *bp++ = *sp++;
3138                         }
3139                 *bp++ = '\0';
3140                 ne_num++;
3141                 }
3142
3143         if (!(n = X509_NAME_new()))
3144                 goto error;
3145
3146         for (i = 0; i < ne_num; i++)
3147                 {
3148                 if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef)
3149                         {
3150                         BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]);
3151                         continue;
3152                         }
3153
3154                 if (!*ne_values[i])
3155                         {
3156                         BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]);
3157                         continue;
3158                         }
3159
3160                 if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,0))
3161                         goto error;
3162                 }
3163
3164         OPENSSL_free(ne_values);
3165         OPENSSL_free(ne_types);
3166         OPENSSL_free(buf);
3167         return n;
3168
3169 error:
3170         X509_NAME_free(n);
3171         if (ne_values)
3172                 OPENSSL_free(ne_values);
3173         if (ne_types)
3174                 OPENSSL_free(ne_types);
3175         if (buf)
3176                 OPENSSL_free(buf);
3177         return NULL;
3178 }
3179
3180 int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
3181         {
3182         char buf[25],*pbuf, *p;
3183         int j;
3184         j=i2a_ASN1_OBJECT(bp,obj);
3185         pbuf=buf;
3186         for (j=22-j; j>0; j--)
3187                 *(pbuf++)=' ';
3188         *(pbuf++)=':';
3189         *(pbuf++)='\0';
3190         BIO_puts(bp,buf);
3191
3192         if (str->type == V_ASN1_PRINTABLESTRING)
3193                 BIO_printf(bp,"PRINTABLE:'");
3194         else if (str->type == V_ASN1_T61STRING)
3195                 BIO_printf(bp,"T61STRING:'");
3196         else if (str->type == V_ASN1_IA5STRING)
3197                 BIO_printf(bp,"IA5STRING:'");
3198         else if (str->type == V_ASN1_UNIVERSALSTRING)
3199                 BIO_printf(bp,"UNIVERSALSTRING:'");
3200         else
3201                 BIO_printf(bp,"ASN.1 %2d:'",str->type);
3202                         
3203         p=(char *)str->data;
3204         for (j=str->length; j>0; j--)
3205                 {
3206                 if ((*p >= ' ') && (*p <= '~'))
3207                         BIO_printf(bp,"%c",*p);
3208                 else if (*p & 0x80)
3209                         BIO_printf(bp,"\\0x%02X",*p);
3210                 else if ((unsigned char)*p == 0xf7)
3211                         BIO_printf(bp,"^?");
3212                 else    BIO_printf(bp,"^%c",*p+'@');
3213                 p++;
3214                 }
3215         BIO_printf(bp,"'\n");
3216         return 1;
3217         }
3218
3219 int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, char *str)
3220         {
3221         char *tmp = NULL;
3222         char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
3223         int reason_code = -1;
3224         int i, ret = 0;
3225         ASN1_OBJECT *hold = NULL;
3226         ASN1_GENERALIZEDTIME *comp_time = NULL;
3227         tmp = BUF_strdup(str);
3228
3229         p = strchr(tmp, ',');
3230
3231         rtime_str = tmp;
3232
3233         if (p)
3234                 {
3235                 *p = '\0';
3236                 p++;
3237                 reason_str = p;
3238                 p = strchr(p, ',');
3239                 if (p)
3240                         {
3241                         *p = '\0';
3242                         arg_str = p + 1;
3243                         }
3244                 }
3245
3246         if (prevtm)
3247                 {
3248                 *prevtm = ASN1_UTCTIME_new();
3249                 if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str))
3250                         {
3251                         BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
3252                         goto err;
3253                         }
3254                 }
3255         if (reason_str)
3256                 {
3257                 for (i = 0; i < NUM_REASONS; i++)
3258                         {
3259                         if(!strcasecmp(reason_str, crl_reasons[i]))
3260                                 {
3261                                 reason_code = i;
3262                                 break;
3263                                 }
3264                         }
3265                 if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS)
3266                         {
3267                         BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
3268                         goto err;
3269                         }
3270
3271                 if (reason_code == 7)
3272                         reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
3273                 else if (reason_code == 8)              /* Hold instruction */
3274                         {
3275                         if (!arg_str)
3276                                 {       
3277                                 BIO_printf(bio_err, "missing hold instruction\n");
3278                                 goto err;
3279                                 }
3280                         reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
3281                         hold = OBJ_txt2obj(arg_str, 0);
3282
3283                         if (!hold)
3284                                 {
3285                                 BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
3286                                 goto err;
3287                                 }
3288                         if (phold) *phold = hold;
3289                         }
3290                 else if ((reason_code == 9) || (reason_code == 10))
3291                         {
3292                         if (!arg_str)
3293                                 {       
3294                                 BIO_printf(bio_err, "missing compromised time\n");
3295                                 goto err;
3296                                 }
3297                         comp_time = ASN1_GENERALIZEDTIME_new();
3298                         if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str))
3299                                 {       
3300                                 BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
3301                                 goto err;
3302                                 }
3303                         if (reason_code == 9)
3304                                 reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
3305                         else
3306                                 reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
3307                         }
3308                 }
3309
3310         if (preason) *preason = reason_code;
3311         if (pinvtm) *pinvtm = comp_time;
3312         else ASN1_GENERALIZEDTIME_free(comp_time);
3313
3314         ret = 1;
3315
3316         err:
3317
3318         if (tmp) OPENSSL_free(tmp);
3319         if (!phold) ASN1_OBJECT_free(hold);
3320         if (!pinvtm) ASN1_GENERALIZEDTIME_free(comp_time);
3321
3322         return ret;
3323         }
3324
3325 int make_serial_index(TXT_DB *db)
3326         {
3327         if (!TXT_DB_create_index(db, DB_serial, NULL,
3328                                 LHASH_HASH_FN(index_serial_hash),
3329                                 LHASH_COMP_FN(index_serial_cmp)))
3330                 {
3331                 BIO_printf(bio_err,
3332                   "error creating serial number index:(%ld,%ld,%ld)\n",
3333                                         db->error,db->arg1,db->arg2);
3334                         return 0;
3335                 }
3336         return 1;
3337         }