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