b84e842bc0c6db8dc226cc15ce20619d2425fd8c
[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                                 if (!ASN1_UTCTIME_set_string(r->revocationDate,
1383                                         pp[DB_rev_date]))
1384                                                 goto err;
1385                                 /* strcpy(r->revocationDate,pp[DB_rev_date]);*/
1386
1387                                 (void)BIO_reset(hex);
1388                                 if (!BIO_puts(hex,pp[DB_serial]))
1389                                         goto err;
1390                                 if (!a2i_ASN1_INTEGER(hex,r->serialNumber,
1391                                         buf[0],BSIZE)) goto err;
1392
1393                                 X509_CRL_add0_revoked(crl,r);
1394                                 }
1395                         }
1396                 /* sort the data so it will be written in serial
1397                  * number order */
1398                 sk_X509_REVOKED_sort(ci->revoked);
1399                 for (i=0; i<sk_X509_REVOKED_num(ci->revoked); i++)
1400                         {
1401                         r=sk_X509_REVOKED_value(ci->revoked,i);
1402                         r->sequence=i;
1403                         }
1404
1405                 /* we now have a CRL */
1406                 if (verbose) BIO_printf(bio_err,"signing CRL\n");
1407                 if (md != NULL)
1408                         {
1409                         if ((dgst=EVP_get_digestbyname(md)) == NULL)
1410                                 {
1411                                 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1412                                 goto err;
1413                                 }
1414                         }
1415                 else
1416                         {
1417 #ifndef NO_DSA
1418                         if (pkey->type == EVP_PKEY_DSA) 
1419                                 dgst=EVP_dss1();
1420                         else
1421 #endif
1422                                 dgst=EVP_md5();
1423                         }
1424
1425                 /* Add any extensions asked for */
1426
1427                 if (crl_ext)
1428                         {
1429                         X509V3_CTX crlctx;
1430                         if (ci->version == NULL)
1431                                 if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
1432                         ASN1_INTEGER_set(ci->version,1); /* version 2 CRL */
1433                         X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1434                         X509V3_set_conf_lhash(&crlctx, conf);
1435
1436                         if (!X509V3_EXT_CRL_add_conf(conf, &crlctx,
1437                                 crl_ext, crl)) goto err;
1438                         }
1439
1440                 if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1441
1442                 PEM_write_bio_X509_CRL(Sout,crl);
1443                 }
1444         /*****************************************************************/
1445         if (dorevoke)
1446                 {
1447                 if (infile == NULL) 
1448                         {
1449                         BIO_printf(bio_err,"no input files\n");
1450                         goto err;
1451                         }
1452                 else
1453                         {
1454                         X509 *revcert;
1455                         if (BIO_read_filename(in,infile) <= 0)
1456                                 {
1457                                 perror(infile);
1458                                 BIO_printf(bio_err,"error trying to load '%s' certificate\n",infile);
1459                                 goto err;
1460                                 }
1461                         revcert=PEM_read_bio_X509(in,NULL,NULL,NULL);
1462                         if (revcert == NULL)
1463                                 {
1464                                 BIO_printf(bio_err,"unable to load '%s' certificate\n",infile);
1465                                 goto err;
1466                                 }
1467                         j=do_revoke(revcert,db);
1468                         if (j <= 0) goto err;
1469                         X509_free(revcert);
1470
1471                         strncpy(buf[0],dbfile,BSIZE-4);
1472                         strcat(buf[0],".new");
1473                         if (BIO_write_filename(out,buf[0]) <= 0)
1474                                 {
1475                                 perror(dbfile);
1476                                 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1477                                 goto err;
1478                                 }
1479                         j=TXT_DB_write(out,db);
1480                         if (j <= 0) goto err;
1481                         strncpy(buf[1],dbfile,BSIZE-4);
1482                         strcat(buf[1],".old");
1483                         if (rename(dbfile,buf[1]) < 0)
1484                                 {
1485                                 BIO_printf(bio_err,"unable to rename %s to %s\n", dbfile, buf[1]);
1486                                 perror("reason");
1487                                 goto err;
1488                                 }
1489                         if (rename(buf[0],dbfile) < 0)
1490                                 {
1491                                 BIO_printf(bio_err,"unable to rename %s to %s\n", buf[0],dbfile);
1492                                 perror("reason");
1493                                 rename(buf[1],dbfile);
1494                                 goto err;
1495                                 }
1496                         BIO_printf(bio_err,"Data Base Updated\n"); 
1497                         }
1498                 }
1499         /*****************************************************************/
1500         ret=0;
1501 err:
1502         BIO_free(hex);
1503         BIO_free_all(Cout);
1504         BIO_free_all(Sout);
1505         BIO_free_all(out);
1506         BIO_free(in);
1507
1508         sk_X509_pop_free(cert_sk,X509_free);
1509
1510         if (ret) ERR_print_errors(bio_err);
1511         app_RAND_write_file(randfile, bio_err);
1512         BN_free(serial);
1513         TXT_DB_free(db);
1514         EVP_PKEY_free(pkey);
1515         X509_free(x509);
1516         X509_CRL_free(crl);
1517         CONF_free(conf);
1518         OBJ_cleanup();
1519         EXIT(ret);
1520         }
1521
1522 static void lookup_fail(char *name, char *tag)
1523         {
1524         BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1525         }
1526
1527 static unsigned long index_serial_hash(const char **a)
1528         {
1529         const char *n;
1530
1531         n=a[DB_serial];
1532         while (*n == '0') n++;
1533         return(lh_strhash(n));
1534         }
1535
1536 static int index_serial_cmp(const char **a, const char **b)
1537         {
1538         const char *aa,*bb;
1539
1540         for (aa=a[DB_serial]; *aa == '0'; aa++);
1541         for (bb=b[DB_serial]; *bb == '0'; bb++);
1542         return(strcmp(aa,bb));
1543         }
1544
1545 static unsigned long index_name_hash(const char **a)
1546         { return(lh_strhash(a[DB_name])); }
1547
1548 static int index_name_qual(char **a)
1549         { return(a[0][0] == 'V'); }
1550
1551 static int index_name_cmp(const char **a, const char **b)
1552         { return(strcmp(a[DB_name],
1553              b[DB_name])); }
1554
1555 static BIGNUM *load_serial(char *serialfile)
1556         {
1557         BIO *in=NULL;
1558         BIGNUM *ret=NULL;
1559         MS_STATIC char buf[1024];
1560         ASN1_INTEGER *ai=NULL;
1561
1562         if ((in=BIO_new(BIO_s_file())) == NULL)
1563                 {
1564                 ERR_print_errors(bio_err);
1565                 goto err;
1566                 }
1567
1568         if (BIO_read_filename(in,serialfile) <= 0)
1569                 {
1570                 perror(serialfile);
1571                 goto err;
1572                 }
1573         ai=ASN1_INTEGER_new();
1574         if (ai == NULL) goto err;
1575         if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
1576                 {
1577                 BIO_printf(bio_err,"unable to load number from %s\n",
1578                         serialfile);
1579                 goto err;
1580                 }
1581         ret=ASN1_INTEGER_to_BN(ai,NULL);
1582         if (ret == NULL)
1583                 {
1584                 BIO_printf(bio_err,"error converting number from bin to BIGNUM");
1585                 goto err;
1586                 }
1587 err:
1588         if (in != NULL) BIO_free(in);
1589         if (ai != NULL) ASN1_INTEGER_free(ai);
1590         return(ret);
1591         }
1592
1593 static int save_serial(char *serialfile, BIGNUM *serial)
1594         {
1595         BIO *out;
1596         int ret=0;
1597         ASN1_INTEGER *ai=NULL;
1598
1599         out=BIO_new(BIO_s_file());
1600         if (out == NULL)
1601                 {
1602                 ERR_print_errors(bio_err);
1603                 goto err;
1604                 }
1605         if (BIO_write_filename(out,serialfile) <= 0)
1606                 {
1607                 perror(serialfile);
1608                 goto err;
1609                 }
1610
1611         if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
1612                 {
1613                 BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
1614                 goto err;
1615                 }
1616         i2a_ASN1_INTEGER(out,ai);
1617         BIO_puts(out,"\n");
1618         ret=1;
1619 err:
1620         if (out != NULL) BIO_free_all(out);
1621         if (ai != NULL) ASN1_INTEGER_free(ai);
1622         return(ret);
1623         }
1624
1625 static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1626              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1627              BIGNUM *serial, char *startdate, char *enddate, int days,
1628              int batch, char *ext_sect, LHASH *lconf, int verbose)
1629         {
1630         X509_REQ *req=NULL;
1631         BIO *in=NULL;
1632         EVP_PKEY *pktmp=NULL;
1633         int ok= -1,i;
1634
1635         in=BIO_new(BIO_s_file());
1636
1637         if (BIO_read_filename(in,infile) <= 0)
1638                 {
1639                 perror(infile);
1640                 goto err;
1641                 }
1642         if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
1643                 {
1644                 BIO_printf(bio_err,"Error reading certificate request in %s\n",
1645                         infile);
1646                 goto err;
1647                 }
1648         if (verbose)
1649                 X509_REQ_print(bio_err,req);
1650
1651         BIO_printf(bio_err,"Check that the request matches the signature\n");
1652
1653         if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
1654                 {
1655                 BIO_printf(bio_err,"error unpacking public key\n");
1656                 goto err;
1657                 }
1658         i=X509_REQ_verify(req,pktmp);
1659         EVP_PKEY_free(pktmp);
1660         if (i < 0)
1661                 {
1662                 ok=0;
1663                 BIO_printf(bio_err,"Signature verification problems....\n");
1664                 goto err;
1665                 }
1666         if (i == 0)
1667                 {
1668                 ok=0;
1669                 BIO_printf(bio_err,"Signature did not match the certificate request\n");
1670                 goto err;
1671                 }
1672         else
1673                 BIO_printf(bio_err,"Signature ok\n");
1674
1675         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate, enddate,
1676                 days,batch,verbose,req,ext_sect,lconf);
1677
1678 err:
1679         if (req != NULL) X509_REQ_free(req);
1680         if (in != NULL) BIO_free(in);
1681         return(ok);
1682         }
1683
1684 static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1685              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1686              BIGNUM *serial, char *startdate, char *enddate, int days,
1687              int batch, char *ext_sect, LHASH *lconf, int verbose)
1688         {
1689         X509 *req=NULL;
1690         X509_REQ *rreq=NULL;
1691         BIO *in=NULL;
1692         EVP_PKEY *pktmp=NULL;
1693         int ok= -1,i;
1694
1695         in=BIO_new(BIO_s_file());
1696
1697         if (BIO_read_filename(in,infile) <= 0)
1698                 {
1699                 perror(infile);
1700                 goto err;
1701                 }
1702         if ((req=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
1703                 {
1704                 BIO_printf(bio_err,"Error reading self signed certificate in %s\n",infile);
1705                 goto err;
1706                 }
1707         if (verbose)
1708                 X509_print(bio_err,req);
1709
1710         BIO_printf(bio_err,"Check that the request matches the signature\n");
1711
1712         if ((pktmp=X509_get_pubkey(req)) == NULL)
1713                 {
1714                 BIO_printf(bio_err,"error unpacking public key\n");
1715                 goto err;
1716                 }
1717         i=X509_verify(req,pktmp);
1718         EVP_PKEY_free(pktmp);
1719         if (i < 0)
1720                 {
1721                 ok=0;
1722                 BIO_printf(bio_err,"Signature verification problems....\n");
1723                 goto err;
1724                 }
1725         if (i == 0)
1726                 {
1727                 ok=0;
1728                 BIO_printf(bio_err,"Signature did not match the certificate\n");
1729                 goto err;
1730                 }
1731         else
1732                 BIO_printf(bio_err,"Signature ok\n");
1733
1734         if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
1735                 goto err;
1736
1737         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,days,
1738                 batch,verbose,rreq,ext_sect,lconf);
1739
1740 err:
1741         if (rreq != NULL) X509_REQ_free(rreq);
1742         if (req != NULL) X509_free(req);
1743         if (in != NULL) BIO_free(in);
1744         return(ok);
1745         }
1746
1747 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1748              STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
1749              char *startdate, char *enddate, int days, int batch, int verbose,
1750              X509_REQ *req, char *ext_sect, LHASH *lconf)
1751         {
1752         X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
1753         ASN1_UTCTIME *tm,*tmptm;
1754         ASN1_STRING *str,*str2;
1755         ASN1_OBJECT *obj;
1756         X509 *ret=NULL;
1757         X509_CINF *ci;
1758         X509_NAME_ENTRY *ne;
1759         X509_NAME_ENTRY *tne,*push;
1760         EVP_PKEY *pktmp;
1761         int ok= -1,i,j,last,nid;
1762         char *p;
1763         CONF_VALUE *cv;
1764         char *row[DB_NUMBER],**rrow,**irow=NULL;
1765         char buf[25],*pbuf;
1766
1767         tmptm=ASN1_UTCTIME_new();
1768         if (tmptm == NULL)
1769                 {
1770                 BIO_printf(bio_err,"malloc error\n");
1771                 return(0);
1772                 }
1773
1774         for (i=0; i<DB_NUMBER; i++)
1775                 row[i]=NULL;
1776
1777         BIO_printf(bio_err,"The Subjects Distinguished Name is as follows\n");
1778         name=X509_REQ_get_subject_name(req);
1779         for (i=0; i<X509_NAME_entry_count(name); i++)
1780                 {
1781                 ne=(X509_NAME_ENTRY *)X509_NAME_get_entry(name,i);
1782                 obj=X509_NAME_ENTRY_get_object(ne);
1783                 j=i2a_ASN1_OBJECT(bio_err,obj);
1784                 str=X509_NAME_ENTRY_get_data(ne);
1785                 pbuf=buf;
1786                 for (j=22-j; j>0; j--)
1787                         *(pbuf++)=' ';
1788                 *(pbuf++)=':';
1789                 *(pbuf++)='\0';
1790                 BIO_puts(bio_err,buf);
1791
1792                 if (msie_hack)
1793                         {
1794                         /* assume all type should be strings */
1795                         nid=OBJ_obj2nid(ne->object);
1796
1797                         if (str->type == V_ASN1_UNIVERSALSTRING)
1798                                 ASN1_UNIVERSALSTRING_to_string(str);
1799
1800                         if ((str->type == V_ASN1_IA5STRING) &&
1801                                 (nid != NID_pkcs9_emailAddress))
1802                                 str->type=V_ASN1_T61STRING;
1803
1804                         if ((nid == NID_pkcs9_emailAddress) &&
1805                                 (str->type == V_ASN1_PRINTABLESTRING))
1806                                 str->type=V_ASN1_IA5STRING;
1807                         }
1808
1809                 if (str->type == V_ASN1_PRINTABLESTRING)
1810                         BIO_printf(bio_err,"PRINTABLE:'");
1811                 else if (str->type == V_ASN1_T61STRING)
1812                         BIO_printf(bio_err,"T61STRING:'");
1813                 else if (str->type == V_ASN1_IA5STRING)
1814                         BIO_printf(bio_err,"IA5STRING:'");
1815                 else if (str->type == V_ASN1_UNIVERSALSTRING)
1816                         BIO_printf(bio_err,"UNIVERSALSTRING:'");
1817                 else
1818                         BIO_printf(bio_err,"ASN.1 %2d:'",str->type);
1819
1820                 /* check some things */
1821                 if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1822                         (str->type != V_ASN1_IA5STRING))
1823                         {
1824                         BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
1825                         goto err;
1826                         }
1827                 j=ASN1_PRINTABLE_type(str->data,str->length);
1828                 if (    ((j == V_ASN1_T61STRING) &&
1829                          (str->type != V_ASN1_T61STRING)) ||
1830                         ((j == V_ASN1_IA5STRING) &&
1831                          (str->type == V_ASN1_PRINTABLESTRING)))
1832                         {
1833                         BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1834                         goto err;
1835                         }
1836                         
1837                 p=(char *)str->data;
1838                 for (j=str->length; j>0; j--)
1839                         {
1840                         if ((*p >= ' ') && (*p <= '~'))
1841                                 BIO_printf(bio_err,"%c",*p);
1842                         else if (*p & 0x80)
1843                                 BIO_printf(bio_err,"\\0x%02X",*p);
1844                         else if ((unsigned char)*p == 0xf7)
1845                                 BIO_printf(bio_err,"^?");
1846                         else    BIO_printf(bio_err,"^%c",*p+'@');
1847                         p++;
1848                         }
1849                 BIO_printf(bio_err,"'\n");
1850                 }
1851
1852         /* Ok, now we check the 'policy' stuff. */
1853         if ((subject=X509_NAME_new()) == NULL)
1854                 {
1855                 BIO_printf(bio_err,"Memory allocation failure\n");
1856                 goto err;
1857                 }
1858
1859         /* take a copy of the issuer name before we mess with it. */
1860         CAname=X509_NAME_dup(x509->cert_info->subject);
1861         if (CAname == NULL) goto err;
1862         str=str2=NULL;
1863
1864         for (i=0; i<sk_CONF_VALUE_num(policy); i++)
1865                 {
1866                 cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
1867                 if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
1868                         {
1869                         BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
1870                         goto err;
1871                         }
1872                 obj=OBJ_nid2obj(j);
1873
1874                 last= -1;
1875                 for (;;)
1876                         {
1877                         /* lookup the object in the supplied name list */
1878                         j=X509_NAME_get_index_by_OBJ(name,obj,last);
1879                         if (j < 0)
1880                                 {
1881                                 if (last != -1) break;
1882                                 tne=NULL;
1883                                 }
1884                         else
1885                                 {
1886                                 tne=X509_NAME_get_entry(name,j);
1887                                 }
1888                         last=j;
1889
1890                         /* depending on the 'policy', decide what to do. */
1891                         push=NULL;
1892                         if (strcmp(cv->value,"optional") == 0)
1893                                 {
1894                                 if (tne != NULL)
1895                                         push=tne;
1896                                 }
1897                         else if (strcmp(cv->value,"supplied") == 0)
1898                                 {
1899                                 if (tne == NULL)
1900                                         {
1901                                         BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
1902                                         goto err;
1903                                         }
1904                                 else
1905                                         push=tne;
1906                                 }
1907                         else if (strcmp(cv->value,"match") == 0)
1908                                 {
1909                                 int last2;
1910
1911                                 if (tne == NULL)
1912                                         {
1913                                         BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
1914                                         goto err;
1915                                         }
1916
1917                                 last2= -1;
1918
1919 again2:
1920                                 j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
1921                                 if ((j < 0) && (last2 == -1))
1922                                         {
1923                                         BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
1924                                         goto err;
1925                                         }
1926                                 if (j >= 0)
1927                                         {
1928                                         push=X509_NAME_get_entry(CAname,j);
1929                                         str=X509_NAME_ENTRY_get_data(tne);
1930                                         str2=X509_NAME_ENTRY_get_data(push);
1931                                         last2=j;
1932                                         if (ASN1_STRING_cmp(str,str2) != 0)
1933                                                 goto again2;
1934                                         }
1935                                 if (j < 0)
1936                                         {
1937                                         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));
1938                                         goto err;
1939                                         }
1940                                 }
1941                         else
1942                                 {
1943                                 BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
1944                                 goto err;
1945                                 }
1946
1947                         if (push != NULL)
1948                                 {
1949                                 if (!X509_NAME_add_entry(subject,push, -1, 0))
1950                                         {
1951                                         if (push != NULL)
1952                                                 X509_NAME_ENTRY_free(push);
1953                                         BIO_printf(bio_err,"Memory allocation failure\n");
1954                                         goto err;
1955                                         }
1956                                 }
1957                         if (j < 0) break;
1958                         }
1959                 }
1960
1961         if (preserve)
1962                 {
1963                 X509_NAME_free(subject);
1964                 subject=X509_NAME_dup(X509_REQ_get_subject_name(req));
1965                 if (subject == NULL) goto err;
1966                 }
1967
1968         if (verbose)
1969                 BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
1970
1971         row[DB_name]=X509_NAME_oneline(subject,NULL,0);
1972         row[DB_serial]=BN_bn2hex(serial);
1973         if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
1974                 {
1975                 BIO_printf(bio_err,"Memory allocation failure\n");
1976                 goto err;
1977                 }
1978
1979         rrow=TXT_DB_get_by_index(db,DB_name,row);
1980         if (rrow != NULL)
1981                 {
1982                 BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n",
1983                         row[DB_name]);
1984                 }
1985         else
1986                 {
1987                 rrow=TXT_DB_get_by_index(db,DB_serial,row);
1988                 if (rrow != NULL)
1989                         {
1990                         BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
1991                                 row[DB_serial]);
1992                         BIO_printf(bio_err,"      check the database/serial_file for corruption\n");
1993                         }
1994                 }
1995
1996         if (rrow != NULL)
1997                 {
1998                 BIO_printf(bio_err,
1999                         "The matching entry has the following details\n");
2000                 if (rrow[DB_type][0] == 'E')
2001                         p="Expired";
2002                 else if (rrow[DB_type][0] == 'R')
2003                         p="Revoked";
2004                 else if (rrow[DB_type][0] == 'V')
2005                         p="Valid";
2006                 else
2007                         p="\ninvalid type, Data base error\n";
2008                 BIO_printf(bio_err,"Type          :%s\n",p);;
2009                 if (rrow[DB_type][0] == 'R')
2010                         {
2011                         p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2012                         BIO_printf(bio_err,"Was revoked on:%s\n",p);
2013                         }
2014                 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2015                 BIO_printf(bio_err,"Expires on    :%s\n",p);
2016                 p=rrow[DB_serial]; if (p == NULL) p="undef";
2017                 BIO_printf(bio_err,"Serial Number :%s\n",p);
2018                 p=rrow[DB_file]; if (p == NULL) p="undef";
2019                 BIO_printf(bio_err,"File name     :%s\n",p);
2020                 p=rrow[DB_name]; if (p == NULL) p="undef";
2021                 BIO_printf(bio_err,"Subject Name  :%s\n",p);
2022                 ok= -1; /* This is now a 'bad' error. */
2023                 goto err;
2024                 }
2025
2026         /* We are now totally happy, lets make and sign the certificate */
2027         if (verbose)
2028                 BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
2029
2030         if ((ret=X509_new()) == NULL) goto err;
2031         ci=ret->cert_info;
2032
2033 #ifdef X509_V3
2034         /* Make it an X509 v3 certificate. */
2035         if (!X509_set_version(x509,2)) goto err;
2036 #endif
2037
2038         if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
2039                 goto err;
2040         if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
2041                 goto err;
2042
2043         BIO_printf(bio_err,"Certificate is to be certified until ");
2044         if (strcmp(startdate,"today") == 0)
2045                 X509_gmtime_adj(X509_get_notBefore(ret),0);
2046         else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
2047
2048         if (enddate == NULL)
2049                 X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
2050         else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
2051
2052         ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
2053         if (days) BIO_printf(bio_err," (%d days)",days);
2054         BIO_printf(bio_err, "\n");
2055
2056         if (!X509_set_subject_name(ret,subject)) goto err;
2057
2058         pktmp=X509_REQ_get_pubkey(req);
2059         i = X509_set_pubkey(ret,pktmp);
2060         EVP_PKEY_free(pktmp);
2061         if (!i) goto err;
2062
2063         /* Lets add the extensions, if there are any */
2064         if (ext_sect)
2065                 {
2066                 X509V3_CTX ctx;
2067                 if (ci->version == NULL)
2068                         if ((ci->version=ASN1_INTEGER_new()) == NULL)
2069                                 goto err;
2070                 ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
2071
2072                 /* Free the current entries if any, there should not
2073                  * be any I believe */
2074                 if (ci->extensions != NULL)
2075                         sk_X509_EXTENSION_pop_free(ci->extensions,
2076                                                    X509_EXTENSION_free);
2077
2078                 ci->extensions = NULL;
2079
2080                 /* Initialize the context structure */
2081                 X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
2082
2083                 if (extconf)
2084                         {
2085                         if (verbose)
2086                                 BIO_printf(bio_err, "Extra configuration file found\n");
2087  
2088                         /* Use the extconf configuration db LHASH */
2089                         X509V3_set_conf_lhash(&ctx, extconf);
2090  
2091                         /* Test the structure (needed?) */
2092                         /* X509V3_set_ctx_test(&ctx); */
2093
2094                         /* Adds exts contained in the configuration file */
2095                         if (!X509V3_EXT_add_conf(extconf, &ctx, ext_sect,ret))
2096                                 {
2097                                 BIO_printf(bio_err,
2098                                     "ERROR: adding extensions in section %s\n",
2099                                                                 ext_sect);
2100                                 ERR_print_errors(bio_err);
2101                                 goto err;
2102                                 }
2103                         if (verbose)
2104                                 BIO_printf(bio_err, "Successfully added extensions from file.\n");
2105                         }
2106                 else if (ext_sect)
2107                         {
2108                         /* We found extensions to be set from config file */
2109                         X509V3_set_conf_lhash(&ctx, lconf);
2110
2111                         if(!X509V3_EXT_add_conf(lconf, &ctx, ext_sect, ret))
2112                                 {
2113                                 BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2114                                 ERR_print_errors(bio_err);
2115                                 goto err;
2116                                 }
2117
2118                         if (verbose) 
2119                                 BIO_printf(bio_err, "Successfully added extensions from config\n");
2120                         }
2121                 }
2122
2123
2124         if (!batch)
2125                 {
2126                 BIO_printf(bio_err,"Sign the certificate? [y/n]:");
2127                 (void)BIO_flush(bio_err);
2128                 buf[0]='\0';
2129                 fgets(buf,sizeof(buf)-1,stdin);
2130                 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
2131                         {
2132                         BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
2133                         ok=0;
2134                         goto err;
2135                         }
2136                 }
2137
2138
2139 #ifndef NO_DSA
2140         if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
2141         pktmp=X509_get_pubkey(ret);
2142         if (EVP_PKEY_missing_parameters(pktmp) &&
2143                 !EVP_PKEY_missing_parameters(pkey))
2144                 EVP_PKEY_copy_parameters(pktmp,pkey);
2145         EVP_PKEY_free(pktmp);
2146 #endif
2147
2148         if (!X509_sign(ret,pkey,dgst))
2149                 goto err;
2150
2151         /* We now just add it to the database */
2152         row[DB_type]=(char *)OPENSSL_malloc(2);
2153
2154         tm=X509_get_notAfter(ret);
2155         row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2156         memcpy(row[DB_exp_date],tm->data,tm->length);
2157         row[DB_exp_date][tm->length]='\0';
2158
2159         row[DB_rev_date]=NULL;
2160
2161         /* row[DB_serial] done already */
2162         row[DB_file]=(char *)OPENSSL_malloc(8);
2163         /* row[DB_name] done already */
2164
2165         if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2166                 (row[DB_file] == NULL))
2167                 {
2168                 BIO_printf(bio_err,"Memory allocation failure\n");
2169                 goto err;
2170                 }
2171         strcpy(row[DB_file],"unknown");
2172         row[DB_type][0]='V';
2173         row[DB_type][1]='\0';
2174
2175         if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2176                 {
2177                 BIO_printf(bio_err,"Memory allocation failure\n");
2178                 goto err;
2179                 }
2180
2181         for (i=0; i<DB_NUMBER; i++)
2182                 {
2183                 irow[i]=row[i];
2184                 row[i]=NULL;
2185                 }
2186         irow[DB_NUMBER]=NULL;
2187
2188         if (!TXT_DB_insert(db,irow))
2189                 {
2190                 BIO_printf(bio_err,"failed to update database\n");
2191                 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2192                 goto err;
2193                 }
2194         ok=1;
2195 err:
2196         for (i=0; i<DB_NUMBER; i++)
2197                 if (row[i] != NULL) OPENSSL_free(row[i]);
2198
2199         if (CAname != NULL)
2200                 X509_NAME_free(CAname);
2201         if (subject != NULL)
2202                 X509_NAME_free(subject);
2203         if (tmptm != NULL)
2204                 ASN1_UTCTIME_free(tmptm);
2205         if (ok <= 0)
2206                 {
2207                 if (ret != NULL) X509_free(ret);
2208                 ret=NULL;
2209                 }
2210         else
2211                 *xret=ret;
2212         return(ok);
2213         }
2214
2215 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
2216         {
2217
2218         if (output_der)
2219                 {
2220                 (void)i2d_X509_bio(bp,x);
2221                 return;
2222                 }
2223 #if 0
2224         /* ??? Not needed since X509_print prints all this stuff anyway */
2225         f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
2226         BIO_printf(bp,"issuer :%s\n",f);
2227
2228         f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
2229         BIO_printf(bp,"subject:%s\n",f);
2230
2231         BIO_puts(bp,"serial :");
2232         i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
2233         BIO_puts(bp,"\n\n");
2234 #endif
2235         if (!notext)X509_print(bp,x);
2236         PEM_write_bio_X509(bp,x);
2237         }
2238
2239 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
2240              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
2241              BIGNUM *serial, char *startdate, char *enddate, int days,
2242              char *ext_sect, LHASH *lconf, int verbose)
2243         {
2244         STACK_OF(CONF_VALUE) *sk=NULL;
2245         LHASH *parms=NULL;
2246         X509_REQ *req=NULL;
2247         CONF_VALUE *cv=NULL;
2248         NETSCAPE_SPKI *spki = NULL;
2249         X509_REQ_INFO *ri;
2250         char *type,*buf;
2251         EVP_PKEY *pktmp=NULL;
2252         X509_NAME *n=NULL;
2253         X509_NAME_ENTRY *ne=NULL;
2254         int ok= -1,i,j;
2255         long errline;
2256         int nid;
2257
2258         /*
2259          * Load input file into a hash table.  (This is just an easy
2260          * way to read and parse the file, then put it into a convenient
2261          * STACK format).
2262          */
2263         parms=CONF_load(NULL,infile,&errline);
2264         if (parms == NULL)
2265                 {
2266                 BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
2267                 ERR_print_errors(bio_err);
2268                 goto err;
2269                 }
2270
2271         sk=CONF_get_section(parms, "default");
2272         if (sk_CONF_VALUE_num(sk) == 0)
2273                 {
2274                 BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2275                 CONF_free(parms);
2276                 goto err;
2277                 }
2278
2279         /*
2280          * Now create a dummy X509 request structure.  We don't actually
2281          * have an X509 request, but we have many of the components
2282          * (a public key, various DN components).  The idea is that we
2283          * put these components into the right X509 request structure
2284          * and we can use the same code as if you had a real X509 request.
2285          */
2286         req=X509_REQ_new();
2287         if (req == NULL)
2288                 {
2289                 ERR_print_errors(bio_err);
2290                 goto err;
2291                 }
2292
2293         /*
2294          * Build up the subject name set.
2295          */
2296         ri=req->req_info;
2297         n = ri->subject;
2298
2299         for (i = 0; ; i++)
2300                 {
2301                 if (sk_CONF_VALUE_num(sk) <= i) break;
2302
2303                 cv=sk_CONF_VALUE_value(sk,i);
2304                 type=cv->name;
2305                 /* Skip past any leading X. X: X, etc to allow for
2306                  * multiple instances
2307                  */
2308                 for (buf = cv->name; *buf ; buf++)
2309                         if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2310                                 {
2311                                 buf++;
2312                                 if (*buf) type = buf;
2313                                 break;
2314                                 }
2315
2316                 buf=cv->value;
2317                 if ((nid=OBJ_txt2nid(type)) == NID_undef)
2318                         {
2319                         if (strcmp(type, "SPKAC") == 0)
2320                                 {
2321                                 spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2322                                 if (spki == NULL)
2323                                         {
2324                                         BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2325                                         ERR_print_errors(bio_err);
2326                                         goto err;
2327                                         }
2328                                 }
2329                         continue;
2330                         }
2331
2332                 j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
2333                 if (fix_data(nid, &j) == 0)
2334                         {
2335                         BIO_printf(bio_err,
2336                                 "invalid characters in string %s\n",buf);
2337                         goto err;
2338                         }
2339
2340                 if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
2341                         (unsigned char *)buf,
2342                         strlen(buf))) == NULL)
2343                         goto err;
2344
2345                 if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
2346                 }
2347         if (spki == NULL)
2348                 {
2349                 BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2350                         infile);
2351                 goto err;
2352                 }
2353
2354         /*
2355          * Now extract the key from the SPKI structure.
2356          */
2357
2358         BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2359
2360         if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
2361                 {
2362                 BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2363                 goto err;
2364                 }
2365
2366         j = NETSCAPE_SPKI_verify(spki, pktmp);
2367         if (j <= 0)
2368                 {
2369                 BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2370                 goto err;
2371                 }
2372         BIO_printf(bio_err,"Signature ok\n");
2373
2374         X509_REQ_set_pubkey(req,pktmp);
2375         EVP_PKEY_free(pktmp);
2376         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,
2377                    days,1,verbose,req,ext_sect,lconf);
2378 err:
2379         if (req != NULL) X509_REQ_free(req);
2380         if (parms != NULL) CONF_free(parms);
2381         if (spki != NULL) NETSCAPE_SPKI_free(spki);
2382         if (ne != NULL) X509_NAME_ENTRY_free(ne);
2383
2384         return(ok);
2385         }
2386
2387 static int fix_data(int nid, int *type)
2388         {
2389         if (nid == NID_pkcs9_emailAddress)
2390                 *type=V_ASN1_IA5STRING;
2391         if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
2392                 *type=V_ASN1_T61STRING;
2393         if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
2394                 *type=V_ASN1_T61STRING;
2395         if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
2396                 return(0);
2397         if (nid == NID_pkcs9_unstructuredName)
2398                 *type=V_ASN1_IA5STRING;
2399         return(1);
2400         }
2401
2402 static int check_time_format(char *str)
2403         {
2404         ASN1_UTCTIME tm;
2405
2406         tm.data=(unsigned char *)str;
2407         tm.length=strlen(str);
2408         tm.type=V_ASN1_UTCTIME;
2409         return(ASN1_UTCTIME_check(&tm));
2410         }
2411
2412 static int do_revoke(X509 *x509, TXT_DB *db)
2413         {
2414         ASN1_UTCTIME *tm=NULL, *revtm=NULL;
2415         char *row[DB_NUMBER],**rrow,**irow;
2416         BIGNUM *bn = NULL;
2417         int ok=-1,i;
2418
2419         for (i=0; i<DB_NUMBER; i++)
2420                 row[i]=NULL;
2421         row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2422         bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2423         row[DB_serial]=BN_bn2hex(bn);
2424         BN_free(bn);
2425         if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2426                 {
2427                 BIO_printf(bio_err,"Memory allocation failure\n");
2428                 goto err;
2429                 }
2430         /* We have to lookup by serial number because name lookup
2431          * skips revoked certs
2432          */
2433         rrow=TXT_DB_get_by_index(db,DB_serial,row);
2434         if (rrow == NULL)
2435                 {
2436                 BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]);
2437
2438                 /* We now just add it to the database */
2439                 row[DB_type]=(char *)OPENSSL_malloc(2);
2440
2441                 tm=X509_get_notAfter(x509);
2442                 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2443                 memcpy(row[DB_exp_date],tm->data,tm->length);
2444                 row[DB_exp_date][tm->length]='\0';
2445
2446                 row[DB_rev_date]=NULL;
2447
2448                 /* row[DB_serial] done already */
2449                 row[DB_file]=(char *)OPENSSL_malloc(8);
2450
2451                 /* row[DB_name] done already */
2452
2453                 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2454                         (row[DB_file] == NULL))
2455                         {
2456                         BIO_printf(bio_err,"Memory allocation failure\n");
2457                         goto err;
2458                         }
2459                 strcpy(row[DB_file],"unknown");
2460                 row[DB_type][0]='V';
2461                 row[DB_type][1]='\0';
2462
2463                 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2464                         {
2465                         BIO_printf(bio_err,"Memory allocation failure\n");
2466                         goto err;
2467                         }
2468
2469                 for (i=0; i<DB_NUMBER; i++)
2470                         {
2471                         irow[i]=row[i];
2472                         row[i]=NULL;
2473                         }
2474                 irow[DB_NUMBER]=NULL;
2475
2476                 if (!TXT_DB_insert(db,irow))
2477                         {
2478                         BIO_printf(bio_err,"failed to update database\n");
2479                         BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2480                         goto err;
2481                         }
2482
2483                 /* Revoke Certificate */
2484                 ok = do_revoke(x509,db);
2485
2486                 goto err;
2487
2488                 }
2489         else if (index_name_cmp((const char **)row,(const char **)rrow))
2490                 {
2491                 BIO_printf(bio_err,"ERROR:name does not match %s\n",
2492                            row[DB_name]);
2493                 goto err;
2494                 }
2495         else if (rrow[DB_type][0]=='R')
2496                 {
2497                 BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2498                            row[DB_serial]);
2499                 goto err;
2500                 }
2501         else
2502                 {
2503                 BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2504                 revtm = ASN1_UTCTIME_new();
2505                 revtm=X509_gmtime_adj(revtm,0);
2506                 rrow[DB_type][0]='R';
2507                 rrow[DB_type][1]='\0';
2508                 rrow[DB_rev_date]=(char *)OPENSSL_malloc(revtm->length+1);
2509                 memcpy(rrow[DB_rev_date],revtm->data,revtm->length);
2510                 rrow[DB_rev_date][revtm->length]='\0';
2511                 ASN1_UTCTIME_free(revtm);
2512                 }
2513         ok=1;
2514 err:
2515         for (i=0; i<DB_NUMBER; i++)
2516                 {
2517                 if (row[i] != NULL) 
2518                         OPENSSL_free(row[i]);
2519                 }
2520         return(ok);
2521         }
2522
2523 static int get_certificate_status(const char *serial, TXT_DB *db)
2524         {
2525         char *row[DB_NUMBER],**rrow;
2526         int ok=-1,i;
2527
2528         /* Free Resources */
2529         for (i=0; i<DB_NUMBER; i++)
2530                 row[i]=NULL;
2531
2532         /* Malloc needed char spaces */
2533         row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2534         if (row[DB_serial] == NULL)
2535                 {
2536                 BIO_printf(bio_err,"Malloc failure\n");
2537                 goto err;
2538                 }
2539
2540         if (strlen(serial) % 2)
2541                 {
2542                 /* Set the first char to 0 */;
2543                 row[DB_serial][0]='0';
2544
2545                 /* Copy String from serial to row[DB_serial] */
2546                 memcpy(row[DB_serial]+1, serial, strlen(serial));
2547                 row[DB_serial][strlen(serial)+1]='\0';
2548                 }
2549         else
2550                 {
2551                 /* Copy String from serial to row[DB_serial] */
2552                 memcpy(row[DB_serial], serial, strlen(serial));
2553                 row[DB_serial][strlen(serial)]='\0';
2554                 }
2555                         
2556         /* Make it Upper Case */
2557         for (i=0; row[DB_serial][i] != '\0'; i++)
2558                 row[DB_serial][i] = toupper(row[DB_serial][i]);
2559         
2560
2561         ok=1;
2562
2563         /* Search for the certificate */
2564         rrow=TXT_DB_get_by_index(db,DB_serial,row);
2565         if (rrow == NULL)
2566                 {
2567                 BIO_printf(bio_err,"Serial %s not present in db.\n",
2568                                  row[DB_serial]);
2569                 ok=-1;
2570                 goto err;
2571                 }
2572         else if (rrow[DB_type][0]=='V')
2573                 {
2574                 BIO_printf(bio_err,"%s=Valid (%c)\n",
2575                         row[DB_serial], rrow[DB_type][0]);
2576                 goto err;
2577                 }
2578         else if (rrow[DB_type][0]=='R')
2579                 {
2580                 BIO_printf(bio_err,"%s=Revoked (%c)\n",
2581                         row[DB_serial], rrow[DB_type][0]);
2582                 goto err;
2583                 }
2584         else if (rrow[DB_type][0]=='E')
2585                 {
2586                 BIO_printf(bio_err,"%s=Expired (%c)\n",
2587                         row[DB_serial], rrow[DB_type][0]);
2588                 goto err;
2589                 }
2590         else if (rrow[DB_type][0]=='S')
2591                 {
2592                 BIO_printf(bio_err,"%s=Suspended (%c)\n",
2593                         row[DB_serial], rrow[DB_type][0]);
2594                 goto err;
2595                 }
2596         else
2597                 {
2598                 BIO_printf(bio_err,"%s=Unknown (%c).\n",
2599                         row[DB_serial], rrow[DB_type][0]);
2600                 ok=-1;
2601                 }
2602 err:
2603         for (i=0; i<DB_NUMBER; i++)
2604                 {
2605                 if (row[i] != NULL)
2606                         OPENSSL_free(row[i]);
2607                 }
2608         return(ok);
2609         }
2610
2611 static int do_updatedb (TXT_DB *db)
2612         {
2613         ASN1_UTCTIME    *a_tm = NULL;
2614         int i, cnt = 0;
2615         int db_y2k, a_y2k;  /* flags = 1 if y >= 2000 */ 
2616         char **rrow, *a_tm_s;
2617
2618         a_tm = ASN1_UTCTIME_new();
2619
2620         /* get actual time and make a string */
2621         a_tm = X509_gmtime_adj(a_tm, 0);
2622         a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2623         if (a_tm_s == NULL)
2624                 {
2625                 cnt = -1;
2626                 goto err;
2627                 }
2628
2629         memcpy(a_tm_s, a_tm->data, a_tm->length);
2630         a_tm_s[a_tm->length] = '\0';
2631
2632         if (strncmp(a_tm_s, "49", 2) <= 0)
2633                 a_y2k = 1;
2634         else
2635                 a_y2k = 0;
2636
2637         for (i = 0; i < sk_num(db->data); i++)
2638                 {
2639                 rrow = (char **) sk_value(db->data, i);
2640
2641                 if (rrow[DB_type][0] == 'V')
2642                         {
2643                         /* ignore entries that are not valid */
2644                         if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2645                                 db_y2k = 1;
2646                         else
2647                                 db_y2k = 0;
2648
2649                         if (db_y2k == a_y2k)
2650                                 {
2651                                 /* all on the same y2k side */
2652                                 if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2653                                         {
2654                                         rrow[DB_type][0]  = 'E';
2655                                         rrow[DB_type][1]  = '\0';
2656                                         cnt++;
2657
2658                                         BIO_printf(bio_err, "%s=Expired\n",
2659                                                         rrow[DB_serial]);
2660                                         }
2661                                 }
2662                         else if (db_y2k < a_y2k)
2663                                 {
2664                                 rrow[DB_type][0]  = 'E';
2665                                 rrow[DB_type][1]  = '\0';
2666                                 cnt++;
2667
2668                                 BIO_printf(bio_err, "%s=Expired\n",
2669                                                         rrow[DB_serial]);
2670                                 }
2671
2672                         }
2673                 }
2674
2675 err:
2676
2677         ASN1_UTCTIME_free(a_tm);
2678         OPENSSL_free(a_tm_s);
2679
2680         return (cnt);
2681         }