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