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