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