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