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