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