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