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