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