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