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