From reports I've seen, it looks like TIMES is wrong for Darwin.
[oweals/openssl.git] / apps / ca.c
1 /* apps/ca.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 /* The PPKI stuff has been donated by Jeff Barber <jeffb@issl.atl.hp.com> */
60
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <sys/types.h>
65 #include <sys/stat.h>
66 #include "apps.h"
67 #include <openssl/conf.h>
68 #include <openssl/bio.h>
69 #include <openssl/err.h>
70 #include <openssl/bn.h>
71 #include <openssl/txt_db.h>
72 #include <openssl/evp.h>
73 #include <openssl/x509.h>
74 #include <openssl/x509v3.h>
75 #include <openssl/objects.h>
76 #include <openssl/pem.h>
77
78 #ifndef W_OK
79 #  ifdef VMS
80 #    if defined(__DECC)
81 #      include <unistd.h>
82 #    else
83 #      include <unixlib.h>
84 #    endif
85 #  else
86 #    include <sys/file.h>
87 #  endif
88 #endif
89
90 #ifndef W_OK
91 #  define F_OK 0
92 #  define X_OK 1
93 #  define W_OK 2
94 #  define R_OK 4
95 #endif
96
97 #undef PROG
98 #define PROG ca_main
99
100 #define BASE_SECTION    "ca"
101 #define CONFIG_FILE "openssl.cnf"
102
103 #define ENV_DEFAULT_CA          "default_ca"
104
105 #define ENV_DIR                 "dir"
106 #define ENV_CERTS               "certs"
107 #define ENV_CRL_DIR             "crl_dir"
108 #define ENV_CA_DB               "CA_DB"
109 #define ENV_NEW_CERTS_DIR       "new_certs_dir"
110 #define ENV_CERTIFICATE         "certificate"
111 #define ENV_SERIAL              "serial"
112 #define ENV_CRL                 "crl"
113 #define ENV_PRIVATE_KEY         "private_key"
114 #define ENV_RANDFILE            "RANDFILE"
115 #define ENV_DEFAULT_DAYS        "default_days"
116 #define ENV_DEFAULT_STARTDATE   "default_startdate"
117 #define ENV_DEFAULT_ENDDATE     "default_enddate"
118 #define ENV_DEFAULT_CRL_DAYS    "default_crl_days"
119 #define ENV_DEFAULT_CRL_HOURS   "default_crl_hours"
120 #define ENV_DEFAULT_MD          "default_md"
121 #define ENV_PRESERVE            "preserve"
122 #define ENV_POLICY              "policy"
123 #define ENV_EXTENSIONS          "x509_extensions"
124 #define ENV_CRLEXT              "crl_extensions"
125 #define ENV_MSIE_HACK           "msie_hack"
126
127 #define ENV_DATABASE            "database"
128
129 #define DB_type         0
130 #define DB_exp_date     1
131 #define DB_rev_date     2
132 #define DB_serial       3       /* index - unique */
133 #define DB_file         4       
134 #define DB_name         5       /* index - unique for active */
135 #define DB_NUMBER       6
136
137 #define DB_TYPE_REV     'R'
138 #define DB_TYPE_EXP     'E'
139 #define DB_TYPE_VAL     'V'
140
141 static char *ca_usage[]={
142 "usage: ca args\n",
143 "\n",
144 " -verbose        - Talk alot while doing things\n",
145 " -config file    - A config file\n",
146 " -name arg       - The particular CA definition to use\n",
147 " -gencrl         - Generate a new CRL\n",
148 " -crldays days   - Days is when the next CRL is due\n",
149 " -crlhours hours - Hours is when the next CRL is due\n",
150 " -startdate YYMMDDHHMMSSZ  - certificate validity notBefore\n",
151 " -enddate YYMMDDHHMMSSZ    - certificate validity notAfter (overrides -days)\n",
152 " -days arg       - number of days to certify the certificate for\n",
153 " -md arg         - md to use, one of md2, md5, sha or sha1\n",
154 " -policy arg     - The CA 'policy' to support\n",
155 " -keyfile arg    - PEM private key file\n",
156 " -key arg        - key to decode the private key if it is encrypted\n",
157 " -cert file      - The CA certificate\n",
158 " -in file        - The input PEM encoded certificate request(s)\n",
159 " -out file       - Where to put the output file(s)\n",
160 " -outdir dir     - Where to put output certificates\n",
161 " -infiles ....   - The last argument, requests to process\n",
162 " -spkac file     - File contains DN and signed public key and challenge\n",
163 " -ss_cert file   - File contains a self signed cert to sign\n",
164 " -preserveDN     - Don't re-order the DN\n",
165 " -batch          - Don't ask questions\n",
166 " -msie_hack      - msie modifications to handle all those universal strings\n",
167 " -revoke file    - Revoke a certificate (given in file)\n",
168 " -extensions ..  - Extension section (override value in config file)\n",
169 " -crlexts ..     - CRL extension section (override value in config file)\n",
170 NULL
171 };
172
173 #ifdef EFENCE
174 extern int EF_PROTECT_FREE;
175 extern int EF_PROTECT_BELOW;
176 extern int EF_ALIGNMENT;
177 #endif
178
179 static void lookup_fail(char *name,char *tag);
180 static unsigned long index_serial_hash(char **a);
181 static int index_serial_cmp(char **a, char **b);
182 static unsigned long index_name_hash(char **a);
183 static int index_name_qual(char **a);
184 static int index_name_cmp(char **a,char **b);
185 static BIGNUM *load_serial(char *serialfile);
186 static int save_serial(char *serialfile, BIGNUM *serial);
187 static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
188                    const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,TXT_DB *db,
189                    BIGNUM *serial, char *startdate,char *enddate, int days,
190                    int batch, char *ext_sect, LHASH *conf,int verbose);
191 static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
192                         const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
193                         TXT_DB *db, BIGNUM *serial,char *startdate,
194                         char *enddate, int days, int batch, char *ext_sect,
195                         LHASH *conf,int verbose);
196 static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
197                          const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
198                          TXT_DB *db, BIGNUM *serial,char *startdate,
199                          char *enddate, int days, char *ext_sect,LHASH *conf,
200                                 int verbose);
201 static int fix_data(int nid, int *type);
202 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
203 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
204         STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
205         char *startdate, char *enddate, int days, int batch, int verbose,
206         X509_REQ *req, char *ext_sect, LHASH *conf);
207 static int do_revoke(X509 *x509, TXT_DB *db);
208 static int check_time_format(char *str);
209 static LHASH *conf=NULL;
210 static char *section=NULL;
211
212 static int preserve=0;
213 static int msie_hack=0;
214
215 int MAIN(int, char **);
216
217 int MAIN(int argc, char **argv)
218         {
219         char *key=NULL,*passargin=NULL;
220         int total=0;
221         int total_done=0;
222         int badops=0;
223         int ret=1;
224         int req=0;
225         int verbose=0;
226         int gencrl=0;
227         int dorevoke=0;
228         long crldays=0;
229         long crlhours=0;
230         long errorline= -1;
231         char *configfile=NULL;
232         char *md=NULL;
233         char *policy=NULL;
234         char *keyfile=NULL;
235         char *certfile=NULL;
236         char *infile=NULL;
237         char *spkac_file=NULL;
238         char *ss_cert_file=NULL;
239         EVP_PKEY *pkey=NULL;
240         int output_der = 0;
241         char *outfile=NULL;
242         char *outdir=NULL;
243         char *serialfile=NULL;
244         char *extensions=NULL;
245         char *crl_ext=NULL;
246         BIGNUM *serial=NULL;
247         char *startdate=NULL;
248         char *enddate=NULL;
249         int days=0;
250         int batch=0;
251         int notext=0;
252         X509 *x509=NULL;
253         X509 *x=NULL;
254         BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
255         char *dbfile=NULL;
256         TXT_DB *db=NULL;
257         X509_CRL *crl=NULL;
258         X509_CRL_INFO *ci=NULL;
259         X509_REVOKED *r=NULL;
260         char **pp,*p,*f;
261         int i,j;
262         long l;
263         const EVP_MD *dgst=NULL;
264         STACK_OF(CONF_VALUE) *attribs=NULL;
265         STACK_OF(X509) *cert_sk=NULL;
266         BIO *hex=NULL;
267 #undef BSIZE
268 #define BSIZE 256
269         MS_STATIC char buf[3][BSIZE];
270         char *randfile=NULL;
271
272 #ifdef EFENCE
273 EF_PROTECT_FREE=1;
274 EF_PROTECT_BELOW=1;
275 EF_ALIGNMENT=0;
276 #endif
277
278         apps_startup();
279
280         conf = NULL;
281         key = NULL;
282         section = NULL;
283
284         preserve=0;
285         msie_hack=0;
286         if (bio_err == NULL)
287                 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
288                         BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
289
290         argc--;
291         argv++;
292         while (argc >= 1)
293                 {
294                 if      (strcmp(*argv,"-verbose") == 0)
295                         verbose=1;
296                 else if (strcmp(*argv,"-config") == 0)
297                         {
298                         if (--argc < 1) goto bad;
299                         configfile= *(++argv);
300                         }
301                 else if (strcmp(*argv,"-name") == 0)
302                         {
303                         if (--argc < 1) goto bad;
304                         section= *(++argv);
305                         }
306                 else if (strcmp(*argv,"-startdate") == 0)
307                         {
308                         if (--argc < 1) goto bad;
309                         startdate= *(++argv);
310                         }
311                 else if (strcmp(*argv,"-enddate") == 0)
312                         {
313                         if (--argc < 1) goto bad;
314                         enddate= *(++argv);
315                         }
316                 else if (strcmp(*argv,"-days") == 0)
317                         {
318                         if (--argc < 1) goto bad;
319                         days=atoi(*(++argv));
320                         }
321                 else if (strcmp(*argv,"-md") == 0)
322                         {
323                         if (--argc < 1) goto bad;
324                         md= *(++argv);
325                         }
326                 else if (strcmp(*argv,"-policy") == 0)
327                         {
328                         if (--argc < 1) goto bad;
329                         policy= *(++argv);
330                         }
331                 else if (strcmp(*argv,"-keyfile") == 0)
332                         {
333                         if (--argc < 1) goto bad;
334                         keyfile= *(++argv);
335                         }
336                 else if (strcmp(*argv,"-passin") == 0)
337                         {
338                         if (--argc < 1) goto bad;
339                         passargin= *(++argv);
340                         }
341                 else if (strcmp(*argv,"-key") == 0)
342                         {
343                         if (--argc < 1) goto bad;
344                         key= *(++argv);
345                         }
346                 else if (strcmp(*argv,"-cert") == 0)
347                         {
348                         if (--argc < 1) goto bad;
349                         certfile= *(++argv);
350                         }
351                 else if (strcmp(*argv,"-in") == 0)
352                         {
353                         if (--argc < 1) goto bad;
354                         infile= *(++argv);
355                         req=1;
356                         }
357                 else if (strcmp(*argv,"-out") == 0)
358                         {
359                         if (--argc < 1) goto bad;
360                         outfile= *(++argv);
361                         }
362                 else if (strcmp(*argv,"-outdir") == 0)
363                         {
364                         if (--argc < 1) goto bad;
365                         outdir= *(++argv);
366                         }
367                 else if (strcmp(*argv,"-notext") == 0)
368                         notext=1;
369                 else if (strcmp(*argv,"-batch") == 0)
370                         batch=1;
371                 else if (strcmp(*argv,"-preserveDN") == 0)
372                         preserve=1;
373                 else if (strcmp(*argv,"-gencrl") == 0)
374                         gencrl=1;
375                 else if (strcmp(*argv,"-msie_hack") == 0)
376                         msie_hack=1;
377                 else if (strcmp(*argv,"-crldays") == 0)
378                         {
379                         if (--argc < 1) goto bad;
380                         crldays= atol(*(++argv));
381                         }
382                 else if (strcmp(*argv,"-crlhours") == 0)
383                         {
384                         if (--argc < 1) goto bad;
385                         crlhours= atol(*(++argv));
386                         }
387                 else if (strcmp(*argv,"-infiles") == 0)
388                         {
389                         argc--;
390                         argv++;
391                         req=1;
392                         break;
393                         }
394                 else if (strcmp(*argv, "-ss_cert") == 0)
395                         {
396                         if (--argc < 1) goto bad;
397                         ss_cert_file = *(++argv);
398                         req=1;
399                         }
400                 else if (strcmp(*argv, "-spkac") == 0)
401                         {
402                         if (--argc < 1) goto bad;
403                         spkac_file = *(++argv);
404                         req=1;
405                         }
406                 else if (strcmp(*argv,"-revoke") == 0)
407                         {
408                         if (--argc < 1) goto bad;
409                         infile= *(++argv);
410                         dorevoke=1;
411                         }
412                 else if (strcmp(*argv,"-extensions") == 0)
413                         {
414                         if (--argc < 1) goto bad;
415                         extensions= *(++argv);
416                         }
417                 else if (strcmp(*argv,"-crlexts") == 0)
418                         {
419                         if (--argc < 1) goto bad;
420                         crl_ext= *(++argv);
421                         }
422                 else
423                         {
424 bad:
425                         BIO_printf(bio_err,"unknown option %s\n",*argv);
426                         badops=1;
427                         break;
428                         }
429                 argc--;
430                 argv++;
431                 }
432
433         if (badops)
434                 {
435                 for (pp=ca_usage; (*pp != NULL); pp++)
436                         BIO_printf(bio_err,*pp);
437                 goto err;
438                 }
439
440         ERR_load_crypto_strings();
441
442         /*****************************************************************/
443         if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
444         if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
445         if (configfile == NULL)
446                 {
447                 /* We will just use 'buf[0]' as a temporary buffer.  */
448 #ifdef VMS
449                 strncpy(buf[0],X509_get_default_cert_area(),
450                         sizeof(buf[0])-1-sizeof(CONFIG_FILE));
451 #else
452                 strncpy(buf[0],X509_get_default_cert_area(),
453                         sizeof(buf[0])-2-sizeof(CONFIG_FILE));
454                 strcat(buf[0],"/");
455 #endif
456                 strcat(buf[0],CONFIG_FILE);
457                 configfile=buf[0];
458                 }
459
460         BIO_printf(bio_err,"Using configuration from %s\n",configfile);
461         if ((conf=CONF_load(NULL,configfile,&errorline)) == NULL)
462                 {
463                 if (errorline <= 0)
464                         BIO_printf(bio_err,"error loading the config file '%s'\n",
465                                 configfile);
466                 else
467                         BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
468                                 ,errorline,configfile);
469                 goto err;
470                 }
471
472         /* Lets get the config section we are using */
473         if (section == NULL)
474                 {
475                 section=CONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
476                 if (section == NULL)
477                         {
478                         lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
479                         goto err;
480                         }
481                 }
482
483         if (conf != NULL)
484                 {
485                 p=CONF_get_string(conf,NULL,"oid_file");
486                 if (p != NULL)
487                         {
488                         BIO *oid_bio;
489
490                         oid_bio=BIO_new_file(p,"r");
491                         if (oid_bio == NULL) 
492                                 {
493                                 /*
494                                 BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
495                                 ERR_print_errors(bio_err);
496                                 */
497                                 ERR_clear_error();
498                                 }
499                         else
500                                 {
501                                 OBJ_create_objects(oid_bio);
502                                 BIO_free(oid_bio);
503                                 }
504                         }
505                 if(!add_oid_section(bio_err,conf)) 
506                         {
507                         ERR_print_errors(bio_err);
508                         goto err;
509                         }
510                 }
511
512         randfile = CONF_get_string(conf, BASE_SECTION, "RANDFILE");
513         app_RAND_load_file(randfile, bio_err, 0);
514         
515         in=BIO_new(BIO_s_file());
516         out=BIO_new(BIO_s_file());
517         Sout=BIO_new(BIO_s_file());
518         Cout=BIO_new(BIO_s_file());
519         if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL))
520                 {
521                 ERR_print_errors(bio_err);
522                 goto err;
523                 }
524
525         /*****************************************************************/
526         /* we definitely need an public key, so lets get it */
527
528         if ((keyfile == NULL) && ((keyfile=CONF_get_string(conf,
529                 section,ENV_PRIVATE_KEY)) == NULL))
530                 {
531                 lookup_fail(section,ENV_PRIVATE_KEY);
532                 goto err;
533                 }
534         if(!key && !app_passwd(bio_err, passargin, NULL, &key, NULL))
535                 {
536                 BIO_printf(bio_err,"Error getting password\n");
537                 goto err;
538                 }
539         if (BIO_read_filename(in,keyfile) <= 0)
540                 {
541                 perror(keyfile);
542                 BIO_printf(bio_err,"trying to load CA private key\n");
543                 goto err;
544                 }
545                 pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,key);
546                 if(key) memset(key,0,strlen(key));
547         if (pkey == NULL)
548                 {
549                 BIO_printf(bio_err,"unable to load CA private key\n");
550                 goto err;
551                 }
552
553         /*****************************************************************/
554         /* we need a certificate */
555         if ((certfile == NULL) && ((certfile=CONF_get_string(conf,
556                 section,ENV_CERTIFICATE)) == NULL))
557                 {
558                 lookup_fail(section,ENV_CERTIFICATE);
559                 goto err;
560                 }
561         if (BIO_read_filename(in,certfile) <= 0)
562                 {
563                 perror(certfile);
564                 BIO_printf(bio_err,"trying to load CA certificate\n");
565                 goto err;
566                 }
567         x509=PEM_read_bio_X509(in,NULL,NULL,NULL);
568         if (x509 == NULL)
569                 {
570                 BIO_printf(bio_err,"unable to load CA certificate\n");
571                 goto err;
572                 }
573
574         if (!X509_check_private_key(x509,pkey))
575                 {
576                 BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
577                 goto err;
578                 }
579
580         f=CONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
581         if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
582                 preserve=1;
583         f=CONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
584         if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
585                 msie_hack=1;
586
587         /*****************************************************************/
588         /* lookup where to write new certificates */
589         if ((outdir == NULL) && (req))
590                 {
591                 struct stat sb;
592
593                 if ((outdir=CONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
594                         == NULL)
595                         {
596                         BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
597                         goto err;
598                         }
599 #ifndef VMS /* outdir is a directory spec, but access() for VMS demands a
600                filename.  In any case, stat(), below, will catch the problem
601                if outdir is not a directory spec, and the fopen() or open()
602                will catch an error if there is no write access.
603
604                Presumably, this problem could also be solved by using the DEC
605                C routines to convert the directory syntax to Unixly, and give
606                that to access().  However, time's too short to do that just
607                now.
608             */
609                 if (access(outdir,R_OK|W_OK|X_OK) != 0)
610                         {
611                         BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
612                         perror(outdir);
613                         goto err;
614                         }
615
616                 if (stat(outdir,&sb) != 0)
617                         {
618                         BIO_printf(bio_err,"unable to stat(%s)\n",outdir);
619                         perror(outdir);
620                         goto err;
621                         }
622 #ifdef S_IFDIR
623                 if (!(sb.st_mode & S_IFDIR))
624                         {
625                         BIO_printf(bio_err,"%s need to be a directory\n",outdir);
626                         perror(outdir);
627                         goto err;
628                         }
629 #endif
630 #endif
631                 }
632
633         /*****************************************************************/
634         /* we need to load the database file */
635         if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL)
636                 {
637                 lookup_fail(section,ENV_DATABASE);
638                 goto err;
639                 }
640         if (BIO_read_filename(in,dbfile) <= 0)
641                 {
642                 perror(dbfile);
643                 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
644                 goto err;
645                 }
646         db=TXT_DB_read(in,DB_NUMBER);
647         if (db == NULL) goto err;
648
649         /* Lets check some fields */
650         for (i=0; i<sk_num(db->data); i++)
651                 {
652                 pp=(char **)sk_value(db->data,i);
653                 if ((pp[DB_type][0] != DB_TYPE_REV) &&
654                         (pp[DB_rev_date][0] != '\0'))
655                         {
656                         BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
657                         goto err;
658                         }
659                 if ((pp[DB_type][0] == DB_TYPE_REV) &&
660                         !check_time_format(pp[DB_rev_date]))
661                         {
662                         BIO_printf(bio_err,"entry %d: invalid revocation date\n",
663                                 i+1);
664                         goto err;
665                         }
666                 if (!check_time_format(pp[DB_exp_date]))
667                         {
668                         BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
669                         goto err;
670                         }
671                 p=pp[DB_serial];
672                 j=strlen(p);
673                 if ((j&1) || (j < 2))
674                         {
675                         BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
676                         goto err;
677                         }
678                 while (*p)
679                         {
680                         if (!(  ((*p >= '0') && (*p <= '9')) ||
681                                 ((*p >= 'A') && (*p <= 'F')) ||
682                                 ((*p >= 'a') && (*p <= 'f')))  )
683                                 {
684                                 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);
685                                 goto err;
686                                 }
687                         p++;
688                         }
689                 }
690         if (verbose)
691                 {
692                 BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
693 #ifdef VMS
694                 {
695                 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
696                 out = BIO_push(tmpbio, out);
697                 }
698 #endif
699                 TXT_DB_write(out,db);
700                 BIO_printf(bio_err,"%d entries loaded from the database\n",
701                         db->data->num);
702                 BIO_printf(bio_err,"generating index\n");
703                 }
704         
705         if (!TXT_DB_create_index(db,DB_serial,NULL,index_serial_hash,
706                 index_serial_cmp))
707                 {
708                 BIO_printf(bio_err,"error creating serial number index:(%ld,%ld,%ld)\n",db->error,db->arg1,db->arg2);
709                 goto err;
710                 }
711
712         if (!TXT_DB_create_index(db,DB_name,index_name_qual,index_name_hash,
713                 index_name_cmp))
714                 {
715                 BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
716                         db->error,db->arg1,db->arg2);
717                 goto err;
718                 }
719
720         /*****************************************************************/
721         if (req || gencrl)
722                 {
723                 if (outfile != NULL)
724                         {
725
726                         if (BIO_write_filename(Sout,outfile) <= 0)
727                                 {
728                                 perror(outfile);
729                                 goto err;
730                                 }
731                         }
732                 else
733                         {
734                         BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
735 #ifdef VMS
736                         {
737                         BIO *tmpbio = BIO_new(BIO_f_linebuffer());
738                         Sout = BIO_push(tmpbio, Sout);
739                         }
740 #endif
741                         }
742                 }
743
744         if (req)
745                 {
746                 if ((md == NULL) && ((md=CONF_get_string(conf,
747                         section,ENV_DEFAULT_MD)) == NULL))
748                         {
749                         lookup_fail(section,ENV_DEFAULT_MD);
750                         goto err;
751                         }
752                 if ((dgst=EVP_get_digestbyname(md)) == NULL)
753                         {
754                         BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
755                         goto err;
756                         }
757                 if (verbose)
758                         BIO_printf(bio_err,"message digest is %s\n",
759                                 OBJ_nid2ln(dgst->type));
760                 if ((policy == NULL) && ((policy=CONF_get_string(conf,
761                         section,ENV_POLICY)) == NULL))
762                         {
763                         lookup_fail(section,ENV_POLICY);
764                         goto err;
765                         }
766                 if (verbose)
767                         BIO_printf(bio_err,"policy is %s\n",policy);
768
769                 if ((serialfile=CONF_get_string(conf,section,ENV_SERIAL))
770                         == NULL)
771                         {
772                         lookup_fail(section,ENV_SERIAL);
773                         goto err;
774                         }
775                 if(!extensions)
776                         extensions=CONF_get_string(conf,section,ENV_EXTENSIONS);
777                 if(extensions) {
778                         /* Check syntax of file */
779                         X509V3_CTX ctx;
780                         X509V3_set_ctx_test(&ctx);
781                         X509V3_set_conf_lhash(&ctx, conf);
782                         if(!X509V3_EXT_add_conf(conf, &ctx, extensions, NULL)) {
783                                 BIO_printf(bio_err,
784                                  "Error Loading extension section %s\n",
785                                                                  extensions);
786                                 ret = 1;
787                                 goto err;
788                         }
789                 }
790
791                 if (startdate == NULL)
792                         {
793                         startdate=CONF_get_string(conf,section,
794                                 ENV_DEFAULT_STARTDATE);
795                         }
796                 if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
797                         {
798                         BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
799                         goto err;
800                         }
801                 if (startdate == NULL) startdate="today";
802
803                 if (enddate == NULL)
804                         {
805                         enddate=CONF_get_string(conf,section,
806                                 ENV_DEFAULT_ENDDATE);
807                         }
808                 if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
809                         {
810                         BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
811                         goto err;
812                         }
813
814                 if (days == 0)
815                         {
816                         days=(int)CONF_get_number(conf,section,
817                                 ENV_DEFAULT_DAYS);
818                         }
819                 if (!enddate && (days == 0))
820                         {
821                         BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
822                         goto err;
823                         }
824
825                 if ((serial=load_serial(serialfile)) == NULL)
826                         {
827                         BIO_printf(bio_err,"error while loading serial number\n");
828                         goto err;
829                         }
830                 if (verbose)
831                         {
832                         if ((f=BN_bn2hex(serial)) == NULL) goto err;
833                         BIO_printf(bio_err,"next serial number is %s\n",f);
834                         OPENSSL_free(f);
835                         }
836
837                 if ((attribs=CONF_get_section(conf,policy)) == NULL)
838                         {
839                         BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
840                         goto err;
841                         }
842
843                 if ((cert_sk=sk_X509_new_null()) == NULL)
844                         {
845                         BIO_printf(bio_err,"Memory allocation failure\n");
846                         goto err;
847                         }
848                 if (spkac_file != NULL)
849                         {
850                         total++;
851                         j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
852                                 serial,startdate,enddate, days,extensions,conf,
853                                 verbose);
854                         if (j < 0) goto err;
855                         if (j > 0)
856                                 {
857                                 total_done++;
858                                 BIO_printf(bio_err,"\n");
859                                 if (!BN_add_word(serial,1)) goto err;
860                                 if (!sk_X509_push(cert_sk,x))
861                                         {
862                                         BIO_printf(bio_err,"Memory allocation failure\n");
863                                         goto err;
864                                         }
865                                 if (outfile)
866                                         {
867                                         output_der = 1;
868                                         batch = 1;
869                                         }
870                                 }
871                         }
872                 if (ss_cert_file != NULL)
873                         {
874                         total++;
875                         j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
876                                 db,serial,startdate,enddate,days,batch,
877                                 extensions,conf,verbose);
878                         if (j < 0) goto err;
879                         if (j > 0)
880                                 {
881                                 total_done++;
882                                 BIO_printf(bio_err,"\n");
883                                 if (!BN_add_word(serial,1)) goto err;
884                                 if (!sk_X509_push(cert_sk,x))
885                                         {
886                                         BIO_printf(bio_err,"Memory allocation failure\n");
887                                         goto err;
888                                         }
889                                 }
890                         }
891                 if (infile != NULL)
892                         {
893                         total++;
894                         j=certify(&x,infile,pkey,x509,dgst,attribs,db,
895                                 serial,startdate,enddate,days,batch,
896                                 extensions,conf,verbose);
897                         if (j < 0) goto err;
898                         if (j > 0)
899                                 {
900                                 total_done++;
901                                 BIO_printf(bio_err,"\n");
902                                 if (!BN_add_word(serial,1)) goto err;
903                                 if (!sk_X509_push(cert_sk,x))
904                                         {
905                                         BIO_printf(bio_err,"Memory allocation failure\n");
906                                         goto err;
907                                         }
908                                 }
909                         }
910                 for (i=0; i<argc; i++)
911                         {
912                         total++;
913                         j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
914                                 serial,startdate,enddate,days,batch,
915                                 extensions,conf,verbose);
916                         if (j < 0) goto err;
917                         if (j > 0)
918                                 {
919                                 total_done++;
920                                 BIO_printf(bio_err,"\n");
921                                 if (!BN_add_word(serial,1)) goto err;
922                                 if (!sk_X509_push(cert_sk,x))
923                                         {
924                                         BIO_printf(bio_err,"Memory allocation failure\n");
925                                         goto err;
926                                         }
927                                 }
928                         }       
929                 /* we have a stack of newly certified certificates
930                  * and a data base and serial number that need
931                  * updating */
932
933                 if (sk_X509_num(cert_sk) > 0)
934                         {
935                         if (!batch)
936                                 {
937                                 BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
938                                 (void)BIO_flush(bio_err);
939                                 buf[0][0]='\0';
940                                 fgets(buf[0],10,stdin);
941                                 if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
942                                         {
943                                         BIO_printf(bio_err,"CERTIFICATION CANCELED\n"); 
944                                         ret=0;
945                                         goto err;
946                                         }
947                                 }
948
949                         BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
950
951                         strncpy(buf[0],serialfile,BSIZE-4);
952
953 #ifdef VMS
954                         strcat(buf[0],"-new");
955 #else
956                         strcat(buf[0],".new");
957 #endif
958
959                         if (!save_serial(buf[0],serial)) goto err;
960
961                         strncpy(buf[1],dbfile,BSIZE-4);
962
963 #ifdef VMS
964                         strcat(buf[1],"-new");
965 #else
966                         strcat(buf[1],".new");
967 #endif
968
969                         if (BIO_write_filename(out,buf[1]) <= 0)
970                                 {
971                                 perror(dbfile);
972                                 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
973                                 goto err;
974                                 }
975                         l=TXT_DB_write(out,db);
976                         if (l <= 0) goto err;
977                         }
978         
979                 if (verbose)
980                         BIO_printf(bio_err,"writing new certificates\n");
981                 for (i=0; i<sk_X509_num(cert_sk); i++)
982                         {
983                         int k;
984                         unsigned char *n;
985
986                         x=sk_X509_value(cert_sk,i);
987
988                         j=x->cert_info->serialNumber->length;
989                         p=(char *)x->cert_info->serialNumber->data;
990                         
991                         strncpy(buf[2],outdir,BSIZE-(j*2)-6);
992
993 #ifndef VMS
994                         strcat(buf[2],"/");
995 #endif
996
997                         n=(unsigned char *)&(buf[2][strlen(buf[2])]);
998                         if (j > 0)
999                                 {
1000                                 for (k=0; k<j; k++)
1001                                         {
1002                                         sprintf((char *)n,"%02X",(unsigned char)*(p++));
1003                                         n+=2;
1004                                         }
1005                                 }
1006                         else
1007                                 {
1008                                 *(n++)='0';
1009                                 *(n++)='0';
1010                                 }
1011                         *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
1012                         *n='\0';
1013                         if (verbose)
1014                                 BIO_printf(bio_err,"writing %s\n",buf[2]);
1015
1016                         if (BIO_write_filename(Cout,buf[2]) <= 0)
1017                                 {
1018                                 perror(buf[2]);
1019                                 goto err;
1020                                 }
1021                         write_new_certificate(Cout,x, 0, notext);
1022                         write_new_certificate(Sout,x, output_der, notext);
1023                         }
1024
1025                 if (sk_X509_num(cert_sk))
1026                         {
1027                         /* Rename the database and the serial file */
1028                         strncpy(buf[2],serialfile,BSIZE-4);
1029
1030 #ifdef VMS
1031                         strcat(buf[2],"-old");
1032 #else
1033                         strcat(buf[2],".old");
1034 #endif
1035
1036                         BIO_free(in);
1037                         BIO_free_all(out);
1038                         in=NULL;
1039                         out=NULL;
1040                         if (rename(serialfile,buf[2]) < 0)
1041                                 {
1042                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1043                                         serialfile,buf[2]);
1044                                 perror("reason");
1045                                 goto err;
1046                                 }
1047                         if (rename(buf[0],serialfile) < 0)
1048                                 {
1049                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1050                                         buf[0],serialfile);
1051                                 perror("reason");
1052                                 rename(buf[2],serialfile);
1053                                 goto err;
1054                                 }
1055
1056                         strncpy(buf[2],dbfile,BSIZE-4);
1057
1058 #ifdef VMS
1059                         strcat(buf[2],"-old");
1060 #else
1061                         strcat(buf[2],".old");
1062 #endif
1063
1064                         if (rename(dbfile,buf[2]) < 0)
1065                                 {
1066                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1067                                         dbfile,buf[2]);
1068                                 perror("reason");
1069                                 goto err;
1070                                 }
1071                         if (rename(buf[1],dbfile) < 0)
1072                                 {
1073                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1074                                         buf[1],dbfile);
1075                                 perror("reason");
1076                                 rename(buf[2],dbfile);
1077                                 goto err;
1078                                 }
1079                         BIO_printf(bio_err,"Data Base Updated\n");
1080                         }
1081                 }
1082         
1083         /*****************************************************************/
1084         if (gencrl)
1085                 {
1086                 if(!crl_ext) crl_ext=CONF_get_string(conf,section,ENV_CRLEXT);
1087                 if(crl_ext) {
1088                         /* Check syntax of file */
1089                         X509V3_CTX ctx;
1090                         X509V3_set_ctx_test(&ctx);
1091                         X509V3_set_conf_lhash(&ctx, conf);
1092                         if(!X509V3_EXT_add_conf(conf, &ctx, crl_ext, NULL)) {
1093                                 BIO_printf(bio_err,
1094                                  "Error Loading CRL extension section %s\n",
1095                                                                  crl_ext);
1096                                 ret = 1;
1097                                 goto err;
1098                         }
1099                 }
1100                 if ((hex=BIO_new(BIO_s_mem())) == NULL) goto err;
1101
1102                 if (!crldays && !crlhours)
1103                         {
1104                         crldays=CONF_get_number(conf,section,
1105                                 ENV_DEFAULT_CRL_DAYS);
1106                         crlhours=CONF_get_number(conf,section,
1107                                 ENV_DEFAULT_CRL_HOURS);
1108                         }
1109                 if ((crldays == 0) && (crlhours == 0))
1110                         {
1111                         BIO_printf(bio_err,"cannot lookup how long until the next CRL is issuer\n");
1112                         goto err;
1113                         }
1114
1115                 if (verbose) BIO_printf(bio_err,"making CRL\n");
1116                 if ((crl=X509_CRL_new()) == NULL) goto err;
1117                 ci=crl->crl;
1118                 X509_NAME_free(ci->issuer);
1119                 ci->issuer=X509_NAME_dup(x509->cert_info->subject);
1120                 if (ci->issuer == NULL) goto err;
1121
1122                 X509_gmtime_adj(ci->lastUpdate,0);
1123                 if (ci->nextUpdate == NULL)
1124                         ci->nextUpdate=ASN1_UTCTIME_new();
1125                 X509_gmtime_adj(ci->nextUpdate,(crldays*24+crlhours)*60*60);
1126
1127                 for (i=0; i<sk_num(db->data); i++)
1128                         {
1129                         pp=(char **)sk_value(db->data,i);
1130                         if (pp[DB_type][0] == DB_TYPE_REV)
1131                                 {
1132                                 if ((r=X509_REVOKED_new()) == NULL) goto err;
1133                                 ASN1_STRING_set((ASN1_STRING *)
1134                                         r->revocationDate,
1135                                         (unsigned char *)pp[DB_rev_date],
1136                                         strlen(pp[DB_rev_date]));
1137                                 /* strcpy(r->revocationDate,pp[DB_rev_date]);*/
1138
1139                                 (void)BIO_reset(hex);
1140                                 if (!BIO_puts(hex,pp[DB_serial]))
1141                                         goto err;
1142                                 if (!a2i_ASN1_INTEGER(hex,r->serialNumber,
1143                                         buf[0],BSIZE)) goto err;
1144
1145                                 sk_X509_REVOKED_push(ci->revoked,r);
1146                                 }
1147                         }
1148                 /* sort the data so it will be written in serial
1149                  * number order */
1150                 sk_X509_REVOKED_sort(ci->revoked);
1151                 for (i=0; i<sk_X509_REVOKED_num(ci->revoked); i++)
1152                         {
1153                         r=sk_X509_REVOKED_value(ci->revoked,i);
1154                         r->sequence=i;
1155                         }
1156
1157                 /* we now have a CRL */
1158                 if (verbose) BIO_printf(bio_err,"signing CRL\n");
1159                 if (md != NULL)
1160                         {
1161                         if ((dgst=EVP_get_digestbyname(md)) == NULL)
1162                                 {
1163                                 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1164                                 goto err;
1165                                 }
1166                         }
1167                 else
1168                     {
1169 #ifndef NO_DSA
1170                     if (pkey->type == EVP_PKEY_DSA) 
1171                         dgst=EVP_dss1();
1172                     else
1173 #endif
1174                         dgst=EVP_md5();
1175                     }
1176
1177                 /* Add any extensions asked for */
1178
1179                 if(crl_ext) {
1180                     X509V3_CTX crlctx;
1181                     if (ci->version == NULL)
1182                     if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
1183                     ASN1_INTEGER_set(ci->version,1); /* version 2 CRL */
1184                     X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1185                     X509V3_set_conf_lhash(&crlctx, conf);
1186
1187                     if(!X509V3_EXT_CRL_add_conf(conf, &crlctx,
1188                                                  crl_ext, crl)) goto err;
1189                 }
1190
1191                 if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1192
1193                 PEM_write_bio_X509_CRL(Sout,crl);
1194                 }
1195         /*****************************************************************/
1196         if (dorevoke)
1197                 {
1198                 if (infile == NULL) 
1199                         {
1200                         BIO_printf(bio_err,"no input files\n");
1201                         goto err;
1202                         }
1203                 else
1204                         {
1205                         X509 *revcert;
1206                         if (BIO_read_filename(in,infile) <= 0)
1207                                 {
1208                                 perror(infile);
1209                                 BIO_printf(bio_err,"error trying to load '%s' certificate\n",infile);
1210                                 goto err;
1211                                 }
1212                         revcert=PEM_read_bio_X509(in,NULL,NULL,NULL);
1213                         if (revcert == NULL)
1214                                 {
1215                                 BIO_printf(bio_err,"unable to load '%s' certificate\n",infile);
1216                                 goto err;
1217                                 }
1218                         j=do_revoke(revcert,db);
1219                         if (j <= 0) goto err;
1220                         X509_free(revcert);
1221
1222                         strncpy(buf[0],dbfile,BSIZE-4);
1223 #ifndef VMS
1224                         strcat(buf[0],".new");
1225 #else
1226                         strcat(buf[0],"-new");
1227 #endif
1228                         if (BIO_write_filename(out,buf[0]) <= 0)
1229                                 {
1230                                 perror(dbfile);
1231                                 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1232                                 goto err;
1233                                 }
1234                         j=TXT_DB_write(out,db);
1235                         if (j <= 0) goto err;
1236                         strncpy(buf[1],dbfile,BSIZE-4);
1237 #ifndef VMS
1238                         strcat(buf[1],".old");
1239 #else
1240                         strcat(buf[1],"-old");
1241 #endif
1242                         if (rename(dbfile,buf[1]) < 0)
1243                                 {
1244                                 BIO_printf(bio_err,"unable to rename %s to %s\n", dbfile, buf[1]);
1245                                 perror("reason");
1246                                 goto err;
1247                                 }
1248                         if (rename(buf[0],dbfile) < 0)
1249                                 {
1250                                 BIO_printf(bio_err,"unable to rename %s to %s\n", buf[0],dbfile);
1251                                 perror("reason");
1252                                 rename(buf[1],dbfile);
1253                                 goto err;
1254                                 }
1255                         BIO_printf(bio_err,"Data Base Updated\n"); 
1256                         }
1257                 }
1258         /*****************************************************************/
1259         ret=0;
1260 err:
1261         BIO_free(hex);
1262         BIO_free_all(Cout);
1263         BIO_free_all(Sout);
1264         BIO_free_all(out);
1265         BIO_free(in);
1266
1267         sk_X509_pop_free(cert_sk,X509_free);
1268
1269         if (ret) ERR_print_errors(bio_err);
1270         app_RAND_write_file(randfile, bio_err);
1271         BN_free(serial);
1272         TXT_DB_free(db);
1273         EVP_PKEY_free(pkey);
1274         X509_free(x509);
1275         X509_CRL_free(crl);
1276         CONF_free(conf);
1277         OBJ_cleanup();
1278         EXIT(ret);
1279         }
1280
1281 static void lookup_fail(char *name, char *tag)
1282         {
1283         BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1284         }
1285
1286 static unsigned long index_serial_hash(char **a)
1287         {
1288         char *n;
1289
1290         n=a[DB_serial];
1291         while (*n == '0') n++;
1292         return(lh_strhash(n));
1293         }
1294
1295 static int index_serial_cmp(char **a, char **b)
1296         {
1297         char *aa,*bb;
1298
1299         for (aa=a[DB_serial]; *aa == '0'; aa++);
1300         for (bb=b[DB_serial]; *bb == '0'; bb++);
1301         return(strcmp(aa,bb));
1302         }
1303
1304 static unsigned long index_name_hash(char **a)
1305         { return(lh_strhash(a[DB_name])); }
1306
1307 static int index_name_qual(char **a)
1308         { return(a[0][0] == 'V'); }
1309
1310 static int index_name_cmp(char **a, char **b)
1311         { return(strcmp(a[DB_name],
1312              b[DB_name])); }
1313
1314 static BIGNUM *load_serial(char *serialfile)
1315         {
1316         BIO *in=NULL;
1317         BIGNUM *ret=NULL;
1318         MS_STATIC char buf[1024];
1319         ASN1_INTEGER *ai=NULL;
1320
1321         if ((in=BIO_new(BIO_s_file())) == NULL)
1322                 {
1323                 ERR_print_errors(bio_err);
1324                 goto err;
1325                 }
1326
1327         if (BIO_read_filename(in,serialfile) <= 0)
1328                 {
1329                 perror(serialfile);
1330                 goto err;
1331                 }
1332         ai=ASN1_INTEGER_new();
1333         if (ai == NULL) goto err;
1334         if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
1335                 {
1336                 BIO_printf(bio_err,"unable to load number from %s\n",
1337                         serialfile);
1338                 goto err;
1339                 }
1340         ret=ASN1_INTEGER_to_BN(ai,NULL);
1341         if (ret == NULL)
1342                 {
1343                 BIO_printf(bio_err,"error converting number from bin to BIGNUM");
1344                 goto err;
1345                 }
1346 err:
1347         if (in != NULL) BIO_free(in);
1348         if (ai != NULL) ASN1_INTEGER_free(ai);
1349         return(ret);
1350         }
1351
1352 static int save_serial(char *serialfile, BIGNUM *serial)
1353         {
1354         BIO *out;
1355         int ret=0;
1356         ASN1_INTEGER *ai=NULL;
1357
1358         out=BIO_new(BIO_s_file());
1359         if (out == NULL)
1360                 {
1361                 ERR_print_errors(bio_err);
1362                 goto err;
1363                 }
1364         if (BIO_write_filename(out,serialfile) <= 0)
1365                 {
1366                 perror(serialfile);
1367                 goto err;
1368                 }
1369
1370         if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
1371                 {
1372                 BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
1373                 goto err;
1374                 }
1375         i2a_ASN1_INTEGER(out,ai);
1376         BIO_puts(out,"\n");
1377         ret=1;
1378 err:
1379         if (out != NULL) BIO_free_all(out);
1380         if (ai != NULL) ASN1_INTEGER_free(ai);
1381         return(ret);
1382         }
1383
1384 static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1385              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1386              BIGNUM *serial, char *startdate, char *enddate, int days,
1387              int batch, char *ext_sect, LHASH *lconf, int verbose)
1388         {
1389         X509_REQ *req=NULL;
1390         BIO *in=NULL;
1391         EVP_PKEY *pktmp=NULL;
1392         int ok= -1,i;
1393
1394         in=BIO_new(BIO_s_file());
1395
1396         if (BIO_read_filename(in,infile) <= 0)
1397                 {
1398                 perror(infile);
1399                 goto err;
1400                 }
1401         if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
1402                 {
1403                 BIO_printf(bio_err,"Error reading certificate request in %s\n",
1404                         infile);
1405                 goto err;
1406                 }
1407         if (verbose)
1408                 X509_REQ_print(bio_err,req);
1409
1410         BIO_printf(bio_err,"Check that the request matches the signature\n");
1411
1412         if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
1413                 {
1414                 BIO_printf(bio_err,"error unpacking public key\n");
1415                 goto err;
1416                 }
1417         i=X509_REQ_verify(req,pktmp);
1418         EVP_PKEY_free(pktmp);
1419         if (i < 0)
1420                 {
1421                 ok=0;
1422                 BIO_printf(bio_err,"Signature verification problems....\n");
1423                 goto err;
1424                 }
1425         if (i == 0)
1426                 {
1427                 ok=0;
1428                 BIO_printf(bio_err,"Signature did not match the certificate request\n");
1429                 goto err;
1430                 }
1431         else
1432                 BIO_printf(bio_err,"Signature ok\n");
1433
1434         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate, enddate,
1435                 days,batch,verbose,req,ext_sect,lconf);
1436
1437 err:
1438         if (req != NULL) X509_REQ_free(req);
1439         if (in != NULL) BIO_free(in);
1440         return(ok);
1441         }
1442
1443 static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1444              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1445              BIGNUM *serial, char *startdate, char *enddate, int days,
1446              int batch, char *ext_sect, LHASH *lconf, int verbose)
1447         {
1448         X509 *req=NULL;
1449         X509_REQ *rreq=NULL;
1450         BIO *in=NULL;
1451         EVP_PKEY *pktmp=NULL;
1452         int ok= -1,i;
1453
1454         in=BIO_new(BIO_s_file());
1455
1456         if (BIO_read_filename(in,infile) <= 0)
1457                 {
1458                 perror(infile);
1459                 goto err;
1460                 }
1461         if ((req=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
1462                 {
1463                 BIO_printf(bio_err,"Error reading self signed certificate in %s\n",infile);
1464                 goto err;
1465                 }
1466         if (verbose)
1467                 X509_print(bio_err,req);
1468
1469         BIO_printf(bio_err,"Check that the request matches the signature\n");
1470
1471         if ((pktmp=X509_get_pubkey(req)) == NULL)
1472                 {
1473                 BIO_printf(bio_err,"error unpacking public key\n");
1474                 goto err;
1475                 }
1476         i=X509_verify(req,pktmp);
1477         EVP_PKEY_free(pktmp);
1478         if (i < 0)
1479                 {
1480                 ok=0;
1481                 BIO_printf(bio_err,"Signature verification problems....\n");
1482                 goto err;
1483                 }
1484         if (i == 0)
1485                 {
1486                 ok=0;
1487                 BIO_printf(bio_err,"Signature did not match the certificate\n");
1488                 goto err;
1489                 }
1490         else
1491                 BIO_printf(bio_err,"Signature ok\n");
1492
1493         if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
1494                 goto err;
1495
1496         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,days,
1497                 batch,verbose,rreq,ext_sect,lconf);
1498
1499 err:
1500         if (rreq != NULL) X509_REQ_free(rreq);
1501         if (req != NULL) X509_free(req);
1502         if (in != NULL) BIO_free(in);
1503         return(ok);
1504         }
1505
1506 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1507              STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
1508              char *startdate, char *enddate, int days, int batch, int verbose,
1509              X509_REQ *req, char *ext_sect, LHASH *lconf)
1510         {
1511         X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
1512         ASN1_UTCTIME *tm,*tmptm;
1513         ASN1_STRING *str,*str2;
1514         ASN1_OBJECT *obj;
1515         X509 *ret=NULL;
1516         X509_CINF *ci;
1517         X509_NAME_ENTRY *ne;
1518         X509_NAME_ENTRY *tne,*push;
1519         EVP_PKEY *pktmp;
1520         int ok= -1,i,j,last,nid;
1521         char *p;
1522         CONF_VALUE *cv;
1523         char *row[DB_NUMBER],**rrow,**irow=NULL;
1524         char buf[25],*pbuf;
1525
1526         tmptm=ASN1_UTCTIME_new();
1527         if (tmptm == NULL)
1528                 {
1529                 BIO_printf(bio_err,"malloc error\n");
1530                 return(0);
1531                 }
1532
1533         for (i=0; i<DB_NUMBER; i++)
1534                 row[i]=NULL;
1535
1536         BIO_printf(bio_err,"The Subjects Distinguished Name is as follows\n");
1537         name=X509_REQ_get_subject_name(req);
1538         for (i=0; i<X509_NAME_entry_count(name); i++)
1539                 {
1540                 ne=(X509_NAME_ENTRY *)X509_NAME_get_entry(name,i);
1541                 obj=X509_NAME_ENTRY_get_object(ne);
1542                 j=i2a_ASN1_OBJECT(bio_err,obj);
1543                 str=X509_NAME_ENTRY_get_data(ne);
1544                 pbuf=buf;
1545                 for (j=22-j; j>0; j--)
1546                         *(pbuf++)=' ';
1547                 *(pbuf++)=':';
1548                 *(pbuf++)='\0';
1549                 BIO_puts(bio_err,buf);
1550
1551                 if (msie_hack)
1552                         {
1553                         /* assume all type should be strings */
1554                         nid=OBJ_obj2nid(ne->object);
1555
1556                         if (str->type == V_ASN1_UNIVERSALSTRING)
1557                                 ASN1_UNIVERSALSTRING_to_string(str);
1558
1559                         if ((str->type == V_ASN1_IA5STRING) &&
1560                                 (nid != NID_pkcs9_emailAddress))
1561                                 str->type=V_ASN1_T61STRING;
1562
1563                         if ((nid == NID_pkcs9_emailAddress) &&
1564                                 (str->type == V_ASN1_PRINTABLESTRING))
1565                                 str->type=V_ASN1_IA5STRING;
1566                         }
1567
1568                 if (str->type == V_ASN1_PRINTABLESTRING)
1569                         BIO_printf(bio_err,"PRINTABLE:'");
1570                 else if (str->type == V_ASN1_T61STRING)
1571                         BIO_printf(bio_err,"T61STRING:'");
1572                 else if (str->type == V_ASN1_IA5STRING)
1573                         BIO_printf(bio_err,"IA5STRING:'");
1574                 else if (str->type == V_ASN1_UNIVERSALSTRING)
1575                         BIO_printf(bio_err,"UNIVERSALSTRING:'");
1576                 else
1577                         BIO_printf(bio_err,"ASN.1 %2d:'",str->type);
1578
1579                 /* check some things */
1580                 if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1581                         (str->type != V_ASN1_IA5STRING))
1582                         {
1583                         BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
1584                         goto err;
1585                         }
1586                 j=ASN1_PRINTABLE_type(str->data,str->length);
1587                 if (    ((j == V_ASN1_T61STRING) &&
1588                          (str->type != V_ASN1_T61STRING)) ||
1589                         ((j == V_ASN1_IA5STRING) &&
1590                          (str->type == V_ASN1_PRINTABLESTRING)))
1591                         {
1592                         BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1593                         goto err;
1594                         }
1595                         
1596                 p=(char *)str->data;
1597                 for (j=str->length; j>0; j--)
1598                         {
1599                         if ((*p >= ' ') && (*p <= '~'))
1600                                 BIO_printf(bio_err,"%c",*p);
1601                         else if (*p & 0x80)
1602                                 BIO_printf(bio_err,"\\0x%02X",*p);
1603                         else if ((unsigned char)*p == 0xf7)
1604                                 BIO_printf(bio_err,"^?");
1605                         else    BIO_printf(bio_err,"^%c",*p+'@');
1606                         p++;
1607                         }
1608                 BIO_printf(bio_err,"'\n");
1609                 }
1610
1611         /* Ok, now we check the 'policy' stuff. */
1612         if ((subject=X509_NAME_new()) == NULL)
1613                 {
1614                 BIO_printf(bio_err,"Memory allocation failure\n");
1615                 goto err;
1616                 }
1617
1618         /* take a copy of the issuer name before we mess with it. */
1619         CAname=X509_NAME_dup(x509->cert_info->subject);
1620         if (CAname == NULL) goto err;
1621         str=str2=NULL;
1622
1623         for (i=0; i<sk_CONF_VALUE_num(policy); i++)
1624                 {
1625                 cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
1626                 if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
1627                         {
1628                         BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
1629                         goto err;
1630                         }
1631                 obj=OBJ_nid2obj(j);
1632
1633                 last= -1;
1634                 for (;;)
1635                         {
1636                         /* lookup the object in the supplied name list */
1637                         j=X509_NAME_get_index_by_OBJ(name,obj,last);
1638                         if (j < 0)
1639                                 {
1640                                 if (last != -1) break;
1641                                 tne=NULL;
1642                                 }
1643                         else
1644                                 {
1645                                 tne=X509_NAME_get_entry(name,j);
1646                                 }
1647                         last=j;
1648
1649                         /* depending on the 'policy', decide what to do. */
1650                         push=NULL;
1651                         if (strcmp(cv->value,"optional") == 0)
1652                                 {
1653                                 if (tne != NULL)
1654                                         push=tne;
1655                                 }
1656                         else if (strcmp(cv->value,"supplied") == 0)
1657                                 {
1658                                 if (tne == NULL)
1659                                         {
1660                                         BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
1661                                         goto err;
1662                                         }
1663                                 else
1664                                         push=tne;
1665                                 }
1666                         else if (strcmp(cv->value,"match") == 0)
1667                                 {
1668                                 int last2;
1669
1670                                 if (tne == NULL)
1671                                         {
1672                                         BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
1673                                         goto err;
1674                                         }
1675
1676                                 last2= -1;
1677
1678 again2:
1679                                 j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
1680                                 if ((j < 0) && (last2 == -1))
1681                                         {
1682                                         BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
1683                                         goto err;
1684                                         }
1685                                 if (j >= 0)
1686                                         {
1687                                         push=X509_NAME_get_entry(CAname,j);
1688                                         str=X509_NAME_ENTRY_get_data(tne);
1689                                         str2=X509_NAME_ENTRY_get_data(push);
1690                                         last2=j;
1691                                         if (ASN1_STRING_cmp(str,str2) != 0)
1692                                                 goto again2;
1693                                         }
1694                                 if (j < 0)
1695                                         {
1696                                         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));
1697                                         goto err;
1698                                         }
1699                                 }
1700                         else
1701                                 {
1702                                 BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
1703                                 goto err;
1704                                 }
1705
1706                         if (push != NULL)
1707                                 {
1708                                 if (!X509_NAME_add_entry(subject,push, -1, 0))
1709                                         {
1710                                         if (push != NULL)
1711                                                 X509_NAME_ENTRY_free(push);
1712                                         BIO_printf(bio_err,"Memory allocation failure\n");
1713                                         goto err;
1714                                         }
1715                                 }
1716                         if (j < 0) break;
1717                         }
1718                 }
1719
1720         if (preserve)
1721                 {
1722                 X509_NAME_free(subject);
1723                 subject=X509_NAME_dup(X509_REQ_get_subject_name(req));
1724                 if (subject == NULL) goto err;
1725                 }
1726
1727         if (verbose)
1728                 BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
1729
1730         row[DB_name]=X509_NAME_oneline(subject,NULL,0);
1731         row[DB_serial]=BN_bn2hex(serial);
1732         if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
1733                 {
1734                 BIO_printf(bio_err,"Memory allocation failure\n");
1735                 goto err;
1736                 }
1737
1738         rrow=TXT_DB_get_by_index(db,DB_name,row);
1739         if (rrow != NULL)
1740                 {
1741                 BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n",
1742                         row[DB_name]);
1743                 }
1744         else
1745                 {
1746                 rrow=TXT_DB_get_by_index(db,DB_serial,row);
1747                 if (rrow != NULL)
1748                         {
1749                         BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
1750                                 row[DB_serial]);
1751                         BIO_printf(bio_err,"      check the database/serial_file for corruption\n");
1752                         }
1753                 }
1754
1755         if (rrow != NULL)
1756                 {
1757                 BIO_printf(bio_err,
1758                         "The matching entry has the following details\n");
1759                 if (rrow[DB_type][0] == 'E')
1760                         p="Expired";
1761                 else if (rrow[DB_type][0] == 'R')
1762                         p="Revoked";
1763                 else if (rrow[DB_type][0] == 'V')
1764                         p="Valid";
1765                 else
1766                         p="\ninvalid type, Data base error\n";
1767                 BIO_printf(bio_err,"Type          :%s\n",p);;
1768                 if (rrow[DB_type][0] == 'R')
1769                         {
1770                         p=rrow[DB_exp_date]; if (p == NULL) p="undef";
1771                         BIO_printf(bio_err,"Was revoked on:%s\n",p);
1772                         }
1773                 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
1774                 BIO_printf(bio_err,"Expires on    :%s\n",p);
1775                 p=rrow[DB_serial]; if (p == NULL) p="undef";
1776                 BIO_printf(bio_err,"Serial Number :%s\n",p);
1777                 p=rrow[DB_file]; if (p == NULL) p="undef";
1778                 BIO_printf(bio_err,"File name     :%s\n",p);
1779                 p=rrow[DB_name]; if (p == NULL) p="undef";
1780                 BIO_printf(bio_err,"Subject Name  :%s\n",p);
1781                 ok= -1; /* This is now a 'bad' error. */
1782                 goto err;
1783                 }
1784
1785         /* We are now totally happy, lets make and sign the certificate */
1786         if (verbose)
1787                 BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
1788
1789         if ((ret=X509_new()) == NULL) goto err;
1790         ci=ret->cert_info;
1791
1792 #ifdef X509_V3
1793         /* Make it an X509 v3 certificate. */
1794         if (!X509_set_version(x509,2)) goto err;
1795 #endif
1796
1797         if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
1798                 goto err;
1799         if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
1800                 goto err;
1801
1802         BIO_printf(bio_err,"Certificate is to be certified until ");
1803         if (strcmp(startdate,"today") == 0)
1804                 X509_gmtime_adj(X509_get_notBefore(ret),0);
1805         else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
1806
1807         if (enddate == NULL)
1808                 X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
1809         else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
1810
1811         ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
1812         if(days) BIO_printf(bio_err," (%d days)",days);
1813         BIO_printf(bio_err, "\n");
1814
1815         if (!X509_set_subject_name(ret,subject)) goto err;
1816
1817         pktmp=X509_REQ_get_pubkey(req);
1818         i = X509_set_pubkey(ret,pktmp);
1819         EVP_PKEY_free(pktmp);
1820         if (!i) goto err;
1821
1822         /* Lets add the extensions, if there are any */
1823         if (ext_sect)
1824                 {
1825                 X509V3_CTX ctx;
1826                 if (ci->version == NULL)
1827                         if ((ci->version=ASN1_INTEGER_new()) == NULL)
1828                                 goto err;
1829                 ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
1830
1831                 /* Free the current entries if any, there should not
1832                  * be any I believe */
1833                 if (ci->extensions != NULL)
1834                         sk_X509_EXTENSION_pop_free(ci->extensions,
1835                                                    X509_EXTENSION_free);
1836
1837                 ci->extensions = NULL;
1838
1839                 X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
1840                 X509V3_set_conf_lhash(&ctx, lconf);
1841
1842                 if(!X509V3_EXT_add_conf(lconf, &ctx, ext_sect, ret)) goto err;
1843
1844                 }
1845
1846
1847         if (!batch)
1848                 {
1849                 BIO_printf(bio_err,"Sign the certificate? [y/n]:");
1850                 (void)BIO_flush(bio_err);
1851                 buf[0]='\0';
1852                 fgets(buf,sizeof(buf)-1,stdin);
1853                 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
1854                         {
1855                         BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
1856                         ok=0;
1857                         goto err;
1858                         }
1859                 }
1860
1861
1862 #ifndef NO_DSA
1863         if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
1864         pktmp=X509_get_pubkey(ret);
1865         if (EVP_PKEY_missing_parameters(pktmp) &&
1866                 !EVP_PKEY_missing_parameters(pkey))
1867                 EVP_PKEY_copy_parameters(pktmp,pkey);
1868         EVP_PKEY_free(pktmp);
1869 #endif
1870
1871         if (!X509_sign(ret,pkey,dgst))
1872                 goto err;
1873
1874         /* We now just add it to the database */
1875         row[DB_type]=(char *)OPENSSL_malloc(2);
1876
1877         tm=X509_get_notAfter(ret);
1878         row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
1879         memcpy(row[DB_exp_date],tm->data,tm->length);
1880         row[DB_exp_date][tm->length]='\0';
1881
1882         row[DB_rev_date]=NULL;
1883
1884         /* row[DB_serial] done already */
1885         row[DB_file]=(char *)OPENSSL_malloc(8);
1886         /* row[DB_name] done already */
1887
1888         if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
1889                 (row[DB_file] == NULL))
1890                 {
1891                 BIO_printf(bio_err,"Memory allocation failure\n");
1892                 goto err;
1893                 }
1894         strcpy(row[DB_file],"unknown");
1895         row[DB_type][0]='V';
1896         row[DB_type][1]='\0';
1897
1898         if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
1899                 {
1900                 BIO_printf(bio_err,"Memory allocation failure\n");
1901                 goto err;
1902                 }
1903
1904         for (i=0; i<DB_NUMBER; i++)
1905                 {
1906                 irow[i]=row[i];
1907                 row[i]=NULL;
1908                 }
1909         irow[DB_NUMBER]=NULL;
1910
1911         if (!TXT_DB_insert(db,irow))
1912                 {
1913                 BIO_printf(bio_err,"failed to update database\n");
1914                 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
1915                 goto err;
1916                 }
1917         ok=1;
1918 err:
1919         for (i=0; i<DB_NUMBER; i++)
1920                 if (row[i] != NULL) OPENSSL_free(row[i]);
1921
1922         if (CAname != NULL)
1923                 X509_NAME_free(CAname);
1924         if (subject != NULL)
1925                 X509_NAME_free(subject);
1926         if (tmptm != NULL)
1927                 ASN1_UTCTIME_free(tmptm);
1928         if (ok <= 0)
1929                 {
1930                 if (ret != NULL) X509_free(ret);
1931                 ret=NULL;
1932                 }
1933         else
1934                 *xret=ret;
1935         return(ok);
1936         }
1937
1938 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
1939         {
1940
1941         if (output_der)
1942                 {
1943                 (void)i2d_X509_bio(bp,x);
1944                 return;
1945                 }
1946 #if 0
1947         /* ??? Not needed since X509_print prints all this stuff anyway */
1948         f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
1949         BIO_printf(bp,"issuer :%s\n",f);
1950
1951         f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
1952         BIO_printf(bp,"subject:%s\n",f);
1953
1954         BIO_puts(bp,"serial :");
1955         i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
1956         BIO_puts(bp,"\n\n");
1957 #endif
1958         if(!notext)X509_print(bp,x);
1959         PEM_write_bio_X509(bp,x);
1960         }
1961
1962 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1963              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1964              BIGNUM *serial, char *startdate, char *enddate, int days,
1965              char *ext_sect, LHASH *lconf, int verbose)
1966         {
1967         STACK_OF(CONF_VALUE) *sk=NULL;
1968         LHASH *parms=NULL;
1969         X509_REQ *req=NULL;
1970         CONF_VALUE *cv=NULL;
1971         NETSCAPE_SPKI *spki = NULL;
1972         X509_REQ_INFO *ri;
1973         char *type,*buf;
1974         EVP_PKEY *pktmp=NULL;
1975         X509_NAME *n=NULL;
1976         X509_NAME_ENTRY *ne=NULL;
1977         int ok= -1,i,j;
1978         long errline;
1979         int nid;
1980
1981         /*
1982          * Load input file into a hash table.  (This is just an easy
1983          * way to read and parse the file, then put it into a convenient
1984          * STACK format).
1985          */
1986         parms=CONF_load(NULL,infile,&errline);
1987         if (parms == NULL)
1988                 {
1989                 BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
1990                 ERR_print_errors(bio_err);
1991                 goto err;
1992                 }
1993
1994         sk=CONF_get_section(parms, "default");
1995         if (sk_CONF_VALUE_num(sk) == 0)
1996                 {
1997                 BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
1998                 CONF_free(parms);
1999                 goto err;
2000                 }
2001
2002         /*
2003          * Now create a dummy X509 request structure.  We don't actually
2004          * have an X509 request, but we have many of the components
2005          * (a public key, various DN components).  The idea is that we
2006          * put these components into the right X509 request structure
2007          * and we can use the same code as if you had a real X509 request.
2008          */
2009         req=X509_REQ_new();
2010         if (req == NULL)
2011                 {
2012                 ERR_print_errors(bio_err);
2013                 goto err;
2014                 }
2015
2016         /*
2017          * Build up the subject name set.
2018          */
2019         ri=req->req_info;
2020         n = ri->subject;
2021
2022         for (i = 0; ; i++)
2023                 {
2024                 if (sk_CONF_VALUE_num(sk) <= i) break;
2025
2026                 cv=sk_CONF_VALUE_value(sk,i);
2027                 type=cv->name;
2028                 /* Skip past any leading X. X: X, etc to allow for
2029                  * multiple instances
2030                  */
2031                 for(buf = cv->name; *buf ; buf++)
2032                         if ((*buf == ':') || (*buf == ',') || (*buf == '.')) {
2033                                         buf++;
2034                                         if(*buf) type = buf;
2035                                         break;
2036                 }
2037
2038                 buf=cv->value;
2039                 if ((nid=OBJ_txt2nid(type)) == NID_undef)
2040                         {
2041                         if (strcmp(type, "SPKAC") == 0)
2042                                 {
2043                                 spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2044                                 if (spki == NULL)
2045                                         {
2046                                         BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2047                                         ERR_print_errors(bio_err);
2048                                         goto err;
2049                                         }
2050                                 }
2051                         continue;
2052                         }
2053
2054                 j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
2055                 if (fix_data(nid, &j) == 0)
2056                         {
2057                         BIO_printf(bio_err,
2058                                 "invalid characters in string %s\n",buf);
2059                         goto err;
2060                         }
2061
2062                 if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
2063                         (unsigned char *)buf,
2064                         strlen(buf))) == NULL)
2065                         goto err;
2066
2067                 if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
2068                 }
2069         if (spki == NULL)
2070                 {
2071                 BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2072                         infile);
2073                 goto err;
2074                 }
2075
2076         /*
2077          * Now extract the key from the SPKI structure.
2078          */
2079
2080         BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2081
2082         if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
2083                 {
2084                 BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2085                 goto err;
2086                 }
2087
2088         j = NETSCAPE_SPKI_verify(spki, pktmp);
2089         if (j <= 0)
2090                 {
2091                 BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2092                 goto err;
2093                 }
2094         BIO_printf(bio_err,"Signature ok\n");
2095
2096         X509_REQ_set_pubkey(req,pktmp);
2097         EVP_PKEY_free(pktmp);
2098         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,
2099                    days,1,verbose,req,ext_sect,lconf);
2100 err:
2101         if (req != NULL) X509_REQ_free(req);
2102         if (parms != NULL) CONF_free(parms);
2103         if (spki != NULL) NETSCAPE_SPKI_free(spki);
2104         if (ne != NULL) X509_NAME_ENTRY_free(ne);
2105
2106         return(ok);
2107         }
2108
2109 static int fix_data(int nid, int *type)
2110         {
2111         if (nid == NID_pkcs9_emailAddress)
2112                 *type=V_ASN1_IA5STRING;
2113         if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
2114                 *type=V_ASN1_T61STRING;
2115         if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
2116                 *type=V_ASN1_T61STRING;
2117         if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
2118                 return(0);
2119         if (nid == NID_pkcs9_unstructuredName)
2120                 *type=V_ASN1_IA5STRING;
2121         return(1);
2122         }
2123
2124 static int check_time_format(char *str)
2125         {
2126         ASN1_UTCTIME tm;
2127
2128         tm.data=(unsigned char *)str;
2129         tm.length=strlen(str);
2130         tm.type=V_ASN1_UTCTIME;
2131         return(ASN1_UTCTIME_check(&tm));
2132         }
2133
2134 static int do_revoke(X509 *x509, TXT_DB *db)
2135 {
2136         ASN1_UTCTIME *tm=NULL, *revtm=NULL;
2137         char *row[DB_NUMBER],**rrow,**irow;
2138         BIGNUM *bn = NULL;
2139         int ok=-1,i;
2140
2141         for (i=0; i<DB_NUMBER; i++)
2142                 row[i]=NULL;
2143         row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2144         bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2145         row[DB_serial]=BN_bn2hex(bn);
2146         BN_free(bn);
2147         if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2148                 {
2149                 BIO_printf(bio_err,"Memory allocation failure\n");
2150                 goto err;
2151                 }
2152         /* We have to lookup by serial number because name lookup
2153          * skips revoked certs
2154          */
2155         rrow=TXT_DB_get_by_index(db,DB_serial,row);
2156         if (rrow == NULL)
2157                 {
2158                 BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]);
2159
2160                 /* We now just add it to the database */
2161                 row[DB_type]=(char *)OPENSSL_malloc(2);
2162
2163                 tm=X509_get_notAfter(x509);
2164                 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2165                 memcpy(row[DB_exp_date],tm->data,tm->length);
2166                 row[DB_exp_date][tm->length]='\0';
2167
2168                 row[DB_rev_date]=NULL;
2169
2170                 /* row[DB_serial] done already */
2171                 row[DB_file]=(char *)OPENSSL_malloc(8);
2172
2173                 /* row[DB_name] done already */
2174
2175                 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2176                         (row[DB_file] == NULL))
2177                         {
2178                         BIO_printf(bio_err,"Memory allocation failure\n");
2179                         goto err;
2180                         }
2181                 strcpy(row[DB_file],"unknown");
2182                 row[DB_type][0]='V';
2183                 row[DB_type][1]='\0';
2184
2185                 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2186                         {
2187                         BIO_printf(bio_err,"Memory allocation failure\n");
2188                         goto err;
2189                         }
2190
2191                 for (i=0; i<DB_NUMBER; i++)
2192                         {
2193                         irow[i]=row[i];
2194                         row[i]=NULL;
2195                         }
2196                 irow[DB_NUMBER]=NULL;
2197
2198                 if (!TXT_DB_insert(db,irow))
2199                         {
2200                         BIO_printf(bio_err,"failed to update database\n");
2201                         BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2202                         goto err;
2203                         }
2204
2205                 /* Revoke Certificate */
2206                 ok = do_revoke(x509,db);
2207
2208                 goto err;
2209
2210                 }
2211         else if (index_name_cmp(row,rrow))
2212                 {
2213                 BIO_printf(bio_err,"ERROR:name does not match %s\n",
2214                            row[DB_name]);
2215                 goto err;
2216                 }
2217         else if (rrow[DB_type][0]=='R')
2218                 {
2219                 BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2220                            row[DB_serial]);
2221                 goto err;
2222                 }
2223         else
2224                 {
2225                 BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2226                 revtm = ASN1_UTCTIME_new();
2227                 revtm=X509_gmtime_adj(revtm,0);
2228                 rrow[DB_type][0]='R';
2229                 rrow[DB_type][1]='\0';
2230                 rrow[DB_rev_date]=(char *)OPENSSL_malloc(revtm->length+1);
2231                 memcpy(rrow[DB_rev_date],revtm->data,revtm->length);
2232                 rrow[DB_rev_date][revtm->length]='\0';
2233                 ASN1_UTCTIME_free(revtm);
2234                 }
2235         ok=1;
2236 err:
2237         for (i=0; i<DB_NUMBER; i++)
2238                 {
2239                 if (row[i] != NULL) 
2240                         OPENSSL_free(row[i]);
2241                 }
2242         return(ok);
2243 }
2244