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