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