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