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