contify
[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 alot 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 extentions 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 extentions 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 ASN1_TIME_set_string(X509_get_notAfter(ret),enddate);
2056
2057         if (!X509_set_subject_name(ret,subject)) goto err;
2058
2059         pktmp=X509_REQ_get_pubkey(req);
2060         i = X509_set_pubkey(ret,pktmp);
2061         EVP_PKEY_free(pktmp);
2062         if (!i) goto err;
2063
2064         /* Lets add the extensions, if there are any */
2065         if (ext_sect)
2066                 {
2067                 X509V3_CTX ctx;
2068                 if (ci->version == NULL)
2069                         if ((ci->version=ASN1_INTEGER_new()) == NULL)
2070                                 goto err;
2071                 ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
2072
2073                 /* Free the current entries if any, there should not
2074                  * be any I believe */
2075                 if (ci->extensions != NULL)
2076                         sk_X509_EXTENSION_pop_free(ci->extensions,
2077                                                    X509_EXTENSION_free);
2078
2079                 ci->extensions = NULL;
2080
2081                 /* Initialize the context structure */
2082                 if (selfsign)
2083                         X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0);
2084                 else
2085                         X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
2086
2087                 if (extconf)
2088                         {
2089                         if (verbose)
2090                                 BIO_printf(bio_err, "Extra configuration file found\n");
2091  
2092                         /* Use the extconf configuration db LHASH */
2093                         X509V3_set_nconf(&ctx, extconf);
2094  
2095                         /* Test the structure (needed?) */
2096                         /* X509V3_set_ctx_test(&ctx); */
2097
2098                         /* Adds exts contained in the configuration file */
2099                         if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect,ret))
2100                                 {
2101                                 BIO_printf(bio_err,
2102                                     "ERROR: adding extensions in section %s\n",
2103                                                                 ext_sect);
2104                                 ERR_print_errors(bio_err);
2105                                 goto err;
2106                                 }
2107                         if (verbose)
2108                                 BIO_printf(bio_err, "Successfully added extensions from file.\n");
2109                         }
2110                 else if (ext_sect)
2111                         {
2112                         /* We found extensions to be set from config file */
2113                         X509V3_set_nconf(&ctx, lconf);
2114
2115                         if(!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret))
2116                                 {
2117                                 BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2118                                 ERR_print_errors(bio_err);
2119                                 goto err;
2120                                 }
2121
2122                         if (verbose) 
2123                                 BIO_printf(bio_err, "Successfully added extensions from config\n");
2124                         }
2125                 }
2126
2127         /* Copy extensions from request (if any) */
2128
2129         if (!copy_extensions(ret, req, ext_copy))
2130                 {
2131                 BIO_printf(bio_err, "ERROR: adding extensions from request\n");
2132                 ERR_print_errors(bio_err);
2133                 goto err;
2134                 }
2135
2136         /* Set the right value for the noemailDN option */
2137         if( email_dn == 0 )
2138                 {
2139                 if (!X509_set_subject_name(ret,dn_subject)) goto err;
2140                 }
2141
2142         if (!default_op)
2143                 {
2144                 BIO_printf(bio_err, "Certificate Details:\n");
2145                 /* Never print signature details because signature not present */
2146                 certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
2147                 X509_print_ex(bio_err, ret, nameopt, certopt); 
2148                 }
2149
2150         BIO_printf(bio_err,"Certificate is to be certified until ");
2151         ASN1_TIME_print(bio_err,X509_get_notAfter(ret));
2152         if (days) BIO_printf(bio_err," (%ld days)",days);
2153         BIO_printf(bio_err, "\n");
2154
2155         if (!batch)
2156                 {
2157
2158                 BIO_printf(bio_err,"Sign the certificate? [y/n]:");
2159                 (void)BIO_flush(bio_err);
2160                 buf[0]='\0';
2161                 if (!fgets(buf,sizeof(buf)-1,stdin))
2162                         {
2163                         BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n");
2164                         ok=0;
2165                         goto err;
2166                         }
2167                 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
2168                         {
2169                         BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
2170                         ok=0;
2171                         goto err;
2172                         }
2173                 }
2174
2175         pktmp=X509_get_pubkey(ret);
2176         if (EVP_PKEY_missing_parameters(pktmp) &&
2177                 !EVP_PKEY_missing_parameters(pkey))
2178                 EVP_PKEY_copy_parameters(pktmp,pkey);
2179         EVP_PKEY_free(pktmp);
2180
2181         if (!do_X509_sign(bio_err, ret,pkey,dgst, sigopts))
2182                 goto err;
2183
2184         /* We now just add it to the database */
2185         row[DB_type]=(char *)OPENSSL_malloc(2);
2186
2187         tm=X509_get_notAfter(ret);
2188         row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2189         memcpy(row[DB_exp_date],tm->data,tm->length);
2190         row[DB_exp_date][tm->length]='\0';
2191
2192         row[DB_rev_date]=NULL;
2193
2194         /* row[DB_serial] done already */
2195         row[DB_file]=(char *)OPENSSL_malloc(8);
2196         row[DB_name]=X509_NAME_oneline(X509_get_subject_name(ret),NULL,0);
2197
2198         if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2199                 (row[DB_file] == NULL) || (row[DB_name] == NULL))
2200                 {
2201                 BIO_printf(bio_err,"Memory allocation failure\n");
2202                 goto err;
2203                 }
2204         BUF_strlcpy(row[DB_file],"unknown",8);
2205         row[DB_type][0]='V';
2206         row[DB_type][1]='\0';
2207
2208         if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2209                 {
2210                 BIO_printf(bio_err,"Memory allocation failure\n");
2211                 goto err;
2212                 }
2213
2214         for (i=0; i<DB_NUMBER; i++)
2215                 {
2216                 irow[i]=row[i];
2217                 row[i]=NULL;
2218                 }
2219         irow[DB_NUMBER]=NULL;
2220
2221         if (!TXT_DB_insert(db->db,irow))
2222                 {
2223                 BIO_printf(bio_err,"failed to update database\n");
2224                 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error);
2225                 goto err;
2226                 }
2227         ok=1;
2228 err:
2229         for (i=0; i<DB_NUMBER; i++)
2230                 if (row[i] != NULL) OPENSSL_free(row[i]);
2231
2232         if (CAname != NULL)
2233                 X509_NAME_free(CAname);
2234         if (subject != NULL)
2235                 X509_NAME_free(subject);
2236         if ((dn_subject != NULL) && !email_dn)
2237                 X509_NAME_free(dn_subject);
2238         if (tmptm != NULL)
2239                 ASN1_UTCTIME_free(tmptm);
2240         if (ok <= 0)
2241                 {
2242                 if (ret != NULL) X509_free(ret);
2243                 ret=NULL;
2244                 }
2245         else
2246                 *xret=ret;
2247         return(ok);
2248         }
2249
2250 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
2251         {
2252
2253         if (output_der)
2254                 {
2255                 (void)i2d_X509_bio(bp,x);
2256                 return;
2257                 }
2258 #if 0
2259         /* ??? Not needed since X509_print prints all this stuff anyway */
2260         f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
2261         BIO_printf(bp,"issuer :%s\n",f);
2262
2263         f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
2264         BIO_printf(bp,"subject:%s\n",f);
2265
2266         BIO_puts(bp,"serial :");
2267         i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
2268         BIO_puts(bp,"\n\n");
2269 #endif
2270         if (!notext)X509_print(bp,x);
2271         PEM_write_bio_X509(bp,x);
2272         }
2273
2274 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
2275              const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
2276              STACK_OF(CONF_VALUE) *policy, CA_DB *db,
2277              BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate,
2278              long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt,
2279              unsigned long nameopt, int default_op, int ext_copy)
2280         {
2281         STACK_OF(CONF_VALUE) *sk=NULL;
2282         LHASH_OF(CONF_VALUE) *parms=NULL;
2283         X509_REQ *req=NULL;
2284         CONF_VALUE *cv=NULL;
2285         NETSCAPE_SPKI *spki = NULL;
2286         X509_REQ_INFO *ri;
2287         char *type,*buf;
2288         EVP_PKEY *pktmp=NULL;
2289         X509_NAME *n=NULL;
2290         X509_NAME_ENTRY *ne=NULL;
2291         int ok= -1,i,j;
2292         long errline;
2293         int nid;
2294
2295         /*
2296          * Load input file into a hash table.  (This is just an easy
2297          * way to read and parse the file, then put it into a convenient
2298          * STACK format).
2299          */
2300         parms=CONF_load(NULL,infile,&errline);
2301         if (parms == NULL)
2302                 {
2303                 BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
2304                 ERR_print_errors(bio_err);
2305                 goto err;
2306                 }
2307
2308         sk=CONF_get_section(parms, "default");
2309         if (sk_CONF_VALUE_num(sk) == 0)
2310                 {
2311                 BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2312                 CONF_free(parms);
2313                 goto err;
2314                 }
2315
2316         /*
2317          * Now create a dummy X509 request structure.  We don't actually
2318          * have an X509 request, but we have many of the components
2319          * (a public key, various DN components).  The idea is that we
2320          * put these components into the right X509 request structure
2321          * and we can use the same code as if you had a real X509 request.
2322          */
2323         req=X509_REQ_new();
2324         if (req == NULL)
2325                 {
2326                 ERR_print_errors(bio_err);
2327                 goto err;
2328                 }
2329
2330         /*
2331          * Build up the subject name set.
2332          */
2333         ri=req->req_info;
2334         n = ri->subject;
2335
2336         for (i = 0; ; i++)
2337                 {
2338                 if (sk_CONF_VALUE_num(sk) <= i) break;
2339
2340                 cv=sk_CONF_VALUE_value(sk,i);
2341                 type=cv->name;
2342                 /* Skip past any leading X. X: X, etc to allow for
2343                  * multiple instances
2344                  */
2345                 for (buf = cv->name; *buf ; buf++)
2346                         if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2347                                 {
2348                                 buf++;
2349                                 if (*buf) type = buf;
2350                                 break;
2351                                 }
2352
2353                 buf=cv->value;
2354                 if ((nid=OBJ_txt2nid(type)) == NID_undef)
2355                         {
2356                         if (strcmp(type, "SPKAC") == 0)
2357                                 {
2358                                 spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2359                                 if (spki == NULL)
2360                                         {
2361                                         BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2362                                         ERR_print_errors(bio_err);
2363                                         goto err;
2364                                         }
2365                                 }
2366                         continue;
2367                         }
2368
2369                 if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
2370                                 (unsigned char *)buf, -1, -1, 0))
2371                         goto err;
2372                 }
2373         if (spki == NULL)
2374                 {
2375                 BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2376                         infile);
2377                 goto err;
2378                 }
2379
2380         /*
2381          * Now extract the key from the SPKI structure.
2382          */
2383
2384         BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2385
2386         if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
2387                 {
2388                 BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2389                 goto err;
2390                 }
2391
2392         j = NETSCAPE_SPKI_verify(spki, pktmp);
2393         if (j <= 0)
2394                 {
2395                 BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2396                 goto err;
2397                 }
2398         BIO_printf(bio_err,"Signature ok\n");
2399
2400         X509_REQ_set_pubkey(req,pktmp);
2401         EVP_PKEY_free(pktmp);
2402         ok=do_body(xret,pkey,x509,dgst,sigopts,policy,db,serial,subj,chtype,
2403                    multirdn,email_dn,startdate,enddate, days,1,verbose,req,
2404                    ext_sect,lconf, certopt, nameopt, default_op, ext_copy, 0);
2405 err:
2406         if (req != NULL) X509_REQ_free(req);
2407         if (parms != NULL) CONF_free(parms);
2408         if (spki != NULL) NETSCAPE_SPKI_free(spki);
2409         if (ne != NULL) X509_NAME_ENTRY_free(ne);
2410
2411         return(ok);
2412         }
2413
2414 static int check_time_format(const char *str)
2415         {
2416         return ASN1_TIME_set_string(NULL, str);
2417         }
2418
2419 static int do_revoke(X509 *x509, CA_DB *db, int type, char *value)
2420         {
2421         ASN1_UTCTIME *tm=NULL;
2422         char *row[DB_NUMBER],**rrow,**irow;
2423         char *rev_str = NULL;
2424         BIGNUM *bn = NULL;
2425         int ok=-1,i;
2426
2427         for (i=0; i<DB_NUMBER; i++)
2428                 row[i]=NULL;
2429         row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2430         bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2431         if (!bn)
2432                 goto err;
2433         if (BN_is_zero(bn))
2434                 row[DB_serial]=BUF_strdup("00");
2435         else
2436                 row[DB_serial]=BN_bn2hex(bn);
2437         BN_free(bn);
2438         if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2439                 {
2440                 BIO_printf(bio_err,"Memory allocation failure\n");
2441                 goto err;
2442                 }
2443         /* We have to lookup by serial number because name lookup
2444          * skips revoked certs
2445          */
2446         rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
2447         if (rrow == NULL)
2448                 {
2449                 BIO_printf(bio_err,"Adding Entry with serial number %s to DB for %s\n", row[DB_serial], row[DB_name]);
2450
2451                 /* We now just add it to the database */
2452                 row[DB_type]=(char *)OPENSSL_malloc(2);
2453
2454                 tm=X509_get_notAfter(x509);
2455                 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2456                 memcpy(row[DB_exp_date],tm->data,tm->length);
2457                 row[DB_exp_date][tm->length]='\0';
2458
2459                 row[DB_rev_date]=NULL;
2460
2461                 /* row[DB_serial] done already */
2462                 row[DB_file]=(char *)OPENSSL_malloc(8);
2463
2464                 /* row[DB_name] done already */
2465
2466                 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2467                         (row[DB_file] == NULL))
2468                         {
2469                         BIO_printf(bio_err,"Memory allocation failure\n");
2470                         goto err;
2471                         }
2472                 BUF_strlcpy(row[DB_file],"unknown",8);
2473                 row[DB_type][0]='V';
2474                 row[DB_type][1]='\0';
2475
2476                 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2477                         {
2478                         BIO_printf(bio_err,"Memory allocation failure\n");
2479                         goto err;
2480                         }
2481
2482                 for (i=0; i<DB_NUMBER; i++)
2483                         {
2484                         irow[i]=row[i];
2485                         row[i]=NULL;
2486                         }
2487                 irow[DB_NUMBER]=NULL;
2488
2489                 if (!TXT_DB_insert(db->db,irow))
2490                         {
2491                         BIO_printf(bio_err,"failed to update database\n");
2492                         BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error);
2493                         goto err;
2494                         }
2495
2496                 /* Revoke Certificate */
2497                 if (type == -1)
2498                         ok = 1;
2499                 else
2500                         ok = do_revoke(x509,db, type, value);
2501
2502                 goto err;
2503
2504                 }
2505         else if (index_name_cmp_noconst(row, rrow))
2506                 {
2507                 BIO_printf(bio_err,"ERROR:name does not match %s\n",
2508                            row[DB_name]);
2509                 goto err;
2510                 }
2511         else if (type == -1)
2512                 {
2513                 BIO_printf(bio_err,"ERROR:Already present, serial number %s\n",
2514                            row[DB_serial]);
2515                 goto err;
2516                 }
2517         else if (rrow[DB_type][0]=='R')
2518                 {
2519                 BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2520                            row[DB_serial]);
2521                 goto err;
2522                 }
2523         else
2524                 {
2525                 BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2526                 rev_str = make_revocation_str(type, value);
2527                 if (!rev_str)
2528                         {
2529                         BIO_printf(bio_err, "Error in revocation arguments\n");
2530                         goto err;
2531                         }
2532                 rrow[DB_type][0]='R';
2533                 rrow[DB_type][1]='\0';
2534                 rrow[DB_rev_date] = rev_str;
2535                 }
2536         ok=1;
2537 err:
2538         for (i=0; i<DB_NUMBER; i++)
2539                 {
2540                 if (row[i] != NULL) 
2541                         OPENSSL_free(row[i]);
2542                 }
2543         return(ok);
2544         }
2545
2546 static int get_certificate_status(const char *serial, CA_DB *db)
2547         {
2548         char *row[DB_NUMBER],**rrow;
2549         int ok=-1,i;
2550
2551         /* Free Resources */
2552         for (i=0; i<DB_NUMBER; i++)
2553                 row[i]=NULL;
2554
2555         /* Malloc needed char spaces */
2556         row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2557         if (row[DB_serial] == NULL)
2558                 {
2559                 BIO_printf(bio_err,"Malloc failure\n");
2560                 goto err;
2561                 }
2562
2563         if (strlen(serial) % 2)
2564                 {
2565                 /* Set the first char to 0 */;
2566                 row[DB_serial][0]='0';
2567
2568                 /* Copy String from serial to row[DB_serial] */
2569                 memcpy(row[DB_serial]+1, serial, strlen(serial));
2570                 row[DB_serial][strlen(serial)+1]='\0';
2571                 }
2572         else
2573                 {
2574                 /* Copy String from serial to row[DB_serial] */
2575                 memcpy(row[DB_serial], serial, strlen(serial));
2576                 row[DB_serial][strlen(serial)]='\0';
2577                 }
2578                         
2579         /* Make it Upper Case */
2580         for (i=0; row[DB_serial][i] != '\0'; i++)
2581                 row[DB_serial][i] = toupper((unsigned char)row[DB_serial][i]);
2582         
2583
2584         ok=1;
2585
2586         /* Search for the certificate */
2587         rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
2588         if (rrow == NULL)
2589                 {
2590                 BIO_printf(bio_err,"Serial %s not present in db.\n",
2591                                  row[DB_serial]);
2592                 ok=-1;
2593                 goto err;
2594                 }
2595         else if (rrow[DB_type][0]=='V')
2596                 {
2597                 BIO_printf(bio_err,"%s=Valid (%c)\n",
2598                         row[DB_serial], rrow[DB_type][0]);
2599                 goto err;
2600                 }
2601         else if (rrow[DB_type][0]=='R')
2602                 {
2603                 BIO_printf(bio_err,"%s=Revoked (%c)\n",
2604                         row[DB_serial], rrow[DB_type][0]);
2605                 goto err;
2606                 }
2607         else if (rrow[DB_type][0]=='E')
2608                 {
2609                 BIO_printf(bio_err,"%s=Expired (%c)\n",
2610                         row[DB_serial], rrow[DB_type][0]);
2611                 goto err;
2612                 }
2613         else if (rrow[DB_type][0]=='S')
2614                 {
2615                 BIO_printf(bio_err,"%s=Suspended (%c)\n",
2616                         row[DB_serial], rrow[DB_type][0]);
2617                 goto err;
2618                 }
2619         else
2620                 {
2621                 BIO_printf(bio_err,"%s=Unknown (%c).\n",
2622                         row[DB_serial], rrow[DB_type][0]);
2623                 ok=-1;
2624                 }
2625 err:
2626         for (i=0; i<DB_NUMBER; i++)
2627                 {
2628                 if (row[i] != NULL)
2629                         OPENSSL_free(row[i]);
2630                 }
2631         return(ok);
2632         }
2633
2634 static int do_updatedb (CA_DB *db)
2635         {
2636         ASN1_UTCTIME    *a_tm = NULL;
2637         int i, cnt = 0;
2638         int db_y2k, a_y2k;  /* flags = 1 if y >= 2000 */ 
2639         char **rrow, *a_tm_s;
2640
2641         a_tm = ASN1_UTCTIME_new();
2642
2643         /* get actual time and make a string */
2644         a_tm = X509_gmtime_adj(a_tm, 0);
2645         a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2646         if (a_tm_s == NULL)
2647                 {
2648                 cnt = -1;
2649                 goto err;
2650                 }
2651
2652         memcpy(a_tm_s, a_tm->data, a_tm->length);
2653         a_tm_s[a_tm->length] = '\0';
2654
2655         if (strncmp(a_tm_s, "49", 2) <= 0)
2656                 a_y2k = 1;
2657         else
2658                 a_y2k = 0;
2659
2660         for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
2661                 {
2662                 rrow = sk_OPENSSL_PSTRING_value(db->db->data, i);
2663
2664                 if (rrow[DB_type][0] == 'V')
2665                         {
2666                         /* ignore entries that are not valid */
2667                         if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2668                                 db_y2k = 1;
2669                         else
2670                                 db_y2k = 0;
2671
2672                         if (db_y2k == a_y2k)
2673                                 {
2674                                 /* all on the same y2k side */
2675                                 if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2676                                         {
2677                                         rrow[DB_type][0]  = 'E';
2678                                         rrow[DB_type][1]  = '\0';
2679                                         cnt++;
2680
2681                                         BIO_printf(bio_err, "%s=Expired\n",
2682                                                         rrow[DB_serial]);
2683                                         }
2684                                 }
2685                         else if (db_y2k < a_y2k)
2686                                 {
2687                                 rrow[DB_type][0]  = 'E';
2688                                 rrow[DB_type][1]  = '\0';
2689                                 cnt++;
2690
2691                                 BIO_printf(bio_err, "%s=Expired\n",
2692                                                         rrow[DB_serial]);
2693                                 }
2694
2695                         }
2696                 }
2697
2698 err:
2699
2700         ASN1_UTCTIME_free(a_tm);
2701         OPENSSL_free(a_tm_s);
2702
2703         return (cnt);
2704         }
2705
2706 static const char *crl_reasons[] = {
2707         /* CRL reason strings */
2708         "unspecified",
2709         "keyCompromise",
2710         "CACompromise",
2711         "affiliationChanged",
2712         "superseded", 
2713         "cessationOfOperation",
2714         "certificateHold",
2715         "removeFromCRL",
2716         /* Additional pseudo reasons */
2717         "holdInstruction",
2718         "keyTime",
2719         "CAkeyTime"
2720 };
2721
2722 #define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2723
2724 /* Given revocation information convert to a DB string.
2725  * The format of the string is:
2726  * revtime[,reason,extra]. Where 'revtime' is the
2727  * revocation time (the current time). 'reason' is the
2728  * optional CRL reason and 'extra' is any additional
2729  * argument
2730  */
2731
2732 char *make_revocation_str(int rev_type, char *rev_arg)
2733         {
2734         char *other = NULL, *str;
2735         const char *reason = NULL;
2736         ASN1_OBJECT *otmp;
2737         ASN1_UTCTIME *revtm = NULL;
2738         int i;
2739         switch (rev_type)
2740                 {
2741         case REV_NONE:
2742                 break;
2743
2744         case REV_CRL_REASON:
2745                 for (i = 0; i < 8; i++)
2746                         {
2747                         if (!strcasecmp(rev_arg, crl_reasons[i]))
2748                                 {
2749                                 reason = crl_reasons[i];
2750                                 break;
2751                                 }
2752                         }
2753                 if (reason == NULL)
2754                         {
2755                         BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2756                         return NULL;
2757                         }
2758                 break;
2759
2760         case REV_HOLD:
2761                 /* Argument is an OID */
2762
2763                 otmp = OBJ_txt2obj(rev_arg, 0);
2764                 ASN1_OBJECT_free(otmp);
2765
2766                 if (otmp == NULL)
2767                         {
2768                         BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2769                         return NULL;
2770                         }
2771
2772                 reason = "holdInstruction";
2773                 other = rev_arg;
2774                 break;
2775                 
2776         case REV_KEY_COMPROMISE:
2777         case REV_CA_COMPROMISE:
2778
2779                 /* Argument is the key compromise time  */
2780                 if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg))
2781                         {       
2782                         BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg);
2783                         return NULL;
2784                         }
2785                 other = rev_arg;
2786                 if (rev_type == REV_KEY_COMPROMISE)
2787                         reason = "keyTime";
2788                 else 
2789                         reason = "CAkeyTime";
2790
2791                 break;
2792
2793                 }
2794
2795         revtm = X509_gmtime_adj(NULL, 0);
2796
2797         i = revtm->length + 1;
2798
2799         if (reason) i += strlen(reason) + 1;
2800         if (other) i += strlen(other) + 1;
2801
2802         str = OPENSSL_malloc(i);
2803
2804         if (!str) return NULL;
2805
2806         BUF_strlcpy(str, (char *)revtm->data, i);
2807         if (reason)
2808                 {
2809                 BUF_strlcat(str, ",", i);
2810                 BUF_strlcat(str, reason, i);
2811                 }
2812         if (other)
2813                 {
2814                 BUF_strlcat(str, ",", i);
2815                 BUF_strlcat(str, other, i);
2816                 }
2817         ASN1_UTCTIME_free(revtm);
2818         return str;
2819         }
2820
2821 /* Convert revocation field to X509_REVOKED entry 
2822  * return code:
2823  * 0 error
2824  * 1 OK
2825  * 2 OK and some extensions added (i.e. V2 CRL)
2826  */
2827
2828
2829 int make_revoked(X509_REVOKED *rev, const char *str)
2830         {
2831         char *tmp = NULL;
2832         int reason_code = -1;
2833         int i, ret = 0;
2834         ASN1_OBJECT *hold = NULL;
2835         ASN1_GENERALIZEDTIME *comp_time = NULL;
2836         ASN1_ENUMERATED *rtmp = NULL;
2837
2838         ASN1_TIME *revDate = NULL;
2839
2840         i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str);
2841
2842         if (i == 0)
2843                 goto err;
2844
2845         if (rev && !X509_REVOKED_set_revocationDate(rev, revDate))
2846                 goto err;
2847
2848         if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
2849                 {
2850                 rtmp = ASN1_ENUMERATED_new();
2851                 if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
2852                         goto err;
2853                 if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
2854                         goto err;
2855                 }
2856
2857         if (rev && comp_time)
2858                 {
2859                 if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
2860                         goto err;
2861                 }
2862         if (rev && hold)
2863                 {
2864                 if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
2865                         goto err;
2866                 }
2867
2868         if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
2869                 ret = 2;
2870         else ret = 1;
2871
2872         err:
2873
2874         if (tmp) OPENSSL_free(tmp);
2875         ASN1_OBJECT_free(hold);
2876         ASN1_GENERALIZEDTIME_free(comp_time);
2877         ASN1_ENUMERATED_free(rtmp);
2878         ASN1_TIME_free(revDate);
2879
2880         return ret;
2881         }
2882
2883 int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
2884         {
2885         char buf[25],*pbuf, *p;
2886         int j;
2887         j=i2a_ASN1_OBJECT(bp,obj);
2888         pbuf=buf;
2889         for (j=22-j; j>0; j--)
2890                 *(pbuf++)=' ';
2891         *(pbuf++)=':';
2892         *(pbuf++)='\0';
2893         BIO_puts(bp,buf);
2894
2895         if (str->type == V_ASN1_PRINTABLESTRING)
2896                 BIO_printf(bp,"PRINTABLE:'");
2897         else if (str->type == V_ASN1_T61STRING)
2898                 BIO_printf(bp,"T61STRING:'");
2899         else if (str->type == V_ASN1_IA5STRING)
2900                 BIO_printf(bp,"IA5STRING:'");
2901         else if (str->type == V_ASN1_UNIVERSALSTRING)
2902                 BIO_printf(bp,"UNIVERSALSTRING:'");
2903         else
2904                 BIO_printf(bp,"ASN.1 %2d:'",str->type);
2905                         
2906         p=(char *)str->data;
2907         for (j=str->length; j>0; j--)
2908                 {
2909                 if ((*p >= ' ') && (*p <= '~'))
2910                         BIO_printf(bp,"%c",*p);
2911                 else if (*p & 0x80)
2912                         BIO_printf(bp,"\\0x%02X",*p);
2913                 else if ((unsigned char)*p == 0xf7)
2914                         BIO_printf(bp,"^?");
2915                 else    BIO_printf(bp,"^%c",*p+'@');
2916                 p++;
2917                 }
2918         BIO_printf(bp,"'\n");
2919         return 1;
2920         }
2921
2922 int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, const char *str)
2923         {
2924         char *tmp = NULL;
2925         char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
2926         int reason_code = -1;
2927         int ret = 0;
2928         unsigned int i;
2929         ASN1_OBJECT *hold = NULL;
2930         ASN1_GENERALIZEDTIME *comp_time = NULL;
2931         tmp = BUF_strdup(str);
2932
2933         p = strchr(tmp, ',');
2934
2935         rtime_str = tmp;
2936
2937         if (p)
2938                 {
2939                 *p = '\0';
2940                 p++;
2941                 reason_str = p;
2942                 p = strchr(p, ',');
2943                 if (p)
2944                         {
2945                         *p = '\0';
2946                         arg_str = p + 1;
2947                         }
2948                 }
2949
2950         if (prevtm)
2951                 {
2952                 *prevtm = ASN1_UTCTIME_new();
2953                 if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str))
2954                         {
2955                         BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
2956                         goto err;
2957                         }
2958                 }
2959         if (reason_str)
2960                 {
2961                 for (i = 0; i < NUM_REASONS; i++)
2962                         {
2963                         if(!strcasecmp(reason_str, crl_reasons[i]))
2964                                 {
2965                                 reason_code = i;
2966                                 break;
2967                                 }
2968                         }
2969                 if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS)
2970                         {
2971                         BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
2972                         goto err;
2973                         }
2974
2975                 if (reason_code == 7)
2976                         reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
2977                 else if (reason_code == 8)              /* Hold instruction */
2978                         {
2979                         if (!arg_str)
2980                                 {       
2981                                 BIO_printf(bio_err, "missing hold instruction\n");
2982                                 goto err;
2983                                 }
2984                         reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
2985                         hold = OBJ_txt2obj(arg_str, 0);
2986
2987                         if (!hold)
2988                                 {
2989                                 BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
2990                                 goto err;
2991                                 }
2992                         if (phold) *phold = hold;
2993                         }
2994                 else if ((reason_code == 9) || (reason_code == 10))
2995                         {
2996                         if (!arg_str)
2997                                 {       
2998                                 BIO_printf(bio_err, "missing compromised time\n");
2999                                 goto err;
3000                                 }
3001                         comp_time = ASN1_GENERALIZEDTIME_new();
3002                         if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str))
3003                                 {       
3004                                 BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
3005                                 goto err;
3006                                 }
3007                         if (reason_code == 9)
3008                                 reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
3009                         else
3010                                 reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
3011                         }
3012                 }
3013
3014         if (preason) *preason = reason_code;
3015         if (pinvtm) *pinvtm = comp_time;
3016         else ASN1_GENERALIZEDTIME_free(comp_time);
3017
3018         ret = 1;
3019
3020         err:
3021
3022         if (tmp) OPENSSL_free(tmp);
3023         if (!phold) ASN1_OBJECT_free(hold);
3024         if (!pinvtm) ASN1_GENERALIZEDTIME_free(comp_time);
3025
3026         return ret;
3027         }