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