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