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