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