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