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