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