New '-extfile' option for 'openssl ca'.
[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 "apps.h"
68 #include <openssl/conf.h>
69 #include <openssl/bio.h>
70 #include <openssl/err.h>
71 #include <openssl/bn.h>
72 #include <openssl/txt_db.h>
73 #include <openssl/evp.h>
74 #include <openssl/x509.h>
75 #include <openssl/x509v3.h>
76 #include <openssl/objects.h>
77 #include <openssl/pem.h>
78 #include <openssl/engine.h>
79
80 #ifndef W_OK
81 #  ifdef VMS
82 #    if defined(__DECC)
83 #      include <unistd.h>
84 #    else
85 #      include <unixlib.h>
86 #    endif
87 #  else
88 #    include <sys/file.h>
89 #  endif
90 #endif
91
92 #ifndef W_OK
93 #  define F_OK 0
94 #  define X_OK 1
95 #  define W_OK 2
96 #  define R_OK 4
97 #endif
98
99 #undef PROG
100 #define PROG ca_main
101
102 #define BASE_SECTION    "ca"
103 #define CONFIG_FILE "openssl.cnf"
104
105 #define ENV_DEFAULT_CA          "default_ca"
106
107 #define ENV_DIR                 "dir"
108 #define ENV_CERTS               "certs"
109 #define ENV_CRL_DIR             "crl_dir"
110 #define ENV_CA_DB               "CA_DB"
111 #define ENV_NEW_CERTS_DIR       "new_certs_dir"
112 #define ENV_CERTIFICATE         "certificate"
113 #define ENV_SERIAL              "serial"
114 #define ENV_CRL                 "crl"
115 #define ENV_PRIVATE_KEY         "private_key"
116 #define ENV_RANDFILE            "RANDFILE"
117 #define ENV_DEFAULT_DAYS        "default_days"
118 #define ENV_DEFAULT_STARTDATE   "default_startdate"
119 #define ENV_DEFAULT_ENDDATE     "default_enddate"
120 #define ENV_DEFAULT_CRL_DAYS    "default_crl_days"
121 #define ENV_DEFAULT_CRL_HOURS   "default_crl_hours"
122 #define ENV_DEFAULT_MD          "default_md"
123 #define ENV_PRESERVE            "preserve"
124 #define ENV_POLICY              "policy"
125 #define ENV_EXTENSIONS          "x509_extensions"
126 #define ENV_CRLEXT              "crl_extensions"
127 #define ENV_MSIE_HACK           "msie_hack"
128
129 #define ENV_DATABASE            "database"
130
131 #define DB_type         0
132 #define DB_exp_date     1
133 #define DB_rev_date     2
134 #define DB_serial       3       /* index - unique */
135 #define DB_file         4       
136 #define DB_name         5       /* index - unique for active */
137 #define DB_NUMBER       6
138
139 #define DB_TYPE_REV     'R'
140 #define DB_TYPE_EXP     'E'
141 #define DB_TYPE_VAL     'V'
142
143 static char *ca_usage[]={
144 "usage: ca args\n",
145 "\n",
146 " -verbose        - Talk alot while doing things\n",
147 " -config file    - A config file\n",
148 " -name arg       - The particular CA definition to use\n",
149 " -gencrl         - Generate a new CRL\n",
150 " -crldays days   - Days is when the next CRL is due\n",
151 " -crlhours hours - Hours is when the next CRL is due\n",
152 " -startdate YYMMDDHHMMSSZ  - certificate validity notBefore\n",
153 " -enddate YYMMDDHHMMSSZ    - certificate validity notAfter (overrides -days)\n",
154 " -days arg       - number of days to certify the certificate for\n",
155 " -md arg         - md to use, one of md2, md5, sha or sha1\n",
156 " -policy arg     - The CA 'policy' to support\n",
157 " -keyfile arg    - private key file\n",
158 " -keyform arg    - private key file format (PEM or ENGINE)\n",
159 " -key arg        - key to decode the private key if it is encrypted\n",
160 " -cert file      - The CA certificate\n",
161 " -in file        - The input PEM encoded certificate request(s)\n",
162 " -out file       - Where to put the output file(s)\n",
163 " -outdir dir     - Where to put output certificates\n",
164 " -infiles ....   - The last argument, requests to process\n",
165 " -spkac file     - File contains DN and signed public key and challenge\n",
166 " -ss_cert file   - File contains a self signed cert to sign\n",
167 " -preserveDN     - Don't re-order the DN\n",
168 " -batch          - Don't ask questions\n",
169 " -msie_hack      - msie modifications to handle all those universal strings\n",
170 " -revoke file    - Revoke a certificate (given in file)\n",
171 " -extensions ..  - Extension section (override value in config file)\n",
172 " -extfile file   - Configuration file with X509v3 extentions to add\n",
173 " -crlexts ..     - CRL extension section (override value in config file)\n",
174 " -engine e       - use engine e, possibly a hardware device.\n",
175 " -status serial  - Shows certificate status given the serial number\n",
176 " -updatedb       - Updates db for expired certificates\n",
177 NULL
178 };
179
180 #ifdef EFENCE
181 extern int EF_PROTECT_FREE;
182 extern int EF_PROTECT_BELOW;
183 extern int EF_ALIGNMENT;
184 #endif
185
186 static void lookup_fail(char *name,char *tag);
187 static unsigned long index_serial_hash(const char **a);
188 static int index_serial_cmp(const char **a, const char **b);
189 static unsigned long index_name_hash(const char **a);
190 static int index_name_qual(char **a);
191 static int index_name_cmp(const char **a,const char **b);
192 static BIGNUM *load_serial(char *serialfile);
193 static int save_serial(char *serialfile, BIGNUM *serial);
194 static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
195                    const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,TXT_DB *db,
196                    BIGNUM *serial, char *startdate,char *enddate, int days,
197                    int batch, char *ext_sect, LHASH *conf,int verbose);
198 static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
199                         const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
200                         TXT_DB *db, BIGNUM *serial,char *startdate,
201                         char *enddate, int days, int batch, char *ext_sect,
202                         LHASH *conf,int verbose);
203 static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
204                          const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
205                          TXT_DB *db, BIGNUM *serial,char *startdate,
206                          char *enddate, int days, char *ext_sect,LHASH *conf,
207                                 int verbose);
208 static int fix_data(int nid, int *type);
209 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
210 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
211         STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
212         char *startdate, char *enddate, int days, int batch, int verbose,
213         X509_REQ *req, char *ext_sect, LHASH *conf);
214 static int do_revoke(X509 *x509, TXT_DB *db);
215 static int get_certificate_status(const char *ser_status, TXT_DB *db);
216 static int do_updatedb(TXT_DB *db);
217 static int check_time_format(char *str);
218 static LHASH *conf=NULL;
219 static LHASH *extconf=NULL;
220 static char *section=NULL;
221
222 static int preserve=0;
223 static int msie_hack=0;
224
225 static IMPLEMENT_LHASH_HASH_FN(index_serial_hash,const char **)
226 static IMPLEMENT_LHASH_COMP_FN(index_serial_cmp,const char **)
227 static IMPLEMENT_LHASH_HASH_FN(index_name_hash,const char **)
228 static IMPLEMENT_LHASH_COMP_FN(index_name_cmp,const char **)
229
230
231 int MAIN(int, char **);
232
233 int MAIN(int argc, char **argv)
234         {
235         ENGINE *e = NULL;
236         char *key=NULL,*passargin=NULL;
237         int total=0;
238         int total_done=0;
239         int badops=0;
240         int ret=1;
241         int req=0;
242         int verbose=0;
243         int gencrl=0;
244         int dorevoke=0;
245         int doupdatedb=0;
246         long crldays=0;
247         long crlhours=0;
248         long errorline= -1;
249         char *configfile=NULL;
250         char *md=NULL;
251         char *policy=NULL;
252         char *keyfile=NULL;
253         char *certfile=NULL;
254         int keyform=FORMAT_PEM;
255         char *infile=NULL;
256         char *spkac_file=NULL;
257         char *ss_cert_file=NULL;
258         char *ser_status=NULL;
259         EVP_PKEY *pkey=NULL;
260         int output_der = 0;
261         char *outfile=NULL;
262         char *outdir=NULL;
263         char *serialfile=NULL;
264         char *extensions=NULL;
265         char *extfile=NULL;
266         char *crl_ext=NULL;
267         BIGNUM *serial=NULL;
268         char *startdate=NULL;
269         char *enddate=NULL;
270         int days=0;
271         int batch=0;
272         int notext=0;
273         X509 *x509=NULL;
274         X509 *x=NULL;
275         BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
276         char *dbfile=NULL;
277         TXT_DB *db=NULL;
278         X509_CRL *crl=NULL;
279         X509_CRL_INFO *ci=NULL;
280         X509_REVOKED *r=NULL;
281         char **pp,*p,*f;
282         int i,j;
283         long l;
284         const EVP_MD *dgst=NULL;
285         STACK_OF(CONF_VALUE) *attribs=NULL;
286         STACK_OF(X509) *cert_sk=NULL;
287         BIO *hex=NULL;
288 #undef BSIZE
289 #define BSIZE 256
290         MS_STATIC char buf[3][BSIZE];
291         char *randfile=NULL;
292         char *engine = NULL;
293
294 #ifdef EFENCE
295 EF_PROTECT_FREE=1;
296 EF_PROTECT_BELOW=1;
297 EF_ALIGNMENT=0;
298 #endif
299
300         apps_startup();
301
302         conf = NULL;
303         key = NULL;
304         section = NULL;
305
306         preserve=0;
307         msie_hack=0;
308         if (bio_err == NULL)
309                 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
310                         BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
311
312         argc--;
313         argv++;
314         while (argc >= 1)
315                 {
316                 if      (strcmp(*argv,"-verbose") == 0)
317                         verbose=1;
318                 else if (strcmp(*argv,"-config") == 0)
319                         {
320                         if (--argc < 1) goto bad;
321                         configfile= *(++argv);
322                         }
323                 else if (strcmp(*argv,"-name") == 0)
324                         {
325                         if (--argc < 1) goto bad;
326                         section= *(++argv);
327                         }
328                 else if (strcmp(*argv,"-startdate") == 0)
329                         {
330                         if (--argc < 1) goto bad;
331                         startdate= *(++argv);
332                         }
333                 else if (strcmp(*argv,"-enddate") == 0)
334                         {
335                         if (--argc < 1) goto bad;
336                         enddate= *(++argv);
337                         }
338                 else if (strcmp(*argv,"-days") == 0)
339                         {
340                         if (--argc < 1) goto bad;
341                         days=atoi(*(++argv));
342                         }
343                 else if (strcmp(*argv,"-md") == 0)
344                         {
345                         if (--argc < 1) goto bad;
346                         md= *(++argv);
347                         }
348                 else if (strcmp(*argv,"-policy") == 0)
349                         {
350                         if (--argc < 1) goto bad;
351                         policy= *(++argv);
352                         }
353                 else if (strcmp(*argv,"-keyfile") == 0)
354                         {
355                         if (--argc < 1) goto bad;
356                         keyfile= *(++argv);
357                         }
358                 else if (strcmp(*argv,"-keyform") == 0)
359                         {
360                         if (--argc < 1) goto bad;
361                         keyform=str2fmt(*(++argv));
362                         }
363                 else if (strcmp(*argv,"-passin") == 0)
364                         {
365                         if (--argc < 1) goto bad;
366                         passargin= *(++argv);
367                         }
368                 else if (strcmp(*argv,"-key") == 0)
369                         {
370                         if (--argc < 1) goto bad;
371                         key= *(++argv);
372                         }
373                 else if (strcmp(*argv,"-cert") == 0)
374                         {
375                         if (--argc < 1) goto bad;
376                         certfile= *(++argv);
377                         }
378                 else if (strcmp(*argv,"-in") == 0)
379                         {
380                         if (--argc < 1) goto bad;
381                         infile= *(++argv);
382                         req=1;
383                         }
384                 else if (strcmp(*argv,"-out") == 0)
385                         {
386                         if (--argc < 1) goto bad;
387                         outfile= *(++argv);
388                         }
389                 else if (strcmp(*argv,"-outdir") == 0)
390                         {
391                         if (--argc < 1) goto bad;
392                         outdir= *(++argv);
393                         }
394                 else if (strcmp(*argv,"-notext") == 0)
395                         notext=1;
396                 else if (strcmp(*argv,"-batch") == 0)
397                         batch=1;
398                 else if (strcmp(*argv,"-preserveDN") == 0)
399                         preserve=1;
400                 else if (strcmp(*argv,"-gencrl") == 0)
401                         gencrl=1;
402                 else if (strcmp(*argv,"-msie_hack") == 0)
403                         msie_hack=1;
404                 else if (strcmp(*argv,"-crldays") == 0)
405                         {
406                         if (--argc < 1) goto bad;
407                         crldays= atol(*(++argv));
408                         }
409                 else if (strcmp(*argv,"-crlhours") == 0)
410                         {
411                         if (--argc < 1) goto bad;
412                         crlhours= atol(*(++argv));
413                         }
414                 else if (strcmp(*argv,"-infiles") == 0)
415                         {
416                         argc--;
417                         argv++;
418                         req=1;
419                         break;
420                         }
421                 else if (strcmp(*argv, "-ss_cert") == 0)
422                         {
423                         if (--argc < 1) goto bad;
424                         ss_cert_file = *(++argv);
425                         req=1;
426                         }
427                 else if (strcmp(*argv, "-spkac") == 0)
428                         {
429                         if (--argc < 1) goto bad;
430                         spkac_file = *(++argv);
431                         req=1;
432                         }
433                 else if (strcmp(*argv,"-revoke") == 0)
434                         {
435                         if (--argc < 1) goto bad;
436                         infile= *(++argv);
437                         dorevoke=1;
438                         }
439                 else if (strcmp(*argv,"-extensions") == 0)
440                         {
441                         if (--argc < 1) goto bad;
442                         extensions= *(++argv);
443                         }
444                 else if (strcmp(*argv,"-extfile") == 0)
445                         {
446                         if (--argc < 1) goto bad;
447                         extfile= *(++argv);
448                         }
449                 else if (strcmp(*argv,"-status") == 0)
450                         {
451                         if (--argc < 1) goto bad;
452                         ser_status= *(++argv);
453                         }
454                 else if (strcmp(*argv,"-updatedb") == 0)
455                         {
456                         doupdatedb=1;
457                         }
458                 else if (strcmp(*argv,"-crlexts") == 0)
459                         {
460                         if (--argc < 1) goto bad;
461                         crl_ext= *(++argv);
462                         }
463                 else if (strcmp(*argv,"-engine") == 0)
464                         {
465                         if (--argc < 1) goto bad;
466                         engine= *(++argv);
467                         }
468                 else
469                         {
470 bad:
471                         BIO_printf(bio_err,"unknown option %s\n",*argv);
472                         badops=1;
473                         break;
474                         }
475                 argc--;
476                 argv++;
477                 }
478
479         if (badops)
480                 {
481                 for (pp=ca_usage; (*pp != NULL); pp++)
482                         BIO_printf(bio_err,*pp);
483                 goto err;
484                 }
485
486         ERR_load_crypto_strings();
487
488         if (engine != NULL)
489                 {
490                 if ((e = ENGINE_by_id(engine)) == NULL)
491                         {
492                         BIO_printf(bio_err,"invalid engine \"%s\"\n",
493                                 engine);
494                         goto err;
495                         }
496                 if (!ENGINE_set_default(e, ENGINE_METHOD_ALL))
497                         {
498                         BIO_printf(bio_err,"can't use that engine\n");
499                         goto err;
500                         }
501                 BIO_printf(bio_err,"engine \"%s\" set.\n", engine);
502                 /* Free our "structural" reference. */
503                 ENGINE_free(e);
504                 }
505
506         /*****************************************************************/
507         if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
508         if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
509         if (configfile == NULL)
510                 {
511                 /* We will just use 'buf[0]' as a temporary buffer.  */
512 #ifdef VMS
513                 strncpy(buf[0],X509_get_default_cert_area(),
514                         sizeof(buf[0])-1-sizeof(CONFIG_FILE));
515 #else
516                 strncpy(buf[0],X509_get_default_cert_area(),
517                         sizeof(buf[0])-2-sizeof(CONFIG_FILE));
518                 strcat(buf[0],"/");
519 #endif
520                 strcat(buf[0],CONFIG_FILE);
521                 configfile=buf[0];
522                 }
523
524         BIO_printf(bio_err,"Using configuration from %s\n",configfile);
525         if ((conf=CONF_load(NULL,configfile,&errorline)) == NULL)
526                 {
527                 if (errorline <= 0)
528                         BIO_printf(bio_err,"error loading the config file '%s'\n",
529                                 configfile);
530                 else
531                         BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
532                                 ,errorline,configfile);
533                 goto err;
534                 }
535
536         /* Lets get the config section we are using */
537         if (section == NULL)
538                 {
539                 section=CONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
540                 if (section == NULL)
541                         {
542                         lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
543                         goto err;
544                         }
545                 }
546
547         if (conf != NULL)
548                 {
549                 p=CONF_get_string(conf,NULL,"oid_file");
550                 if (p == NULL)
551                         ERR_clear_error();
552                 if (p != NULL)
553                         {
554                         BIO *oid_bio;
555
556                         oid_bio=BIO_new_file(p,"r");
557                         if (oid_bio == NULL) 
558                                 {
559                                 /*
560                                 BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
561                                 ERR_print_errors(bio_err);
562                                 */
563                                 ERR_clear_error();
564                                 }
565                         else
566                                 {
567                                 OBJ_create_objects(oid_bio);
568                                 BIO_free(oid_bio);
569                                 }
570                         }
571                 if (!add_oid_section(bio_err,conf)) 
572                         {
573                         ERR_print_errors(bio_err);
574                         goto err;
575                         }
576                 }
577
578         randfile = CONF_get_string(conf, BASE_SECTION, "RANDFILE");
579         if (randfile == NULL)
580                 ERR_clear_error();
581         app_RAND_load_file(randfile, bio_err, 0);
582         
583         in=BIO_new(BIO_s_file());
584         out=BIO_new(BIO_s_file());
585         Sout=BIO_new(BIO_s_file());
586         Cout=BIO_new(BIO_s_file());
587         if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL))
588                 {
589                 ERR_print_errors(bio_err);
590                 goto err;
591                 }
592
593         /*****************************************************************/
594         /* report status of cert with serial number given on command line */
595         if (ser_status)
596         {
597                 if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL)
598                         {
599                         lookup_fail(section,ENV_DATABASE);
600                         goto err;
601                         }
602                 if (BIO_read_filename(in,dbfile) <= 0)
603                         {
604                         perror(dbfile);
605                         BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
606                         goto err;
607                         }
608                 db=TXT_DB_read(in,DB_NUMBER);
609                 if (db == NULL) goto err;
610
611                 if (!TXT_DB_create_index(db, DB_serial, NULL,
612                                         LHASH_HASH_FN(index_serial_hash),
613                                         LHASH_COMP_FN(index_serial_cmp)))
614                         {
615                         BIO_printf(bio_err,
616                           "error creating serial number index:(%ld,%ld,%ld)\n",
617                                                 db->error,db->arg1,db->arg2);
618                         goto err;
619                         }
620
621                 if (get_certificate_status(ser_status,db) != 1)
622                         BIO_printf(bio_err,"Error verifying serial %s!\n",
623                                  ser_status);
624                 goto err;
625         }
626
627         /*****************************************************************/
628         /* we definitely need a public key, so let's get it */
629
630         if ((keyfile == NULL) && ((keyfile=CONF_get_string(conf,
631                 section,ENV_PRIVATE_KEY)) == NULL))
632                 {
633                 lookup_fail(section,ENV_PRIVATE_KEY);
634                 goto err;
635                 }
636         if (!key && !app_passwd(bio_err, passargin, NULL, &key, NULL))
637                 {
638                 BIO_printf(bio_err,"Error getting password\n");
639                 goto err;
640                 }
641         if (keyform == FORMAT_ENGINE)
642                 {
643                 if (!e)
644                         {
645                         BIO_printf(bio_err,"no engine specified\n");
646                         goto err;
647                         }
648                 pkey = ENGINE_load_private_key(e, keyfile, key);
649                 }
650         else if (keyform == FORMAT_PEM)
651                 {
652                 if (BIO_read_filename(in,keyfile) <= 0)
653                         {
654                         perror(keyfile);
655                         BIO_printf(bio_err,"trying to load CA private key\n");
656                         goto err;
657                         }
658                 pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,key);
659                 }
660         else
661                 {
662                 BIO_printf(bio_err,"bad input format specified for key file\n");
663                 goto err;
664                 }
665         if (key) memset(key,0,strlen(key));
666         if (pkey == NULL)
667                 {
668                 BIO_printf(bio_err,"unable to load CA private key\n");
669                 goto err;
670                 }
671
672         /*****************************************************************/
673         /* we need a certificate */
674         if ((certfile == NULL) && ((certfile=CONF_get_string(conf,
675                 section,ENV_CERTIFICATE)) == NULL))
676                 {
677                 lookup_fail(section,ENV_CERTIFICATE);
678                 goto err;
679                 }
680         if (BIO_read_filename(in,certfile) <= 0)
681                 {
682                 perror(certfile);
683                 BIO_printf(bio_err,"trying to load CA certificate\n");
684                 goto err;
685                 }
686         x509=PEM_read_bio_X509(in,NULL,NULL,NULL);
687         if (x509 == NULL)
688                 {
689                 BIO_printf(bio_err,"unable to load CA certificate\n");
690                 goto err;
691                 }
692
693         if (!X509_check_private_key(x509,pkey))
694                 {
695                 BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
696                 goto err;
697                 }
698
699         f=CONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
700         if (f == NULL)
701                 ERR_clear_error();
702         if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
703                 preserve=1;
704         f=CONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
705         if (f == NULL)
706                 ERR_clear_error();
707         if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
708                 msie_hack=1;
709
710         /*****************************************************************/
711         /* lookup where to write new certificates */
712         if ((outdir == NULL) && (req))
713                 {
714                 struct stat sb;
715
716                 if ((outdir=CONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
717                         == NULL)
718                         {
719                         BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
720                         goto err;
721                         }
722 #ifndef VMS /* outdir is a directory spec, but access() for VMS demands a
723                filename.  In any case, stat(), below, will catch the problem
724                if outdir is not a directory spec, and the fopen() or open()
725                will catch an error if there is no write access.
726
727                Presumably, this problem could also be solved by using the DEC
728                C routines to convert the directory syntax to Unixly, and give
729                that to access().  However, time's too short to do that just
730                now.
731             */
732                 if (access(outdir,R_OK|W_OK|X_OK) != 0)
733                         {
734                         BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
735                         perror(outdir);
736                         goto err;
737                         }
738
739                 if (stat(outdir,&sb) != 0)
740                         {
741                         BIO_printf(bio_err,"unable to stat(%s)\n",outdir);
742                         perror(outdir);
743                         goto err;
744                         }
745 #ifdef S_IFDIR
746                 if (!(sb.st_mode & S_IFDIR))
747                         {
748                         BIO_printf(bio_err,"%s need to be a directory\n",outdir);
749                         perror(outdir);
750                         goto err;
751                         }
752 #endif
753 #endif
754                 }
755
756         /*****************************************************************/
757         /* we need to load the database file */
758         if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL)
759                 {
760                 lookup_fail(section,ENV_DATABASE);
761                 goto err;
762                 }
763         if (BIO_read_filename(in,dbfile) <= 0)
764                 {
765                 perror(dbfile);
766                 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
767                 goto err;
768                 }
769         db=TXT_DB_read(in,DB_NUMBER);
770         if (db == NULL) goto err;
771
772         /* Lets check some fields */
773         for (i=0; i<sk_num(db->data); i++)
774                 {
775                 pp=(char **)sk_value(db->data,i);
776                 if ((pp[DB_type][0] != DB_TYPE_REV) &&
777                         (pp[DB_rev_date][0] != '\0'))
778                         {
779                         BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
780                         goto err;
781                         }
782                 if ((pp[DB_type][0] == DB_TYPE_REV) &&
783                         !check_time_format(pp[DB_rev_date]))
784                         {
785                         BIO_printf(bio_err,"entry %d: invalid revocation date\n",
786                                 i+1);
787                         goto err;
788                         }
789                 if (!check_time_format(pp[DB_exp_date]))
790                         {
791                         BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
792                         goto err;
793                         }
794                 p=pp[DB_serial];
795                 j=strlen(p);
796                 if ((j&1) || (j < 2))
797                         {
798                         BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
799                         goto err;
800                         }
801                 while (*p)
802                         {
803                         if (!(  ((*p >= '0') && (*p <= '9')) ||
804                                 ((*p >= 'A') && (*p <= 'F')) ||
805                                 ((*p >= 'a') && (*p <= 'f')))  )
806                                 {
807                                 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);
808                                 goto err;
809                                 }
810                         p++;
811                         }
812                 }
813         if (verbose)
814                 {
815                 BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
816 #ifdef VMS
817                 {
818                 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
819                 out = BIO_push(tmpbio, out);
820                 }
821 #endif
822                 TXT_DB_write(out,db);
823                 BIO_printf(bio_err,"%d entries loaded from the database\n",
824                         db->data->num);
825                 BIO_printf(bio_err,"generating index\n");
826                 }
827         
828         if (!TXT_DB_create_index(db, DB_serial, NULL,
829                         LHASH_HASH_FN(index_serial_hash),
830                         LHASH_COMP_FN(index_serial_cmp)))
831                 {
832                 BIO_printf(bio_err,"error creating serial number index:(%ld,%ld,%ld)\n",db->error,db->arg1,db->arg2);
833                 goto err;
834                 }
835
836         if (!TXT_DB_create_index(db, DB_name, index_name_qual,
837                         LHASH_HASH_FN(index_name_hash),
838                         LHASH_COMP_FN(index_name_cmp)))
839                 {
840                 BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
841                         db->error,db->arg1,db->arg2);
842                 goto err;
843                 }
844
845         /*****************************************************************/
846         /* Update the db file for expired certificates */
847         if (doupdatedb)
848                 {
849                 if (verbose)
850                         BIO_printf(bio_err, "Updating %s ...\n",
851                                                         dbfile);
852
853                 i = do_updatedb(db);
854                 if (i == -1)
855                         {
856                         BIO_printf(bio_err,"Malloc failure\n");
857                         goto err;
858                         }
859                 else if (i == 0)
860                         {
861                         if (verbose) BIO_printf(bio_err,
862                                         "No entries found to mark expired\n"); 
863                         }
864                 else
865                         {
866                         out = BIO_new(BIO_s_file());
867                         if (out == NULL)
868                                 {
869                                 ERR_print_errors(bio_err);
870                                 goto err;
871                                 }
872
873                         j = BIO_snprintf(buf[0], sizeof buf[0], "%s.new", dbfile);
874                         if (j < 0 || j >= sizeof buf[0])
875                                 {
876                                 BIO_printf(bio_err, "file name too long\n");
877                                 goto err;
878                                 }
879                         if (BIO_write_filename(out,buf[0]) <= 0)
880                                 {
881                                 perror(dbfile);
882                                 BIO_printf(bio_err,"unable to open '%s'\n",
883                                                                         dbfile);
884                                 goto err;
885                                 }
886                         j=TXT_DB_write(out,db);
887                         if (j <= 0) goto err;
888                         
889                         BIO_free(out);
890                         out = NULL;
891                         j = BIO_snprintf(buf[1], sizeof buf[1], "%s.old", dbfile);
892                         if (j < 0 || j >= sizeof buf[1])
893                                 {
894                                 BIO_printf(bio_err, "file name too long\n");
895                                 goto err;
896                                 }
897                         if (rename(dbfile,buf[1]) < 0)
898                                 {
899                                 BIO_printf(bio_err,
900                                                 "unable to rename %s to %s\n",
901                                                 dbfile, buf[1]);
902                                 perror("reason");
903                                 goto err;
904                                 }
905                         if (rename(buf[0],dbfile) < 0)
906                                 {
907                                 BIO_printf(bio_err,
908                                                 "unable to rename %s to %s\n",
909                                                 buf[0],dbfile);
910                                 perror("reason");
911                                 rename(buf[1],dbfile);
912                                 goto err;
913                                 }
914                                 
915                         if (verbose) BIO_printf(bio_err,
916                                 "Done. %d entries marked as expired\n",i); 
917                         }
918                         goto err;
919                 }
920
921         /*****************************************************************/
922         /* Read extentions config file                                   */
923         if (extfile)
924                 {
925                 long errorline;
926                 if (!(extconf=CONF_load(NULL,extfile,&errorline)))
927                         {
928                         if (errorline <= 0)
929                                 BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
930                                         extfile);
931                         else
932                                 BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n",
933                                         errorline,extfile);
934                         ret = 1;
935                         goto err;
936                         }
937
938                 if (verbose)
939                         BIO_printf(bio_err, "Succesfully loaded extensions file %s\n", extfile);
940
941                 /* We can have sections in the ext file */
942                 if (!extensions && !(extensions = CONF_get_string(extconf, "default", "extensions")))
943                         extensions = "default";
944                 }
945
946         /*****************************************************************/
947         if (req || gencrl)
948                 {
949                 if (outfile != NULL)
950                         {
951                         if (BIO_write_filename(Sout,outfile) <= 0)
952                                 {
953                                 perror(outfile);
954                                 goto err;
955                                 }
956                         }
957                 else
958                         {
959                         BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
960 #ifdef VMS
961                         {
962                         BIO *tmpbio = BIO_new(BIO_f_linebuffer());
963                         Sout = BIO_push(tmpbio, Sout);
964                         }
965 #endif
966                         }
967                 }
968
969         if (req)
970                 {
971                 if ((md == NULL) && ((md=CONF_get_string(conf,
972                         section,ENV_DEFAULT_MD)) == NULL))
973                         {
974                         lookup_fail(section,ENV_DEFAULT_MD);
975                         goto err;
976                         }
977                 if ((dgst=EVP_get_digestbyname(md)) == NULL)
978                         {
979                         BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
980                         goto err;
981                         }
982                 if (verbose)
983                         BIO_printf(bio_err,"message digest is %s\n",
984                                 OBJ_nid2ln(dgst->type));
985                 if ((policy == NULL) && ((policy=CONF_get_string(conf,
986                         section,ENV_POLICY)) == NULL))
987                         {
988                         lookup_fail(section,ENV_POLICY);
989                         goto err;
990                         }
991                 if (verbose)
992                         BIO_printf(bio_err,"policy is %s\n",policy);
993
994                 if ((serialfile=CONF_get_string(conf,section,ENV_SERIAL))
995                         == NULL)
996                         {
997                         lookup_fail(section,ENV_SERIAL);
998                         goto err;
999                         }
1000
1001                 if (!extconf)
1002                         {
1003                         /* no '-extfile' option, so we look for extensions
1004                          * in the main configuration file */
1005                         if (!extensions)
1006                                 {
1007                                 extensions=CONF_get_string(conf,section,
1008                                                                 ENV_EXTENSIONS);
1009                                 if (!extensions)
1010                                         ERR_clear_error();
1011                                 }
1012                         if (extensions)
1013                                 {
1014                                 /* Check syntax of file */
1015                                 X509V3_CTX ctx;
1016                                 X509V3_set_ctx_test(&ctx);
1017                                 X509V3_set_conf_lhash(&ctx, conf);
1018                                 if (!X509V3_EXT_add_conf(conf, &ctx, extensions,
1019                                                                 NULL))
1020                                         {
1021                                         BIO_printf(bio_err,
1022                                         "Error Loading extension section %s\n",
1023                                                                  extensions);
1024                                         ret = 1;
1025                                         goto err;
1026                                         }
1027                                 }
1028                         }
1029
1030                 if (startdate == NULL)
1031                         {
1032                         startdate=CONF_get_string(conf,section,
1033                                 ENV_DEFAULT_STARTDATE);
1034                         if (startdate == NULL)
1035                                 ERR_clear_error();
1036                         }
1037                 if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
1038                         {
1039                         BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
1040                         goto err;
1041                         }
1042                 if (startdate == NULL) startdate="today";
1043
1044                 if (enddate == NULL)
1045                         {
1046                         enddate=CONF_get_string(conf,section,
1047                                 ENV_DEFAULT_ENDDATE);
1048                         if (enddate == NULL)
1049                                 ERR_clear_error();
1050                         }
1051                 if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
1052                         {
1053                         BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
1054                         goto err;
1055                         }
1056
1057                 if (days == 0)
1058                         {
1059                         days=(int)CONF_get_number(conf,section,
1060                                 ENV_DEFAULT_DAYS);
1061                         }
1062                 if (!enddate && (days == 0))
1063                         {
1064                         BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
1065                         goto err;
1066                         }
1067
1068                 if ((serial=load_serial(serialfile)) == NULL)
1069                         {
1070                         BIO_printf(bio_err,"error while loading serial number\n");
1071                         goto err;
1072                         }
1073                 if (verbose)
1074                         {
1075                         if ((f=BN_bn2hex(serial)) == NULL) goto err;
1076                         BIO_printf(bio_err,"next serial number is %s\n",f);
1077                         OPENSSL_free(f);
1078                         }
1079
1080                 if ((attribs=CONF_get_section(conf,policy)) == NULL)
1081                         {
1082                         BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
1083                         goto err;
1084                         }
1085
1086                 if ((cert_sk=sk_X509_new_null()) == NULL)
1087                         {
1088                         BIO_printf(bio_err,"Memory allocation failure\n");
1089                         goto err;
1090                         }
1091                 if (spkac_file != NULL)
1092                         {
1093                         total++;
1094                         j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
1095                                 serial,startdate,enddate, days,extensions,conf,
1096                                 verbose);
1097                         if (j < 0) goto err;
1098                         if (j > 0)
1099                                 {
1100                                 total_done++;
1101                                 BIO_printf(bio_err,"\n");
1102                                 if (!BN_add_word(serial,1)) goto err;
1103                                 if (!sk_X509_push(cert_sk,x))
1104                                         {
1105                                         BIO_printf(bio_err,"Memory allocation failure\n");
1106                                         goto err;
1107                                         }
1108                                 if (outfile)
1109                                         {
1110                                         output_der = 1;
1111                                         batch = 1;
1112                                         }
1113                                 }
1114                         }
1115                 if (ss_cert_file != NULL)
1116                         {
1117                         total++;
1118                         j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
1119                                 db,serial,startdate,enddate,days,batch,
1120                                 extensions,conf,verbose);
1121                         if (j < 0) goto err;
1122                         if (j > 0)
1123                                 {
1124                                 total_done++;
1125                                 BIO_printf(bio_err,"\n");
1126                                 if (!BN_add_word(serial,1)) goto err;
1127                                 if (!sk_X509_push(cert_sk,x))
1128                                         {
1129                                         BIO_printf(bio_err,"Memory allocation failure\n");
1130                                         goto err;
1131                                         }
1132                                 }
1133                         }
1134                 if (infile != NULL)
1135                         {
1136                         total++;
1137                         j=certify(&x,infile,pkey,x509,dgst,attribs,db,
1138                                 serial,startdate,enddate,days,batch,
1139                                 extensions,conf,verbose);
1140                         if (j < 0) goto err;
1141                         if (j > 0)
1142                                 {
1143                                 total_done++;
1144                                 BIO_printf(bio_err,"\n");
1145                                 if (!BN_add_word(serial,1)) goto err;
1146                                 if (!sk_X509_push(cert_sk,x))
1147                                         {
1148                                         BIO_printf(bio_err,"Memory allocation failure\n");
1149                                         goto err;
1150                                         }
1151                                 }
1152                         }
1153                 for (i=0; i<argc; i++)
1154                         {
1155                         total++;
1156                         j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
1157                                 serial,startdate,enddate,days,batch,
1158                                 extensions,conf,verbose);
1159                         if (j < 0) goto err;
1160                         if (j > 0)
1161                                 {
1162                                 total_done++;
1163                                 BIO_printf(bio_err,"\n");
1164                                 if (!BN_add_word(serial,1)) goto err;
1165                                 if (!sk_X509_push(cert_sk,x))
1166                                         {
1167                                         BIO_printf(bio_err,"Memory allocation failure\n");
1168                                         goto err;
1169                                         }
1170                                 }
1171                         }       
1172                 /* we have a stack of newly certified certificates
1173                  * and a data base and serial number that need
1174                  * updating */
1175
1176                 if (sk_X509_num(cert_sk) > 0)
1177                         {
1178                         if (!batch)
1179                                 {
1180                                 BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
1181                                 (void)BIO_flush(bio_err);
1182                                 buf[0][0]='\0';
1183                                 fgets(buf[0],10,stdin);
1184                                 if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
1185                                         {
1186                                         BIO_printf(bio_err,"CERTIFICATION CANCELED\n"); 
1187                                         ret=0;
1188                                         goto err;
1189                                         }
1190                                 }
1191
1192                         BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
1193
1194                         strncpy(buf[0],serialfile,BSIZE-4);
1195
1196 #ifdef VMS
1197                         strcat(buf[0],"-new");
1198 #else
1199                         strcat(buf[0],".new");
1200 #endif
1201
1202                         if (!save_serial(buf[0],serial)) goto err;
1203
1204                         strncpy(buf[1],dbfile,BSIZE-4);
1205
1206 #ifdef VMS
1207                         strcat(buf[1],"-new");
1208 #else
1209                         strcat(buf[1],".new");
1210 #endif
1211
1212                         if (BIO_write_filename(out,buf[1]) <= 0)
1213                                 {
1214                                 perror(dbfile);
1215                                 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1216                                 goto err;
1217                                 }
1218                         l=TXT_DB_write(out,db);
1219                         if (l <= 0) goto err;
1220                         }
1221         
1222                 if (verbose)
1223                         BIO_printf(bio_err,"writing new certificates\n");
1224                 for (i=0; i<sk_X509_num(cert_sk); i++)
1225                         {
1226                         int k;
1227                         unsigned char *n;
1228
1229                         x=sk_X509_value(cert_sk,i);
1230
1231                         j=x->cert_info->serialNumber->length;
1232                         p=(char *)x->cert_info->serialNumber->data;
1233                         
1234                         strncpy(buf[2],outdir,BSIZE-(j*2)-6);
1235
1236 #ifndef VMS
1237                         strcat(buf[2],"/");
1238 #endif
1239
1240                         n=(unsigned char *)&(buf[2][strlen(buf[2])]);
1241                         if (j > 0)
1242                                 {
1243                                 for (k=0; k<j; k++)
1244                                         {
1245                                         sprintf((char *)n,"%02X",(unsigned char)*(p++));
1246                                         n+=2;
1247                                         }
1248                                 }
1249                         else
1250                                 {
1251                                 *(n++)='0';
1252                                 *(n++)='0';
1253                                 }
1254                         *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
1255                         *n='\0';
1256                         if (verbose)
1257                                 BIO_printf(bio_err,"writing %s\n",buf[2]);
1258
1259                         if (BIO_write_filename(Cout,buf[2]) <= 0)
1260                                 {
1261                                 perror(buf[2]);
1262                                 goto err;
1263                                 }
1264                         write_new_certificate(Cout,x, 0, notext);
1265                         write_new_certificate(Sout,x, output_der, notext);
1266                         }
1267
1268                 if (sk_X509_num(cert_sk))
1269                         {
1270                         /* Rename the database and the serial file */
1271                         strncpy(buf[2],serialfile,BSIZE-4);
1272
1273 #ifdef VMS
1274                         strcat(buf[2],"-old");
1275 #else
1276                         strcat(buf[2],".old");
1277 #endif
1278
1279                         BIO_free(in);
1280                         BIO_free_all(out);
1281                         in=NULL;
1282                         out=NULL;
1283                         if (rename(serialfile,buf[2]) < 0)
1284                                 {
1285                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1286                                         serialfile,buf[2]);
1287                                 perror("reason");
1288                                 goto err;
1289                                 }
1290                         if (rename(buf[0],serialfile) < 0)
1291                                 {
1292                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1293                                         buf[0],serialfile);
1294                                 perror("reason");
1295                                 rename(buf[2],serialfile);
1296                                 goto err;
1297                                 }
1298
1299                         strncpy(buf[2],dbfile,BSIZE-4);
1300
1301 #ifdef VMS
1302                         strcat(buf[2],"-old");
1303 #else
1304                         strcat(buf[2],".old");
1305 #endif
1306
1307                         if (rename(dbfile,buf[2]) < 0)
1308                                 {
1309                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1310                                         dbfile,buf[2]);
1311                                 perror("reason");
1312                                 goto err;
1313                                 }
1314                         if (rename(buf[1],dbfile) < 0)
1315                                 {
1316                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1317                                         buf[1],dbfile);
1318                                 perror("reason");
1319                                 rename(buf[2],dbfile);
1320                                 goto err;
1321                                 }
1322                         BIO_printf(bio_err,"Data Base Updated\n");
1323                         }
1324                 }
1325         
1326         /*****************************************************************/
1327         if (gencrl)
1328                 {
1329                 if (!crl_ext)
1330                         {
1331                         crl_ext=CONF_get_string(conf,section,ENV_CRLEXT);
1332                         if (!crl_ext)
1333                                 ERR_clear_error();
1334                         }
1335                 if (crl_ext)
1336                         {
1337                         /* Check syntax of file */
1338                         X509V3_CTX ctx;
1339                         X509V3_set_ctx_test(&ctx);
1340                         X509V3_set_conf_lhash(&ctx, conf);
1341                         if (!X509V3_EXT_add_conf(conf, &ctx, crl_ext, NULL))
1342                                 {
1343                                 BIO_printf(bio_err,
1344                                  "Error Loading CRL extension section %s\n",
1345                                                                  crl_ext);
1346                                 ret = 1;
1347                                 goto err;
1348                                 }
1349                         }
1350                 if ((hex=BIO_new(BIO_s_mem())) == NULL) goto err;
1351
1352                 if (!crldays && !crlhours)
1353                         {
1354                         crldays=CONF_get_number(conf,section,
1355                                 ENV_DEFAULT_CRL_DAYS);
1356                         crlhours=CONF_get_number(conf,section,
1357                                 ENV_DEFAULT_CRL_HOURS);
1358                         }
1359                 if ((crldays == 0) && (crlhours == 0))
1360                         {
1361                         BIO_printf(bio_err,"cannot lookup how long until the next CRL is issuer\n");
1362                         goto err;
1363                         }
1364
1365                 if (verbose) BIO_printf(bio_err,"making CRL\n");
1366                 if ((crl=X509_CRL_new()) == NULL) goto err;
1367                 ci=crl->crl;
1368                 X509_NAME_free(ci->issuer);
1369                 ci->issuer=X509_NAME_dup(x509->cert_info->subject);
1370                 if (ci->issuer == NULL) goto err;
1371
1372                 X509_gmtime_adj(ci->lastUpdate,0);
1373                 if (ci->nextUpdate == NULL)
1374                         ci->nextUpdate=ASN1_UTCTIME_new();
1375                 X509_gmtime_adj(ci->nextUpdate,(crldays*24+crlhours)*60*60);
1376
1377                 for (i=0; i<sk_num(db->data); i++)
1378                         {
1379                         pp=(char **)sk_value(db->data,i);
1380                         if (pp[DB_type][0] == DB_TYPE_REV)
1381                                 {
1382                                 if ((r=X509_REVOKED_new()) == NULL) goto err;
1383                                 ASN1_STRING_set((ASN1_STRING *)
1384                                         r->revocationDate,
1385                                         (unsigned char *)pp[DB_rev_date],
1386                                         strlen(pp[DB_rev_date]));
1387                                 /* strcpy(r->revocationDate,pp[DB_rev_date]);*/
1388
1389                                 (void)BIO_reset(hex);
1390                                 if (!BIO_puts(hex,pp[DB_serial]))
1391                                         goto err;
1392                                 if (!a2i_ASN1_INTEGER(hex,r->serialNumber,
1393                                         buf[0],BSIZE)) goto err;
1394
1395                                 X509_CRL_add0_revoked(crl,r);
1396                                 }
1397                         }
1398                 /* sort the data so it will be written in serial
1399                  * number order */
1400                 sk_X509_REVOKED_sort(ci->revoked);
1401                 for (i=0; i<sk_X509_REVOKED_num(ci->revoked); i++)
1402                         {
1403                         r=sk_X509_REVOKED_value(ci->revoked,i);
1404                         r->sequence=i;
1405                         }
1406
1407                 /* we now have a CRL */
1408                 if (verbose) BIO_printf(bio_err,"signing CRL\n");
1409                 if (md != NULL)
1410                         {
1411                         if ((dgst=EVP_get_digestbyname(md)) == NULL)
1412                                 {
1413                                 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1414                                 goto err;
1415                                 }
1416                         }
1417                 else
1418                         {
1419 #ifndef NO_DSA
1420                         if (pkey->type == EVP_PKEY_DSA) 
1421                                 dgst=EVP_dss1();
1422                         else
1423 #endif
1424                                 dgst=EVP_md5();
1425                         }
1426
1427                 /* Add any extensions asked for */
1428
1429                 if (crl_ext)
1430                         {
1431                         X509V3_CTX crlctx;
1432                         if (ci->version == NULL)
1433                                 if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
1434                         ASN1_INTEGER_set(ci->version,1); /* version 2 CRL */
1435                         X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1436                         X509V3_set_conf_lhash(&crlctx, conf);
1437
1438                         if (!X509V3_EXT_CRL_add_conf(conf, &crlctx,
1439                                 crl_ext, crl)) goto err;
1440                         }
1441
1442                 if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1443
1444                 PEM_write_bio_X509_CRL(Sout,crl);
1445                 }
1446         /*****************************************************************/
1447         if (dorevoke)
1448                 {
1449                 if (infile == NULL) 
1450                         {
1451                         BIO_printf(bio_err,"no input files\n");
1452                         goto err;
1453                         }
1454                 else
1455                         {
1456                         X509 *revcert;
1457                         if (BIO_read_filename(in,infile) <= 0)
1458                                 {
1459                                 perror(infile);
1460                                 BIO_printf(bio_err,"error trying to load '%s' certificate\n",infile);
1461                                 goto err;
1462                                 }
1463                         revcert=PEM_read_bio_X509(in,NULL,NULL,NULL);
1464                         if (revcert == NULL)
1465                                 {
1466                                 BIO_printf(bio_err,"unable to load '%s' certificate\n",infile);
1467                                 goto err;
1468                                 }
1469                         j=do_revoke(revcert,db);
1470                         if (j <= 0) goto err;
1471                         X509_free(revcert);
1472
1473                         strncpy(buf[0],dbfile,BSIZE-4);
1474                         strcat(buf[0],".new");
1475                         if (BIO_write_filename(out,buf[0]) <= 0)
1476                                 {
1477                                 perror(dbfile);
1478                                 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1479                                 goto err;
1480                                 }
1481                         j=TXT_DB_write(out,db);
1482                         if (j <= 0) goto err;
1483                         strncpy(buf[1],dbfile,BSIZE-4);
1484                         strcat(buf[1],".old");
1485                         if (rename(dbfile,buf[1]) < 0)
1486                                 {
1487                                 BIO_printf(bio_err,"unable to rename %s to %s\n", dbfile, buf[1]);
1488                                 perror("reason");
1489                                 goto err;
1490                                 }
1491                         if (rename(buf[0],dbfile) < 0)
1492                                 {
1493                                 BIO_printf(bio_err,"unable to rename %s to %s\n", buf[0],dbfile);
1494                                 perror("reason");
1495                                 rename(buf[1],dbfile);
1496                                 goto err;
1497                                 }
1498                         BIO_printf(bio_err,"Data Base Updated\n"); 
1499                         }
1500                 }
1501         /*****************************************************************/
1502         ret=0;
1503 err:
1504         BIO_free(hex);
1505         BIO_free_all(Cout);
1506         BIO_free_all(Sout);
1507         BIO_free_all(out);
1508         BIO_free(in);
1509
1510         sk_X509_pop_free(cert_sk,X509_free);
1511
1512         if (ret) ERR_print_errors(bio_err);
1513         app_RAND_write_file(randfile, bio_err);
1514         BN_free(serial);
1515         TXT_DB_free(db);
1516         EVP_PKEY_free(pkey);
1517         X509_free(x509);
1518         X509_CRL_free(crl);
1519         CONF_free(conf);
1520         OBJ_cleanup();
1521         EXIT(ret);
1522         }
1523
1524 static void lookup_fail(char *name, char *tag)
1525         {
1526         BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1527         }
1528
1529 static unsigned long index_serial_hash(const char **a)
1530         {
1531         const char *n;
1532
1533         n=a[DB_serial];
1534         while (*n == '0') n++;
1535         return(lh_strhash(n));
1536         }
1537
1538 static int index_serial_cmp(const char **a, const char **b)
1539         {
1540         const char *aa,*bb;
1541
1542         for (aa=a[DB_serial]; *aa == '0'; aa++);
1543         for (bb=b[DB_serial]; *bb == '0'; bb++);
1544         return(strcmp(aa,bb));
1545         }
1546
1547 static unsigned long index_name_hash(const char **a)
1548         { return(lh_strhash(a[DB_name])); }
1549
1550 static int index_name_qual(char **a)
1551         { return(a[0][0] == 'V'); }
1552
1553 static int index_name_cmp(const char **a, const char **b)
1554         { return(strcmp(a[DB_name],
1555              b[DB_name])); }
1556
1557 static BIGNUM *load_serial(char *serialfile)
1558         {
1559         BIO *in=NULL;
1560         BIGNUM *ret=NULL;
1561         MS_STATIC char buf[1024];
1562         ASN1_INTEGER *ai=NULL;
1563
1564         if ((in=BIO_new(BIO_s_file())) == NULL)
1565                 {
1566                 ERR_print_errors(bio_err);
1567                 goto err;
1568                 }
1569
1570         if (BIO_read_filename(in,serialfile) <= 0)
1571                 {
1572                 perror(serialfile);
1573                 goto err;
1574                 }
1575         ai=ASN1_INTEGER_new();
1576         if (ai == NULL) goto err;
1577         if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
1578                 {
1579                 BIO_printf(bio_err,"unable to load number from %s\n",
1580                         serialfile);
1581                 goto err;
1582                 }
1583         ret=ASN1_INTEGER_to_BN(ai,NULL);
1584         if (ret == NULL)
1585                 {
1586                 BIO_printf(bio_err,"error converting number from bin to BIGNUM");
1587                 goto err;
1588                 }
1589 err:
1590         if (in != NULL) BIO_free(in);
1591         if (ai != NULL) ASN1_INTEGER_free(ai);
1592         return(ret);
1593         }
1594
1595 static int save_serial(char *serialfile, BIGNUM *serial)
1596         {
1597         BIO *out;
1598         int ret=0;
1599         ASN1_INTEGER *ai=NULL;
1600
1601         out=BIO_new(BIO_s_file());
1602         if (out == NULL)
1603                 {
1604                 ERR_print_errors(bio_err);
1605                 goto err;
1606                 }
1607         if (BIO_write_filename(out,serialfile) <= 0)
1608                 {
1609                 perror(serialfile);
1610                 goto err;
1611                 }
1612
1613         if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
1614                 {
1615                 BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
1616                 goto err;
1617                 }
1618         i2a_ASN1_INTEGER(out,ai);
1619         BIO_puts(out,"\n");
1620         ret=1;
1621 err:
1622         if (out != NULL) BIO_free_all(out);
1623         if (ai != NULL) ASN1_INTEGER_free(ai);
1624         return(ret);
1625         }
1626
1627 static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1628              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1629              BIGNUM *serial, char *startdate, char *enddate, int days,
1630              int batch, char *ext_sect, LHASH *lconf, int verbose)
1631         {
1632         X509_REQ *req=NULL;
1633         BIO *in=NULL;
1634         EVP_PKEY *pktmp=NULL;
1635         int ok= -1,i;
1636
1637         in=BIO_new(BIO_s_file());
1638
1639         if (BIO_read_filename(in,infile) <= 0)
1640                 {
1641                 perror(infile);
1642                 goto err;
1643                 }
1644         if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
1645                 {
1646                 BIO_printf(bio_err,"Error reading certificate request in %s\n",
1647                         infile);
1648                 goto err;
1649                 }
1650         if (verbose)
1651                 X509_REQ_print(bio_err,req);
1652
1653         BIO_printf(bio_err,"Check that the request matches the signature\n");
1654
1655         if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
1656                 {
1657                 BIO_printf(bio_err,"error unpacking public key\n");
1658                 goto err;
1659                 }
1660         i=X509_REQ_verify(req,pktmp);
1661         EVP_PKEY_free(pktmp);
1662         if (i < 0)
1663                 {
1664                 ok=0;
1665                 BIO_printf(bio_err,"Signature verification problems....\n");
1666                 goto err;
1667                 }
1668         if (i == 0)
1669                 {
1670                 ok=0;
1671                 BIO_printf(bio_err,"Signature did not match the certificate request\n");
1672                 goto err;
1673                 }
1674         else
1675                 BIO_printf(bio_err,"Signature ok\n");
1676
1677         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate, enddate,
1678                 days,batch,verbose,req,ext_sect,lconf);
1679
1680 err:
1681         if (req != NULL) X509_REQ_free(req);
1682         if (in != NULL) BIO_free(in);
1683         return(ok);
1684         }
1685
1686 static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1687              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1688              BIGNUM *serial, char *startdate, char *enddate, int days,
1689              int batch, char *ext_sect, LHASH *lconf, int verbose)
1690         {
1691         X509 *req=NULL;
1692         X509_REQ *rreq=NULL;
1693         BIO *in=NULL;
1694         EVP_PKEY *pktmp=NULL;
1695         int ok= -1,i;
1696
1697         in=BIO_new(BIO_s_file());
1698
1699         if (BIO_read_filename(in,infile) <= 0)
1700                 {
1701                 perror(infile);
1702                 goto err;
1703                 }
1704         if ((req=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
1705                 {
1706                 BIO_printf(bio_err,"Error reading self signed certificate in %s\n",infile);
1707                 goto err;
1708                 }
1709         if (verbose)
1710                 X509_print(bio_err,req);
1711
1712         BIO_printf(bio_err,"Check that the request matches the signature\n");
1713
1714         if ((pktmp=X509_get_pubkey(req)) == NULL)
1715                 {
1716                 BIO_printf(bio_err,"error unpacking public key\n");
1717                 goto err;
1718                 }
1719         i=X509_verify(req,pktmp);
1720         EVP_PKEY_free(pktmp);
1721         if (i < 0)
1722                 {
1723                 ok=0;
1724                 BIO_printf(bio_err,"Signature verification problems....\n");
1725                 goto err;
1726                 }
1727         if (i == 0)
1728                 {
1729                 ok=0;
1730                 BIO_printf(bio_err,"Signature did not match the certificate\n");
1731                 goto err;
1732                 }
1733         else
1734                 BIO_printf(bio_err,"Signature ok\n");
1735
1736         if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
1737                 goto err;
1738
1739         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,days,
1740                 batch,verbose,rreq,ext_sect,lconf);
1741
1742 err:
1743         if (rreq != NULL) X509_REQ_free(rreq);
1744         if (req != NULL) X509_free(req);
1745         if (in != NULL) BIO_free(in);
1746         return(ok);
1747         }
1748
1749 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1750              STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
1751              char *startdate, char *enddate, int days, int batch, int verbose,
1752              X509_REQ *req, char *ext_sect, LHASH *lconf)
1753         {
1754         X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
1755         ASN1_UTCTIME *tm,*tmptm;
1756         ASN1_STRING *str,*str2;
1757         ASN1_OBJECT *obj;
1758         X509 *ret=NULL;
1759         X509_CINF *ci;
1760         X509_NAME_ENTRY *ne;
1761         X509_NAME_ENTRY *tne,*push;
1762         EVP_PKEY *pktmp;
1763         int ok= -1,i,j,last,nid;
1764         char *p;
1765         CONF_VALUE *cv;
1766         char *row[DB_NUMBER],**rrow,**irow=NULL;
1767         char buf[25],*pbuf;
1768
1769         tmptm=ASN1_UTCTIME_new();
1770         if (tmptm == NULL)
1771                 {
1772                 BIO_printf(bio_err,"malloc error\n");
1773                 return(0);
1774                 }
1775
1776         for (i=0; i<DB_NUMBER; i++)
1777                 row[i]=NULL;
1778
1779         BIO_printf(bio_err,"The Subjects Distinguished Name is as follows\n");
1780         name=X509_REQ_get_subject_name(req);
1781         for (i=0; i<X509_NAME_entry_count(name); i++)
1782                 {
1783                 ne=(X509_NAME_ENTRY *)X509_NAME_get_entry(name,i);
1784                 obj=X509_NAME_ENTRY_get_object(ne);
1785                 j=i2a_ASN1_OBJECT(bio_err,obj);
1786                 str=X509_NAME_ENTRY_get_data(ne);
1787                 pbuf=buf;
1788                 for (j=22-j; j>0; j--)
1789                         *(pbuf++)=' ';
1790                 *(pbuf++)=':';
1791                 *(pbuf++)='\0';
1792                 BIO_puts(bio_err,buf);
1793
1794                 if (msie_hack)
1795                         {
1796                         /* assume all type should be strings */
1797                         nid=OBJ_obj2nid(ne->object);
1798
1799                         if (str->type == V_ASN1_UNIVERSALSTRING)
1800                                 ASN1_UNIVERSALSTRING_to_string(str);
1801
1802                         if ((str->type == V_ASN1_IA5STRING) &&
1803                                 (nid != NID_pkcs9_emailAddress))
1804                                 str->type=V_ASN1_T61STRING;
1805
1806                         if ((nid == NID_pkcs9_emailAddress) &&
1807                                 (str->type == V_ASN1_PRINTABLESTRING))
1808                                 str->type=V_ASN1_IA5STRING;
1809                         }
1810
1811                 if (str->type == V_ASN1_PRINTABLESTRING)
1812                         BIO_printf(bio_err,"PRINTABLE:'");
1813                 else if (str->type == V_ASN1_T61STRING)
1814                         BIO_printf(bio_err,"T61STRING:'");
1815                 else if (str->type == V_ASN1_IA5STRING)
1816                         BIO_printf(bio_err,"IA5STRING:'");
1817                 else if (str->type == V_ASN1_UNIVERSALSTRING)
1818                         BIO_printf(bio_err,"UNIVERSALSTRING:'");
1819                 else
1820                         BIO_printf(bio_err,"ASN.1 %2d:'",str->type);
1821
1822                 /* check some things */
1823                 if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1824                         (str->type != V_ASN1_IA5STRING))
1825                         {
1826                         BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
1827                         goto err;
1828                         }
1829                 j=ASN1_PRINTABLE_type(str->data,str->length);
1830                 if (    ((j == V_ASN1_T61STRING) &&
1831                          (str->type != V_ASN1_T61STRING)) ||
1832                         ((j == V_ASN1_IA5STRING) &&
1833                          (str->type == V_ASN1_PRINTABLESTRING)))
1834                         {
1835                         BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1836                         goto err;
1837                         }
1838                         
1839                 p=(char *)str->data;
1840                 for (j=str->length; j>0; j--)
1841                         {
1842                         if ((*p >= ' ') && (*p <= '~'))
1843                                 BIO_printf(bio_err,"%c",*p);
1844                         else if (*p & 0x80)
1845                                 BIO_printf(bio_err,"\\0x%02X",*p);
1846                         else if ((unsigned char)*p == 0xf7)
1847                                 BIO_printf(bio_err,"^?");
1848                         else    BIO_printf(bio_err,"^%c",*p+'@');
1849                         p++;
1850                         }
1851                 BIO_printf(bio_err,"'\n");
1852                 }
1853
1854         /* Ok, now we check the 'policy' stuff. */
1855         if ((subject=X509_NAME_new()) == NULL)
1856                 {
1857                 BIO_printf(bio_err,"Memory allocation failure\n");
1858                 goto err;
1859                 }
1860
1861         /* take a copy of the issuer name before we mess with it. */
1862         CAname=X509_NAME_dup(x509->cert_info->subject);
1863         if (CAname == NULL) goto err;
1864         str=str2=NULL;
1865
1866         for (i=0; i<sk_CONF_VALUE_num(policy); i++)
1867                 {
1868                 cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
1869                 if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
1870                         {
1871                         BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
1872                         goto err;
1873                         }
1874                 obj=OBJ_nid2obj(j);
1875
1876                 last= -1;
1877                 for (;;)
1878                         {
1879                         /* lookup the object in the supplied name list */
1880                         j=X509_NAME_get_index_by_OBJ(name,obj,last);
1881                         if (j < 0)
1882                                 {
1883                                 if (last != -1) break;
1884                                 tne=NULL;
1885                                 }
1886                         else
1887                                 {
1888                                 tne=X509_NAME_get_entry(name,j);
1889                                 }
1890                         last=j;
1891
1892                         /* depending on the 'policy', decide what to do. */
1893                         push=NULL;
1894                         if (strcmp(cv->value,"optional") == 0)
1895                                 {
1896                                 if (tne != NULL)
1897                                         push=tne;
1898                                 }
1899                         else if (strcmp(cv->value,"supplied") == 0)
1900                                 {
1901                                 if (tne == NULL)
1902                                         {
1903                                         BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
1904                                         goto err;
1905                                         }
1906                                 else
1907                                         push=tne;
1908                                 }
1909                         else if (strcmp(cv->value,"match") == 0)
1910                                 {
1911                                 int last2;
1912
1913                                 if (tne == NULL)
1914                                         {
1915                                         BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
1916                                         goto err;
1917                                         }
1918
1919                                 last2= -1;
1920
1921 again2:
1922                                 j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
1923                                 if ((j < 0) && (last2 == -1))
1924                                         {
1925                                         BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
1926                                         goto err;
1927                                         }
1928                                 if (j >= 0)
1929                                         {
1930                                         push=X509_NAME_get_entry(CAname,j);
1931                                         str=X509_NAME_ENTRY_get_data(tne);
1932                                         str2=X509_NAME_ENTRY_get_data(push);
1933                                         last2=j;
1934                                         if (ASN1_STRING_cmp(str,str2) != 0)
1935                                                 goto again2;
1936                                         }
1937                                 if (j < 0)
1938                                         {
1939                                         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));
1940                                         goto err;
1941                                         }
1942                                 }
1943                         else
1944                                 {
1945                                 BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
1946                                 goto err;
1947                                 }
1948
1949                         if (push != NULL)
1950                                 {
1951                                 if (!X509_NAME_add_entry(subject,push, -1, 0))
1952                                         {
1953                                         if (push != NULL)
1954                                                 X509_NAME_ENTRY_free(push);
1955                                         BIO_printf(bio_err,"Memory allocation failure\n");
1956                                         goto err;
1957                                         }
1958                                 }
1959                         if (j < 0) break;
1960                         }
1961                 }
1962
1963         if (preserve)
1964                 {
1965                 X509_NAME_free(subject);
1966                 subject=X509_NAME_dup(X509_REQ_get_subject_name(req));
1967                 if (subject == NULL) goto err;
1968                 }
1969
1970         if (verbose)
1971                 BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
1972
1973         row[DB_name]=X509_NAME_oneline(subject,NULL,0);
1974         row[DB_serial]=BN_bn2hex(serial);
1975         if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
1976                 {
1977                 BIO_printf(bio_err,"Memory allocation failure\n");
1978                 goto err;
1979                 }
1980
1981         rrow=TXT_DB_get_by_index(db,DB_name,row);
1982         if (rrow != NULL)
1983                 {
1984                 BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n",
1985                         row[DB_name]);
1986                 }
1987         else
1988                 {
1989                 rrow=TXT_DB_get_by_index(db,DB_serial,row);
1990                 if (rrow != NULL)
1991                         {
1992                         BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
1993                                 row[DB_serial]);
1994                         BIO_printf(bio_err,"      check the database/serial_file for corruption\n");
1995                         }
1996                 }
1997
1998         if (rrow != NULL)
1999                 {
2000                 BIO_printf(bio_err,
2001                         "The matching entry has the following details\n");
2002                 if (rrow[DB_type][0] == 'E')
2003                         p="Expired";
2004                 else if (rrow[DB_type][0] == 'R')
2005                         p="Revoked";
2006                 else if (rrow[DB_type][0] == 'V')
2007                         p="Valid";
2008                 else
2009                         p="\ninvalid type, Data base error\n";
2010                 BIO_printf(bio_err,"Type          :%s\n",p);;
2011                 if (rrow[DB_type][0] == 'R')
2012                         {
2013                         p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2014                         BIO_printf(bio_err,"Was revoked on:%s\n",p);
2015                         }
2016                 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2017                 BIO_printf(bio_err,"Expires on    :%s\n",p);
2018                 p=rrow[DB_serial]; if (p == NULL) p="undef";
2019                 BIO_printf(bio_err,"Serial Number :%s\n",p);
2020                 p=rrow[DB_file]; if (p == NULL) p="undef";
2021                 BIO_printf(bio_err,"File name     :%s\n",p);
2022                 p=rrow[DB_name]; if (p == NULL) p="undef";
2023                 BIO_printf(bio_err,"Subject Name  :%s\n",p);
2024                 ok= -1; /* This is now a 'bad' error. */
2025                 goto err;
2026                 }
2027
2028         /* We are now totally happy, lets make and sign the certificate */
2029         if (verbose)
2030                 BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
2031
2032         if ((ret=X509_new()) == NULL) goto err;
2033         ci=ret->cert_info;
2034
2035 #ifdef X509_V3
2036         /* Make it an X509 v3 certificate. */
2037         if (!X509_set_version(x509,2)) goto err;
2038 #endif
2039
2040         if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
2041                 goto err;
2042         if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
2043                 goto err;
2044
2045         BIO_printf(bio_err,"Certificate is to be certified until ");
2046         if (strcmp(startdate,"today") == 0)
2047                 X509_gmtime_adj(X509_get_notBefore(ret),0);
2048         else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
2049
2050         if (enddate == NULL)
2051                 X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
2052         else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
2053
2054         ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
2055         if (days) BIO_printf(bio_err," (%d days)",days);
2056         BIO_printf(bio_err, "\n");
2057
2058         if (!X509_set_subject_name(ret,subject)) goto err;
2059
2060         pktmp=X509_REQ_get_pubkey(req);
2061         i = X509_set_pubkey(ret,pktmp);
2062         EVP_PKEY_free(pktmp);
2063         if (!i) goto err;
2064
2065         /* Lets add the extensions, if there are any */
2066         if (ext_sect)
2067                 {
2068                 X509V3_CTX ctx;
2069                 if (ci->version == NULL)
2070                         if ((ci->version=ASN1_INTEGER_new()) == NULL)
2071                                 goto err;
2072                 ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
2073
2074                 /* Free the current entries if any, there should not
2075                  * be any I believe */
2076                 if (ci->extensions != NULL)
2077                         sk_X509_EXTENSION_pop_free(ci->extensions,
2078                                                    X509_EXTENSION_free);
2079
2080                 ci->extensions = NULL;
2081
2082                 /* Initialize the context structure */
2083                 X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
2084
2085                 if (extconf)
2086                         {
2087                         if (verbose)
2088                                 BIO_printf(bio_err, "Extra configuration file found\n");
2089  
2090                         /* Use the extconf configuration db LHASH */
2091                         X509V3_set_conf_lhash(&ctx, extconf);
2092  
2093                         /* Test the structure (needed?) */
2094                         /* X509V3_set_ctx_test(&ctx); */
2095
2096                         /* Adds exts contained in the configuration file */
2097                         if (!X509V3_EXT_add_conf(extconf, &ctx, ext_sect,ret))
2098                                 {
2099                                 BIO_printf(bio_err,
2100                                     "ERROR: adding extensions in section %s\n",
2101                                                                 ext_sect);
2102                                 ERR_print_errors(bio_err);
2103                                 goto err;
2104                                 }
2105                         if (verbose)
2106                                 BIO_printf(bio_err, "Successfully added extensions from file.\n");
2107                         }
2108                 else if (ext_sect)
2109                         {
2110                         /* We found extensions to be set from config file */
2111                         X509V3_set_conf_lhash(&ctx, lconf);
2112
2113                         if(!X509V3_EXT_add_conf(lconf, &ctx, ext_sect, ret))
2114                                 {
2115                                 BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2116                                 ERR_print_errors(bio_err);
2117                                 goto err;
2118                                 }
2119
2120                         if (verbose) 
2121                                 BIO_printf(bio_err, "Successfully added extensions from config\n");
2122                         }
2123                 }
2124
2125
2126         if (!batch)
2127                 {
2128                 BIO_printf(bio_err,"Sign the certificate? [y/n]:");
2129                 (void)BIO_flush(bio_err);
2130                 buf[0]='\0';
2131                 fgets(buf,sizeof(buf)-1,stdin);
2132                 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
2133                         {
2134                         BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
2135                         ok=0;
2136                         goto err;
2137                         }
2138                 }
2139
2140
2141 #ifndef NO_DSA
2142         if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
2143         pktmp=X509_get_pubkey(ret);
2144         if (EVP_PKEY_missing_parameters(pktmp) &&
2145                 !EVP_PKEY_missing_parameters(pkey))
2146                 EVP_PKEY_copy_parameters(pktmp,pkey);
2147         EVP_PKEY_free(pktmp);
2148 #endif
2149
2150         if (!X509_sign(ret,pkey,dgst))
2151                 goto err;
2152
2153         /* We now just add it to the database */
2154         row[DB_type]=(char *)OPENSSL_malloc(2);
2155
2156         tm=X509_get_notAfter(ret);
2157         row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2158         memcpy(row[DB_exp_date],tm->data,tm->length);
2159         row[DB_exp_date][tm->length]='\0';
2160
2161         row[DB_rev_date]=NULL;
2162
2163         /* row[DB_serial] done already */
2164         row[DB_file]=(char *)OPENSSL_malloc(8);
2165         /* row[DB_name] done already */
2166
2167         if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2168                 (row[DB_file] == NULL))
2169                 {
2170                 BIO_printf(bio_err,"Memory allocation failure\n");
2171                 goto err;
2172                 }
2173         strcpy(row[DB_file],"unknown");
2174         row[DB_type][0]='V';
2175         row[DB_type][1]='\0';
2176
2177         if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2178                 {
2179                 BIO_printf(bio_err,"Memory allocation failure\n");
2180                 goto err;
2181                 }
2182
2183         for (i=0; i<DB_NUMBER; i++)
2184                 {
2185                 irow[i]=row[i];
2186                 row[i]=NULL;
2187                 }
2188         irow[DB_NUMBER]=NULL;
2189
2190         if (!TXT_DB_insert(db,irow))
2191                 {
2192                 BIO_printf(bio_err,"failed to update database\n");
2193                 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2194                 goto err;
2195                 }
2196         ok=1;
2197 err:
2198         for (i=0; i<DB_NUMBER; i++)
2199                 if (row[i] != NULL) OPENSSL_free(row[i]);
2200
2201         if (CAname != NULL)
2202                 X509_NAME_free(CAname);
2203         if (subject != NULL)
2204                 X509_NAME_free(subject);
2205         if (tmptm != NULL)
2206                 ASN1_UTCTIME_free(tmptm);
2207         if (ok <= 0)
2208                 {
2209                 if (ret != NULL) X509_free(ret);
2210                 ret=NULL;
2211                 }
2212         else
2213                 *xret=ret;
2214         return(ok);
2215         }
2216
2217 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
2218         {
2219
2220         if (output_der)
2221                 {
2222                 (void)i2d_X509_bio(bp,x);
2223                 return;
2224                 }
2225 #if 0
2226         /* ??? Not needed since X509_print prints all this stuff anyway */
2227         f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
2228         BIO_printf(bp,"issuer :%s\n",f);
2229
2230         f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
2231         BIO_printf(bp,"subject:%s\n",f);
2232
2233         BIO_puts(bp,"serial :");
2234         i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
2235         BIO_puts(bp,"\n\n");
2236 #endif
2237         if (!notext)X509_print(bp,x);
2238         PEM_write_bio_X509(bp,x);
2239         }
2240
2241 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
2242              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
2243              BIGNUM *serial, char *startdate, char *enddate, int days,
2244              char *ext_sect, LHASH *lconf, int verbose)
2245         {
2246         STACK_OF(CONF_VALUE) *sk=NULL;
2247         LHASH *parms=NULL;
2248         X509_REQ *req=NULL;
2249         CONF_VALUE *cv=NULL;
2250         NETSCAPE_SPKI *spki = NULL;
2251         X509_REQ_INFO *ri;
2252         char *type,*buf;
2253         EVP_PKEY *pktmp=NULL;
2254         X509_NAME *n=NULL;
2255         X509_NAME_ENTRY *ne=NULL;
2256         int ok= -1,i,j;
2257         long errline;
2258         int nid;
2259
2260         /*
2261          * Load input file into a hash table.  (This is just an easy
2262          * way to read and parse the file, then put it into a convenient
2263          * STACK format).
2264          */
2265         parms=CONF_load(NULL,infile,&errline);
2266         if (parms == NULL)
2267                 {
2268                 BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
2269                 ERR_print_errors(bio_err);
2270                 goto err;
2271                 }
2272
2273         sk=CONF_get_section(parms, "default");
2274         if (sk_CONF_VALUE_num(sk) == 0)
2275                 {
2276                 BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2277                 CONF_free(parms);
2278                 goto err;
2279                 }
2280
2281         /*
2282          * Now create a dummy X509 request structure.  We don't actually
2283          * have an X509 request, but we have many of the components
2284          * (a public key, various DN components).  The idea is that we
2285          * put these components into the right X509 request structure
2286          * and we can use the same code as if you had a real X509 request.
2287          */
2288         req=X509_REQ_new();
2289         if (req == NULL)
2290                 {
2291                 ERR_print_errors(bio_err);
2292                 goto err;
2293                 }
2294
2295         /*
2296          * Build up the subject name set.
2297          */
2298         ri=req->req_info;
2299         n = ri->subject;
2300
2301         for (i = 0; ; i++)
2302                 {
2303                 if (sk_CONF_VALUE_num(sk) <= i) break;
2304
2305                 cv=sk_CONF_VALUE_value(sk,i);
2306                 type=cv->name;
2307                 /* Skip past any leading X. X: X, etc to allow for
2308                  * multiple instances
2309                  */
2310                 for (buf = cv->name; *buf ; buf++)
2311                         if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2312                                 {
2313                                 buf++;
2314                                 if (*buf) type = buf;
2315                                 break;
2316                                 }
2317
2318                 buf=cv->value;
2319                 if ((nid=OBJ_txt2nid(type)) == NID_undef)
2320                         {
2321                         if (strcmp(type, "SPKAC") == 0)
2322                                 {
2323                                 spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2324                                 if (spki == NULL)
2325                                         {
2326                                         BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2327                                         ERR_print_errors(bio_err);
2328                                         goto err;
2329                                         }
2330                                 }
2331                         continue;
2332                         }
2333
2334                 j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
2335                 if (fix_data(nid, &j) == 0)
2336                         {
2337                         BIO_printf(bio_err,
2338                                 "invalid characters in string %s\n",buf);
2339                         goto err;
2340                         }
2341
2342                 if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
2343                         (unsigned char *)buf,
2344                         strlen(buf))) == NULL)
2345                         goto err;
2346
2347                 if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
2348                 }
2349         if (spki == NULL)
2350                 {
2351                 BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2352                         infile);
2353                 goto err;
2354                 }
2355
2356         /*
2357          * Now extract the key from the SPKI structure.
2358          */
2359
2360         BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2361
2362         if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
2363                 {
2364                 BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2365                 goto err;
2366                 }
2367
2368         j = NETSCAPE_SPKI_verify(spki, pktmp);
2369         if (j <= 0)
2370                 {
2371                 BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2372                 goto err;
2373                 }
2374         BIO_printf(bio_err,"Signature ok\n");
2375
2376         X509_REQ_set_pubkey(req,pktmp);
2377         EVP_PKEY_free(pktmp);
2378         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,
2379                    days,1,verbose,req,ext_sect,lconf);
2380 err:
2381         if (req != NULL) X509_REQ_free(req);
2382         if (parms != NULL) CONF_free(parms);
2383         if (spki != NULL) NETSCAPE_SPKI_free(spki);
2384         if (ne != NULL) X509_NAME_ENTRY_free(ne);
2385
2386         return(ok);
2387         }
2388
2389 static int fix_data(int nid, int *type)
2390         {
2391         if (nid == NID_pkcs9_emailAddress)
2392                 *type=V_ASN1_IA5STRING;
2393         if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
2394                 *type=V_ASN1_T61STRING;
2395         if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
2396                 *type=V_ASN1_T61STRING;
2397         if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
2398                 return(0);
2399         if (nid == NID_pkcs9_unstructuredName)
2400                 *type=V_ASN1_IA5STRING;
2401         return(1);
2402         }
2403
2404 static int check_time_format(char *str)
2405         {
2406         ASN1_UTCTIME tm;
2407
2408         tm.data=(unsigned char *)str;
2409         tm.length=strlen(str);
2410         tm.type=V_ASN1_UTCTIME;
2411         return(ASN1_UTCTIME_check(&tm));
2412         }
2413
2414 static int do_revoke(X509 *x509, TXT_DB *db)
2415         {
2416         ASN1_UTCTIME *tm=NULL, *revtm=NULL;
2417         char *row[DB_NUMBER],**rrow,**irow;
2418         BIGNUM *bn = NULL;
2419         int ok=-1,i;
2420
2421         for (i=0; i<DB_NUMBER; i++)
2422                 row[i]=NULL;
2423         row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2424         bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2425         row[DB_serial]=BN_bn2hex(bn);
2426         BN_free(bn);
2427         if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2428                 {
2429                 BIO_printf(bio_err,"Memory allocation failure\n");
2430                 goto err;
2431                 }
2432         /* We have to lookup by serial number because name lookup
2433          * skips revoked certs
2434          */
2435         rrow=TXT_DB_get_by_index(db,DB_serial,row);
2436         if (rrow == NULL)
2437                 {
2438                 BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]);
2439
2440                 /* We now just add it to the database */
2441                 row[DB_type]=(char *)OPENSSL_malloc(2);
2442
2443                 tm=X509_get_notAfter(x509);
2444                 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2445                 memcpy(row[DB_exp_date],tm->data,tm->length);
2446                 row[DB_exp_date][tm->length]='\0';
2447
2448                 row[DB_rev_date]=NULL;
2449
2450                 /* row[DB_serial] done already */
2451                 row[DB_file]=(char *)OPENSSL_malloc(8);
2452
2453                 /* row[DB_name] done already */
2454
2455                 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2456                         (row[DB_file] == NULL))
2457                         {
2458                         BIO_printf(bio_err,"Memory allocation failure\n");
2459                         goto err;
2460                         }
2461                 strcpy(row[DB_file],"unknown");
2462                 row[DB_type][0]='V';
2463                 row[DB_type][1]='\0';
2464
2465                 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2466                         {
2467                         BIO_printf(bio_err,"Memory allocation failure\n");
2468                         goto err;
2469                         }
2470
2471                 for (i=0; i<DB_NUMBER; i++)
2472                         {
2473                         irow[i]=row[i];
2474                         row[i]=NULL;
2475                         }
2476                 irow[DB_NUMBER]=NULL;
2477
2478                 if (!TXT_DB_insert(db,irow))
2479                         {
2480                         BIO_printf(bio_err,"failed to update database\n");
2481                         BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2482                         goto err;
2483                         }
2484
2485                 /* Revoke Certificate */
2486                 ok = do_revoke(x509,db);
2487
2488                 goto err;
2489
2490                 }
2491         else if (index_name_cmp((const char **)row,(const char **)rrow))
2492                 {
2493                 BIO_printf(bio_err,"ERROR:name does not match %s\n",
2494                            row[DB_name]);
2495                 goto err;
2496                 }
2497         else if (rrow[DB_type][0]=='R')
2498                 {
2499                 BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2500                            row[DB_serial]);
2501                 goto err;
2502                 }
2503         else
2504                 {
2505                 BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2506                 revtm = ASN1_UTCTIME_new();
2507                 revtm=X509_gmtime_adj(revtm,0);
2508                 rrow[DB_type][0]='R';
2509                 rrow[DB_type][1]='\0';
2510                 rrow[DB_rev_date]=(char *)OPENSSL_malloc(revtm->length+1);
2511                 memcpy(rrow[DB_rev_date],revtm->data,revtm->length);
2512                 rrow[DB_rev_date][revtm->length]='\0';
2513                 ASN1_UTCTIME_free(revtm);
2514                 }
2515         ok=1;
2516 err:
2517         for (i=0; i<DB_NUMBER; i++)
2518                 {
2519                 if (row[i] != NULL) 
2520                         OPENSSL_free(row[i]);
2521                 }
2522         return(ok);
2523         }
2524
2525 static int get_certificate_status(const char *serial, TXT_DB *db)
2526         {
2527         char *row[DB_NUMBER],**rrow;
2528         int ok=-1,i;
2529
2530         /* Free Resources */
2531         for (i=0; i<DB_NUMBER; i++)
2532                 row[i]=NULL;
2533
2534         /* Malloc needed char spaces */
2535         row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2536         if (row[DB_serial] == NULL)
2537                 {
2538                 BIO_printf(bio_err,"Malloc failure\n");
2539                 goto err;
2540                 }
2541
2542         if (strlen(serial) % 2)
2543                 {
2544                 /* Set the first char to 0 */;
2545                 row[DB_serial][0]='0';
2546
2547                 /* Copy String from serial to row[DB_serial] */
2548                 memcpy(row[DB_serial]+1, serial, strlen(serial));
2549                 row[DB_serial][strlen(serial)+1]='\0';
2550                 }
2551         else
2552                 {
2553                 /* Copy String from serial to row[DB_serial] */
2554                 memcpy(row[DB_serial], serial, strlen(serial));
2555                 row[DB_serial][strlen(serial)]='\0';
2556                 }
2557                         
2558         /* Make it Upper Case */
2559         for (i=0; row[DB_serial][i] != '\0'; i++)
2560                 row[DB_serial][i] = toupper(row[DB_serial][i]);
2561         
2562
2563         ok=1;
2564
2565         /* Search for the certificate */
2566         rrow=TXT_DB_get_by_index(db,DB_serial,row);
2567         if (rrow == NULL)
2568                 {
2569                 BIO_printf(bio_err,"Serial %s not present in db.\n",
2570                                  row[DB_serial]);
2571                 ok=-1;
2572                 goto err;
2573                 }
2574         else if (rrow[DB_type][0]=='V')
2575                 {
2576                 BIO_printf(bio_err,"%s=Valid (%c)\n",
2577                         row[DB_serial], rrow[DB_type][0]);
2578                 goto err;
2579                 }
2580         else if (rrow[DB_type][0]=='R')
2581                 {
2582                 BIO_printf(bio_err,"%s=Revoked (%c)\n",
2583                         row[DB_serial], rrow[DB_type][0]);
2584                 goto err;
2585                 }
2586         else if (rrow[DB_type][0]=='E')
2587                 {
2588                 BIO_printf(bio_err,"%s=Expired (%c)\n",
2589                         row[DB_serial], rrow[DB_type][0]);
2590                 goto err;
2591                 }
2592         else if (rrow[DB_type][0]=='S')
2593                 {
2594                 BIO_printf(bio_err,"%s=Suspended (%c)\n",
2595                         row[DB_serial], rrow[DB_type][0]);
2596                 goto err;
2597                 }
2598         else
2599                 {
2600                 BIO_printf(bio_err,"%s=Unknown (%c).\n",
2601                         row[DB_serial], rrow[DB_type][0]);
2602                 ok=-1;
2603                 }
2604 err:
2605         for (i=0; i<DB_NUMBER; i++)
2606                 {
2607                 if (row[i] != NULL)
2608                         OPENSSL_free(row[i]);
2609                 }
2610         return(ok);
2611         }
2612
2613 static int do_updatedb (TXT_DB *db)
2614         {
2615         ASN1_UTCTIME    *a_tm = NULL;
2616         int i, cnt = 0;
2617         int db_y2k, a_y2k;  /* flags = 1 if y >= 2000 */ 
2618         char **rrow, *a_tm_s;
2619
2620         a_tm = ASN1_UTCTIME_new();
2621
2622         /* get actual time and make a string */
2623         a_tm = X509_gmtime_adj(a_tm, 0);
2624         a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2625         if (a_tm_s == NULL)
2626                 {
2627                 cnt = -1;
2628                 goto err;
2629                 }
2630
2631         memcpy(a_tm_s, a_tm->data, a_tm->length);
2632         a_tm_s[a_tm->length] = '\0';
2633
2634         if (strncmp(a_tm_s, "49", 2) <= 0)
2635                 a_y2k = 1;
2636         else
2637                 a_y2k = 0;
2638
2639         for (i = 0; i < sk_num(db->data); i++)
2640                 {
2641                 rrow = (char **) sk_value(db->data, i);
2642
2643                 if (rrow[DB_type][0] == 'V')
2644                         {
2645                         /* ignore entries that are not valid */
2646                         if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2647                                 db_y2k = 1;
2648                         else
2649                                 db_y2k = 0;
2650
2651                         if (db_y2k == a_y2k)
2652                                 {
2653                                 /* all on the same y2k side */
2654                                 if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2655                                         {
2656                                         rrow[DB_type][0]  = 'E';
2657                                         rrow[DB_type][1]  = '\0';
2658                                         cnt++;
2659
2660                                         BIO_printf(bio_err, "%s=Expired\n",
2661                                                         rrow[DB_serial]);
2662                                         }
2663                                 }
2664                         else if (db_y2k < a_y2k)
2665                                 {
2666                                 rrow[DB_type][0]  = 'E';
2667                                 rrow[DB_type][1]  = '\0';
2668                                 cnt++;
2669
2670                                 BIO_printf(bio_err, "%s=Expired\n",
2671                                                         rrow[DB_serial]);
2672                                 }
2673
2674                         }
2675                 }
2676
2677 err:
2678
2679         ASN1_UTCTIME_free(a_tm);
2680         OPENSSL_free(a_tm_s);
2681
2682         return (cnt);
2683         }