format strings
[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,"%s",*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                 if (!(extconf=CONF_load(NULL,extfile,&errorline)))
926                         {
927                         if (errorline <= 0)
928                                 BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
929                                         extfile);
930                         else
931                                 BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n",
932                                         errorline,extfile);
933                         ret = 1;
934                         goto err;
935                         }
936
937                 if (verbose)
938                         BIO_printf(bio_err, "Succesfully loaded extensions file %s\n", extfile);
939
940                 /* We can have sections in the ext file */
941                 if (!extensions && !(extensions = CONF_get_string(extconf, "default", "extensions")))
942                         extensions = "default";
943                 }
944
945         /*****************************************************************/
946         if (req || gencrl)
947                 {
948                 if (outfile != NULL)
949                         {
950                         if (BIO_write_filename(Sout,outfile) <= 0)
951                                 {
952                                 perror(outfile);
953                                 goto err;
954                                 }
955                         }
956                 else
957                         {
958                         BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
959 #ifdef VMS
960                         {
961                         BIO *tmpbio = BIO_new(BIO_f_linebuffer());
962                         Sout = BIO_push(tmpbio, Sout);
963                         }
964 #endif
965                         }
966                 }
967
968         if (req)
969                 {
970                 if ((md == NULL) && ((md=CONF_get_string(conf,
971                         section,ENV_DEFAULT_MD)) == NULL))
972                         {
973                         lookup_fail(section,ENV_DEFAULT_MD);
974                         goto err;
975                         }
976                 if ((dgst=EVP_get_digestbyname(md)) == NULL)
977                         {
978                         BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
979                         goto err;
980                         }
981                 if (verbose)
982                         BIO_printf(bio_err,"message digest is %s\n",
983                                 OBJ_nid2ln(dgst->type));
984                 if ((policy == NULL) && ((policy=CONF_get_string(conf,
985                         section,ENV_POLICY)) == NULL))
986                         {
987                         lookup_fail(section,ENV_POLICY);
988                         goto err;
989                         }
990                 if (verbose)
991                         BIO_printf(bio_err,"policy is %s\n",policy);
992
993                 if ((serialfile=CONF_get_string(conf,section,ENV_SERIAL))
994                         == NULL)
995                         {
996                         lookup_fail(section,ENV_SERIAL);
997                         goto err;
998                         }
999
1000                 if (!extconf)
1001                         {
1002                         /* no '-extfile' option, so we look for extensions
1003                          * in the main configuration file */
1004                         if (!extensions)
1005                                 {
1006                                 extensions=CONF_get_string(conf,section,
1007                                                                 ENV_EXTENSIONS);
1008                                 if (!extensions)
1009                                         ERR_clear_error();
1010                                 }
1011                         if (extensions)
1012                                 {
1013                                 /* Check syntax of file */
1014                                 X509V3_CTX ctx;
1015                                 X509V3_set_ctx_test(&ctx);
1016                                 X509V3_set_conf_lhash(&ctx, conf);
1017                                 if (!X509V3_EXT_add_conf(conf, &ctx, extensions,
1018                                                                 NULL))
1019                                         {
1020                                         BIO_printf(bio_err,
1021                                         "Error Loading extension section %s\n",
1022                                                                  extensions);
1023                                         ret = 1;
1024                                         goto err;
1025                                         }
1026                                 }
1027                         }
1028
1029                 if (startdate == NULL)
1030                         {
1031                         startdate=CONF_get_string(conf,section,
1032                                 ENV_DEFAULT_STARTDATE);
1033                         if (startdate == NULL)
1034                                 ERR_clear_error();
1035                         }
1036                 if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
1037                         {
1038                         BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
1039                         goto err;
1040                         }
1041                 if (startdate == NULL) startdate="today";
1042
1043                 if (enddate == NULL)
1044                         {
1045                         enddate=CONF_get_string(conf,section,
1046                                 ENV_DEFAULT_ENDDATE);
1047                         if (enddate == NULL)
1048                                 ERR_clear_error();
1049                         }
1050                 if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
1051                         {
1052                         BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
1053                         goto err;
1054                         }
1055
1056                 if (days == 0)
1057                         {
1058                         days=(int)CONF_get_number(conf,section,
1059                                 ENV_DEFAULT_DAYS);
1060                         }
1061                 if (!enddate && (days == 0))
1062                         {
1063                         BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
1064                         goto err;
1065                         }
1066
1067                 if ((serial=load_serial(serialfile)) == NULL)
1068                         {
1069                         BIO_printf(bio_err,"error while loading serial number\n");
1070                         goto err;
1071                         }
1072                 if (verbose)
1073                         {
1074                         if ((f=BN_bn2hex(serial)) == NULL) goto err;
1075                         BIO_printf(bio_err,"next serial number is %s\n",f);
1076                         OPENSSL_free(f);
1077                         }
1078
1079                 if ((attribs=CONF_get_section(conf,policy)) == NULL)
1080                         {
1081                         BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
1082                         goto err;
1083                         }
1084
1085                 if ((cert_sk=sk_X509_new_null()) == NULL)
1086                         {
1087                         BIO_printf(bio_err,"Memory allocation failure\n");
1088                         goto err;
1089                         }
1090                 if (spkac_file != NULL)
1091                         {
1092                         total++;
1093                         j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
1094                                 serial,startdate,enddate, days,extensions,conf,
1095                                 verbose);
1096                         if (j < 0) goto err;
1097                         if (j > 0)
1098                                 {
1099                                 total_done++;
1100                                 BIO_printf(bio_err,"\n");
1101                                 if (!BN_add_word(serial,1)) goto err;
1102                                 if (!sk_X509_push(cert_sk,x))
1103                                         {
1104                                         BIO_printf(bio_err,"Memory allocation failure\n");
1105                                         goto err;
1106                                         }
1107                                 if (outfile)
1108                                         {
1109                                         output_der = 1;
1110                                         batch = 1;
1111                                         }
1112                                 }
1113                         }
1114                 if (ss_cert_file != NULL)
1115                         {
1116                         total++;
1117                         j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
1118                                 db,serial,startdate,enddate,days,batch,
1119                                 extensions,conf,verbose);
1120                         if (j < 0) goto err;
1121                         if (j > 0)
1122                                 {
1123                                 total_done++;
1124                                 BIO_printf(bio_err,"\n");
1125                                 if (!BN_add_word(serial,1)) goto err;
1126                                 if (!sk_X509_push(cert_sk,x))
1127                                         {
1128                                         BIO_printf(bio_err,"Memory allocation failure\n");
1129                                         goto err;
1130                                         }
1131                                 }
1132                         }
1133                 if (infile != NULL)
1134                         {
1135                         total++;
1136                         j=certify(&x,infile,pkey,x509,dgst,attribs,db,
1137                                 serial,startdate,enddate,days,batch,
1138                                 extensions,conf,verbose);
1139                         if (j < 0) goto err;
1140                         if (j > 0)
1141                                 {
1142                                 total_done++;
1143                                 BIO_printf(bio_err,"\n");
1144                                 if (!BN_add_word(serial,1)) goto err;
1145                                 if (!sk_X509_push(cert_sk,x))
1146                                         {
1147                                         BIO_printf(bio_err,"Memory allocation failure\n");
1148                                         goto err;
1149                                         }
1150                                 }
1151                         }
1152                 for (i=0; i<argc; i++)
1153                         {
1154                         total++;
1155                         j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
1156                                 serial,startdate,enddate,days,batch,
1157                                 extensions,conf,verbose);
1158                         if (j < 0) goto err;
1159                         if (j > 0)
1160                                 {
1161                                 total_done++;
1162                                 BIO_printf(bio_err,"\n");
1163                                 if (!BN_add_word(serial,1)) goto err;
1164                                 if (!sk_X509_push(cert_sk,x))
1165                                         {
1166                                         BIO_printf(bio_err,"Memory allocation failure\n");
1167                                         goto err;
1168                                         }
1169                                 }
1170                         }       
1171                 /* we have a stack of newly certified certificates
1172                  * and a data base and serial number that need
1173                  * updating */
1174
1175                 if (sk_X509_num(cert_sk) > 0)
1176                         {
1177                         if (!batch)
1178                                 {
1179                                 BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
1180                                 (void)BIO_flush(bio_err);
1181                                 buf[0][0]='\0';
1182                                 fgets(buf[0],10,stdin);
1183                                 if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
1184                                         {
1185                                         BIO_printf(bio_err,"CERTIFICATION CANCELED\n"); 
1186                                         ret=0;
1187                                         goto err;
1188                                         }
1189                                 }
1190
1191                         BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
1192
1193                         strncpy(buf[0],serialfile,BSIZE-4);
1194
1195 #ifdef VMS
1196                         strcat(buf[0],"-new");
1197 #else
1198                         strcat(buf[0],".new");
1199 #endif
1200
1201                         if (!save_serial(buf[0],serial)) goto err;
1202
1203                         strncpy(buf[1],dbfile,BSIZE-4);
1204
1205 #ifdef VMS
1206                         strcat(buf[1],"-new");
1207 #else
1208                         strcat(buf[1],".new");
1209 #endif
1210
1211                         if (BIO_write_filename(out,buf[1]) <= 0)
1212                                 {
1213                                 perror(dbfile);
1214                                 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1215                                 goto err;
1216                                 }
1217                         l=TXT_DB_write(out,db);
1218                         if (l <= 0) goto err;
1219                         }
1220         
1221                 if (verbose)
1222                         BIO_printf(bio_err,"writing new certificates\n");
1223                 for (i=0; i<sk_X509_num(cert_sk); i++)
1224                         {
1225                         int k;
1226                         unsigned char *n;
1227
1228                         x=sk_X509_value(cert_sk,i);
1229
1230                         j=x->cert_info->serialNumber->length;
1231                         p=(char *)x->cert_info->serialNumber->data;
1232                         
1233                         strncpy(buf[2],outdir,BSIZE-(j*2)-6);
1234
1235 #ifndef VMS
1236                         strcat(buf[2],"/");
1237 #endif
1238
1239                         n=(unsigned char *)&(buf[2][strlen(buf[2])]);
1240                         if (j > 0)
1241                                 {
1242                                 for (k=0; k<j; k++)
1243                                         {
1244                                         sprintf((char *)n,"%02X",(unsigned char)*(p++));
1245                                         n+=2;
1246                                         }
1247                                 }
1248                         else
1249                                 {
1250                                 *(n++)='0';
1251                                 *(n++)='0';
1252                                 }
1253                         *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
1254                         *n='\0';
1255                         if (verbose)
1256                                 BIO_printf(bio_err,"writing %s\n",buf[2]);
1257
1258                         if (BIO_write_filename(Cout,buf[2]) <= 0)
1259                                 {
1260                                 perror(buf[2]);
1261                                 goto err;
1262                                 }
1263                         write_new_certificate(Cout,x, 0, notext);
1264                         write_new_certificate(Sout,x, output_der, notext);
1265                         }
1266
1267                 if (sk_X509_num(cert_sk))
1268                         {
1269                         /* Rename the database and the serial file */
1270                         strncpy(buf[2],serialfile,BSIZE-4);
1271
1272 #ifdef VMS
1273                         strcat(buf[2],"-old");
1274 #else
1275                         strcat(buf[2],".old");
1276 #endif
1277
1278                         BIO_free(in);
1279                         BIO_free_all(out);
1280                         in=NULL;
1281                         out=NULL;
1282                         if (rename(serialfile,buf[2]) < 0)
1283                                 {
1284                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1285                                         serialfile,buf[2]);
1286                                 perror("reason");
1287                                 goto err;
1288                                 }
1289                         if (rename(buf[0],serialfile) < 0)
1290                                 {
1291                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1292                                         buf[0],serialfile);
1293                                 perror("reason");
1294                                 rename(buf[2],serialfile);
1295                                 goto err;
1296                                 }
1297
1298                         strncpy(buf[2],dbfile,BSIZE-4);
1299
1300 #ifdef VMS
1301                         strcat(buf[2],"-old");
1302 #else
1303                         strcat(buf[2],".old");
1304 #endif
1305
1306                         if (rename(dbfile,buf[2]) < 0)
1307                                 {
1308                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1309                                         dbfile,buf[2]);
1310                                 perror("reason");
1311                                 goto err;
1312                                 }
1313                         if (rename(buf[1],dbfile) < 0)
1314                                 {
1315                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1316                                         buf[1],dbfile);
1317                                 perror("reason");
1318                                 rename(buf[2],dbfile);
1319                                 goto err;
1320                                 }
1321                         BIO_printf(bio_err,"Data Base Updated\n");
1322                         }
1323                 }
1324         
1325         /*****************************************************************/
1326         if (gencrl)
1327                 {
1328                 if (!crl_ext)
1329                         {
1330                         crl_ext=CONF_get_string(conf,section,ENV_CRLEXT);
1331                         if (!crl_ext)
1332                                 ERR_clear_error();
1333                         }
1334                 if (crl_ext)
1335                         {
1336                         /* Check syntax of file */
1337                         X509V3_CTX ctx;
1338                         X509V3_set_ctx_test(&ctx);
1339                         X509V3_set_conf_lhash(&ctx, conf);
1340                         if (!X509V3_EXT_add_conf(conf, &ctx, crl_ext, NULL))
1341                                 {
1342                                 BIO_printf(bio_err,
1343                                  "Error Loading CRL extension section %s\n",
1344                                                                  crl_ext);
1345                                 ret = 1;
1346                                 goto err;
1347                                 }
1348                         }
1349                 if ((hex=BIO_new(BIO_s_mem())) == NULL) goto err;
1350
1351                 if (!crldays && !crlhours)
1352                         {
1353                         crldays=CONF_get_number(conf,section,
1354                                 ENV_DEFAULT_CRL_DAYS);
1355                         crlhours=CONF_get_number(conf,section,
1356                                 ENV_DEFAULT_CRL_HOURS);
1357                         }
1358                 if ((crldays == 0) && (crlhours == 0))
1359                         {
1360                         BIO_printf(bio_err,"cannot lookup how long until the next CRL is issuer\n");
1361                         goto err;
1362                         }
1363
1364                 if (verbose) BIO_printf(bio_err,"making CRL\n");
1365                 if ((crl=X509_CRL_new()) == NULL) goto err;
1366                 ci=crl->crl;
1367                 X509_NAME_free(ci->issuer);
1368                 ci->issuer=X509_NAME_dup(x509->cert_info->subject);
1369                 if (ci->issuer == NULL) goto err;
1370
1371                 X509_gmtime_adj(ci->lastUpdate,0);
1372                 if (ci->nextUpdate == NULL)
1373                         ci->nextUpdate=ASN1_UTCTIME_new();
1374                 X509_gmtime_adj(ci->nextUpdate,(crldays*24+crlhours)*60*60);
1375
1376                 for (i=0; i<sk_num(db->data); i++)
1377                         {
1378                         pp=(char **)sk_value(db->data,i);
1379                         if (pp[DB_type][0] == DB_TYPE_REV)
1380                                 {
1381                                 if ((r=X509_REVOKED_new()) == NULL) goto err;
1382                                 ASN1_STRING_set((ASN1_STRING *)
1383                                         r->revocationDate,
1384                                         (unsigned char *)pp[DB_rev_date],
1385                                         strlen(pp[DB_rev_date]));
1386                                 /* strcpy(r->revocationDate,pp[DB_rev_date]);*/
1387
1388                                 (void)BIO_reset(hex);
1389                                 if (!BIO_puts(hex,pp[DB_serial]))
1390                                         goto err;
1391                                 if (!a2i_ASN1_INTEGER(hex,r->serialNumber,
1392                                         buf[0],BSIZE)) goto err;
1393
1394                                 X509_CRL_add0_revoked(crl,r);
1395                                 }
1396                         }
1397                 /* sort the data so it will be written in serial
1398                  * number order */
1399                 sk_X509_REVOKED_sort(ci->revoked);
1400                 for (i=0; i<sk_X509_REVOKED_num(ci->revoked); i++)
1401                         {
1402                         r=sk_X509_REVOKED_value(ci->revoked,i);
1403                         r->sequence=i;
1404                         }
1405
1406                 /* we now have a CRL */
1407                 if (verbose) BIO_printf(bio_err,"signing CRL\n");
1408                 if (md != NULL)
1409                         {
1410                         if ((dgst=EVP_get_digestbyname(md)) == NULL)
1411                                 {
1412                                 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1413                                 goto err;
1414                                 }
1415                         }
1416                 else
1417                         {
1418 #ifndef NO_DSA
1419                         if (pkey->type == EVP_PKEY_DSA) 
1420                                 dgst=EVP_dss1();
1421                         else
1422 #endif
1423                                 dgst=EVP_md5();
1424                         }
1425
1426                 /* Add any extensions asked for */
1427
1428                 if (crl_ext)
1429                         {
1430                         X509V3_CTX crlctx;
1431                         if (ci->version == NULL)
1432                                 if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
1433                         ASN1_INTEGER_set(ci->version,1); /* version 2 CRL */
1434                         X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1435                         X509V3_set_conf_lhash(&crlctx, conf);
1436
1437                         if (!X509V3_EXT_CRL_add_conf(conf, &crlctx,
1438                                 crl_ext, crl)) goto err;
1439                         }
1440
1441                 if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1442
1443                 PEM_write_bio_X509_CRL(Sout,crl);
1444                 }
1445         /*****************************************************************/
1446         if (dorevoke)
1447                 {
1448                 if (infile == NULL) 
1449                         {
1450                         BIO_printf(bio_err,"no input files\n");
1451                         goto err;
1452                         }
1453                 else
1454                         {
1455                         X509 *revcert;
1456                         if (BIO_read_filename(in,infile) <= 0)
1457                                 {
1458                                 perror(infile);
1459                                 BIO_printf(bio_err,"error trying to load '%s' certificate\n",infile);
1460                                 goto err;
1461                                 }
1462                         revcert=PEM_read_bio_X509(in,NULL,NULL,NULL);
1463                         if (revcert == NULL)
1464                                 {
1465                                 BIO_printf(bio_err,"unable to load '%s' certificate\n",infile);
1466                                 goto err;
1467                                 }
1468                         j=do_revoke(revcert,db);
1469                         if (j <= 0) goto err;
1470                         X509_free(revcert);
1471
1472                         strncpy(buf[0],dbfile,BSIZE-4);
1473                         strcat(buf[0],".new");
1474                         if (BIO_write_filename(out,buf[0]) <= 0)
1475                                 {
1476                                 perror(dbfile);
1477                                 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1478                                 goto err;
1479                                 }
1480                         j=TXT_DB_write(out,db);
1481                         if (j <= 0) goto err;
1482                         strncpy(buf[1],dbfile,BSIZE-4);
1483                         strcat(buf[1],".old");
1484                         if (rename(dbfile,buf[1]) < 0)
1485                                 {
1486                                 BIO_printf(bio_err,"unable to rename %s to %s\n", dbfile, buf[1]);
1487                                 perror("reason");
1488                                 goto err;
1489                                 }
1490                         if (rename(buf[0],dbfile) < 0)
1491                                 {
1492                                 BIO_printf(bio_err,"unable to rename %s to %s\n", buf[0],dbfile);
1493                                 perror("reason");
1494                                 rename(buf[1],dbfile);
1495                                 goto err;
1496                                 }
1497                         BIO_printf(bio_err,"Data Base Updated\n"); 
1498                         }
1499                 }
1500         /*****************************************************************/
1501         ret=0;
1502 err:
1503         BIO_free(hex);
1504         BIO_free_all(Cout);
1505         BIO_free_all(Sout);
1506         BIO_free_all(out);
1507         BIO_free(in);
1508
1509         sk_X509_pop_free(cert_sk,X509_free);
1510
1511         if (ret) ERR_print_errors(bio_err);
1512         app_RAND_write_file(randfile, bio_err);
1513         BN_free(serial);
1514         TXT_DB_free(db);
1515         EVP_PKEY_free(pkey);
1516         X509_free(x509);
1517         X509_CRL_free(crl);
1518         CONF_free(conf);
1519         OBJ_cleanup();
1520         EXIT(ret);
1521         }
1522
1523 static void lookup_fail(char *name, char *tag)
1524         {
1525         BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1526         }
1527
1528 static unsigned long index_serial_hash(const char **a)
1529         {
1530         const char *n;
1531
1532         n=a[DB_serial];
1533         while (*n == '0') n++;
1534         return(lh_strhash(n));
1535         }
1536
1537 static int index_serial_cmp(const char **a, const char **b)
1538         {
1539         const char *aa,*bb;
1540
1541         for (aa=a[DB_serial]; *aa == '0'; aa++);
1542         for (bb=b[DB_serial]; *bb == '0'; bb++);
1543         return(strcmp(aa,bb));
1544         }
1545
1546 static unsigned long index_name_hash(const char **a)
1547         { return(lh_strhash(a[DB_name])); }
1548
1549 static int index_name_qual(char **a)
1550         { return(a[0][0] == 'V'); }
1551
1552 static int index_name_cmp(const char **a, const char **b)
1553         { return(strcmp(a[DB_name],
1554              b[DB_name])); }
1555
1556 static BIGNUM *load_serial(char *serialfile)
1557         {
1558         BIO *in=NULL;
1559         BIGNUM *ret=NULL;
1560         MS_STATIC char buf[1024];
1561         ASN1_INTEGER *ai=NULL;
1562
1563         if ((in=BIO_new(BIO_s_file())) == NULL)
1564                 {
1565                 ERR_print_errors(bio_err);
1566                 goto err;
1567                 }
1568
1569         if (BIO_read_filename(in,serialfile) <= 0)
1570                 {
1571                 perror(serialfile);
1572                 goto err;
1573                 }
1574         ai=ASN1_INTEGER_new();
1575         if (ai == NULL) goto err;
1576         if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
1577                 {
1578                 BIO_printf(bio_err,"unable to load number from %s\n",
1579                         serialfile);
1580                 goto err;
1581                 }
1582         ret=ASN1_INTEGER_to_BN(ai,NULL);
1583         if (ret == NULL)
1584                 {
1585                 BIO_printf(bio_err,"error converting number from bin to BIGNUM");
1586                 goto err;
1587                 }
1588 err:
1589         if (in != NULL) BIO_free(in);
1590         if (ai != NULL) ASN1_INTEGER_free(ai);
1591         return(ret);
1592         }
1593
1594 static int save_serial(char *serialfile, BIGNUM *serial)
1595         {
1596         BIO *out;
1597         int ret=0;
1598         ASN1_INTEGER *ai=NULL;
1599
1600         out=BIO_new(BIO_s_file());
1601         if (out == NULL)
1602                 {
1603                 ERR_print_errors(bio_err);
1604                 goto err;
1605                 }
1606         if (BIO_write_filename(out,serialfile) <= 0)
1607                 {
1608                 perror(serialfile);
1609                 goto err;
1610                 }
1611
1612         if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
1613                 {
1614                 BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
1615                 goto err;
1616                 }
1617         i2a_ASN1_INTEGER(out,ai);
1618         BIO_puts(out,"\n");
1619         ret=1;
1620 err:
1621         if (out != NULL) BIO_free_all(out);
1622         if (ai != NULL) ASN1_INTEGER_free(ai);
1623         return(ret);
1624         }
1625
1626 static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1627              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1628              BIGNUM *serial, char *startdate, char *enddate, int days,
1629              int batch, char *ext_sect, LHASH *lconf, int verbose)
1630         {
1631         X509_REQ *req=NULL;
1632         BIO *in=NULL;
1633         EVP_PKEY *pktmp=NULL;
1634         int ok= -1,i;
1635
1636         in=BIO_new(BIO_s_file());
1637
1638         if (BIO_read_filename(in,infile) <= 0)
1639                 {
1640                 perror(infile);
1641                 goto err;
1642                 }
1643         if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
1644                 {
1645                 BIO_printf(bio_err,"Error reading certificate request in %s\n",
1646                         infile);
1647                 goto err;
1648                 }
1649         if (verbose)
1650                 X509_REQ_print(bio_err,req);
1651
1652         BIO_printf(bio_err,"Check that the request matches the signature\n");
1653
1654         if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
1655                 {
1656                 BIO_printf(bio_err,"error unpacking public key\n");
1657                 goto err;
1658                 }
1659         i=X509_REQ_verify(req,pktmp);
1660         EVP_PKEY_free(pktmp);
1661         if (i < 0)
1662                 {
1663                 ok=0;
1664                 BIO_printf(bio_err,"Signature verification problems....\n");
1665                 goto err;
1666                 }
1667         if (i == 0)
1668                 {
1669                 ok=0;
1670                 BIO_printf(bio_err,"Signature did not match the certificate request\n");
1671                 goto err;
1672                 }
1673         else
1674                 BIO_printf(bio_err,"Signature ok\n");
1675
1676         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate, enddate,
1677                 days,batch,verbose,req,ext_sect,lconf);
1678
1679 err:
1680         if (req != NULL) X509_REQ_free(req);
1681         if (in != NULL) BIO_free(in);
1682         return(ok);
1683         }
1684
1685 static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1686              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1687              BIGNUM *serial, char *startdate, char *enddate, int days,
1688              int batch, char *ext_sect, LHASH *lconf, int verbose)
1689         {
1690         X509 *req=NULL;
1691         X509_REQ *rreq=NULL;
1692         BIO *in=NULL;
1693         EVP_PKEY *pktmp=NULL;
1694         int ok= -1,i;
1695
1696         in=BIO_new(BIO_s_file());
1697
1698         if (BIO_read_filename(in,infile) <= 0)
1699                 {
1700                 perror(infile);
1701                 goto err;
1702                 }
1703         if ((req=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
1704                 {
1705                 BIO_printf(bio_err,"Error reading self signed certificate in %s\n",infile);
1706                 goto err;
1707                 }
1708         if (verbose)
1709                 X509_print(bio_err,req);
1710
1711         BIO_printf(bio_err,"Check that the request matches the signature\n");
1712
1713         if ((pktmp=X509_get_pubkey(req)) == NULL)
1714                 {
1715                 BIO_printf(bio_err,"error unpacking public key\n");
1716                 goto err;
1717                 }
1718         i=X509_verify(req,pktmp);
1719         EVP_PKEY_free(pktmp);
1720         if (i < 0)
1721                 {
1722                 ok=0;
1723                 BIO_printf(bio_err,"Signature verification problems....\n");
1724                 goto err;
1725                 }
1726         if (i == 0)
1727                 {
1728                 ok=0;
1729                 BIO_printf(bio_err,"Signature did not match the certificate\n");
1730                 goto err;
1731                 }
1732         else
1733                 BIO_printf(bio_err,"Signature ok\n");
1734
1735         if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
1736                 goto err;
1737
1738         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,days,
1739                 batch,verbose,rreq,ext_sect,lconf);
1740
1741 err:
1742         if (rreq != NULL) X509_REQ_free(rreq);
1743         if (req != NULL) X509_free(req);
1744         if (in != NULL) BIO_free(in);
1745         return(ok);
1746         }
1747
1748 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1749              STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
1750              char *startdate, char *enddate, int days, int batch, int verbose,
1751              X509_REQ *req, char *ext_sect, LHASH *lconf)
1752         {
1753         X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
1754         ASN1_UTCTIME *tm,*tmptm;
1755         ASN1_STRING *str,*str2;
1756         ASN1_OBJECT *obj;
1757         X509 *ret=NULL;
1758         X509_CINF *ci;
1759         X509_NAME_ENTRY *ne;
1760         X509_NAME_ENTRY *tne,*push;
1761         EVP_PKEY *pktmp;
1762         int ok= -1,i,j,last,nid;
1763         char *p;
1764         CONF_VALUE *cv;
1765         char *row[DB_NUMBER],**rrow,**irow=NULL;
1766         char buf[25],*pbuf;
1767
1768         tmptm=ASN1_UTCTIME_new();
1769         if (tmptm == NULL)
1770                 {
1771                 BIO_printf(bio_err,"malloc error\n");
1772                 return(0);
1773                 }
1774
1775         for (i=0; i<DB_NUMBER; i++)
1776                 row[i]=NULL;
1777
1778         BIO_printf(bio_err,"The Subjects Distinguished Name is as follows\n");
1779         name=X509_REQ_get_subject_name(req);
1780         for (i=0; i<X509_NAME_entry_count(name); i++)
1781                 {
1782                 ne=(X509_NAME_ENTRY *)X509_NAME_get_entry(name,i);
1783                 obj=X509_NAME_ENTRY_get_object(ne);
1784                 j=i2a_ASN1_OBJECT(bio_err,obj);
1785                 str=X509_NAME_ENTRY_get_data(ne);
1786                 pbuf=buf;
1787                 for (j=22-j; j>0; j--)
1788                         *(pbuf++)=' ';
1789                 *(pbuf++)=':';
1790                 *(pbuf++)='\0';
1791                 BIO_puts(bio_err,buf);
1792
1793                 if (msie_hack)
1794                         {
1795                         /* assume all type should be strings */
1796                         nid=OBJ_obj2nid(ne->object);
1797
1798                         if (str->type == V_ASN1_UNIVERSALSTRING)
1799                                 ASN1_UNIVERSALSTRING_to_string(str);
1800
1801                         if ((str->type == V_ASN1_IA5STRING) &&
1802                                 (nid != NID_pkcs9_emailAddress))
1803                                 str->type=V_ASN1_T61STRING;
1804
1805                         if ((nid == NID_pkcs9_emailAddress) &&
1806                                 (str->type == V_ASN1_PRINTABLESTRING))
1807                                 str->type=V_ASN1_IA5STRING;
1808                         }
1809
1810                 if (str->type == V_ASN1_PRINTABLESTRING)
1811                         BIO_printf(bio_err,"PRINTABLE:'");
1812                 else if (str->type == V_ASN1_T61STRING)
1813                         BIO_printf(bio_err,"T61STRING:'");
1814                 else if (str->type == V_ASN1_IA5STRING)
1815                         BIO_printf(bio_err,"IA5STRING:'");
1816                 else if (str->type == V_ASN1_UNIVERSALSTRING)
1817                         BIO_printf(bio_err,"UNIVERSALSTRING:'");
1818                 else
1819                         BIO_printf(bio_err,"ASN.1 %2d:'",str->type);
1820
1821                 /* check some things */
1822                 if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1823                         (str->type != V_ASN1_IA5STRING))
1824                         {
1825                         BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
1826                         goto err;
1827                         }
1828                 j=ASN1_PRINTABLE_type(str->data,str->length);
1829                 if (    ((j == V_ASN1_T61STRING) &&
1830                          (str->type != V_ASN1_T61STRING)) ||
1831                         ((j == V_ASN1_IA5STRING) &&
1832                          (str->type == V_ASN1_PRINTABLESTRING)))
1833                         {
1834                         BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1835                         goto err;
1836                         }
1837                         
1838                 p=(char *)str->data;
1839                 for (j=str->length; j>0; j--)
1840                         {
1841                         if ((*p >= ' ') && (*p <= '~'))
1842                                 BIO_printf(bio_err,"%c",*p);
1843                         else if (*p & 0x80)
1844                                 BIO_printf(bio_err,"\\0x%02X",*p);
1845                         else if ((unsigned char)*p == 0xf7)
1846                                 BIO_printf(bio_err,"^?");
1847                         else    BIO_printf(bio_err,"^%c",*p+'@');
1848                         p++;
1849                         }
1850                 BIO_printf(bio_err,"'\n");
1851                 }
1852
1853         /* Ok, now we check the 'policy' stuff. */
1854         if ((subject=X509_NAME_new()) == NULL)
1855                 {
1856                 BIO_printf(bio_err,"Memory allocation failure\n");
1857                 goto err;
1858                 }
1859
1860         /* take a copy of the issuer name before we mess with it. */
1861         CAname=X509_NAME_dup(x509->cert_info->subject);
1862         if (CAname == NULL) goto err;
1863         str=str2=NULL;
1864
1865         for (i=0; i<sk_CONF_VALUE_num(policy); i++)
1866                 {
1867                 cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
1868                 if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
1869                         {
1870                         BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
1871                         goto err;
1872                         }
1873                 obj=OBJ_nid2obj(j);
1874
1875                 last= -1;
1876                 for (;;)
1877                         {
1878                         /* lookup the object in the supplied name list */
1879                         j=X509_NAME_get_index_by_OBJ(name,obj,last);
1880                         if (j < 0)
1881                                 {
1882                                 if (last != -1) break;
1883                                 tne=NULL;
1884                                 }
1885                         else
1886                                 {
1887                                 tne=X509_NAME_get_entry(name,j);
1888                                 }
1889                         last=j;
1890
1891                         /* depending on the 'policy', decide what to do. */
1892                         push=NULL;
1893                         if (strcmp(cv->value,"optional") == 0)
1894                                 {
1895                                 if (tne != NULL)
1896                                         push=tne;
1897                                 }
1898                         else if (strcmp(cv->value,"supplied") == 0)
1899                                 {
1900                                 if (tne == NULL)
1901                                         {
1902                                         BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
1903                                         goto err;
1904                                         }
1905                                 else
1906                                         push=tne;
1907                                 }
1908                         else if (strcmp(cv->value,"match") == 0)
1909                                 {
1910                                 int last2;
1911
1912                                 if (tne == NULL)
1913                                         {
1914                                         BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
1915                                         goto err;
1916                                         }
1917
1918                                 last2= -1;
1919
1920 again2:
1921                                 j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
1922                                 if ((j < 0) && (last2 == -1))
1923                                         {
1924                                         BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
1925                                         goto err;
1926                                         }
1927                                 if (j >= 0)
1928                                         {
1929                                         push=X509_NAME_get_entry(CAname,j);
1930                                         str=X509_NAME_ENTRY_get_data(tne);
1931                                         str2=X509_NAME_ENTRY_get_data(push);
1932                                         last2=j;
1933                                         if (ASN1_STRING_cmp(str,str2) != 0)
1934                                                 goto again2;
1935                                         }
1936                                 if (j < 0)
1937                                         {
1938                                         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));
1939                                         goto err;
1940                                         }
1941                                 }
1942                         else
1943                                 {
1944                                 BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
1945                                 goto err;
1946                                 }
1947
1948                         if (push != NULL)
1949                                 {
1950                                 if (!X509_NAME_add_entry(subject,push, -1, 0))
1951                                         {
1952                                         if (push != NULL)
1953                                                 X509_NAME_ENTRY_free(push);
1954                                         BIO_printf(bio_err,"Memory allocation failure\n");
1955                                         goto err;
1956                                         }
1957                                 }
1958                         if (j < 0) break;
1959                         }
1960                 }
1961
1962         if (preserve)
1963                 {
1964                 X509_NAME_free(subject);
1965                 subject=X509_NAME_dup(X509_REQ_get_subject_name(req));
1966                 if (subject == NULL) goto err;
1967                 }
1968
1969         if (verbose)
1970                 BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
1971
1972         row[DB_name]=X509_NAME_oneline(subject,NULL,0);
1973         row[DB_serial]=BN_bn2hex(serial);
1974         if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
1975                 {
1976                 BIO_printf(bio_err,"Memory allocation failure\n");
1977                 goto err;
1978                 }
1979
1980         rrow=TXT_DB_get_by_index(db,DB_name,row);
1981         if (rrow != NULL)
1982                 {
1983                 BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n",
1984                         row[DB_name]);
1985                 }
1986         else
1987                 {
1988                 rrow=TXT_DB_get_by_index(db,DB_serial,row);
1989                 if (rrow != NULL)
1990                         {
1991                         BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
1992                                 row[DB_serial]);
1993                         BIO_printf(bio_err,"      check the database/serial_file for corruption\n");
1994                         }
1995                 }
1996
1997         if (rrow != NULL)
1998                 {
1999                 BIO_printf(bio_err,
2000                         "The matching entry has the following details\n");
2001                 if (rrow[DB_type][0] == 'E')
2002                         p="Expired";
2003                 else if (rrow[DB_type][0] == 'R')
2004                         p="Revoked";
2005                 else if (rrow[DB_type][0] == 'V')
2006                         p="Valid";
2007                 else
2008                         p="\ninvalid type, Data base error\n";
2009                 BIO_printf(bio_err,"Type          :%s\n",p);;
2010                 if (rrow[DB_type][0] == 'R')
2011                         {
2012                         p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2013                         BIO_printf(bio_err,"Was revoked on:%s\n",p);
2014                         }
2015                 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2016                 BIO_printf(bio_err,"Expires on    :%s\n",p);
2017                 p=rrow[DB_serial]; if (p == NULL) p="undef";
2018                 BIO_printf(bio_err,"Serial Number :%s\n",p);
2019                 p=rrow[DB_file]; if (p == NULL) p="undef";
2020                 BIO_printf(bio_err,"File name     :%s\n",p);
2021                 p=rrow[DB_name]; if (p == NULL) p="undef";
2022                 BIO_printf(bio_err,"Subject Name  :%s\n",p);
2023                 ok= -1; /* This is now a 'bad' error. */
2024                 goto err;
2025                 }
2026
2027         /* We are now totally happy, lets make and sign the certificate */
2028         if (verbose)
2029                 BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
2030
2031         if ((ret=X509_new()) == NULL) goto err;
2032         ci=ret->cert_info;
2033
2034 #ifdef X509_V3
2035         /* Make it an X509 v3 certificate. */
2036         if (!X509_set_version(x509,2)) goto err;
2037 #endif
2038
2039         if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
2040                 goto err;
2041         if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
2042                 goto err;
2043
2044         BIO_printf(bio_err,"Certificate is to be certified until ");
2045         if (strcmp(startdate,"today") == 0)
2046                 X509_gmtime_adj(X509_get_notBefore(ret),0);
2047         else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
2048
2049         if (enddate == NULL)
2050                 X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
2051         else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
2052
2053         ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
2054         if (days) BIO_printf(bio_err," (%d days)",days);
2055         BIO_printf(bio_err, "\n");
2056
2057         if (!X509_set_subject_name(ret,subject)) goto err;
2058
2059         pktmp=X509_REQ_get_pubkey(req);
2060         i = X509_set_pubkey(ret,pktmp);
2061         EVP_PKEY_free(pktmp);
2062         if (!i) goto err;
2063
2064         /* Lets add the extensions, if there are any */
2065         if (ext_sect)
2066                 {
2067                 X509V3_CTX ctx;
2068                 if (ci->version == NULL)
2069                         if ((ci->version=ASN1_INTEGER_new()) == NULL)
2070                                 goto err;
2071                 ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
2072
2073                 /* Free the current entries if any, there should not
2074                  * be any I believe */
2075                 if (ci->extensions != NULL)
2076                         sk_X509_EXTENSION_pop_free(ci->extensions,
2077                                                    X509_EXTENSION_free);
2078
2079                 ci->extensions = NULL;
2080
2081                 /* Initialize the context structure */
2082                 X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
2083
2084                 if (extconf)
2085                         {
2086                         if (verbose)
2087                                 BIO_printf(bio_err, "Extra configuration file found\n");
2088  
2089                         /* Use the extconf configuration db LHASH */
2090                         X509V3_set_conf_lhash(&ctx, extconf);
2091  
2092                         /* Test the structure (needed?) */
2093                         /* X509V3_set_ctx_test(&ctx); */
2094
2095                         /* Adds exts contained in the configuration file */
2096                         if (!X509V3_EXT_add_conf(extconf, &ctx, ext_sect,ret))
2097                                 {
2098                                 BIO_printf(bio_err,
2099                                     "ERROR: adding extensions in section %s\n",
2100                                                                 ext_sect);
2101                                 ERR_print_errors(bio_err);
2102                                 goto err;
2103                                 }
2104                         if (verbose)
2105                                 BIO_printf(bio_err, "Successfully added extensions from file.\n");
2106                         }
2107                 else if (ext_sect)
2108                         {
2109                         /* We found extensions to be set from config file */
2110                         X509V3_set_conf_lhash(&ctx, lconf);
2111
2112                         if(!X509V3_EXT_add_conf(lconf, &ctx, ext_sect, ret))
2113                                 {
2114                                 BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2115                                 ERR_print_errors(bio_err);
2116                                 goto err;
2117                                 }
2118
2119                         if (verbose) 
2120                                 BIO_printf(bio_err, "Successfully added extensions from config\n");
2121                         }
2122                 }
2123
2124
2125         if (!batch)
2126                 {
2127                 BIO_printf(bio_err,"Sign the certificate? [y/n]:");
2128                 (void)BIO_flush(bio_err);
2129                 buf[0]='\0';
2130                 fgets(buf,sizeof(buf)-1,stdin);
2131                 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
2132                         {
2133                         BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
2134                         ok=0;
2135                         goto err;
2136                         }
2137                 }
2138
2139
2140 #ifndef NO_DSA
2141         if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
2142         pktmp=X509_get_pubkey(ret);
2143         if (EVP_PKEY_missing_parameters(pktmp) &&
2144                 !EVP_PKEY_missing_parameters(pkey))
2145                 EVP_PKEY_copy_parameters(pktmp,pkey);
2146         EVP_PKEY_free(pktmp);
2147 #endif
2148
2149         if (!X509_sign(ret,pkey,dgst))
2150                 goto err;
2151
2152         /* We now just add it to the database */
2153         row[DB_type]=(char *)OPENSSL_malloc(2);
2154
2155         tm=X509_get_notAfter(ret);
2156         row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2157         memcpy(row[DB_exp_date],tm->data,tm->length);
2158         row[DB_exp_date][tm->length]='\0';
2159
2160         row[DB_rev_date]=NULL;
2161
2162         /* row[DB_serial] done already */
2163         row[DB_file]=(char *)OPENSSL_malloc(8);
2164         /* row[DB_name] done already */
2165
2166         if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2167                 (row[DB_file] == NULL))
2168                 {
2169                 BIO_printf(bio_err,"Memory allocation failure\n");
2170                 goto err;
2171                 }
2172         strcpy(row[DB_file],"unknown");
2173         row[DB_type][0]='V';
2174         row[DB_type][1]='\0';
2175
2176         if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2177                 {
2178                 BIO_printf(bio_err,"Memory allocation failure\n");
2179                 goto err;
2180                 }
2181
2182         for (i=0; i<DB_NUMBER; i++)
2183                 {
2184                 irow[i]=row[i];
2185                 row[i]=NULL;
2186                 }
2187         irow[DB_NUMBER]=NULL;
2188
2189         if (!TXT_DB_insert(db,irow))
2190                 {
2191                 BIO_printf(bio_err,"failed to update database\n");
2192                 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2193                 goto err;
2194                 }
2195         ok=1;
2196 err:
2197         for (i=0; i<DB_NUMBER; i++)
2198                 if (row[i] != NULL) OPENSSL_free(row[i]);
2199
2200         if (CAname != NULL)
2201                 X509_NAME_free(CAname);
2202         if (subject != NULL)
2203                 X509_NAME_free(subject);
2204         if (tmptm != NULL)
2205                 ASN1_UTCTIME_free(tmptm);
2206         if (ok <= 0)
2207                 {
2208                 if (ret != NULL) X509_free(ret);
2209                 ret=NULL;
2210                 }
2211         else
2212                 *xret=ret;
2213         return(ok);
2214         }
2215
2216 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
2217         {
2218
2219         if (output_der)
2220                 {
2221                 (void)i2d_X509_bio(bp,x);
2222                 return;
2223                 }
2224 #if 0
2225         /* ??? Not needed since X509_print prints all this stuff anyway */
2226         f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
2227         BIO_printf(bp,"issuer :%s\n",f);
2228
2229         f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
2230         BIO_printf(bp,"subject:%s\n",f);
2231
2232         BIO_puts(bp,"serial :");
2233         i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
2234         BIO_puts(bp,"\n\n");
2235 #endif
2236         if (!notext)X509_print(bp,x);
2237         PEM_write_bio_X509(bp,x);
2238         }
2239
2240 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
2241              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
2242              BIGNUM *serial, char *startdate, char *enddate, int days,
2243              char *ext_sect, LHASH *lconf, int verbose)
2244         {
2245         STACK_OF(CONF_VALUE) *sk=NULL;
2246         LHASH *parms=NULL;
2247         X509_REQ *req=NULL;
2248         CONF_VALUE *cv=NULL;
2249         NETSCAPE_SPKI *spki = NULL;
2250         X509_REQ_INFO *ri;
2251         char *type,*buf;
2252         EVP_PKEY *pktmp=NULL;
2253         X509_NAME *n=NULL;
2254         X509_NAME_ENTRY *ne=NULL;
2255         int ok= -1,i,j;
2256         long errline;
2257         int nid;
2258
2259         /*
2260          * Load input file into a hash table.  (This is just an easy
2261          * way to read and parse the file, then put it into a convenient
2262          * STACK format).
2263          */
2264         parms=CONF_load(NULL,infile,&errline);
2265         if (parms == NULL)
2266                 {
2267                 BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
2268                 ERR_print_errors(bio_err);
2269                 goto err;
2270                 }
2271
2272         sk=CONF_get_section(parms, "default");
2273         if (sk_CONF_VALUE_num(sk) == 0)
2274                 {
2275                 BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2276                 CONF_free(parms);
2277                 goto err;
2278                 }
2279
2280         /*
2281          * Now create a dummy X509 request structure.  We don't actually
2282          * have an X509 request, but we have many of the components
2283          * (a public key, various DN components).  The idea is that we
2284          * put these components into the right X509 request structure
2285          * and we can use the same code as if you had a real X509 request.
2286          */
2287         req=X509_REQ_new();
2288         if (req == NULL)
2289                 {
2290                 ERR_print_errors(bio_err);
2291                 goto err;
2292                 }
2293
2294         /*
2295          * Build up the subject name set.
2296          */
2297         ri=req->req_info;
2298         n = ri->subject;
2299
2300         for (i = 0; ; i++)
2301                 {
2302                 if (sk_CONF_VALUE_num(sk) <= i) break;
2303
2304                 cv=sk_CONF_VALUE_value(sk,i);
2305                 type=cv->name;
2306                 /* Skip past any leading X. X: X, etc to allow for
2307                  * multiple instances
2308                  */
2309                 for (buf = cv->name; *buf ; buf++)
2310                         if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2311                                 {
2312                                 buf++;
2313                                 if (*buf) type = buf;
2314                                 break;
2315                                 }
2316
2317                 buf=cv->value;
2318                 if ((nid=OBJ_txt2nid(type)) == NID_undef)
2319                         {
2320                         if (strcmp(type, "SPKAC") == 0)
2321                                 {
2322                                 spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2323                                 if (spki == NULL)
2324                                         {
2325                                         BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2326                                         ERR_print_errors(bio_err);
2327                                         goto err;
2328                                         }
2329                                 }
2330                         continue;
2331                         }
2332
2333                 j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
2334                 if (fix_data(nid, &j) == 0)
2335                         {
2336                         BIO_printf(bio_err,
2337                                 "invalid characters in string %s\n",buf);
2338                         goto err;
2339                         }
2340
2341                 if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
2342                         (unsigned char *)buf,
2343                         strlen(buf))) == NULL)
2344                         goto err;
2345
2346                 if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
2347                 }
2348         if (spki == NULL)
2349                 {
2350                 BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2351                         infile);
2352                 goto err;
2353                 }
2354
2355         /*
2356          * Now extract the key from the SPKI structure.
2357          */
2358
2359         BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2360
2361         if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
2362                 {
2363                 BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2364                 goto err;
2365                 }
2366
2367         j = NETSCAPE_SPKI_verify(spki, pktmp);
2368         if (j <= 0)
2369                 {
2370                 BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2371                 goto err;
2372                 }
2373         BIO_printf(bio_err,"Signature ok\n");
2374
2375         X509_REQ_set_pubkey(req,pktmp);
2376         EVP_PKEY_free(pktmp);
2377         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,
2378                    days,1,verbose,req,ext_sect,lconf);
2379 err:
2380         if (req != NULL) X509_REQ_free(req);
2381         if (parms != NULL) CONF_free(parms);
2382         if (spki != NULL) NETSCAPE_SPKI_free(spki);
2383         if (ne != NULL) X509_NAME_ENTRY_free(ne);
2384
2385         return(ok);
2386         }
2387
2388 static int fix_data(int nid, int *type)
2389         {
2390         if (nid == NID_pkcs9_emailAddress)
2391                 *type=V_ASN1_IA5STRING;
2392         if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
2393                 *type=V_ASN1_T61STRING;
2394         if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
2395                 *type=V_ASN1_T61STRING;
2396         if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
2397                 return(0);
2398         if (nid == NID_pkcs9_unstructuredName)
2399                 *type=V_ASN1_IA5STRING;
2400         return(1);
2401         }
2402
2403 static int check_time_format(char *str)
2404         {
2405         ASN1_UTCTIME tm;
2406
2407         tm.data=(unsigned char *)str;
2408         tm.length=strlen(str);
2409         tm.type=V_ASN1_UTCTIME;
2410         return(ASN1_UTCTIME_check(&tm));
2411         }
2412
2413 static int do_revoke(X509 *x509, TXT_DB *db)
2414         {
2415         ASN1_UTCTIME *tm=NULL, *revtm=NULL;
2416         char *row[DB_NUMBER],**rrow,**irow;
2417         BIGNUM *bn = NULL;
2418         int ok=-1,i;
2419
2420         for (i=0; i<DB_NUMBER; i++)
2421                 row[i]=NULL;
2422         row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2423         bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2424         row[DB_serial]=BN_bn2hex(bn);
2425         BN_free(bn);
2426         if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2427                 {
2428                 BIO_printf(bio_err,"Memory allocation failure\n");
2429                 goto err;
2430                 }
2431         /* We have to lookup by serial number because name lookup
2432          * skips revoked certs
2433          */
2434         rrow=TXT_DB_get_by_index(db,DB_serial,row);
2435         if (rrow == NULL)
2436                 {
2437                 BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]);
2438
2439                 /* We now just add it to the database */
2440                 row[DB_type]=(char *)OPENSSL_malloc(2);
2441
2442                 tm=X509_get_notAfter(x509);
2443                 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2444                 memcpy(row[DB_exp_date],tm->data,tm->length);
2445                 row[DB_exp_date][tm->length]='\0';
2446
2447                 row[DB_rev_date]=NULL;
2448
2449                 /* row[DB_serial] done already */
2450                 row[DB_file]=(char *)OPENSSL_malloc(8);
2451
2452                 /* row[DB_name] done already */
2453
2454                 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2455                         (row[DB_file] == NULL))
2456                         {
2457                         BIO_printf(bio_err,"Memory allocation failure\n");
2458                         goto err;
2459                         }
2460                 strcpy(row[DB_file],"unknown");
2461                 row[DB_type][0]='V';
2462                 row[DB_type][1]='\0';
2463
2464                 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2465                         {
2466                         BIO_printf(bio_err,"Memory allocation failure\n");
2467                         goto err;
2468                         }
2469
2470                 for (i=0; i<DB_NUMBER; i++)
2471                         {
2472                         irow[i]=row[i];
2473                         row[i]=NULL;
2474                         }
2475                 irow[DB_NUMBER]=NULL;
2476
2477                 if (!TXT_DB_insert(db,irow))
2478                         {
2479                         BIO_printf(bio_err,"failed to update database\n");
2480                         BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2481                         goto err;
2482                         }
2483
2484                 /* Revoke Certificate */
2485                 ok = do_revoke(x509,db);
2486
2487                 goto err;
2488
2489                 }
2490         else if (index_name_cmp((const char **)row,(const char **)rrow))
2491                 {
2492                 BIO_printf(bio_err,"ERROR:name does not match %s\n",
2493                            row[DB_name]);
2494                 goto err;
2495                 }
2496         else if (rrow[DB_type][0]=='R')
2497                 {
2498                 BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2499                            row[DB_serial]);
2500                 goto err;
2501                 }
2502         else
2503                 {
2504                 BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2505                 revtm = ASN1_UTCTIME_new();
2506                 revtm=X509_gmtime_adj(revtm,0);
2507                 rrow[DB_type][0]='R';
2508                 rrow[DB_type][1]='\0';
2509                 rrow[DB_rev_date]=(char *)OPENSSL_malloc(revtm->length+1);
2510                 memcpy(rrow[DB_rev_date],revtm->data,revtm->length);
2511                 rrow[DB_rev_date][revtm->length]='\0';
2512                 ASN1_UTCTIME_free(revtm);
2513                 }
2514         ok=1;
2515 err:
2516         for (i=0; i<DB_NUMBER; i++)
2517                 {
2518                 if (row[i] != NULL) 
2519                         OPENSSL_free(row[i]);
2520                 }
2521         return(ok);
2522         }
2523
2524 static int get_certificate_status(const char *serial, TXT_DB *db)
2525         {
2526         char *row[DB_NUMBER],**rrow;
2527         int ok=-1,i;
2528
2529         /* Free Resources */
2530         for (i=0; i<DB_NUMBER; i++)
2531                 row[i]=NULL;
2532
2533         /* Malloc needed char spaces */
2534         row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2535         if (row[DB_serial] == NULL)
2536                 {
2537                 BIO_printf(bio_err,"Malloc failure\n");
2538                 goto err;
2539                 }
2540
2541         if (strlen(serial) % 2)
2542                 {
2543                 /* Set the first char to 0 */;
2544                 row[DB_serial][0]='0';
2545
2546                 /* Copy String from serial to row[DB_serial] */
2547                 memcpy(row[DB_serial]+1, serial, strlen(serial));
2548                 row[DB_serial][strlen(serial)+1]='\0';
2549                 }
2550         else
2551                 {
2552                 /* Copy String from serial to row[DB_serial] */
2553                 memcpy(row[DB_serial], serial, strlen(serial));
2554                 row[DB_serial][strlen(serial)]='\0';
2555                 }
2556                         
2557         /* Make it Upper Case */
2558         for (i=0; row[DB_serial][i] != '\0'; i++)
2559                 row[DB_serial][i] = toupper(row[DB_serial][i]);
2560         
2561
2562         ok=1;
2563
2564         /* Search for the certificate */
2565         rrow=TXT_DB_get_by_index(db,DB_serial,row);
2566         if (rrow == NULL)
2567                 {
2568                 BIO_printf(bio_err,"Serial %s not present in db.\n",
2569                                  row[DB_serial]);
2570                 ok=-1;
2571                 goto err;
2572                 }
2573         else if (rrow[DB_type][0]=='V')
2574                 {
2575                 BIO_printf(bio_err,"%s=Valid (%c)\n",
2576                         row[DB_serial], rrow[DB_type][0]);
2577                 goto err;
2578                 }
2579         else if (rrow[DB_type][0]=='R')
2580                 {
2581                 BIO_printf(bio_err,"%s=Revoked (%c)\n",
2582                         row[DB_serial], rrow[DB_type][0]);
2583                 goto err;
2584                 }
2585         else if (rrow[DB_type][0]=='E')
2586                 {
2587                 BIO_printf(bio_err,"%s=Expired (%c)\n",
2588                         row[DB_serial], rrow[DB_type][0]);
2589                 goto err;
2590                 }
2591         else if (rrow[DB_type][0]=='S')
2592                 {
2593                 BIO_printf(bio_err,"%s=Suspended (%c)\n",
2594                         row[DB_serial], rrow[DB_type][0]);
2595                 goto err;
2596                 }
2597         else
2598                 {
2599                 BIO_printf(bio_err,"%s=Unknown (%c).\n",
2600                         row[DB_serial], rrow[DB_type][0]);
2601                 ok=-1;
2602                 }
2603 err:
2604         for (i=0; i<DB_NUMBER; i++)
2605                 {
2606                 if (row[i] != NULL)
2607                         OPENSSL_free(row[i]);
2608                 }
2609         return(ok);
2610         }
2611
2612 static int do_updatedb (TXT_DB *db)
2613         {
2614         ASN1_UTCTIME    *a_tm = NULL;
2615         int i, cnt = 0;
2616         int db_y2k, a_y2k;  /* flags = 1 if y >= 2000 */ 
2617         char **rrow, *a_tm_s;
2618
2619         a_tm = ASN1_UTCTIME_new();
2620
2621         /* get actual time and make a string */
2622         a_tm = X509_gmtime_adj(a_tm, 0);
2623         a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2624         if (a_tm_s == NULL)
2625                 {
2626                 cnt = -1;
2627                 goto err;
2628                 }
2629
2630         memcpy(a_tm_s, a_tm->data, a_tm->length);
2631         a_tm_s[a_tm->length] = '\0';
2632
2633         if (strncmp(a_tm_s, "49", 2) <= 0)
2634                 a_y2k = 1;
2635         else
2636                 a_y2k = 0;
2637
2638         for (i = 0; i < sk_num(db->data); i++)
2639                 {
2640                 rrow = (char **) sk_value(db->data, i);
2641
2642                 if (rrow[DB_type][0] == 'V')
2643                         {
2644                         /* ignore entries that are not valid */
2645                         if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2646                                 db_y2k = 1;
2647                         else
2648                                 db_y2k = 0;
2649
2650                         if (db_y2k == a_y2k)
2651                                 {
2652                                 /* all on the same y2k side */
2653                                 if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2654                                         {
2655                                         rrow[DB_type][0]  = 'E';
2656                                         rrow[DB_type][1]  = '\0';
2657                                         cnt++;
2658
2659                                         BIO_printf(bio_err, "%s=Expired\n",
2660                                                         rrow[DB_serial]);
2661                                         }
2662                                 }
2663                         else if (db_y2k < a_y2k)
2664                                 {
2665                                 rrow[DB_type][0]  = 'E';
2666                                 rrow[DB_type][1]  = '\0';
2667                                 cnt++;
2668
2669                                 BIO_printf(bio_err, "%s=Expired\n",
2670                                                         rrow[DB_serial]);
2671                                 }
2672
2673                         }
2674                 }
2675
2676 err:
2677
2678         ASN1_UTCTIME_free(a_tm);
2679         OPENSSL_free(a_tm_s);
2680
2681         return (cnt);
2682         }