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