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