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