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