7bee4b625bdd7fd5b7b55ac2a33d2beb15829c6c
[openssl.git] / apps / ca.c
1 /* apps/ca.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 /* The PPKI stuff has been donated by Jeff Barber <jeffb@issl.atl.hp.com> */
60
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <ctype.h>
65 #include <sys/types.h>
66 #include <sys/stat.h>
67 #include "apps.h"
68 #include <openssl/conf.h>
69 #include <openssl/bio.h>
70 #include <openssl/err.h>
71 #include <openssl/bn.h>
72 #include <openssl/txt_db.h>
73 #include <openssl/evp.h>
74 #include <openssl/x509.h>
75 #include <openssl/x509v3.h>
76 #include <openssl/objects.h>
77 #include <openssl/ocsp.h>
78 #include <openssl/pem.h>
79 #include <openssl/engine.h>
80
81 #ifdef OPENSSL_SYS_WINDOWS
82 #define strcasecmp _stricmp
83 #else
84 #include <strings.h>
85 #endif
86
87 #ifndef W_OK
88 #  ifdef OPENSSL_SYS_VMS
89 #    if defined(__DECC)
90 #      include <unistd.h>
91 #    else
92 #      include <unixlib.h>
93 #    endif
94 #  else
95 #    include <sys/file.h>
96 #  endif
97 #endif
98
99 #ifndef W_OK
100 #  define F_OK 0
101 #  define X_OK 1
102 #  define W_OK 2
103 #  define R_OK 4
104 #endif
105
106 #undef PROG
107 #define PROG ca_main
108
109 #define BASE_SECTION    "ca"
110 #define CONFIG_FILE "openssl.cnf"
111
112 #define ENV_DEFAULT_CA          "default_ca"
113
114 #define ENV_DIR                 "dir"
115 #define ENV_CERTS               "certs"
116 #define ENV_CRL_DIR             "crl_dir"
117 #define ENV_CA_DB               "CA_DB"
118 #define ENV_NEW_CERTS_DIR       "new_certs_dir"
119 #define ENV_CERTIFICATE         "certificate"
120 #define ENV_SERIAL              "serial"
121 #define ENV_CRL                 "crl"
122 #define ENV_PRIVATE_KEY         "private_key"
123 #define ENV_RANDFILE            "RANDFILE"
124 #define ENV_DEFAULT_DAYS        "default_days"
125 #define ENV_DEFAULT_STARTDATE   "default_startdate"
126 #define ENV_DEFAULT_ENDDATE     "default_enddate"
127 #define ENV_DEFAULT_CRL_DAYS    "default_crl_days"
128 #define ENV_DEFAULT_CRL_HOURS   "default_crl_hours"
129 #define ENV_DEFAULT_MD          "default_md"
130 #define ENV_PRESERVE            "preserve"
131 #define ENV_POLICY              "policy"
132 #define ENV_EXTENSIONS          "x509_extensions"
133 #define ENV_CRLEXT              "crl_extensions"
134 #define ENV_MSIE_HACK           "msie_hack"
135 #define ENV_NAMEOPT             "name_opt"
136 #define ENV_CERTOPT             "cert_opt"
137 #define ENV_EXTCOPY             "copy_extensions"
138
139 #define ENV_DATABASE            "database"
140
141 #define DB_type         0
142 #define DB_exp_date     1
143 #define DB_rev_date     2
144 #define DB_serial       3       /* index - unique */
145 #define DB_file         4       
146 #define DB_name         5       /* index - unique for active */
147 #define DB_NUMBER       6
148
149 #define DB_TYPE_REV     'R'
150 #define DB_TYPE_EXP     'E'
151 #define DB_TYPE_VAL     'V'
152
153 /* Additional revocation information types */
154
155 #define REV_NONE                0       /* No addditional information */
156 #define REV_CRL_REASON          1       /* Value is CRL reason code */
157 #define REV_HOLD                2       /* Value is hold instruction */
158 #define REV_KEY_COMPROMISE      3       /* Value is cert key compromise time */
159 #define REV_CA_COMPROMISE       4       /* Value is CA key compromise time */
160
161 static char *ca_usage[]={
162 "usage: ca args\n",
163 "\n",
164 " -verbose        - Talk alot while doing things\n",
165 " -config file    - A config file\n",
166 " -name arg       - The particular CA definition to use\n",
167 " -gencrl         - Generate a new CRL\n",
168 " -crldays days   - Days is when the next CRL is due\n",
169 " -crlhours hours - Hours is when the next CRL is due\n",
170 " -startdate YYMMDDHHMMSSZ  - certificate validity notBefore\n",
171 " -enddate YYMMDDHHMMSSZ    - certificate validity notAfter (overrides -days)\n",
172 " -days arg       - number of days to certify the certificate for\n",
173 " -md arg         - md to use, one of md2, md5, sha or sha1\n",
174 " -policy arg     - The CA 'policy' to support\n",
175 " -keyfile arg    - private key file\n",
176 " -keyform arg    - private key file format (PEM or ENGINE)\n",
177 " -key arg        - key to decode the private key if it is encrypted\n",
178 " -cert file      - The CA certificate\n",
179 " -in file        - The input PEM encoded certificate request(s)\n",
180 " -out file       - Where to put the output file(s)\n",
181 " -outdir dir     - Where to put output certificates\n",
182 " -infiles ....   - The last argument, requests to process\n",
183 " -spkac file     - File contains DN and signed public key and challenge\n",
184 " -ss_cert file   - File contains a self signed cert to sign\n",
185 " -preserveDN     - Don't re-order the DN\n",
186 " -batch          - Don't ask questions\n",
187 " -msie_hack      - msie modifications to handle all those universal strings\n",
188 " -revoke file    - Revoke a certificate (given in file)\n",
189 " -subj arg       - Use arg instead of request's subject\n",
190 " -extensions ..  - Extension section (override value in config file)\n",
191 " -extfile file   - Configuration file with X509v3 extentions to add\n",
192 " -crlexts ..     - CRL extension section (override value in config file)\n",
193 " -engine e       - use engine e, possibly a hardware device.\n",
194 " -status serial  - Shows certificate status given the serial number\n",
195 " -updatedb       - Updates db for expired certificates\n",
196 NULL
197 };
198
199 #ifdef EFENCE
200 extern int EF_PROTECT_FREE;
201 extern int EF_PROTECT_BELOW;
202 extern int EF_ALIGNMENT;
203 #endif
204
205 static void lookup_fail(char *name,char *tag);
206 static unsigned long index_serial_hash(const char **a);
207 static int index_serial_cmp(const char **a, const char **b);
208 static unsigned long index_name_hash(const char **a);
209 static int index_name_qual(char **a);
210 static int index_name_cmp(const char **a,const char **b);
211 static BIGNUM *load_serial(char *serialfile);
212 static int save_serial(char *serialfile, BIGNUM *serial);
213 static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
214                    const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,TXT_DB *db,
215                    BIGNUM *serial, char *subj, char *startdate,char *enddate,
216                    long days, int batch, char *ext_sect, CONF *conf,int verbose,
217                    unsigned long certopt, unsigned long nameopt, int default_op,
218                    int ext_copy);
219 static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
220                         const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
221                         TXT_DB *db, BIGNUM *serial, char *subj, char *startdate,
222                         char *enddate, long days, int batch, char *ext_sect,
223                         CONF *conf,int verbose, unsigned long certopt,
224                         unsigned long nameopt, int default_op, int ext_copy,
225                         ENGINE *e);
226 static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
227                          const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
228                          TXT_DB *db, BIGNUM *serial,char *subj, char *startdate,
229                          char *enddate, long days, char *ext_sect,CONF *conf,
230                          int verbose, unsigned long certopt, unsigned long nameopt,
231                          int default_op, int ext_copy);
232 static int fix_data(int nid, int *type);
233 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
234 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
235         STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,char *subj,
236         char *startdate, char *enddate, long days, int batch, int verbose,
237         X509_REQ *req, char *ext_sect, CONF *conf,
238         unsigned long certopt, unsigned long nameopt, int default_op,
239         int ext_copy);
240 static X509_NAME *do_subject(char *subject);
241 static int do_revoke(X509 *x509, TXT_DB *db, int ext, char *extval);
242 static int get_certificate_status(const char *ser_status, TXT_DB *db);
243 static int do_updatedb(TXT_DB *db);
244 static int check_time_format(char *str);
245 char *make_revocation_str(int rev_type, char *rev_arg);
246 int make_revoked(X509_REVOKED *rev, char *str);
247 int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str);
248 static CONF *conf=NULL;
249 static CONF *extconf=NULL;
250 static char *section=NULL;
251
252 static int preserve=0;
253 static int msie_hack=0;
254
255 static IMPLEMENT_LHASH_HASH_FN(index_serial_hash,const char **)
256 static IMPLEMENT_LHASH_COMP_FN(index_serial_cmp,const char **)
257 static IMPLEMENT_LHASH_HASH_FN(index_name_hash,const char **)
258 static IMPLEMENT_LHASH_COMP_FN(index_name_cmp,const char **)
259
260
261 int MAIN(int, char **);
262
263 int MAIN(int argc, char **argv)
264         {
265         ENGINE *e = NULL;
266         char *key=NULL,*passargin=NULL;
267         int total=0;
268         int total_done=0;
269         int badops=0;
270         int ret=1;
271         int req=0;
272         int verbose=0;
273         int gencrl=0;
274         int dorevoke=0;
275         int doupdatedb=0;
276         long crldays=0;
277         long crlhours=0;
278         long errorline= -1;
279         char *configfile=NULL;
280         char *md=NULL;
281         char *policy=NULL;
282         char *keyfile=NULL;
283         char *certfile=NULL;
284         int keyform=FORMAT_PEM;
285         char *infile=NULL;
286         char *spkac_file=NULL;
287         char *ss_cert_file=NULL;
288         char *ser_status=NULL;
289         EVP_PKEY *pkey=NULL;
290         int output_der = 0;
291         char *outfile=NULL;
292         char *outdir=NULL;
293         char *serialfile=NULL;
294         char *extensions=NULL;
295         char *extfile=NULL;
296         char *subj=NULL;
297         char *crl_ext=NULL;
298         int rev_type = REV_NONE;
299         char *rev_arg = NULL;
300         BIGNUM *serial=NULL;
301         char *startdate=NULL;
302         char *enddate=NULL;
303         long days=0;
304         int batch=0;
305         int notext=0;
306         unsigned long nameopt = 0, certopt = 0;
307         int default_op = 1;
308         int ext_copy = EXT_COPY_NONE;
309         X509 *x509=NULL;
310         X509 *x=NULL;
311         BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
312         char *dbfile=NULL;
313         TXT_DB *db=NULL;
314         X509_CRL *crl=NULL;
315         X509_CRL_INFO *ci=NULL;
316         X509_REVOKED *r=NULL;
317         char **pp,*p,*f;
318         int i,j;
319         long l;
320         const EVP_MD *dgst=NULL;
321         STACK_OF(CONF_VALUE) *attribs=NULL;
322         STACK_OF(X509) *cert_sk=NULL;
323 #undef BSIZE
324 #define BSIZE 256
325         MS_STATIC char buf[3][BSIZE];
326         char *randfile=NULL;
327         char *engine = NULL;
328
329 #ifdef EFENCE
330 EF_PROTECT_FREE=1;
331 EF_PROTECT_BELOW=1;
332 EF_ALIGNMENT=0;
333 #endif
334
335         apps_startup();
336
337         conf = NULL;
338         key = NULL;
339         section = NULL;
340
341         preserve=0;
342         msie_hack=0;
343         if (bio_err == NULL)
344                 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
345                         BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
346
347         argc--;
348         argv++;
349         while (argc >= 1)
350                 {
351                 if      (strcmp(*argv,"-verbose") == 0)
352                         verbose=1;
353                 else if (strcmp(*argv,"-config") == 0)
354                         {
355                         if (--argc < 1) goto bad;
356                         configfile= *(++argv);
357                         }
358                 else if (strcmp(*argv,"-name") == 0)
359                         {
360                         if (--argc < 1) goto bad;
361                         section= *(++argv);
362                         }
363                 else if (strcmp(*argv,"-subj") == 0)
364                         {
365                         if (--argc < 1) goto bad;
366                         subj= *(++argv);
367                         /* preserve=1; */
368                         }
369                 else if (strcmp(*argv,"-startdate") == 0)
370                         {
371                         if (--argc < 1) goto bad;
372                         startdate= *(++argv);
373                         }
374                 else if (strcmp(*argv,"-enddate") == 0)
375                         {
376                         if (--argc < 1) goto bad;
377                         enddate= *(++argv);
378                         }
379                 else if (strcmp(*argv,"-days") == 0)
380                         {
381                         if (--argc < 1) goto bad;
382                         days=atoi(*(++argv));
383                         }
384                 else if (strcmp(*argv,"-md") == 0)
385                         {
386                         if (--argc < 1) goto bad;
387                         md= *(++argv);
388                         }
389                 else if (strcmp(*argv,"-policy") == 0)
390                         {
391                         if (--argc < 1) goto bad;
392                         policy= *(++argv);
393                         }
394                 else if (strcmp(*argv,"-keyfile") == 0)
395                         {
396                         if (--argc < 1) goto bad;
397                         keyfile= *(++argv);
398                         }
399                 else if (strcmp(*argv,"-keyform") == 0)
400                         {
401                         if (--argc < 1) goto bad;
402                         keyform=str2fmt(*(++argv));
403                         }
404                 else if (strcmp(*argv,"-passin") == 0)
405                         {
406                         if (--argc < 1) goto bad;
407                         passargin= *(++argv);
408                         }
409                 else if (strcmp(*argv,"-key") == 0)
410                         {
411                         if (--argc < 1) goto bad;
412                         key= *(++argv);
413                         }
414                 else if (strcmp(*argv,"-cert") == 0)
415                         {
416                         if (--argc < 1) goto bad;
417                         certfile= *(++argv);
418                         }
419                 else if (strcmp(*argv,"-in") == 0)
420                         {
421                         if (--argc < 1) goto bad;
422                         infile= *(++argv);
423                         req=1;
424                         }
425                 else if (strcmp(*argv,"-out") == 0)
426                         {
427                         if (--argc < 1) goto bad;
428                         outfile= *(++argv);
429                         }
430                 else if (strcmp(*argv,"-outdir") == 0)
431                         {
432                         if (--argc < 1) goto bad;
433                         outdir= *(++argv);
434                         }
435                 else if (strcmp(*argv,"-notext") == 0)
436                         notext=1;
437                 else if (strcmp(*argv,"-batch") == 0)
438                         batch=1;
439                 else if (strcmp(*argv,"-preserveDN") == 0)
440                         preserve=1;
441                 else if (strcmp(*argv,"-gencrl") == 0)
442                         gencrl=1;
443                 else if (strcmp(*argv,"-msie_hack") == 0)
444                         msie_hack=1;
445                 else if (strcmp(*argv,"-crldays") == 0)
446                         {
447                         if (--argc < 1) goto bad;
448                         crldays= atol(*(++argv));
449                         }
450                 else if (strcmp(*argv,"-crlhours") == 0)
451                         {
452                         if (--argc < 1) goto bad;
453                         crlhours= atol(*(++argv));
454                         }
455                 else if (strcmp(*argv,"-infiles") == 0)
456                         {
457                         argc--;
458                         argv++;
459                         req=1;
460                         break;
461                         }
462                 else if (strcmp(*argv, "-ss_cert") == 0)
463                         {
464                         if (--argc < 1) goto bad;
465                         ss_cert_file = *(++argv);
466                         req=1;
467                         }
468                 else if (strcmp(*argv, "-spkac") == 0)
469                         {
470                         if (--argc < 1) goto bad;
471                         spkac_file = *(++argv);
472                         req=1;
473                         }
474                 else if (strcmp(*argv,"-revoke") == 0)
475                         {
476                         if (--argc < 1) goto bad;
477                         infile= *(++argv);
478                         dorevoke=1;
479                         }
480                 else if (strcmp(*argv,"-extensions") == 0)
481                         {
482                         if (--argc < 1) goto bad;
483                         extensions= *(++argv);
484                         }
485                 else if (strcmp(*argv,"-extfile") == 0)
486                         {
487                         if (--argc < 1) goto bad;
488                         extfile= *(++argv);
489                         }
490                 else if (strcmp(*argv,"-status") == 0)
491                         {
492                         if (--argc < 1) goto bad;
493                         ser_status= *(++argv);
494                         }
495                 else if (strcmp(*argv,"-updatedb") == 0)
496                         {
497                         doupdatedb=1;
498                         }
499                 else if (strcmp(*argv,"-crlexts") == 0)
500                         {
501                         if (--argc < 1) goto bad;
502                         crl_ext= *(++argv);
503                         }
504                 else if (strcmp(*argv,"-crl_reason") == 0)
505                         {
506                         if (--argc < 1) goto bad;
507                         rev_arg = *(++argv);
508                         rev_type = REV_CRL_REASON;
509                         }
510                 else if (strcmp(*argv,"-crl_hold") == 0)
511                         {
512                         if (--argc < 1) goto bad;
513                         rev_arg = *(++argv);
514                         rev_type = REV_HOLD;
515                         }
516                 else if (strcmp(*argv,"-crl_compromise") == 0)
517                         {
518                         if (--argc < 1) goto bad;
519                         rev_arg = *(++argv);
520                         rev_type = REV_KEY_COMPROMISE;
521                         }
522                 else if (strcmp(*argv,"-crl_CA_compromise") == 0)
523                         {
524                         if (--argc < 1) goto bad;
525                         rev_arg = *(++argv);
526                         rev_type = REV_CA_COMPROMISE;
527                         }
528                 else if (strcmp(*argv,"-engine") == 0)
529                         {
530                         if (--argc < 1) goto bad;
531                         engine= *(++argv);
532                         }
533                 else
534                         {
535 bad:
536                         BIO_printf(bio_err,"unknown option %s\n",*argv);
537                         badops=1;
538                         break;
539                         }
540                 argc--;
541                 argv++;
542                 }
543
544         if (badops)
545                 {
546                 for (pp=ca_usage; (*pp != NULL); pp++)
547                         BIO_printf(bio_err,"%s",*pp);
548                 goto err;
549                 }
550
551         ERR_load_crypto_strings();
552
553         e = setup_engine(bio_err, engine, 0);
554
555         /*****************************************************************/
556         if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
557         if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
558         if (configfile == NULL)
559                 {
560                 /* We will just use 'buf[0]' as a temporary buffer.  */
561 #ifdef OPENSSL_SYS_VMS
562                 strncpy(buf[0],X509_get_default_cert_area(),
563                         sizeof(buf[0])-1-sizeof(CONFIG_FILE));
564 #else
565                 strncpy(buf[0],X509_get_default_cert_area(),
566                         sizeof(buf[0])-2-sizeof(CONFIG_FILE));
567                 strcat(buf[0],"/");
568 #endif
569                 strcat(buf[0],CONFIG_FILE);
570                 configfile=buf[0];
571                 }
572
573         BIO_printf(bio_err,"Using configuration from %s\n",configfile);
574         conf = NCONF_new(NULL);
575         if (NCONF_load(conf,configfile,&errorline) <= 0)
576                 {
577                 if (errorline <= 0)
578                         BIO_printf(bio_err,"error loading the config file '%s'\n",
579                                 configfile);
580                 else
581                         BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
582                                 ,errorline,configfile);
583                 goto err;
584                 }
585
586         /* Lets get the config section we are using */
587         if (section == NULL)
588                 {
589                 section=NCONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
590                 if (section == NULL)
591                         {
592                         lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
593                         goto err;
594                         }
595                 }
596
597         if (conf != NULL)
598                 {
599                 p=NCONF_get_string(conf,NULL,"oid_file");
600                 if (p == NULL)
601                         ERR_clear_error();
602                 if (p != NULL)
603                         {
604                         BIO *oid_bio;
605
606                         oid_bio=BIO_new_file(p,"r");
607                         if (oid_bio == NULL) 
608                                 {
609                                 /*
610                                 BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
611                                 ERR_print_errors(bio_err);
612                                 */
613                                 ERR_clear_error();
614                                 }
615                         else
616                                 {
617                                 OBJ_create_objects(oid_bio);
618                                 BIO_free(oid_bio);
619                                 }
620                         }
621                 if (!add_oid_section(bio_err,conf)) 
622                         {
623                         ERR_print_errors(bio_err);
624                         goto err;
625                         }
626                 }
627
628         randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
629         if (randfile == NULL)
630                 ERR_clear_error();
631         app_RAND_load_file(randfile, bio_err, 0);
632         
633         in=BIO_new(BIO_s_file());
634         out=BIO_new(BIO_s_file());
635         Sout=BIO_new(BIO_s_file());
636         Cout=BIO_new(BIO_s_file());
637         if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL))
638                 {
639                 ERR_print_errors(bio_err);
640                 goto err;
641                 }
642
643         /*****************************************************************/
644         /* report status of cert with serial number given on command line */
645         if (ser_status)
646         {
647                 if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
648                         {
649                         lookup_fail(section,ENV_DATABASE);
650                         goto err;
651                         }
652                 if (BIO_read_filename(in,dbfile) <= 0)
653                         {
654                         perror(dbfile);
655                         BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
656                         goto err;
657                         }
658                 db=TXT_DB_read(in,DB_NUMBER);
659                 if (db == NULL) goto err;
660
661                 if (!make_serial_index(db))
662                         goto err;
663
664                 if (get_certificate_status(ser_status,db) != 1)
665                         BIO_printf(bio_err,"Error verifying serial %s!\n",
666                                  ser_status);
667                 goto err;
668         }
669
670         /*****************************************************************/
671         /* we definitely need a public key, so let's get it */
672
673         if ((keyfile == NULL) && ((keyfile=NCONF_get_string(conf,
674                 section,ENV_PRIVATE_KEY)) == NULL))
675                 {
676                 lookup_fail(section,ENV_PRIVATE_KEY);
677                 goto err;
678                 }
679         if (!key && !app_passwd(bio_err, passargin, NULL, &key, NULL))
680                 {
681                 BIO_printf(bio_err,"Error getting password\n");
682                 goto err;
683                 }
684         pkey = load_key(bio_err, keyfile, keyform, key, e, 
685                 "CA private key");
686         if (key) memset(key,0,strlen(key));
687         if (pkey == NULL)
688                 {
689                 /* load_key() has already printed an appropriate message */
690                 goto err;
691                 }
692
693         /*****************************************************************/
694         /* we need a certificate */
695         if ((certfile == NULL) && ((certfile=NCONF_get_string(conf,
696                 section,ENV_CERTIFICATE)) == NULL))
697                 {
698                 lookup_fail(section,ENV_CERTIFICATE);
699                 goto err;
700                 }
701         x509=load_cert(bio_err, certfile, FORMAT_PEM, NULL, e,
702                 "CA certificate");
703         if (x509 == NULL)
704                 goto err;
705
706         if (!X509_check_private_key(x509,pkey))
707                 {
708                 BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
709                 goto err;
710                 }
711
712         f=NCONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
713         if (f == NULL)
714                 ERR_clear_error();
715         if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
716                 preserve=1;
717         f=NCONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
718         if (f == NULL)
719                 ERR_clear_error();
720         if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
721                 msie_hack=1;
722
723         f=NCONF_get_string(conf,section,ENV_NAMEOPT);
724
725         if (f)
726                 {
727                 if (!set_name_ex(&nameopt, f))
728                         {
729                         BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f);
730                         goto err;
731                         }
732                 default_op = 0;
733                 }
734         else
735                 ERR_clear_error();
736
737         f=NCONF_get_string(conf,section,ENV_CERTOPT);
738
739         if (f)
740                 {
741                 if (!set_cert_ex(&certopt, f))
742                         {
743                         BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f);
744                         goto err;
745                         }
746                 default_op = 0;
747                 }
748         else
749                 ERR_clear_error();
750
751         f=NCONF_get_string(conf,section,ENV_EXTCOPY);
752
753         if (f)
754                 {
755                 if (!set_ext_copy(&ext_copy, f))
756                         {
757                         BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f);
758                         goto err;
759                         }
760                 }
761         else
762                 ERR_clear_error();
763
764         /*****************************************************************/
765         /* lookup where to write new certificates */
766         if ((outdir == NULL) && (req))
767                 {
768                 struct stat sb;
769
770                 if ((outdir=NCONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
771                         == NULL)
772                         {
773                         BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
774                         goto err;
775                         }
776 #ifndef OPENSSL_SYS_VMS
777             /* outdir is a directory spec, but access() for VMS demands a
778                filename.  In any case, stat(), below, will catch the problem
779                if outdir is not a directory spec, and the fopen() or open()
780                will catch an error if there is no write access.
781
782                Presumably, this problem could also be solved by using the DEC
783                C routines to convert the directory syntax to Unixly, and give
784                that to access().  However, time's too short to do that just
785                now.
786             */
787                 if (access(outdir,R_OK|W_OK|X_OK) != 0)
788                         {
789                         BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
790                         perror(outdir);
791                         goto err;
792                         }
793
794                 if (stat(outdir,&sb) != 0)
795                         {
796                         BIO_printf(bio_err,"unable to stat(%s)\n",outdir);
797                         perror(outdir);
798                         goto err;
799                         }
800 #ifdef S_IFDIR
801                 if (!(sb.st_mode & S_IFDIR))
802                         {
803                         BIO_printf(bio_err,"%s need to be a directory\n",outdir);
804                         perror(outdir);
805                         goto err;
806                         }
807 #endif
808 #endif
809                 }
810
811         /*****************************************************************/
812         /* we need to load the database file */
813         if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
814                 {
815                 lookup_fail(section,ENV_DATABASE);
816                 goto err;
817                 }
818         if (BIO_read_filename(in,dbfile) <= 0)
819                 {
820                 perror(dbfile);
821                 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
822                 goto err;
823                 }
824         db=TXT_DB_read(in,DB_NUMBER);
825         if (db == NULL) goto err;
826
827         /* Lets check some fields */
828         for (i=0; i<sk_num(db->data); i++)
829                 {
830                 pp=(char **)sk_value(db->data,i);
831                 if ((pp[DB_type][0] != DB_TYPE_REV) &&
832                         (pp[DB_rev_date][0] != '\0'))
833                         {
834                         BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
835                         goto err;
836                         }
837                 if ((pp[DB_type][0] == DB_TYPE_REV) &&
838                         !make_revoked(NULL, pp[DB_rev_date]))
839                         {
840                         BIO_printf(bio_err," in entry %d\n", i+1);
841                         goto err;
842                         }
843                 if (!check_time_format(pp[DB_exp_date]))
844                         {
845                         BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
846                         goto err;
847                         }
848                 p=pp[DB_serial];
849                 j=strlen(p);
850                 if (*p == '-')
851                         {
852                         p++;
853                         j--;
854                         }
855                 if ((j&1) || (j < 2))
856                         {
857                         BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
858                         goto err;
859                         }
860                 while (*p)
861                         {
862                         if (!(  ((*p >= '0') && (*p <= '9')) ||
863                                 ((*p >= 'A') && (*p <= 'F')) ||
864                                 ((*p >= 'a') && (*p <= 'f')))  )
865                                 {
866                                 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);
867                                 goto err;
868                                 }
869                         p++;
870                         }
871                 }
872         if (verbose)
873                 {
874                 BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
875 #ifdef OPENSSL_SYS_VMS
876                 {
877                 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
878                 out = BIO_push(tmpbio, out);
879                 }
880 #endif
881                 TXT_DB_write(out,db);
882                 BIO_printf(bio_err,"%d entries loaded from the database\n",
883                         db->data->num);
884                 BIO_printf(bio_err,"generating index\n");
885                 }
886         
887         if (!make_serial_index(db))
888                 goto err;
889
890         if (!TXT_DB_create_index(db, DB_name, index_name_qual,
891                         LHASH_HASH_FN(index_name_hash),
892                         LHASH_COMP_FN(index_name_cmp)))
893                 {
894                 BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
895                         db->error,db->arg1,db->arg2);
896                 goto err;
897                 }
898
899         /*****************************************************************/
900         /* Update the db file for expired certificates */
901         if (doupdatedb)
902                 {
903                 if (verbose)
904                         BIO_printf(bio_err, "Updating %s ...\n",
905                                                         dbfile);
906
907                 i = do_updatedb(db);
908                 if (i == -1)
909                         {
910                         BIO_printf(bio_err,"Malloc failure\n");
911                         goto err;
912                         }
913                 else if (i == 0)
914                         {
915                         if (verbose) BIO_printf(bio_err,
916                                         "No entries found to mark expired\n"); 
917                         }
918                 else
919                         {
920                         out = BIO_new(BIO_s_file());
921                         if (out == NULL)
922                                 {
923                                 ERR_print_errors(bio_err);
924                                 goto err;
925                                 }
926
927 #ifndef OPENSSL_SYS_VMS
928                         j = BIO_snprintf(buf[0], sizeof buf[0], "%s.new", dbfile);
929 #else
930                         j = BIO_snprintf(buf[0], sizeof buf[0], "%s-new", dbfile);
931 #endif
932                         if (j < 0 || j >= sizeof buf[0])
933                                 {
934                                 BIO_printf(bio_err, "file name too long\n");
935                                 goto err;
936                                 }
937                         if (BIO_write_filename(out,buf[0]) <= 0)
938                                 {
939                                 perror(dbfile);
940                                 BIO_printf(bio_err,"unable to open '%s'\n",
941                                                                         dbfile);
942                                 goto err;
943                                 }
944                         j=TXT_DB_write(out,db);
945                         if (j <= 0) goto err;
946                         
947                         BIO_free(out);
948                         out = NULL;
949 #ifndef OPENSSL_SYS_VMS
950                         j = BIO_snprintf(buf[1], sizeof buf[1], "%s.old", dbfile);
951 #else
952                         j = BIO_snprintf(buf[1], sizeof buf[1], "%s-old", dbfile);
953 #endif
954                         if (j < 0 || j >= sizeof buf[1])
955                                 {
956                                 BIO_printf(bio_err, "file name too long\n");
957                                 goto err;
958                                 }
959                         if (rename(dbfile,buf[1]) < 0)
960                                 {
961                                 BIO_printf(bio_err,
962                                                 "unable to rename %s to %s\n",
963                                                 dbfile, buf[1]);
964                                 perror("reason");
965                                 goto err;
966                                 }
967                         if (rename(buf[0],dbfile) < 0)
968                                 {
969                                 BIO_printf(bio_err,
970                                                 "unable to rename %s to %s\n",
971                                                 buf[0],dbfile);
972                                 perror("reason");
973                                 rename(buf[1],dbfile);
974                                 goto err;
975                                 }
976                                 
977                         if (verbose) BIO_printf(bio_err,
978                                 "Done. %d entries marked as expired\n",i); 
979                         }
980                         goto err;
981                 }
982
983         /*****************************************************************/
984         /* Read extentions config file                                   */
985         if (extfile)
986                 {
987                 extconf = NCONF_new(NULL);
988                 if (NCONF_load(extconf,extfile,&errorline) <= 0)
989                         {
990                         if (errorline <= 0)
991                                 BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
992                                         extfile);
993                         else
994                                 BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n",
995                                         errorline,extfile);
996                         ret = 1;
997                         goto err;
998                         }
999
1000                 if (verbose)
1001                         BIO_printf(bio_err, "Succesfully loaded extensions file %s\n", extfile);
1002
1003                 /* We can have sections in the ext file */
1004                 if (!extensions && !(extensions = NCONF_get_string(extconf, "default", "extensions")))
1005                         extensions = "default";
1006                 }
1007
1008         /*****************************************************************/
1009         if (req || gencrl)
1010                 {
1011                 if (outfile != NULL)
1012                         {
1013                         if (BIO_write_filename(Sout,outfile) <= 0)
1014                                 {
1015                                 perror(outfile);
1016                                 goto err;
1017                                 }
1018                         }
1019                 else
1020                         {
1021                         BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
1022 #ifdef OPENSSL_SYS_VMS
1023                         {
1024                         BIO *tmpbio = BIO_new(BIO_f_linebuffer());
1025                         Sout = BIO_push(tmpbio, Sout);
1026                         }
1027 #endif
1028                         }
1029                 }
1030
1031         if (req)
1032                 {
1033                 if ((md == NULL) && ((md=NCONF_get_string(conf,
1034                         section,ENV_DEFAULT_MD)) == NULL))
1035                         {
1036                         lookup_fail(section,ENV_DEFAULT_MD);
1037                         goto err;
1038                         }
1039                 if ((dgst=EVP_get_digestbyname(md)) == NULL)
1040                         {
1041                         BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1042                         goto err;
1043                         }
1044                 if (verbose)
1045                         BIO_printf(bio_err,"message digest is %s\n",
1046                                 OBJ_nid2ln(dgst->type));
1047                 if ((policy == NULL) && ((policy=NCONF_get_string(conf,
1048                         section,ENV_POLICY)) == NULL))
1049                         {
1050                         lookup_fail(section,ENV_POLICY);
1051                         goto err;
1052                         }
1053                 if (verbose)
1054                         BIO_printf(bio_err,"policy is %s\n",policy);
1055
1056                 if ((serialfile=NCONF_get_string(conf,section,ENV_SERIAL))
1057                         == NULL)
1058                         {
1059                         lookup_fail(section,ENV_SERIAL);
1060                         goto err;
1061                         }
1062
1063                 if (!extconf)
1064                         {
1065                         /* no '-extfile' option, so we look for extensions
1066                          * in the main configuration file */
1067                         if (!extensions)
1068                                 {
1069                                 extensions=NCONF_get_string(conf,section,
1070                                                                 ENV_EXTENSIONS);
1071                                 if (!extensions)
1072                                         ERR_clear_error();
1073                                 }
1074                         if (extensions)
1075                                 {
1076                                 /* Check syntax of file */
1077                                 X509V3_CTX ctx;
1078                                 X509V3_set_ctx_test(&ctx);
1079                                 X509V3_set_nconf(&ctx, conf);
1080                                 if (!X509V3_EXT_add_nconf(conf, &ctx, extensions,
1081                                                                 NULL))
1082                                         {
1083                                         BIO_printf(bio_err,
1084                                         "Error Loading extension section %s\n",
1085                                                                  extensions);
1086                                         ret = 1;
1087                                         goto err;
1088                                         }
1089                                 }
1090                         }
1091
1092                 if (startdate == NULL)
1093                         {
1094                         startdate=NCONF_get_string(conf,section,
1095                                 ENV_DEFAULT_STARTDATE);
1096                         if (startdate == NULL)
1097                                 ERR_clear_error();
1098                         }
1099                 if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
1100                         {
1101                         BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
1102                         goto err;
1103                         }
1104                 if (startdate == NULL) startdate="today";
1105
1106                 if (enddate == NULL)
1107                         {
1108                         enddate=NCONF_get_string(conf,section,
1109                                 ENV_DEFAULT_ENDDATE);
1110                         if (enddate == NULL)
1111                                 ERR_clear_error();
1112                         }
1113                 if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
1114                         {
1115                         BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
1116                         goto err;
1117                         }
1118
1119                 if (days == 0)
1120                         {
1121                         if(!NCONF_get_number(conf,section, ENV_DEFAULT_DAYS, &days))
1122                                 days = 0;
1123                         }
1124                 if (!enddate && (days == 0))
1125                         {
1126                         BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
1127                         goto err;
1128                         }
1129
1130                 if ((serial=load_serial(serialfile)) == NULL)
1131                         {
1132                         BIO_printf(bio_err,"error while loading serial number\n");
1133                         goto err;
1134                         }
1135                 if (verbose)
1136                         {
1137                         if ((f=BN_bn2hex(serial)) == NULL) goto err;
1138                         BIO_printf(bio_err,"next serial number is %s\n",f);
1139                         OPENSSL_free(f);
1140                         }
1141
1142                 if ((attribs=NCONF_get_section(conf,policy)) == NULL)
1143                         {
1144                         BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
1145                         goto err;
1146                         }
1147
1148                 if ((cert_sk=sk_X509_new_null()) == NULL)
1149                         {
1150                         BIO_printf(bio_err,"Memory allocation failure\n");
1151                         goto err;
1152                         }
1153                 if (spkac_file != NULL)
1154                         {
1155                         total++;
1156                         j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
1157                                 serial,subj,startdate,enddate, days,extensions,conf,
1158                                 verbose, certopt, nameopt, default_op, ext_copy);
1159                         if (j < 0) goto err;
1160                         if (j > 0)
1161                                 {
1162                                 total_done++;
1163                                 BIO_printf(bio_err,"\n");
1164                                 if (!BN_add_word(serial,1)) goto err;
1165                                 if (!sk_X509_push(cert_sk,x))
1166                                         {
1167                                         BIO_printf(bio_err,"Memory allocation failure\n");
1168                                         goto err;
1169                                         }
1170                                 if (outfile)
1171                                         {
1172                                         output_der = 1;
1173                                         batch = 1;
1174                                         }
1175                                 }
1176                         }
1177                 if (ss_cert_file != NULL)
1178                         {
1179                         total++;
1180                         j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
1181                                 db,serial,subj,startdate,enddate,days,batch,
1182                                 extensions,conf,verbose, certopt, nameopt,
1183                                 default_op, ext_copy, e);
1184                         if (j < 0) goto err;
1185                         if (j > 0)
1186                                 {
1187                                 total_done++;
1188                                 BIO_printf(bio_err,"\n");
1189                                 if (!BN_add_word(serial,1)) goto err;
1190                                 if (!sk_X509_push(cert_sk,x))
1191                                         {
1192                                         BIO_printf(bio_err,"Memory allocation failure\n");
1193                                         goto err;
1194                                         }
1195                                 }
1196                         }
1197                 if (infile != NULL)
1198                         {
1199                         total++;
1200                         j=certify(&x,infile,pkey,x509,dgst,attribs,db,
1201                                 serial,subj,startdate,enddate,days,batch,
1202                                 extensions,conf,verbose, certopt, nameopt,
1203                                 default_op, ext_copy);
1204                         if (j < 0) goto err;
1205                         if (j > 0)
1206                                 {
1207                                 total_done++;
1208                                 BIO_printf(bio_err,"\n");
1209                                 if (!BN_add_word(serial,1)) goto err;
1210                                 if (!sk_X509_push(cert_sk,x))
1211                                         {
1212                                         BIO_printf(bio_err,"Memory allocation failure\n");
1213                                         goto err;
1214                                         }
1215                                 }
1216                         }
1217                 for (i=0; i<argc; i++)
1218                         {
1219                         total++;
1220                         j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
1221                                 serial,subj,startdate,enddate,days,batch,
1222                                 extensions,conf,verbose, certopt, nameopt,
1223                                 default_op, ext_copy);
1224                         if (j < 0) goto err;
1225                         if (j > 0)
1226                                 {
1227                                 total_done++;
1228                                 BIO_printf(bio_err,"\n");
1229                                 if (!BN_add_word(serial,1)) goto err;
1230                                 if (!sk_X509_push(cert_sk,x))
1231                                         {
1232                                         BIO_printf(bio_err,"Memory allocation failure\n");
1233                                         goto err;
1234                                         }
1235                                 }
1236                         }       
1237                 /* we have a stack of newly certified certificates
1238                  * and a data base and serial number that need
1239                  * updating */
1240
1241                 if (sk_X509_num(cert_sk) > 0)
1242                         {
1243                         if (!batch)
1244                                 {
1245                                 BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
1246                                 (void)BIO_flush(bio_err);
1247                                 buf[0][0]='\0';
1248                                 fgets(buf[0],10,stdin);
1249                                 if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
1250                                         {
1251                                         BIO_printf(bio_err,"CERTIFICATION CANCELED\n"); 
1252                                         ret=0;
1253                                         goto err;
1254                                         }
1255                                 }
1256
1257                         BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
1258
1259                         strncpy(buf[0],serialfile,BSIZE-4);
1260
1261 #ifdef OPENSSL_SYS_VMS
1262                         strcat(buf[0],"-new");
1263 #else
1264                         strcat(buf[0],".new");
1265 #endif
1266
1267                         if (!save_serial(buf[0],serial)) goto err;
1268
1269                         strncpy(buf[1],dbfile,BSIZE-4);
1270
1271 #ifdef OPENSSL_SYS_VMS
1272                         strcat(buf[1],"-new");
1273 #else
1274                         strcat(buf[1],".new");
1275 #endif
1276
1277                         if (BIO_write_filename(out,buf[1]) <= 0)
1278                                 {
1279                                 perror(dbfile);
1280                                 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1281                                 goto err;
1282                                 }
1283                         l=TXT_DB_write(out,db);
1284                         if (l <= 0) goto err;
1285                         }
1286         
1287                 if (verbose)
1288                         BIO_printf(bio_err,"writing new certificates\n");
1289                 for (i=0; i<sk_X509_num(cert_sk); i++)
1290                         {
1291                         int k;
1292                         unsigned char *n;
1293
1294                         x=sk_X509_value(cert_sk,i);
1295
1296                         j=x->cert_info->serialNumber->length;
1297                         p=(char *)x->cert_info->serialNumber->data;
1298                         
1299                         strncpy(buf[2],outdir,BSIZE-(j*2)-6);
1300
1301 #ifndef OPENSSL_SYS_VMS
1302                         strcat(buf[2],"/");
1303 #endif
1304
1305                         n=(unsigned char *)&(buf[2][strlen(buf[2])]);
1306                         if (j > 0)
1307                                 {
1308                                 for (k=0; k<j; k++)
1309                                         {
1310                                         sprintf((char *)n,"%02X",(unsigned char)*(p++));
1311                                         n+=2;
1312                                         }
1313                                 }
1314                         else
1315                                 {
1316                                 *(n++)='0';
1317                                 *(n++)='0';
1318                                 }
1319                         *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
1320                         *n='\0';
1321                         if (verbose)
1322                                 BIO_printf(bio_err,"writing %s\n",buf[2]);
1323
1324                         if (BIO_write_filename(Cout,buf[2]) <= 0)
1325                                 {
1326                                 perror(buf[2]);
1327                                 goto err;
1328                                 }
1329                         write_new_certificate(Cout,x, 0, notext);
1330                         write_new_certificate(Sout,x, output_der, notext);
1331                         }
1332
1333                 if (sk_X509_num(cert_sk))
1334                         {
1335                         /* Rename the database and the serial file */
1336                         strncpy(buf[2],serialfile,BSIZE-4);
1337
1338 #ifdef OPENSSL_SYS_VMS
1339                         strcat(buf[2],"-old");
1340 #else
1341                         strcat(buf[2],".old");
1342 #endif
1343
1344                         BIO_free(in);
1345                         BIO_free_all(out);
1346                         in=NULL;
1347                         out=NULL;
1348                         if (rename(serialfile,buf[2]) < 0)
1349                                 {
1350                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1351                                         serialfile,buf[2]);
1352                                 perror("reason");
1353                                 goto err;
1354                                 }
1355                         if (rename(buf[0],serialfile) < 0)
1356                                 {
1357                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1358                                         buf[0],serialfile);
1359                                 perror("reason");
1360                                 rename(buf[2],serialfile);
1361                                 goto err;
1362                                 }
1363
1364                         strncpy(buf[2],dbfile,BSIZE-4);
1365
1366 #ifdef OPENSSL_SYS_VMS
1367                         strcat(buf[2],"-old");
1368 #else
1369                         strcat(buf[2],".old");
1370 #endif
1371
1372                         if (rename(dbfile,buf[2]) < 0)
1373                                 {
1374                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1375                                         dbfile,buf[2]);
1376                                 perror("reason");
1377                                 goto err;
1378                                 }
1379                         if (rename(buf[1],dbfile) < 0)
1380                                 {
1381                                 BIO_printf(bio_err,"unable to rename %s to %s\n",
1382                                         buf[1],dbfile);
1383                                 perror("reason");
1384                                 rename(buf[2],dbfile);
1385                                 goto err;
1386                                 }
1387                         BIO_printf(bio_err,"Data Base Updated\n");
1388                         }
1389                 }
1390         
1391         /*****************************************************************/
1392         if (gencrl)
1393                 {
1394                 int crl_v2 = 0;
1395                 if (!crl_ext)
1396                         {
1397                         crl_ext=NCONF_get_string(conf,section,ENV_CRLEXT);
1398                         if (!crl_ext)
1399                                 ERR_clear_error();
1400                         }
1401                 if (crl_ext)
1402                         {
1403                         /* Check syntax of file */
1404                         X509V3_CTX ctx;
1405                         X509V3_set_ctx_test(&ctx);
1406                         X509V3_set_nconf(&ctx, conf);
1407                         if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL))
1408                                 {
1409                                 BIO_printf(bio_err,
1410                                  "Error Loading CRL extension section %s\n",
1411                                                                  crl_ext);
1412                                 ret = 1;
1413                                 goto err;
1414                                 }
1415                         }
1416
1417                 if (!crldays && !crlhours)
1418                         {
1419                         if (!NCONF_get_number(conf,section,
1420                                 ENV_DEFAULT_CRL_DAYS, &crldays))
1421                                 crldays = 0;
1422                         if (!NCONF_get_number(conf,section,
1423                                 ENV_DEFAULT_CRL_HOURS, &crlhours))
1424                                 crlhours = 0;
1425                         }
1426                 if ((crldays == 0) && (crlhours == 0))
1427                         {
1428                         BIO_printf(bio_err,"cannot lookup how long until the next CRL is issuer\n");
1429                         goto err;
1430                         }
1431
1432                 if (verbose) BIO_printf(bio_err,"making CRL\n");
1433                 if ((crl=X509_CRL_new()) == NULL) goto err;
1434                 ci=crl->crl;
1435                 X509_NAME_free(ci->issuer);
1436                 ci->issuer=X509_NAME_dup(x509->cert_info->subject);
1437                 if (ci->issuer == NULL) goto err;
1438
1439                 X509_gmtime_adj(ci->lastUpdate,0);
1440                 if (ci->nextUpdate == NULL)
1441                         ci->nextUpdate=ASN1_UTCTIME_new();
1442                 X509_gmtime_adj(ci->nextUpdate,(crldays*24+crlhours)*60*60);
1443
1444                 for (i=0; i<sk_num(db->data); i++)
1445                         {
1446                         pp=(char **)sk_value(db->data,i);
1447                         if (pp[DB_type][0] == DB_TYPE_REV)
1448                                 {
1449                                 if ((r=X509_REVOKED_new()) == NULL) goto err;
1450                                 j = make_revoked(r, pp[DB_rev_date]);
1451                                 if (!j) goto err;
1452                                 if (j == 2) crl_v2 = 1;
1453                                 if (!BN_hex2bn(&serial, pp[DB_serial]))
1454                                         goto err;
1455                                 r->serialNumber = BN_to_ASN1_INTEGER(serial, r->serialNumber);
1456                                 BN_free(serial);
1457                                 serial = NULL;
1458                                 if (!r->serialNumber)
1459                                         goto err;
1460                                 X509_CRL_add0_revoked(crl,r);
1461                                 }
1462                         }
1463                 /* sort the data so it will be written in serial
1464                  * number order */
1465                 sk_X509_REVOKED_sort(ci->revoked);
1466                 for (i=0; i<sk_X509_REVOKED_num(ci->revoked); i++)
1467                         {
1468                         r=sk_X509_REVOKED_value(ci->revoked,i);
1469                         r->sequence=i;
1470                         }
1471
1472                 /* we now have a CRL */
1473                 if (verbose) BIO_printf(bio_err,"signing CRL\n");
1474                 if (md != NULL)
1475                         {
1476                         if ((dgst=EVP_get_digestbyname(md)) == NULL)
1477                                 {
1478                                 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1479                                 goto err;
1480                                 }
1481                         }
1482                 else
1483                         {
1484 #ifndef OPENSSL_NO_DSA
1485                         if (pkey->type == EVP_PKEY_DSA) 
1486                                 dgst=EVP_dss1();
1487                         else
1488 #endif
1489                                 dgst=EVP_md5();
1490                         }
1491
1492                 /* Add any extensions asked for */
1493
1494                 if (crl_ext)
1495                         {
1496                         X509V3_CTX crlctx;
1497                         if (ci->version == NULL)
1498                                 if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
1499                         X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1500                         X509V3_set_nconf(&crlctx, conf);
1501
1502                         if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx,
1503                                 crl_ext, crl)) goto err;
1504                         }
1505                 if (crl_ext || crl_v2)
1506                         {
1507                         if (ci->version == NULL)
1508                                 if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
1509                         ASN1_INTEGER_set(ci->version,1); /* version 2 CRL */
1510                         }
1511
1512                 if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1513
1514                 PEM_write_bio_X509_CRL(Sout,crl);
1515                 }
1516         /*****************************************************************/
1517         if (dorevoke)
1518                 {
1519                 if (infile == NULL) 
1520                         {
1521                         BIO_printf(bio_err,"no input files\n");
1522                         goto err;
1523                         }
1524                 else
1525                         {
1526                         X509 *revcert;
1527                         revcert=load_cert(bio_err, infile, FORMAT_PEM,
1528                                 NULL, e, infile);
1529                         if (revcert == NULL)
1530                                 goto err;
1531                         j=do_revoke(revcert,db, rev_type, rev_arg);
1532                         if (j <= 0) goto err;
1533                         X509_free(revcert);
1534
1535                         strncpy(buf[0],dbfile,BSIZE-4);
1536 #ifndef OPENSSL_SYS_VMS
1537                         strcat(buf[0],".new");
1538 #else
1539                         strcat(buf[0],"-new");
1540 #endif
1541                         if (BIO_write_filename(out,buf[0]) <= 0)
1542                                 {
1543                                 perror(dbfile);
1544                                 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1545                                 goto err;
1546                                 }
1547                         j=TXT_DB_write(out,db);
1548                         if (j <= 0) goto err;
1549                         strncpy(buf[1],dbfile,BSIZE-4);
1550 #ifndef OPENSSL_SYS_VMS
1551                         strcat(buf[1],".old");
1552 #else
1553                         strcat(buf[1],"-old");
1554 #endif
1555                         if (rename(dbfile,buf[1]) < 0)
1556                                 {
1557                                 BIO_printf(bio_err,"unable to rename %s to %s\n", dbfile, buf[1]);
1558                                 perror("reason");
1559                                 goto err;
1560                                 }
1561                         if (rename(buf[0],dbfile) < 0)
1562                                 {
1563                                 BIO_printf(bio_err,"unable to rename %s to %s\n", buf[0],dbfile);
1564                                 perror("reason");
1565                                 rename(buf[1],dbfile);
1566                                 goto err;
1567                                 }
1568                         BIO_printf(bio_err,"Data Base Updated\n"); 
1569                         }
1570                 }
1571         /*****************************************************************/
1572         ret=0;
1573 err:
1574         BIO_free_all(Cout);
1575         BIO_free_all(Sout);
1576         BIO_free_all(out);
1577         BIO_free_all(in);
1578
1579         sk_X509_pop_free(cert_sk,X509_free);
1580
1581         if (ret) ERR_print_errors(bio_err);
1582         app_RAND_write_file(randfile, bio_err);
1583         BN_free(serial);
1584         TXT_DB_free(db);
1585         EVP_PKEY_free(pkey);
1586         X509_free(x509);
1587         X509_CRL_free(crl);
1588         NCONF_free(conf);
1589         OBJ_cleanup();
1590         apps_shutdown();
1591         EXIT(ret);
1592         }
1593
1594 static void lookup_fail(char *name, char *tag)
1595         {
1596         BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1597         }
1598
1599 static unsigned long index_serial_hash(const char **a)
1600         {
1601         const char *n;
1602
1603         n=a[DB_serial];
1604         while (*n == '0') n++;
1605         return(lh_strhash(n));
1606         }
1607
1608 static int index_serial_cmp(const char **a, const char **b)
1609         {
1610         const char *aa,*bb;
1611
1612         for (aa=a[DB_serial]; *aa == '0'; aa++);
1613         for (bb=b[DB_serial]; *bb == '0'; bb++);
1614         return(strcmp(aa,bb));
1615         }
1616
1617 static unsigned long index_name_hash(const char **a)
1618         { return(lh_strhash(a[DB_name])); }
1619
1620 static int index_name_qual(char **a)
1621         { return(a[0][0] == 'V'); }
1622
1623 static int index_name_cmp(const char **a, const char **b)
1624         { return(strcmp(a[DB_name],
1625              b[DB_name])); }
1626
1627 static BIGNUM *load_serial(char *serialfile)
1628         {
1629         BIO *in=NULL;
1630         BIGNUM *ret=NULL;
1631         MS_STATIC char buf[1024];
1632         ASN1_INTEGER *ai=NULL;
1633
1634         if ((in=BIO_new(BIO_s_file())) == NULL)
1635                 {
1636                 ERR_print_errors(bio_err);
1637                 goto err;
1638                 }
1639
1640         if (BIO_read_filename(in,serialfile) <= 0)
1641                 {
1642                 perror(serialfile);
1643                 goto err;
1644                 }
1645         ai=ASN1_INTEGER_new();
1646         if (ai == NULL) goto err;
1647         if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
1648                 {
1649                 BIO_printf(bio_err,"unable to load number from %s\n",
1650                         serialfile);
1651                 goto err;
1652                 }
1653         ret=ASN1_INTEGER_to_BN(ai,NULL);
1654         if (ret == NULL)
1655                 {
1656                 BIO_printf(bio_err,"error converting number from bin to BIGNUM");
1657                 goto err;
1658                 }
1659 err:
1660         if (in != NULL) BIO_free(in);
1661         if (ai != NULL) ASN1_INTEGER_free(ai);
1662         return(ret);
1663         }
1664
1665 static int save_serial(char *serialfile, BIGNUM *serial)
1666         {
1667         BIO *out;
1668         int ret=0;
1669         ASN1_INTEGER *ai=NULL;
1670
1671         out=BIO_new(BIO_s_file());
1672         if (out == NULL)
1673                 {
1674                 ERR_print_errors(bio_err);
1675                 goto err;
1676                 }
1677         if (BIO_write_filename(out,serialfile) <= 0)
1678                 {
1679                 perror(serialfile);
1680                 goto err;
1681                 }
1682
1683         if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
1684                 {
1685                 BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
1686                 goto err;
1687                 }
1688         i2a_ASN1_INTEGER(out,ai);
1689         BIO_puts(out,"\n");
1690         ret=1;
1691 err:
1692         if (out != NULL) BIO_free_all(out);
1693         if (ai != NULL) ASN1_INTEGER_free(ai);
1694         return(ret);
1695         }
1696
1697 static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1698              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1699              BIGNUM *serial, char *subj, char *startdate, char *enddate, long days,
1700              int batch, char *ext_sect, CONF *lconf, int verbose,
1701              unsigned long certopt, unsigned long nameopt, int default_op,
1702              int ext_copy)
1703         {
1704         X509_REQ *req=NULL;
1705         BIO *in=NULL;
1706         EVP_PKEY *pktmp=NULL;
1707         int ok= -1,i;
1708
1709         in=BIO_new(BIO_s_file());
1710
1711         if (BIO_read_filename(in,infile) <= 0)
1712                 {
1713                 perror(infile);
1714                 goto err;
1715                 }
1716         if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
1717                 {
1718                 BIO_printf(bio_err,"Error reading certificate request in %s\n",
1719                         infile);
1720                 goto err;
1721                 }
1722         if (verbose)
1723                 X509_REQ_print(bio_err,req);
1724
1725         BIO_printf(bio_err,"Check that the request matches the signature\n");
1726
1727         if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
1728                 {
1729                 BIO_printf(bio_err,"error unpacking public key\n");
1730                 goto err;
1731                 }
1732         i=X509_REQ_verify(req,pktmp);
1733         EVP_PKEY_free(pktmp);
1734         if (i < 0)
1735                 {
1736                 ok=0;
1737                 BIO_printf(bio_err,"Signature verification problems....\n");
1738                 goto err;
1739                 }
1740         if (i == 0)
1741                 {
1742                 ok=0;
1743                 BIO_printf(bio_err,"Signature did not match the certificate request\n");
1744                 goto err;
1745                 }
1746         else
1747                 BIO_printf(bio_err,"Signature ok\n");
1748
1749         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,startdate, enddate,
1750                 days,batch,verbose,req,ext_sect,lconf,
1751                 certopt, nameopt, default_op, ext_copy);
1752
1753 err:
1754         if (req != NULL) X509_REQ_free(req);
1755         if (in != NULL) BIO_free(in);
1756         return(ok);
1757         }
1758
1759 static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1760              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1761              BIGNUM *serial, char *subj, char *startdate, char *enddate, long days,
1762              int batch, char *ext_sect, CONF *lconf, int verbose,
1763              unsigned long certopt, unsigned long nameopt, int default_op,
1764              int ext_copy, ENGINE *e)
1765         {
1766         X509 *req=NULL;
1767         X509_REQ *rreq=NULL;
1768         EVP_PKEY *pktmp=NULL;
1769         int ok= -1,i;
1770
1771         if ((req=load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL)
1772                 goto err;
1773         if (verbose)
1774                 X509_print(bio_err,req);
1775
1776         BIO_printf(bio_err,"Check that the request matches the signature\n");
1777
1778         if ((pktmp=X509_get_pubkey(req)) == NULL)
1779                 {
1780                 BIO_printf(bio_err,"error unpacking public key\n");
1781                 goto err;
1782                 }
1783         i=X509_verify(req,pktmp);
1784         EVP_PKEY_free(pktmp);
1785         if (i < 0)
1786                 {
1787                 ok=0;
1788                 BIO_printf(bio_err,"Signature verification problems....\n");
1789                 goto err;
1790                 }
1791         if (i == 0)
1792                 {
1793                 ok=0;
1794                 BIO_printf(bio_err,"Signature did not match the certificate\n");
1795                 goto err;
1796                 }
1797         else
1798                 BIO_printf(bio_err,"Signature ok\n");
1799
1800         if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
1801                 goto err;
1802
1803         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,startdate,enddate,days,
1804                 batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op,
1805                         ext_copy);
1806
1807 err:
1808         if (rreq != NULL) X509_REQ_free(rreq);
1809         if (req != NULL) X509_free(req);
1810         return(ok);
1811         }
1812
1813 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1814              STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial, char *subj,
1815              char *startdate, char *enddate, long days, int batch, int verbose,
1816              X509_REQ *req, char *ext_sect, CONF *lconf,
1817              unsigned long certopt, unsigned long nameopt, int default_op,
1818              int ext_copy)
1819         {
1820         X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
1821         ASN1_UTCTIME *tm,*tmptm;
1822         ASN1_STRING *str,*str2;
1823         ASN1_OBJECT *obj;
1824         X509 *ret=NULL;
1825         X509_CINF *ci;
1826         X509_NAME_ENTRY *ne;
1827         X509_NAME_ENTRY *tne,*push;
1828         EVP_PKEY *pktmp;
1829         int ok= -1,i,j,last,nid;
1830         char *p;
1831         CONF_VALUE *cv;
1832         char *row[DB_NUMBER],**rrow,**irow=NULL;
1833         char buf[25];
1834
1835         tmptm=ASN1_UTCTIME_new();
1836         if (tmptm == NULL)
1837                 {
1838                 BIO_printf(bio_err,"malloc error\n");
1839                 return(0);
1840                 }
1841
1842         for (i=0; i<DB_NUMBER; i++)
1843                 row[i]=NULL;
1844
1845         if (subj)
1846                 {
1847                 X509_NAME *n = do_subject(subj);
1848
1849                 if (!n)
1850                         {
1851                         ERR_print_errors(bio_err);
1852                         goto err;
1853                         }
1854                 X509_REQ_set_subject_name(req,n);
1855                 req->req_info->enc.modified = 1;
1856                 X509_NAME_free(n);
1857                 }
1858
1859         if (default_op)
1860                 BIO_printf(bio_err,"The Subject's Distinguished Name is as follows\n");
1861         name=X509_REQ_get_subject_name(req);
1862         for (i=0; i<X509_NAME_entry_count(name); i++)
1863                 {
1864                 ne= X509_NAME_get_entry(name,i);
1865                 str=X509_NAME_ENTRY_get_data(ne);
1866                 obj=X509_NAME_ENTRY_get_object(ne);
1867
1868                 if (msie_hack)
1869                         {
1870                         /* assume all type should be strings */
1871                         nid=OBJ_obj2nid(ne->object);
1872
1873                         if (str->type == V_ASN1_UNIVERSALSTRING)
1874                                 ASN1_UNIVERSALSTRING_to_string(str);
1875
1876                         if ((str->type == V_ASN1_IA5STRING) &&
1877                                 (nid != NID_pkcs9_emailAddress))
1878                                 str->type=V_ASN1_T61STRING;
1879
1880                         if ((nid == NID_pkcs9_emailAddress) &&
1881                                 (str->type == V_ASN1_PRINTABLESTRING))
1882                                 str->type=V_ASN1_IA5STRING;
1883                         }
1884
1885                 /* check some things */
1886                 if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1887                         (str->type != V_ASN1_IA5STRING))
1888                         {
1889                         BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
1890                         goto err;
1891                         }
1892                 j=ASN1_PRINTABLE_type(str->data,str->length);
1893                 if (    ((j == V_ASN1_T61STRING) &&
1894                          (str->type != V_ASN1_T61STRING)) ||
1895                         ((j == V_ASN1_IA5STRING) &&
1896                          (str->type == V_ASN1_PRINTABLESTRING)))
1897                         {
1898                         BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1899                         goto err;
1900                         }
1901
1902                 if (default_op)
1903                         old_entry_print(bio_err, obj, str);
1904                 }
1905
1906         /* Ok, now we check the 'policy' stuff. */
1907         if ((subject=X509_NAME_new()) == NULL)
1908                 {
1909                 BIO_printf(bio_err,"Memory allocation failure\n");
1910                 goto err;
1911                 }
1912
1913         /* take a copy of the issuer name before we mess with it. */
1914         CAname=X509_NAME_dup(x509->cert_info->subject);
1915         if (CAname == NULL) goto err;
1916         str=str2=NULL;
1917
1918         for (i=0; i<sk_CONF_VALUE_num(policy); i++)
1919                 {
1920                 cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
1921                 if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
1922                         {
1923                         BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
1924                         goto err;
1925                         }
1926                 obj=OBJ_nid2obj(j);
1927
1928                 last= -1;
1929                 for (;;)
1930                         {
1931                         /* lookup the object in the supplied name list */
1932                         j=X509_NAME_get_index_by_OBJ(name,obj,last);
1933                         if (j < 0)
1934                                 {
1935                                 if (last != -1) break;
1936                                 tne=NULL;
1937                                 }
1938                         else
1939                                 {
1940                                 tne=X509_NAME_get_entry(name,j);
1941                                 }
1942                         last=j;
1943
1944                         /* depending on the 'policy', decide what to do. */
1945                         push=NULL;
1946                         if (strcmp(cv->value,"optional") == 0)
1947                                 {
1948                                 if (tne != NULL)
1949                                         push=tne;
1950                                 }
1951                         else if (strcmp(cv->value,"supplied") == 0)
1952                                 {
1953                                 if (tne == NULL)
1954                                         {
1955                                         BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
1956                                         goto err;
1957                                         }
1958                                 else
1959                                         push=tne;
1960                                 }
1961                         else if (strcmp(cv->value,"match") == 0)
1962                                 {
1963                                 int last2;
1964
1965                                 if (tne == NULL)
1966                                         {
1967                                         BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
1968                                         goto err;
1969                                         }
1970
1971                                 last2= -1;
1972
1973 again2:
1974                                 j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
1975                                 if ((j < 0) && (last2 == -1))
1976                                         {
1977                                         BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
1978                                         goto err;
1979                                         }
1980                                 if (j >= 0)
1981                                         {
1982                                         push=X509_NAME_get_entry(CAname,j);
1983                                         str=X509_NAME_ENTRY_get_data(tne);
1984                                         str2=X509_NAME_ENTRY_get_data(push);
1985                                         last2=j;
1986                                         if (ASN1_STRING_cmp(str,str2) != 0)
1987                                                 goto again2;
1988                                         }
1989                                 if (j < 0)
1990                                         {
1991                                         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));
1992                                         goto err;
1993                                         }
1994                                 }
1995                         else
1996                                 {
1997                                 BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
1998                                 goto err;
1999                                 }
2000
2001                         if (push != NULL)
2002                                 {
2003                                 if (!X509_NAME_add_entry(subject,push, -1, 0))
2004                                         {
2005                                         if (push != NULL)
2006                                                 X509_NAME_ENTRY_free(push);
2007                                         BIO_printf(bio_err,"Memory allocation failure\n");
2008                                         goto err;
2009                                         }
2010                                 }
2011                         if (j < 0) break;
2012                         }
2013                 }
2014
2015         if (preserve)
2016                 {
2017                 X509_NAME_free(subject);
2018                 subject=X509_NAME_dup(X509_REQ_get_subject_name(req));
2019                 if (subject == NULL) goto err;
2020                 }
2021
2022         if (verbose)
2023                 BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
2024
2025         row[DB_name]=X509_NAME_oneline(subject,NULL,0);
2026         row[DB_serial]=BN_bn2hex(serial);
2027         if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2028                 {
2029                 BIO_printf(bio_err,"Memory allocation failure\n");
2030                 goto err;
2031                 }
2032
2033         rrow=TXT_DB_get_by_index(db,DB_name,row);
2034         if (rrow != NULL)
2035                 {
2036                 BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n",
2037                         row[DB_name]);
2038                 }
2039         else
2040                 {
2041                 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2042                 if (rrow != NULL)
2043                         {
2044                         BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
2045                                 row[DB_serial]);
2046                         BIO_printf(bio_err,"      check the database/serial_file for corruption\n");
2047                         }
2048                 }
2049
2050         if (rrow != NULL)
2051                 {
2052                 BIO_printf(bio_err,
2053                         "The matching entry has the following details\n");
2054                 if (rrow[DB_type][0] == 'E')
2055                         p="Expired";
2056                 else if (rrow[DB_type][0] == 'R')
2057                         p="Revoked";
2058                 else if (rrow[DB_type][0] == 'V')
2059                         p="Valid";
2060                 else
2061                         p="\ninvalid type, Data base error\n";
2062                 BIO_printf(bio_err,"Type          :%s\n",p);;
2063                 if (rrow[DB_type][0] == 'R')
2064                         {
2065                         p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2066                         BIO_printf(bio_err,"Was revoked on:%s\n",p);
2067                         }
2068                 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2069                 BIO_printf(bio_err,"Expires on    :%s\n",p);
2070                 p=rrow[DB_serial]; if (p == NULL) p="undef";
2071                 BIO_printf(bio_err,"Serial Number :%s\n",p);
2072                 p=rrow[DB_file]; if (p == NULL) p="undef";
2073                 BIO_printf(bio_err,"File name     :%s\n",p);
2074                 p=rrow[DB_name]; if (p == NULL) p="undef";
2075                 BIO_printf(bio_err,"Subject Name  :%s\n",p);
2076                 ok= -1; /* This is now a 'bad' error. */
2077                 goto err;
2078                 }
2079
2080         /* We are now totally happy, lets make and sign the certificate */
2081         if (verbose)
2082                 BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
2083
2084         if ((ret=X509_new()) == NULL) goto err;
2085         ci=ret->cert_info;
2086
2087 #ifdef X509_V3
2088         /* Make it an X509 v3 certificate. */
2089         if (!X509_set_version(x509,2)) goto err;
2090 #endif
2091
2092         if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
2093                 goto err;
2094         if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
2095                 goto err;
2096
2097         if (strcmp(startdate,"today") == 0)
2098                 X509_gmtime_adj(X509_get_notBefore(ret),0);
2099         else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
2100
2101         if (enddate == NULL)
2102                 X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
2103         else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
2104
2105         if (!X509_set_subject_name(ret,subject)) goto err;
2106
2107         pktmp=X509_REQ_get_pubkey(req);
2108         i = X509_set_pubkey(ret,pktmp);
2109         EVP_PKEY_free(pktmp);
2110         if (!i) goto err;
2111
2112         /* Lets add the extensions, if there are any */
2113         if (ext_sect)
2114                 {
2115                 X509V3_CTX ctx;
2116                 if (ci->version == NULL)
2117                         if ((ci->version=ASN1_INTEGER_new()) == NULL)
2118                                 goto err;
2119                 ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
2120
2121                 /* Free the current entries if any, there should not
2122                  * be any I believe */
2123                 if (ci->extensions != NULL)
2124                         sk_X509_EXTENSION_pop_free(ci->extensions,
2125                                                    X509_EXTENSION_free);
2126
2127                 ci->extensions = NULL;
2128
2129                 /* Initialize the context structure */
2130                 X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
2131
2132                 if (extconf)
2133                         {
2134                         if (verbose)
2135                                 BIO_printf(bio_err, "Extra configuration file found\n");
2136  
2137                         /* Use the extconf configuration db LHASH */
2138                         X509V3_set_nconf(&ctx, extconf);
2139  
2140                         /* Test the structure (needed?) */
2141                         /* X509V3_set_ctx_test(&ctx); */
2142
2143                         /* Adds exts contained in the configuration file */
2144                         if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect,ret))
2145                                 {
2146                                 BIO_printf(bio_err,
2147                                     "ERROR: adding extensions in section %s\n",
2148                                                                 ext_sect);
2149                                 ERR_print_errors(bio_err);
2150                                 goto err;
2151                                 }
2152                         if (verbose)
2153                                 BIO_printf(bio_err, "Successfully added extensions from file.\n");
2154                         }
2155                 else if (ext_sect)
2156                         {
2157                         /* We found extensions to be set from config file */
2158                         X509V3_set_nconf(&ctx, lconf);
2159
2160                         if(!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret))
2161                                 {
2162                                 BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2163                                 ERR_print_errors(bio_err);
2164                                 goto err;
2165                                 }
2166
2167                         if (verbose) 
2168                                 BIO_printf(bio_err, "Successfully added extensions from config\n");
2169                         }
2170                 }
2171
2172         /* Copy extensions from request (if any) */
2173
2174         if (!copy_extensions(ret, req, ext_copy))
2175                 {
2176                 BIO_printf(bio_err, "ERROR: adding extensions from request\n");
2177                 ERR_print_errors(bio_err);
2178                 goto err;
2179                 }
2180
2181
2182         if (!default_op)
2183                 {
2184                 BIO_printf(bio_err, "Certificate Details:\n");
2185                 /* Never print signature details because signature not present */
2186                 certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
2187                 X509_print_ex(bio_err, ret, nameopt, certopt); 
2188                 }
2189
2190         BIO_printf(bio_err,"Certificate is to be certified until ");
2191         ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
2192         if (days) BIO_printf(bio_err," (%d days)",days);
2193         BIO_printf(bio_err, "\n");
2194
2195         if (!batch)
2196                 {
2197
2198                 BIO_printf(bio_err,"Sign the certificate? [y/n]:");
2199                 (void)BIO_flush(bio_err);
2200                 buf[0]='\0';
2201                 fgets(buf,sizeof(buf)-1,stdin);
2202                 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
2203                         {
2204                         BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
2205                         ok=0;
2206                         goto err;
2207                         }
2208                 }
2209
2210
2211 #ifndef OPENSSL_NO_DSA
2212         if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
2213         pktmp=X509_get_pubkey(ret);
2214         if (EVP_PKEY_missing_parameters(pktmp) &&
2215                 !EVP_PKEY_missing_parameters(pkey))
2216                 EVP_PKEY_copy_parameters(pktmp,pkey);
2217         EVP_PKEY_free(pktmp);
2218 #endif
2219
2220         if (!X509_sign(ret,pkey,dgst))
2221                 goto err;
2222
2223         /* We now just add it to the database */
2224         row[DB_type]=(char *)OPENSSL_malloc(2);
2225
2226         tm=X509_get_notAfter(ret);
2227         row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2228         memcpy(row[DB_exp_date],tm->data,tm->length);
2229         row[DB_exp_date][tm->length]='\0';
2230
2231         row[DB_rev_date]=NULL;
2232
2233         /* row[DB_serial] done already */
2234         row[DB_file]=(char *)OPENSSL_malloc(8);
2235         /* row[DB_name] done already */
2236
2237         if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2238                 (row[DB_file] == NULL))
2239                 {
2240                 BIO_printf(bio_err,"Memory allocation failure\n");
2241                 goto err;
2242                 }
2243         strcpy(row[DB_file],"unknown");
2244         row[DB_type][0]='V';
2245         row[DB_type][1]='\0';
2246
2247         if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2248                 {
2249                 BIO_printf(bio_err,"Memory allocation failure\n");
2250                 goto err;
2251                 }
2252
2253         for (i=0; i<DB_NUMBER; i++)
2254                 {
2255                 irow[i]=row[i];
2256                 row[i]=NULL;
2257                 }
2258         irow[DB_NUMBER]=NULL;
2259
2260         if (!TXT_DB_insert(db,irow))
2261                 {
2262                 BIO_printf(bio_err,"failed to update database\n");
2263                 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2264                 goto err;
2265                 }
2266         ok=1;
2267 err:
2268         for (i=0; i<DB_NUMBER; i++)
2269                 if (row[i] != NULL) OPENSSL_free(row[i]);
2270
2271         if (CAname != NULL)
2272                 X509_NAME_free(CAname);
2273         if (subject != NULL)
2274                 X509_NAME_free(subject);
2275         if (tmptm != NULL)
2276                 ASN1_UTCTIME_free(tmptm);
2277         if (ok <= 0)
2278                 {
2279                 if (ret != NULL) X509_free(ret);
2280                 ret=NULL;
2281                 }
2282         else
2283                 *xret=ret;
2284         return(ok);
2285         }
2286
2287 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
2288         {
2289
2290         if (output_der)
2291                 {
2292                 (void)i2d_X509_bio(bp,x);
2293                 return;
2294                 }
2295 #if 0
2296         /* ??? Not needed since X509_print prints all this stuff anyway */
2297         f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
2298         BIO_printf(bp,"issuer :%s\n",f);
2299
2300         f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
2301         BIO_printf(bp,"subject:%s\n",f);
2302
2303         BIO_puts(bp,"serial :");
2304         i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
2305         BIO_puts(bp,"\n\n");
2306 #endif
2307         if (!notext)X509_print(bp,x);
2308         PEM_write_bio_X509(bp,x);
2309         }
2310
2311 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
2312              const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
2313              BIGNUM *serial, char *subj, char *startdate, char *enddate, long days,
2314              char *ext_sect, CONF *lconf, int verbose, unsigned long certopt,
2315              unsigned long nameopt, int default_op, int ext_copy)
2316         {
2317         STACK_OF(CONF_VALUE) *sk=NULL;
2318         LHASH *parms=NULL;
2319         X509_REQ *req=NULL;
2320         CONF_VALUE *cv=NULL;
2321         NETSCAPE_SPKI *spki = NULL;
2322         X509_REQ_INFO *ri;
2323         char *type,*buf;
2324         EVP_PKEY *pktmp=NULL;
2325         X509_NAME *n=NULL;
2326         X509_NAME_ENTRY *ne=NULL;
2327         int ok= -1,i,j;
2328         long errline;
2329         int nid;
2330
2331         /*
2332          * Load input file into a hash table.  (This is just an easy
2333          * way to read and parse the file, then put it into a convenient
2334          * STACK format).
2335          */
2336         parms=CONF_load(NULL,infile,&errline);
2337         if (parms == NULL)
2338                 {
2339                 BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
2340                 ERR_print_errors(bio_err);
2341                 goto err;
2342                 }
2343
2344         sk=CONF_get_section(parms, "default");
2345         if (sk_CONF_VALUE_num(sk) == 0)
2346                 {
2347                 BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2348                 CONF_free(parms);
2349                 goto err;
2350                 }
2351
2352         /*
2353          * Now create a dummy X509 request structure.  We don't actually
2354          * have an X509 request, but we have many of the components
2355          * (a public key, various DN components).  The idea is that we
2356          * put these components into the right X509 request structure
2357          * and we can use the same code as if you had a real X509 request.
2358          */
2359         req=X509_REQ_new();
2360         if (req == NULL)
2361                 {
2362                 ERR_print_errors(bio_err);
2363                 goto err;
2364                 }
2365
2366         /*
2367          * Build up the subject name set.
2368          */
2369         ri=req->req_info;
2370         n = ri->subject;
2371
2372         for (i = 0; ; i++)
2373                 {
2374                 if (sk_CONF_VALUE_num(sk) <= i) break;
2375
2376                 cv=sk_CONF_VALUE_value(sk,i);
2377                 type=cv->name;
2378                 /* Skip past any leading X. X: X, etc to allow for
2379                  * multiple instances
2380                  */
2381                 for (buf = cv->name; *buf ; buf++)
2382                         if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2383                                 {
2384                                 buf++;
2385                                 if (*buf) type = buf;
2386                                 break;
2387                                 }
2388
2389                 buf=cv->value;
2390                 if ((nid=OBJ_txt2nid(type)) == NID_undef)
2391                         {
2392                         if (strcmp(type, "SPKAC") == 0)
2393                                 {
2394                                 spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2395                                 if (spki == NULL)
2396                                         {
2397                                         BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2398                                         ERR_print_errors(bio_err);
2399                                         goto err;
2400                                         }
2401                                 }
2402                         continue;
2403                         }
2404
2405                 j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
2406                 if (fix_data(nid, &j) == 0)
2407                         {
2408                         BIO_printf(bio_err,
2409                                 "invalid characters in string %s\n",buf);
2410                         goto err;
2411                         }
2412
2413                 if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
2414                         (unsigned char *)buf,
2415                         strlen(buf))) == NULL)
2416                         goto err;
2417
2418                 if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
2419                 }
2420         if (spki == NULL)
2421                 {
2422                 BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2423                         infile);
2424                 goto err;
2425                 }
2426
2427         /*
2428          * Now extract the key from the SPKI structure.
2429          */
2430
2431         BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2432
2433         if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
2434                 {
2435                 BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2436                 goto err;
2437                 }
2438
2439         j = NETSCAPE_SPKI_verify(spki, pktmp);
2440         if (j <= 0)
2441                 {
2442                 BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2443                 goto err;
2444                 }
2445         BIO_printf(bio_err,"Signature ok\n");
2446
2447         X509_REQ_set_pubkey(req,pktmp);
2448         EVP_PKEY_free(pktmp);
2449         ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,startdate,enddate,
2450                    days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op,
2451                         ext_copy);
2452 err:
2453         if (req != NULL) X509_REQ_free(req);
2454         if (parms != NULL) CONF_free(parms);
2455         if (spki != NULL) NETSCAPE_SPKI_free(spki);
2456         if (ne != NULL) X509_NAME_ENTRY_free(ne);
2457
2458         return(ok);
2459         }
2460
2461 static int fix_data(int nid, int *type)
2462         {
2463         if (nid == NID_pkcs9_emailAddress)
2464                 *type=V_ASN1_IA5STRING;
2465         if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
2466                 *type=V_ASN1_T61STRING;
2467         if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
2468                 *type=V_ASN1_T61STRING;
2469         if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
2470                 return(0);
2471         if (nid == NID_pkcs9_unstructuredName)
2472                 *type=V_ASN1_IA5STRING;
2473         return(1);
2474         }
2475
2476 static int check_time_format(char *str)
2477         {
2478         ASN1_UTCTIME tm;
2479
2480         tm.data=(unsigned char *)str;
2481         tm.length=strlen(str);
2482         tm.type=V_ASN1_UTCTIME;
2483         return(ASN1_UTCTIME_check(&tm));
2484         }
2485
2486 static int do_revoke(X509 *x509, TXT_DB *db, int type, char *value)
2487         {
2488         ASN1_UTCTIME *tm=NULL;
2489         char *row[DB_NUMBER],**rrow,**irow;
2490         char *rev_str = NULL;
2491         BIGNUM *bn = NULL;
2492         int ok=-1,i;
2493
2494         for (i=0; i<DB_NUMBER; i++)
2495                 row[i]=NULL;
2496         row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2497         bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2498         row[DB_serial]=BN_bn2hex(bn);
2499         BN_free(bn);
2500         if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2501                 {
2502                 BIO_printf(bio_err,"Memory allocation failure\n");
2503                 goto err;
2504                 }
2505         /* We have to lookup by serial number because name lookup
2506          * skips revoked certs
2507          */
2508         rrow=TXT_DB_get_by_index(db,DB_serial,row);
2509         if (rrow == NULL)
2510                 {
2511                 BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]);
2512
2513                 /* We now just add it to the database */
2514                 row[DB_type]=(char *)OPENSSL_malloc(2);
2515
2516                 tm=X509_get_notAfter(x509);
2517                 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2518                 memcpy(row[DB_exp_date],tm->data,tm->length);
2519                 row[DB_exp_date][tm->length]='\0';
2520
2521                 row[DB_rev_date]=NULL;
2522
2523                 /* row[DB_serial] done already */
2524                 row[DB_file]=(char *)OPENSSL_malloc(8);
2525
2526                 /* row[DB_name] done already */
2527
2528                 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2529                         (row[DB_file] == NULL))
2530                         {
2531                         BIO_printf(bio_err,"Memory allocation failure\n");
2532                         goto err;
2533                         }
2534                 strcpy(row[DB_file],"unknown");
2535                 row[DB_type][0]='V';
2536                 row[DB_type][1]='\0';
2537
2538                 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2539                         {
2540                         BIO_printf(bio_err,"Memory allocation failure\n");
2541                         goto err;
2542                         }
2543
2544                 for (i=0; i<DB_NUMBER; i++)
2545                         {
2546                         irow[i]=row[i];
2547                         row[i]=NULL;
2548                         }
2549                 irow[DB_NUMBER]=NULL;
2550
2551                 if (!TXT_DB_insert(db,irow))
2552                         {
2553                         BIO_printf(bio_err,"failed to update database\n");
2554                         BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2555                         goto err;
2556                         }
2557
2558                 /* Revoke Certificate */
2559                 ok = do_revoke(x509,db, type, value);
2560
2561                 goto err;
2562
2563                 }
2564         else if (index_name_cmp((const char **)row,(const char **)rrow))
2565                 {
2566                 BIO_printf(bio_err,"ERROR:name does not match %s\n",
2567                            row[DB_name]);
2568                 goto err;
2569                 }
2570         else if (rrow[DB_type][0]=='R')
2571                 {
2572                 BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2573                            row[DB_serial]);
2574                 goto err;
2575                 }
2576         else
2577                 {
2578                 BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2579                 rev_str = make_revocation_str(type, value);
2580                 if (!rev_str)
2581                         {
2582                         BIO_printf(bio_err, "Error in revocation arguments\n");
2583                         goto err;
2584                         }
2585                 rrow[DB_type][0]='R';
2586                 rrow[DB_type][1]='\0';
2587                 rrow[DB_rev_date] = rev_str;
2588                 }
2589         ok=1;
2590 err:
2591         for (i=0; i<DB_NUMBER; i++)
2592                 {
2593                 if (row[i] != NULL) 
2594                         OPENSSL_free(row[i]);
2595                 }
2596         return(ok);
2597         }
2598
2599 static int get_certificate_status(const char *serial, TXT_DB *db)
2600         {
2601         char *row[DB_NUMBER],**rrow;
2602         int ok=-1,i;
2603
2604         /* Free Resources */
2605         for (i=0; i<DB_NUMBER; i++)
2606                 row[i]=NULL;
2607
2608         /* Malloc needed char spaces */
2609         row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2610         if (row[DB_serial] == NULL)
2611                 {
2612                 BIO_printf(bio_err,"Malloc failure\n");
2613                 goto err;
2614                 }
2615
2616         if (strlen(serial) % 2)
2617                 {
2618                 /* Set the first char to 0 */;
2619                 row[DB_serial][0]='0';
2620
2621                 /* Copy String from serial to row[DB_serial] */
2622                 memcpy(row[DB_serial]+1, serial, strlen(serial));
2623                 row[DB_serial][strlen(serial)+1]='\0';
2624                 }
2625         else
2626                 {
2627                 /* Copy String from serial to row[DB_serial] */
2628                 memcpy(row[DB_serial], serial, strlen(serial));
2629                 row[DB_serial][strlen(serial)]='\0';
2630                 }
2631                         
2632         /* Make it Upper Case */
2633         for (i=0; row[DB_serial][i] != '\0'; i++)
2634                 row[DB_serial][i] = toupper(row[DB_serial][i]);
2635         
2636
2637         ok=1;
2638
2639         /* Search for the certificate */
2640         rrow=TXT_DB_get_by_index(db,DB_serial,row);
2641         if (rrow == NULL)
2642                 {
2643                 BIO_printf(bio_err,"Serial %s not present in db.\n",
2644                                  row[DB_serial]);
2645                 ok=-1;
2646                 goto err;
2647                 }
2648         else if (rrow[DB_type][0]=='V')
2649                 {
2650                 BIO_printf(bio_err,"%s=Valid (%c)\n",
2651                         row[DB_serial], rrow[DB_type][0]);
2652                 goto err;
2653                 }
2654         else if (rrow[DB_type][0]=='R')
2655                 {
2656                 BIO_printf(bio_err,"%s=Revoked (%c)\n",
2657                         row[DB_serial], rrow[DB_type][0]);
2658                 goto err;
2659                 }
2660         else if (rrow[DB_type][0]=='E')
2661                 {
2662                 BIO_printf(bio_err,"%s=Expired (%c)\n",
2663                         row[DB_serial], rrow[DB_type][0]);
2664                 goto err;
2665                 }
2666         else if (rrow[DB_type][0]=='S')
2667                 {
2668                 BIO_printf(bio_err,"%s=Suspended (%c)\n",
2669                         row[DB_serial], rrow[DB_type][0]);
2670                 goto err;
2671                 }
2672         else
2673                 {
2674                 BIO_printf(bio_err,"%s=Unknown (%c).\n",
2675                         row[DB_serial], rrow[DB_type][0]);
2676                 ok=-1;
2677                 }
2678 err:
2679         for (i=0; i<DB_NUMBER; i++)
2680                 {
2681                 if (row[i] != NULL)
2682                         OPENSSL_free(row[i]);
2683                 }
2684         return(ok);
2685         }
2686
2687 static int do_updatedb (TXT_DB *db)
2688         {
2689         ASN1_UTCTIME    *a_tm = NULL;
2690         int i, cnt = 0;
2691         int db_y2k, a_y2k;  /* flags = 1 if y >= 2000 */ 
2692         char **rrow, *a_tm_s;
2693
2694         a_tm = ASN1_UTCTIME_new();
2695
2696         /* get actual time and make a string */
2697         a_tm = X509_gmtime_adj(a_tm, 0);
2698         a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2699         if (a_tm_s == NULL)
2700                 {
2701                 cnt = -1;
2702                 goto err;
2703                 }
2704
2705         memcpy(a_tm_s, a_tm->data, a_tm->length);
2706         a_tm_s[a_tm->length] = '\0';
2707
2708         if (strncmp(a_tm_s, "49", 2) <= 0)
2709                 a_y2k = 1;
2710         else
2711                 a_y2k = 0;
2712
2713         for (i = 0; i < sk_num(db->data); i++)
2714                 {
2715                 rrow = (char **) sk_value(db->data, i);
2716
2717                 if (rrow[DB_type][0] == 'V')
2718                         {
2719                         /* ignore entries that are not valid */
2720                         if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2721                                 db_y2k = 1;
2722                         else
2723                                 db_y2k = 0;
2724
2725                         if (db_y2k == a_y2k)
2726                                 {
2727                                 /* all on the same y2k side */
2728                                 if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2729                                         {
2730                                         rrow[DB_type][0]  = 'E';
2731                                         rrow[DB_type][1]  = '\0';
2732                                         cnt++;
2733
2734                                         BIO_printf(bio_err, "%s=Expired\n",
2735                                                         rrow[DB_serial]);
2736                                         }
2737                                 }
2738                         else if (db_y2k < a_y2k)
2739                                 {
2740                                 rrow[DB_type][0]  = 'E';
2741                                 rrow[DB_type][1]  = '\0';
2742                                 cnt++;
2743
2744                                 BIO_printf(bio_err, "%s=Expired\n",
2745                                                         rrow[DB_serial]);
2746                                 }
2747
2748                         }
2749                 }
2750
2751 err:
2752
2753         ASN1_UTCTIME_free(a_tm);
2754         OPENSSL_free(a_tm_s);
2755
2756         return (cnt);
2757         }
2758
2759 static char *crl_reasons[] = {
2760         /* CRL reason strings */
2761         "unspecified",
2762         "keyCompromise",
2763         "CACompromise",
2764         "affiliationChanged",
2765         "superseded", 
2766         "cessationOfOperation",
2767         "certificateHold",
2768         "removeFromCRL",
2769         /* Additional pseudo reasons */
2770         "holdInstruction",
2771         "keyTime",
2772         "CAkeyTime"
2773 };
2774
2775 #define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2776
2777 /* Given revocation information convert to a DB string.
2778  * The format of the string is:
2779  * revtime[,reason,extra]. Where 'revtime' is the
2780  * revocation time (the current time). 'reason' is the
2781  * optional CRL reason and 'extra' is any additional
2782  * argument
2783  */
2784
2785 char *make_revocation_str(int rev_type, char *rev_arg)
2786         {
2787         char *reason = NULL, *other = NULL, *str;
2788         ASN1_OBJECT *otmp;
2789         ASN1_UTCTIME *revtm = NULL;
2790         int i;
2791         switch (rev_type)
2792                 {
2793         case REV_NONE:
2794                 break;
2795
2796         case REV_CRL_REASON:
2797                 for (i = 0; i < 8; i++)
2798                         {
2799                         if (!strcasecmp(rev_arg, crl_reasons[i]))
2800                                 {
2801                                 reason = crl_reasons[i];
2802                                 break;
2803                                 }
2804                         }
2805                 if (reason == NULL)
2806                         {
2807                         BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2808                         return NULL;
2809                         }
2810                 break;
2811
2812         case REV_HOLD:
2813                 /* Argument is an OID */
2814
2815                 otmp = OBJ_txt2obj(rev_arg, 0);
2816                 ASN1_OBJECT_free(otmp);
2817
2818                 if (otmp == NULL)
2819                         {
2820                         BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2821                         return NULL;
2822                         }
2823
2824                 reason = "holdInstruction";
2825                 other = rev_arg;
2826                 break;
2827                 
2828         case REV_KEY_COMPROMISE:
2829         case REV_CA_COMPROMISE:
2830
2831                 /* Argument is the key compromise time  */
2832                 if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg))
2833                         {       
2834                         BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg);
2835                         return NULL;
2836                         }
2837                 other = rev_arg;
2838                 if (rev_type == REV_KEY_COMPROMISE)
2839                         reason = "keyTime";
2840                 else 
2841                         reason = "CAkeyTime";
2842
2843                 break;
2844
2845                 }
2846
2847         revtm = X509_gmtime_adj(NULL, 0);
2848
2849         i = revtm->length + 1;
2850
2851         if (reason) i += strlen(reason) + 1;
2852         if (other) i += strlen(other) + 1;
2853
2854         str = OPENSSL_malloc(i);
2855
2856         if (!str) return NULL;
2857
2858         strcpy(str, (char *)revtm->data);
2859         if (reason)
2860                 {
2861                 strcat(str, ",");
2862                 strcat(str, reason);
2863                 }
2864         if (other)
2865                 {
2866                 strcat(str, ",");
2867                 strcat(str, other);
2868                 }
2869         ASN1_UTCTIME_free(revtm);
2870         return str;
2871         }
2872
2873 /* Convert revocation field to X509_REVOKED entry 
2874  * return code:
2875  * 0 error
2876  * 1 OK
2877  * 2 OK and some extensions added (i.e. V2 CRL)
2878  */
2879
2880
2881 int make_revoked(X509_REVOKED *rev, char *str)
2882         {
2883         char *tmp = NULL;
2884         int reason_code = -1;
2885         int i, ret = 0;
2886         ASN1_OBJECT *hold = NULL;
2887         ASN1_GENERALIZEDTIME *comp_time = NULL;
2888         ASN1_ENUMERATED *rtmp = NULL;
2889
2890
2891         i = unpack_revinfo(&rev->revocationDate, &reason_code, &hold, &comp_time, str);
2892
2893         if (i == 0)
2894                 goto err;
2895
2896         if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
2897                 {
2898                 rtmp = ASN1_ENUMERATED_new();
2899                 if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
2900                         goto err;
2901                 if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
2902                         goto err;
2903                 }
2904
2905         if (rev && comp_time)
2906                 {
2907                 if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
2908                         goto err;
2909                 }
2910         if (rev && hold)
2911                 {
2912                 if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
2913                         goto err;
2914                 }
2915
2916         if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
2917                 ret = 2;
2918         else ret = 1;
2919
2920         err:
2921
2922         if (tmp) OPENSSL_free(tmp);
2923         ASN1_OBJECT_free(hold);
2924         ASN1_GENERALIZEDTIME_free(comp_time);
2925         ASN1_ENUMERATED_free(rtmp);
2926
2927         return ret;
2928         }
2929
2930 static X509_NAME *do_subject(char *subject)
2931         {
2932         X509_NAME *n = NULL;
2933
2934         int i, nid, ne_num=0;
2935
2936         char *ne_name = NULL;
2937         char *ne_value = NULL;
2938
2939         char *tmp = NULL;
2940         char *p[2];
2941
2942         char *str_list[256];
2943        
2944         p[0] = ",/";
2945         p[1] = "=";
2946
2947         n = X509_NAME_new();
2948
2949         tmp = strtok(subject, p[0]);
2950         while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list)))
2951                 {
2952                 char *token = tmp;
2953
2954                 while (token[0] == ' ')
2955                         token++;
2956                 str_list[ne_num] = token;
2957
2958                 tmp = strtok(NULL, p[0]);
2959                 ne_num++;
2960                 }
2961
2962         for (i = 0; i < ne_num; i++)
2963                 {
2964                 ne_name  = strtok(str_list[i], p[1]);
2965                 ne_value = strtok(NULL, p[1]);
2966
2967                 if ((nid=OBJ_txt2nid(ne_name)) == NID_undef)
2968                         {
2969                         BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_name);
2970                         continue;
2971                         }
2972
2973                 if (ne_value == NULL)
2974                         {
2975                         BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_name);
2976                         continue;
2977                         }
2978
2979                 if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned char*)ne_value, -1,-1,0))
2980                         {
2981                         X509_NAME_free(n);
2982                         return NULL;
2983                         }
2984                 }
2985
2986         return n;
2987         }
2988
2989
2990 int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
2991         {
2992         char buf[25],*pbuf, *p;
2993         int j;
2994         j=i2a_ASN1_OBJECT(bp,obj);
2995         pbuf=buf;
2996         for (j=22-j; j>0; j--)
2997                 *(pbuf++)=' ';
2998         *(pbuf++)=':';
2999         *(pbuf++)='\0';
3000         BIO_puts(bp,buf);
3001
3002         if (str->type == V_ASN1_PRINTABLESTRING)
3003                 BIO_printf(bp,"PRINTABLE:'");
3004         else if (str->type == V_ASN1_T61STRING)
3005                 BIO_printf(bp,"T61STRING:'");
3006         else if (str->type == V_ASN1_IA5STRING)
3007                 BIO_printf(bp,"IA5STRING:'");
3008         else if (str->type == V_ASN1_UNIVERSALSTRING)
3009                 BIO_printf(bp,"UNIVERSALSTRING:'");
3010         else
3011                 BIO_printf(bp,"ASN.1 %2d:'",str->type);
3012                         
3013         p=(char *)str->data;
3014         for (j=str->length; j>0; j--)
3015                 {
3016                 if ((*p >= ' ') && (*p <= '~'))
3017                         BIO_printf(bp,"%c",*p);
3018                 else if (*p & 0x80)
3019                         BIO_printf(bp,"\\0x%02X",*p);
3020                 else if ((unsigned char)*p == 0xf7)
3021                         BIO_printf(bp,"^?");
3022                 else    BIO_printf(bp,"^%c",*p+'@');
3023                 p++;
3024                 }
3025         BIO_printf(bp,"'\n");
3026         return 1;
3027         }
3028
3029 int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, char *str)
3030         {
3031         char *tmp = NULL;
3032         char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
3033         int reason_code = -1;
3034         int i, ret = 0;
3035         ASN1_OBJECT *hold = NULL;
3036         ASN1_GENERALIZEDTIME *comp_time = NULL;
3037         tmp = BUF_strdup(str);
3038
3039         p = strchr(tmp, ',');
3040
3041         rtime_str = tmp;
3042
3043         if (p)
3044                 {
3045                 *p = '\0';
3046                 p++;
3047                 reason_str = p;
3048                 p = strchr(p, ',');
3049                 if (p)
3050                         {
3051                         *p = '\0';
3052                         arg_str = p + 1;
3053                         }
3054                 }
3055
3056         if (prevtm)
3057                 {
3058                 *prevtm = ASN1_UTCTIME_new();
3059                 if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str))
3060                         {
3061                         BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
3062                         goto err;
3063                         }
3064                 }
3065         if (reason_str)
3066                 {
3067                 for (i = 0; i < NUM_REASONS; i++)
3068                         {
3069                         if(!strcasecmp(reason_str, crl_reasons[i]))
3070                                 {
3071                                 reason_code = i;
3072                                 break;
3073                                 }
3074                         }
3075                 if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS)
3076                         {
3077                         BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
3078                         goto err;
3079                         }
3080
3081                 if (reason_code == 7)
3082                         reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
3083                 else if (reason_code == 8)              /* Hold instruction */
3084                         {
3085                         if (!arg_str)
3086                                 {       
3087                                 BIO_printf(bio_err, "missing hold instruction\n");
3088                                 goto err;
3089                                 }
3090                         reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
3091                         hold = OBJ_txt2obj(arg_str, 0);
3092
3093                         if (!hold)
3094                                 {
3095                                 BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
3096                                 goto err;
3097                                 }
3098                         if (phold) *phold = hold;
3099                         }
3100                 else if ((reason_code == 9) || (reason_code == 10))
3101                         {
3102                         if (!arg_str)
3103                                 {       
3104                                 BIO_printf(bio_err, "missing compromised time\n");
3105                                 goto err;
3106                                 }
3107                         comp_time = ASN1_GENERALIZEDTIME_new();
3108                         if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str))
3109                                 {       
3110                                 BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
3111                                 goto err;
3112                                 }
3113                         if (reason_code == 9)
3114                                 reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
3115                         else
3116                                 reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
3117                         }
3118                 }
3119
3120         if (preason) *preason = reason_code;
3121         if (pinvtm) *pinvtm = comp_time;
3122         else ASN1_GENERALIZEDTIME_free(comp_time);
3123
3124         err:
3125
3126         if (tmp) OPENSSL_free(tmp);
3127         if (!phold) ASN1_OBJECT_free(hold);
3128         if (!pinvtm) ASN1_GENERALIZEDTIME_free(comp_time);
3129
3130         return ret;
3131         }
3132
3133 int make_serial_index(TXT_DB *db)
3134         {
3135         if (!TXT_DB_create_index(db, DB_serial, NULL,
3136                                 LHASH_HASH_FN(index_serial_hash),
3137                                 LHASH_COMP_FN(index_serial_cmp)))
3138                 {
3139                 BIO_printf(bio_err,
3140                   "error creating serial number index:(%ld,%ld,%ld)\n",
3141                                         db->error,db->arg1,db->arg2);
3142                         return 0;
3143                 }
3144         return 1;
3145         }