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