11558Srgrimes/* apps/ca.c */
21558Srgrimes/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
31558Srgrimes * All rights reserved.
41558Srgrimes *
51558Srgrimes * This package is an SSL implementation written
61558Srgrimes * by Eric Young (eay@cryptsoft.com).
71558Srgrimes * The implementation was written so as to conform with Netscapes SSL.
81558Srgrimes *
91558Srgrimes * This library is free for commercial and non-commercial use as long as
101558Srgrimes * the following conditions are aheared to.  The following conditions
111558Srgrimes * apply to all code found in this distribution, be it the RC4, RSA,
121558Srgrimes * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
131558Srgrimes * included with this distribution is covered by the same copyright terms
141558Srgrimes * except that the holder is Tim Hudson (tjh@cryptsoft.com).
151558Srgrimes *
161558Srgrimes * Copyright remains Eric Young's, and as such any Copyright notices in
171558Srgrimes * the code are not to be removed.
181558Srgrimes * If this package is used in a product, Eric Young should be given attribution
191558Srgrimes * as the author of the parts of the library used.
201558Srgrimes * This can be in the form of a textual message at program startup or
211558Srgrimes * in documentation (online or textual) provided with the package.
221558Srgrimes *
231558Srgrimes * Redistribution and use in source and binary forms, with or without
241558Srgrimes * modification, are permitted provided that the following conditions
251558Srgrimes * are met:
261558Srgrimes * 1. Redistributions of source code must retain the copyright
271558Srgrimes *    notice, this list of conditions and the following disclaimer.
281558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
291558Srgrimes *    notice, this list of conditions and the following disclaimer in the
301558Srgrimes *    documentation and/or other materials provided with the distribution.
311558Srgrimes * 3. All advertising materials mentioning features or use of this software
321558Srgrimes *    must display the following acknowledgement:
331558Srgrimes *    "This product includes cryptographic software written by
3437663Scharnier *     Eric Young (eay@cryptsoft.com)"
351558Srgrimes *    The word 'cryptographic' can be left out if the rouines from the library
361558Srgrimes *    being used are not cryptographic related :-).
372999Swollman * 4. If you include any Windows specific code (or a derivative thereof) from
381558Srgrimes *    the apps directory (application code) you must include an acknowledgement:
39105267Scharnier *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
401558Srgrimes *
4137663Scharnier * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42105267Scharnier * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4337663Scharnier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
441558Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45105267Scharnier * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46105267Scharnier * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47105267Scharnier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
481558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
491558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5074462Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
511558Srgrimes * SUCH DAMAGE.
521558Srgrimes *
5324330Sguido * The licence and distribution terms for any publically available version or
5496622Siedowse * derivative of this code cannot be changed.  i.e. this code cannot simply be
5596622Siedowse * copied and put under another distribution licence
561558Srgrimes * [including the GNU Public Licence.]
571558Srgrimes */
58109363Smbr
591558Srgrimes/* The PPKI stuff has been donated by Jeff Barber <jeffb@issl.atl.hp.com> */
6074462Salfred
6174462Salfred#include <stdio.h>
621558Srgrimes#include <stdlib.h>
639336Sdfr#include <string.h>
6483653Speter#include <ctype.h>
6523681Speter#include <sys/types.h>
6677162Sru#include <openssl/conf.h>
6777223Sru#include <openssl/bio.h>
6823681Speter#include <openssl/err.h>
691558Srgrimes#include <openssl/bn.h>
701558Srgrimes#include <openssl/txt_db.h>
711558Srgrimes#include <openssl/evp.h>
721558Srgrimes#include <openssl/x509.h>
7337663Scharnier#include <openssl/x509v3.h>
741558Srgrimes#include <openssl/objects.h>
751558Srgrimes#include <openssl/ocsp.h>
76103949Smike#include <openssl/pem.h>
771558Srgrimes
781558Srgrimes#ifndef W_OK
791558Srgrimes# ifdef OPENSSL_SYS_VMS
801558Srgrimes#  if defined(__DECC)
811558Srgrimes#   include <unistd.h>
821558Srgrimes#  else
831558Srgrimes#   include <unixlib.h>
841558Srgrimes#  endif
851558Srgrimes# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_NETWARE)
861558Srgrimes#  include <sys/file.h>
871558Srgrimes# endif
881558Srgrimes#endif
891558Srgrimes
9074462Salfred#include "apps.h"
9174462Salfred
9274462Salfred#ifndef W_OK
9374462Salfred# define F_OK 0
941558Srgrimes# define X_OK 1
951558Srgrimes# define W_OK 2
961558Srgrimes# define R_OK 4
971558Srgrimes#endif
981558Srgrimes
991558Srgrimes#undef PROG
1001558Srgrimes#define PROG ca_main
1011558Srgrimes
1021558Srgrimes#define BASE_SECTION            "ca"
1031558Srgrimes#define CONFIG_FILE             "openssl.cnf"
1041558Srgrimes
1051558Srgrimes#define ENV_DEFAULT_CA          "default_ca"
1061558Srgrimes
1071558Srgrimes#define STRING_MASK             "string_mask"
1081558Srgrimes#define UTF8_IN                 "utf8"
1091558Srgrimes
1101558Srgrimes#define ENV_NEW_CERTS_DIR       "new_certs_dir"
1111558Srgrimes#define ENV_CERTIFICATE         "certificate"
1129336Sdfr#define ENV_SERIAL              "serial"
1131558Srgrimes#define ENV_CRLNUMBER           "crlnumber"
1141558Srgrimes#define ENV_PRIVATE_KEY         "private_key"
1151558Srgrimes#define ENV_DEFAULT_DAYS        "default_days"
1161558Srgrimes#define ENV_DEFAULT_STARTDATE   "default_startdate"
1171558Srgrimes#define ENV_DEFAULT_ENDDATE     "default_enddate"
1181558Srgrimes#define ENV_DEFAULT_CRL_DAYS    "default_crl_days"
1191558Srgrimes#define ENV_DEFAULT_CRL_HOURS   "default_crl_hours"
1201558Srgrimes#define ENV_DEFAULT_MD          "default_md"
12127447Sdfr#define ENV_DEFAULT_EMAIL_DN    "email_in_dn"
1221558Srgrimes#define ENV_PRESERVE            "preserve"
1231558Srgrimes#define ENV_POLICY              "policy"
1241558Srgrimes#define ENV_EXTENSIONS          "x509_extensions"
1251558Srgrimes#define ENV_CRLEXT              "crl_extensions"
1261558Srgrimes#define ENV_MSIE_HACK           "msie_hack"
12774462Salfred#define ENV_NAMEOPT             "name_opt"
12875801Siedowse#define ENV_CERTOPT             "cert_opt"
12942144Sdfr#define ENV_EXTCOPY             "copy_extensions"
1301558Srgrimes#define ENV_UNIQUE_SUBJECT      "unique_subject"
1311558Srgrimes
1321558Srgrimes#define ENV_DATABASE            "database"
13374462Salfred
1341558Srgrimes/* Additional revocation information types */
1351558Srgrimes
1361558Srgrimes#define REV_NONE                0 /* No addditional information */
1371558Srgrimes#define REV_CRL_REASON          1 /* Value is CRL reason code */
1381558Srgrimes#define REV_HOLD                2 /* Value is hold instruction */
1391558Srgrimes#define REV_KEY_COMPROMISE      3 /* Value is cert key compromise time */
1401558Srgrimes#define REV_CA_COMPROMISE       4 /* Value is CA key compromise time */
1411558Srgrimes
1421558Srgrimesstatic const char *ca_usage[] = {
1431558Srgrimes    "usage: ca args\n",
1441558Srgrimes    "\n",
1451558Srgrimes    " -verbose        - Talk alot while doing things\n",
14675641Siedowse    " -config file    - A config file\n",
1477401Swpaul    " -name arg       - The particular CA definition to use\n",
1481558Srgrimes    " -gencrl         - Generate a new CRL\n",
1491558Srgrimes    " -crldays days   - Days is when the next CRL is due\n",
1509336Sdfr    " -crlhours hours - Hours is when the next CRL is due\n",
1511558Srgrimes    " -startdate YYMMDDHHMMSSZ  - certificate validity notBefore\n",
1521558Srgrimes    " -enddate YYMMDDHHMMSSZ    - certificate validity notAfter (overrides -days)\n",
1531558Srgrimes    " -days arg       - number of days to certify the certificate for\n",
1541558Srgrimes    " -md arg         - md to use, one of md2, md5, sha or sha1\n",
1559336Sdfr    " -policy arg     - The CA 'policy' to support\n",
1569336Sdfr    " -keyfile arg    - private key file\n",
1579336Sdfr    " -keyform arg    - private key file format (PEM or ENGINE)\n",
1589336Sdfr    " -key arg        - key to decode the private key if it is encrypted\n",
1599336Sdfr    " -cert file      - The CA certificate\n",
1609336Sdfr    " -selfsign       - sign a certificate with the key associated with it\n",
1611558Srgrimes    " -in file        - The input PEM encoded certificate request(s)\n",
16292882Simp    " -out file       - Where to put the output file(s)\n",
16392882Simp    " -outdir dir     - Where to put output certificates\n",
16492882Simp    " -infiles ....   - The last argument, requests to process\n",
16592882Simp    " -spkac file     - File contains DN and signed public key and challenge\n",
16692882Simp    " -ss_cert file   - File contains a self signed cert to sign\n",
16792882Simp    " -preserveDN     - Don't re-order the DN\n",
16875801Siedowse    " -noemailDN      - Don't add the EMAIL field into certificate' subject\n",
16992882Simp    " -batch          - Don't ask questions\n",
17075635Siedowse    " -msie_hack      - msie modifications to handle all those universal strings\n",
17192882Simp    " -revoke file    - Revoke a certificate (given in file)\n",
17292882Simp    " -subj arg       - Use arg instead of request's subject\n",
17392882Simp    " -utf8           - input characters are UTF8 (default ASCII)\n",
17492882Simp    " -multivalue-rdn - enable support for multivalued RDNs\n",
17592882Simp    " -extensions ..  - Extension section (override value in config file)\n",
17692882Simp    " -extfile file   - Configuration file with X509v3 extentions to add\n",
17792882Simp    " -crlexts ..     - CRL extension section (override value in config file)\n",
17892882Simp#ifndef OPENSSL_NO_ENGINE
17992882Simp    " -engine e       - use engine e, possibly a hardware device.\n",
18092882Simp#endif
18192882Simp    " -status serial  - Shows certificate status given the serial number\n",
18292882Simp    " -updatedb       - Updates db for expired certificates\n",
18392882Simp    NULL
18492882Simp};
18592882Simp
18692882Simp#ifdef EFENCE
18792882Simpextern int EF_PROTECT_FREE;
18892882Simpextern int EF_PROTECT_BELOW;
18992882Simpextern int EF_ALIGNMENT;
19092882Simp#endif
19192882Simp
19275754Siedowsestatic void lookup_fail(const char *name, const char *tag);
19375801Siedowsestatic int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
19492882Simp                   const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
19592882Simp                   STACK_OF(CONF_VALUE) *policy, CA_DB *db,
19692882Simp                   BIGNUM *serial, char *subj, unsigned long chtype,
19792882Simp                   int multirdn, int email_dn, char *startdate, char *enddate,
198100117Salfred                   long days, int batch, char *ext_sect, CONF *conf,
19975801Siedowse                   int verbose, unsigned long certopt, unsigned long nameopt,
20075801Siedowse                   int default_op, int ext_copy, int selfsign);
20175801Siedowsestatic int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
20292882Simp                        const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
20392882Simp                        STACK_OF(CONF_VALUE) *policy, CA_DB *db,
20492882Simp                        BIGNUM *serial, char *subj, unsigned long chtype,
20592882Simp                        int multirdn, int email_dn, char *startdate,
206100117Salfred                        char *enddate, long days, int batch, char *ext_sect,
20792882Simp                        CONF *conf, int verbose, unsigned long certopt,
20892882Simp                        unsigned long nameopt, int default_op, int ext_copy,
20992882Simp                        ENGINE *e);
2101558Srgrimesstatic int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey,
2111558Srgrimes                         X509 *x509, const EVP_MD *dgst,
2121558Srgrimes                         STACK_OF(OPENSSL_STRING) *sigopts,
2131558Srgrimes                         STACK_OF(CONF_VALUE) *policy, CA_DB *db,
2141558Srgrimes                         BIGNUM *serial, char *subj, unsigned long chtype,
21572650Sgreen                         int multirdn, int email_dn, char *startdate,
21691354Sdd                         char *enddate, long days, char *ext_sect, CONF *conf,
21772650Sgreen                         int verbose, unsigned long certopt,
2181558Srgrimes                         unsigned long nameopt, int default_op, int ext_copy);
21972650Sgreenstatic void write_new_certificate(BIO *bp, X509 *x, int output_der,
22072650Sgreen                                  int notext);
2211558Srgrimesstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
22225087Sdfr                   const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
2239336Sdfr                   STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,
2249336Sdfr                   char *subj, unsigned long chtype, int multirdn,
225121767Speter                   int email_dn, char *startdate, char *enddate, long days,
22675754Siedowse                   int batch, int verbose, X509_REQ *req, char *ext_sect,
22774462Salfred                   CONF *conf, unsigned long certopt, unsigned long nameopt,
2281558Srgrimes                   int default_op, int ext_copy, int selfsign);
22974462Salfredstatic int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval);
23074462Salfredstatic int get_certificate_status(const char *ser_status, CA_DB *db);
23174462Salfredstatic int do_updatedb(CA_DB *db);
23275801Siedowsestatic int check_time_format(const char *str);
2331558Srgrimeschar *make_revocation_str(int rev_type, char *rev_arg);
2341558Srgrimesint make_revoked(X509_REVOKED *rev, const char *str);
23583653Speterint old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str);
2361558Srgrimesstatic CONF *conf = NULL;
2371558Srgrimesstatic CONF *extconf = NULL;
2381558Srgrimesstatic char *section = NULL;
23975801Siedowse
240100336Sjoergstatic int preserve = 0;
24174462Salfredstatic int msie_hack = 0;
2421558Srgrimes
2431558Srgrimesint MAIN(int, char **);
2441558Srgrimes
24592882Simpint MAIN(int argc, char **argv)
2461558Srgrimes{
2471558Srgrimes    ENGINE *e = NULL;
2481558Srgrimes    char *key = NULL, *passargin = NULL;
2491558Srgrimes    int create_ser = 0;
2501558Srgrimes    int free_key = 0;
2511558Srgrimes    int total = 0;
2521558Srgrimes    int total_done = 0;
2531558Srgrimes    int badops = 0;
2541558Srgrimes    int ret = 1;
2551558Srgrimes    int email_dn = 1;
2561558Srgrimes    int req = 0;
2571558Srgrimes    int verbose = 0;
2581558Srgrimes    int gencrl = 0;
2591558Srgrimes    int dorevoke = 0;
2601558Srgrimes    int doupdatedb = 0;
2611558Srgrimes    long crldays = 0;
2621558Srgrimes    long crlhours = 0;
26375754Siedowse    long crlsec = 0;
264126572Sbms    long errorline = -1;
265126572Sbms    char *configfile = NULL;
266126572Sbms    char *md = NULL;
26774462Salfred    char *policy = NULL;
26874462Salfred    char *keyfile = NULL;
26974462Salfred    char *certfile = NULL;
27074462Salfred    int keyform = FORMAT_PEM;
271109363Smbr    char *infile = NULL;
27274462Salfred    char *spkac_file = NULL;
273126572Sbms    char *ss_cert_file = NULL;
274126572Sbms    char *ser_status = NULL;
2751558Srgrimes    EVP_PKEY *pkey = NULL;
27675635Siedowse    int output_der = 0;
277126643Smarkm    char *outfile = NULL;
27875635Siedowse    char *outdir = NULL;
27974462Salfred    char *serialfile = NULL;
28074462Salfred    char *crlnumberfile = NULL;
28174462Salfred    char *extensions = NULL;
28274462Salfred    char *extfile = NULL;
28374462Salfred    char *subj = NULL;
284105267Scharnier    unsigned long chtype = MBSTRING_ASC;
28574462Salfred    int multirdn = 0;
28674462Salfred    char *tmp_email_dn = NULL;
28774462Salfred    char *crl_ext = NULL;
28874462Salfred    int rev_type = REV_NONE;
28974462Salfred    char *rev_arg = NULL;
29083687Speter    BIGNUM *serial = NULL;
29183687Speter    BIGNUM *crlnumber = NULL;
29283687Speter    char *startdate = NULL;
29383687Speter    char *enddate = NULL;
2942999Swollman    long days = 0;
2952999Swollman    int batch = 0;
296126572Sbms    int notext = 0;
2971558Srgrimes    unsigned long nameopt = 0, certopt = 0;
29825087Sdfr    int default_op = 1;
29925087Sdfr    int ext_copy = EXT_COPY_NONE;
30025087Sdfr    int selfsign = 0;
3019336Sdfr    X509 *x509 = NULL, *x509p = NULL;
3029336Sdfr    X509 *x = NULL;
3039336Sdfr    BIO *in = NULL, *out = NULL, *Sout = NULL, *Cout = NULL;
3049336Sdfr    char *dbfile = NULL;
3059336Sdfr    CA_DB *db = NULL;
3069336Sdfr    X509_CRL *crl = NULL;
3078688Sphk    X509_REVOKED *r = NULL;
3088688Sphk    ASN1_TIME *tmptm;
3098688Sphk    ASN1_INTEGER *tmpser;
31031656Sguido    char *f;
311121767Speter    const char *p;
31231656Sguido    char *const *pp;
313126572Sbms    int i, j;
314126572Sbms    const EVP_MD *dgst = NULL;
315126572Sbms    STACK_OF(CONF_VALUE) *attribs = NULL;
316126572Sbms    STACK_OF(X509) *cert_sk = NULL;
317126572Sbms    STACK_OF(OPENSSL_STRING) *sigopts = NULL;
318126572Sbms#undef BSIZE
319126572Sbms#define BSIZE 256
3201558Srgrimes    MS_STATIC char buf[3][BSIZE];
32137663Scharnier    char *randfile = NULL;
3221558Srgrimes#ifndef OPENSSL_NO_ENGINE
3231558Srgrimes    char *engine = NULL;
3241558Srgrimes#endif
3251558Srgrimes    char *tofree = NULL;
3261558Srgrimes    DB_ATTR db_attr;
3271558Srgrimes
3281558Srgrimes#ifdef EFENCE
3291558Srgrimes    EF_PROTECT_FREE = 1;
3301558Srgrimes    EF_PROTECT_BELOW = 1;
3311558Srgrimes    EF_ALIGNMENT = 0;
3321558Srgrimes#endif
3331558Srgrimes
3341558Srgrimes    apps_startup();
33537663Scharnier
3361558Srgrimes    conf = NULL;
3371558Srgrimes    key = NULL;
33837663Scharnier    section = NULL;
3391558Srgrimes
3401558Srgrimes    preserve = 0;
34137663Scharnier    msie_hack = 0;
3421558Srgrimes    if (bio_err == NULL)
3431558Srgrimes        if ((bio_err = BIO_new(BIO_s_file())) != NULL)
3441558Srgrimes            BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
3451558Srgrimes
3461558Srgrimes    argc--;
34775754Siedowse    argv++;
34874462Salfred    while (argc >= 1) {
3491558Srgrimes        if (strcmp(*argv, "-verbose") == 0)
3501558Srgrimes            verbose = 1;
3511558Srgrimes        else if (strcmp(*argv, "-config") == 0) {
3521558Srgrimes            if (--argc < 1)
3531558Srgrimes                goto bad;
3541558Srgrimes            configfile = *(++argv);
35574462Salfred        } else if (strcmp(*argv, "-name") == 0) {
35674462Salfred            if (--argc < 1)
35774462Salfred                goto bad;
35874462Salfred            section = *(++argv);
35974791Salfred        } else if (strcmp(*argv, "-subj") == 0) {
36074791Salfred            if (--argc < 1)
361109363Smbr                goto bad;
362109363Smbr            subj = *(++argv);
363109363Smbr            /* preserve=1; */
36474791Salfred        } else if (strcmp(*argv, "-utf8") == 0)
36574791Salfred            chtype = MBSTRING_UTF8;
36674462Salfred        else if (strcmp(*argv, "-create_serial") == 0)
36774462Salfred            create_ser = 1;
36874462Salfred        else if (strcmp(*argv, "-multivalue-rdn") == 0)
36974462Salfred            multirdn = 1;
37074462Salfred        else if (strcmp(*argv, "-startdate") == 0) {
37174462Salfred            if (--argc < 1)
37274462Salfred                goto bad;
37374462Salfred            startdate = *(++argv);
374117684Srwatson        } else if (strcmp(*argv, "-enddate") == 0) {
37574462Salfred            if (--argc < 1)
37674462Salfred                goto bad;
37774462Salfred            enddate = *(++argv);
37874462Salfred        } else if (strcmp(*argv, "-days") == 0) {
379117684Srwatson            if (--argc < 1)
380117684Srwatson                goto bad;
38174462Salfred            days = atoi(*(++argv));
38274462Salfred        } else if (strcmp(*argv, "-md") == 0) {
38374462Salfred            if (--argc < 1)
38474462Salfred                goto bad;
38574791Salfred            md = *(++argv);
38674791Salfred        } else if (strcmp(*argv, "-policy") == 0) {
38724759Sguido            if (--argc < 1)
38883687Speter                goto bad;
38983687Speter            policy = *(++argv);
39083687Speter        } else if (strcmp(*argv, "-keyfile") == 0) {
39124759Sguido            if (--argc < 1)
39224759Sguido                goto bad;
39324759Sguido            keyfile = *(++argv);
39424330Sguido        } else if (strcmp(*argv, "-keyform") == 0) {
395126572Sbms            if (--argc < 1)
396126572Sbms                goto bad;
397126572Sbms            keyform = str2fmt(*(++argv));
398126572Sbms        } else if (strcmp(*argv, "-passin") == 0) {
399126572Sbms            if (--argc < 1)
400126572Sbms                goto bad;
401126572Sbms            passargin = *(++argv);
402126572Sbms        } else if (strcmp(*argv, "-key") == 0) {
403126572Sbms            if (--argc < 1)
404126572Sbms                goto bad;
405126572Sbms            key = *(++argv);
40674462Salfred        } else if (strcmp(*argv, "-cert") == 0) {
407126572Sbms            if (--argc < 1)
408126572Sbms                goto bad;
409126572Sbms            certfile = *(++argv);
410126572Sbms        } else if (strcmp(*argv, "-selfsign") == 0)
411126572Sbms            selfsign = 1;
412126572Sbms        else if (strcmp(*argv, "-in") == 0) {
413126572Sbms            if (--argc < 1)
414126572Sbms                goto bad;
41574462Salfred            infile = *(++argv);
41674462Salfred            req = 1;
41774462Salfred        } else if (strcmp(*argv, "-out") == 0) {
41874462Salfred            if (--argc < 1)
41974462Salfred                goto bad;
42074462Salfred            outfile = *(++argv);
42174462Salfred        } else if (strcmp(*argv, "-outdir") == 0) {
42274462Salfred            if (--argc < 1)
42374462Salfred                goto bad;
42474462Salfred            outdir = *(++argv);
42574462Salfred        } else if (strcmp(*argv, "-sigopt") == 0) {
42674462Salfred            if (--argc < 1)
42774462Salfred                goto bad;
42874462Salfred            if (!sigopts)
42974462Salfred                sigopts = sk_OPENSSL_STRING_new_null();
43074462Salfred            if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
43174462Salfred                goto bad;
43274462Salfred        } else if (strcmp(*argv, "-notext") == 0)
43374462Salfred            notext = 1;
434126572Sbms        else if (strcmp(*argv, "-batch") == 0)
435126572Sbms            batch = 1;
436126572Sbms        else if (strcmp(*argv, "-preserveDN") == 0)
437126572Sbms            preserve = 1;
438126572Sbms        else if (strcmp(*argv, "-noemailDN") == 0)
439126572Sbms            email_dn = 0;
440126572Sbms        else if (strcmp(*argv, "-gencrl") == 0)
441126572Sbms            gencrl = 1;
44274462Salfred        else if (strcmp(*argv, "-msie_hack") == 0)
443109363Smbr            msie_hack = 1;
44474462Salfred        else if (strcmp(*argv, "-crldays") == 0) {
44574462Salfred            if (--argc < 1)
44674462Salfred                goto bad;
44774462Salfred            crldays = atol(*(++argv));
44874462Salfred        } else if (strcmp(*argv, "-crlhours") == 0) {
44974462Salfred            if (--argc < 1)
45074462Salfred                goto bad;
45174462Salfred            crlhours = atol(*(++argv));
45274462Salfred        } else if (strcmp(*argv, "-crlsec") == 0) {
45374462Salfred            if (--argc < 1)
45474462Salfred                goto bad;
45574462Salfred            crlsec = atol(*(++argv));
45674462Salfred        } else if (strcmp(*argv, "-infiles") == 0) {
45774462Salfred            argc--;
45874462Salfred            argv++;
45974462Salfred            req = 1;
46074462Salfred            break;
46174791Salfred        } else if (strcmp(*argv, "-ss_cert") == 0) {
462126572Sbms            if (--argc < 1)
463126572Sbms                goto bad;
464126572Sbms            ss_cert_file = *(++argv);
465126572Sbms            req = 1;
466126572Sbms        } else if (strcmp(*argv, "-spkac") == 0) {
467126572Sbms            if (--argc < 1)
468126572Sbms                goto bad;
469126572Sbms            spkac_file = *(++argv);
470126572Sbms            req = 1;
47174462Salfred        } else if (strcmp(*argv, "-revoke") == 0) {
47274462Salfred            if (--argc < 1)
47374462Salfred                goto bad;
47474462Salfred            infile = *(++argv);
47574462Salfred            dorevoke = 1;
47674462Salfred        } else if (strcmp(*argv, "-extensions") == 0) {
47774462Salfred            if (--argc < 1)
47874462Salfred                goto bad;
47974462Salfred            extensions = *(++argv);
48074462Salfred        } else if (strcmp(*argv, "-extfile") == 0) {
48174462Salfred            if (--argc < 1)
48274462Salfred                goto bad;
48374462Salfred            extfile = *(++argv);
48474462Salfred        } else if (strcmp(*argv, "-status") == 0) {
48574462Salfred            if (--argc < 1)
48674462Salfred                goto bad;
48774462Salfred            ser_status = *(++argv);
48874462Salfred        } else if (strcmp(*argv, "-updatedb") == 0) {
48974791Salfred            doupdatedb = 1;
490126572Sbms        } else if (strcmp(*argv, "-crlexts") == 0) {
491126572Sbms            if (--argc < 1)
492126572Sbms                goto bad;
493126572Sbms            crl_ext = *(++argv);
494126572Sbms        } else if (strcmp(*argv, "-crl_reason") == 0) {
495126572Sbms            if (--argc < 1)
496126572Sbms                goto bad;
497126572Sbms            rev_arg = *(++argv);
498126572Sbms            rev_type = REV_CRL_REASON;
49974462Salfred        } else if (strcmp(*argv, "-crl_hold") == 0) {
500109363Smbr            if (--argc < 1)
50174462Salfred                goto bad;
50274462Salfred            rev_arg = *(++argv);
50374462Salfred            rev_type = REV_HOLD;
50474462Salfred        } else if (strcmp(*argv, "-crl_compromise") == 0) {
50574462Salfred            if (--argc < 1)
50674462Salfred                goto bad;
50774462Salfred            rev_arg = *(++argv);
50874462Salfred            rev_type = REV_KEY_COMPROMISE;
50974462Salfred        } else if (strcmp(*argv, "-crl_CA_compromise") == 0) {
51074462Salfred            if (--argc < 1)
51174462Salfred                goto bad;
51274462Salfred            rev_arg = *(++argv);
51374462Salfred            rev_type = REV_CA_COMPROMISE;
51474462Salfred        }
51574462Salfred#ifndef OPENSSL_NO_ENGINE
51674462Salfred        else if (strcmp(*argv, "-engine") == 0) {
51774462Salfred            if (--argc < 1)
51874462Salfred                goto bad;
51974462Salfred            engine = *(++argv);
5201558Srgrimes        }
5211558Srgrimes#endif
52275754Siedowse        else {
52375754Siedowse bad:
52475754Siedowse            BIO_printf(bio_err, "unknown option %s\n", *argv);
52575754Siedowse            badops = 1;
52675754Siedowse            break;
52775754Siedowse        }
52875754Siedowse        argc--;
52975754Siedowse        argv++;
53075754Siedowse    }
53175754Siedowse
53275754Siedowse    if (badops) {
53375754Siedowse        const char **pp2;
53475754Siedowse
53575754Siedowse        for (pp2 = ca_usage; (*pp2 != NULL); pp2++)
53675754Siedowse            BIO_printf(bio_err, "%s", *pp2);
53775754Siedowse        goto err;
53875754Siedowse    }
53975754Siedowse
54075754Siedowse    ERR_load_crypto_strings();
54175754Siedowse
5421558Srgrimes        /*****************************************************************/
5431558Srgrimes    tofree = NULL;
54437663Scharnier    if (configfile == NULL)
54537663Scharnier        configfile = getenv("OPENSSL_CONF");
54637663Scharnier    if (configfile == NULL)
54737663Scharnier        configfile = getenv("SSLEAY_CONF");
548126572Sbms    if (configfile == NULL) {
549126572Sbms        const char *s = X509_get_default_cert_area();
55037663Scharnier        size_t len;
55137663Scharnier
55237663Scharnier#ifdef OPENSSL_SYS_VMS
5531558Srgrimes        len = strlen(s) + sizeof(CONFIG_FILE);
5541558Srgrimes        tofree = OPENSSL_malloc(len);
5551558Srgrimes        if (!tofree) {
5561558Srgrimes            BIO_printf(bio_err, "Out of memory\n");
5571558Srgrimes            goto err;
5581558Srgrimes        }
5591558Srgrimes        strcpy(tofree, s);
5601558Srgrimes#else
5611558Srgrimes        len = strlen(s) + sizeof(CONFIG_FILE) + 1;
5621558Srgrimes        tofree = OPENSSL_malloc(len);
5639336Sdfr        if (!tofree) {
5641558Srgrimes            BIO_printf(bio_err, "Out of memory\n");
5651558Srgrimes            goto err;
56674462Salfred        }
56774462Salfred        BUF_strlcpy(tofree, s, len);
56874462Salfred        BUF_strlcat(tofree, "/", len);
5699336Sdfr#endif
57023681Speter        BUF_strlcat(tofree, CONFIG_FILE, len);
57128911Sguido        configfile = tofree;
5729336Sdfr    }
5731558Srgrimes
5749336Sdfr    BIO_printf(bio_err, "Using configuration from %s\n", configfile);
5759336Sdfr    conf = NCONF_new(NULL);
57674462Salfred    if (NCONF_load(conf, configfile, &errorline) <= 0) {
57774462Salfred        if (errorline <= 0)
57874462Salfred            BIO_printf(bio_err, "error loading the config file '%s'\n",
57975635Siedowse                       configfile);
58074462Salfred        else
58174462Salfred            BIO_printf(bio_err, "error on line %ld of config file '%s'\n",
58275635Siedowse                       errorline, configfile);
58374462Salfred        goto err;
58474462Salfred    }
58574462Salfred    if (tofree) {
58674462Salfred        OPENSSL_free(tofree);
58774462Salfred        tofree = NULL;
58874462Salfred    }
58974462Salfred
59074462Salfred    if (!load_config(bio_err, conf))
59174462Salfred        goto err;
5921558Srgrimes
5931558Srgrimes#ifndef OPENSSL_NO_ENGINE
594121556Speter    e = setup_engine(bio_err, engine, 0);
59537663Scharnier#endif
5961558Srgrimes
5971558Srgrimes    /* Lets get the config section we are using */
5989336Sdfr    if (section == NULL) {
59931656Sguido        section = NCONF_get_string(conf, BASE_SECTION, ENV_DEFAULT_CA);
60031656Sguido        if (section == NULL) {
60174462Salfred            lookup_fail(BASE_SECTION, ENV_DEFAULT_CA);
6021558Srgrimes            goto err;
6031558Srgrimes        }
6041558Srgrimes    }
605121556Speter
60631656Sguido    if (conf != NULL) {
60774462Salfred        p = NCONF_get_string(conf, NULL, "oid_file");
6081558Srgrimes        if (p == NULL)
6091558Srgrimes            ERR_clear_error();
6101558Srgrimes        if (p != NULL) {
6111558Srgrimes            BIO *oid_bio;
6121558Srgrimes
6131558Srgrimes            oid_bio = BIO_new_file(p, "r");
6149336Sdfr            if (oid_bio == NULL) {
6159336Sdfr                /*-
6161558Srgrimes                BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
61751968Salfred                ERR_print_errors(bio_err);
6181558Srgrimes                */
6199336Sdfr                ERR_clear_error();
62074462Salfred            } else {
6211558Srgrimes                OBJ_create_objects(oid_bio);
6221558Srgrimes                BIO_free(oid_bio);
62331656Sguido            }
62437663Scharnier        }
62574462Salfred        if (!add_oid_section(bio_err, conf)) {
6261558Srgrimes            ERR_print_errors(bio_err);
62737663Scharnier            goto err;
62828911Sguido        }
6291558Srgrimes    }
6301558Srgrimes
6311558Srgrimes    randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
6329336Sdfr    if (randfile == NULL)
6331558Srgrimes        ERR_clear_error();
6349336Sdfr    app_RAND_load_file(randfile, bio_err, 0);
6359336Sdfr
6361558Srgrimes    f = NCONF_get_string(conf, section, STRING_MASK);
63774462Salfred    if (!f)
63874462Salfred        ERR_clear_error();
63974462Salfred
64028911Sguido    if (f && !ASN1_STRING_set_default_mask_asc(f)) {
641121556Speter        BIO_printf(bio_err, "Invalid global string mask setting %s\n", f);
64228911Sguido        goto err;
64337663Scharnier    }
64428911Sguido
64528911Sguido    if (chtype != MBSTRING_UTF8) {
64628911Sguido        f = NCONF_get_string(conf, section, UTF8_IN);
6479336Sdfr        if (!f)
6489336Sdfr            ERR_clear_error();
6499336Sdfr        else if (!strcmp(f, "yes"))
6509336Sdfr            chtype = MBSTRING_UTF8;
6519336Sdfr    }
6521558Srgrimes
65323681Speter    db_attr.unique_subject = 1;
6549336Sdfr    p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT);
6551558Srgrimes    if (p) {
65637663Scharnier#ifdef RL_DEBUG
657121556Speter        BIO_printf(bio_err, "DEBUG: unique_subject = \"%s\"\n", p);
6581558Srgrimes#endif
65937663Scharnier        db_attr.unique_subject = parse_yesno(p, 1);
6609336Sdfr    } else
6611558Srgrimes        ERR_clear_error();
6621558Srgrimes#ifdef RL_DEBUG
663121556Speter    if (!p)
664121556Speter        BIO_printf(bio_err, "DEBUG: unique_subject undefined\n");
66537663Scharnier#endif
66674462Salfred#ifdef RL_DEBUG
66774462Salfred    BIO_printf(bio_err, "DEBUG: configured unique_subject is %d\n",
6681558Srgrimes               db_attr.unique_subject);
66974462Salfred#endif
6701558Srgrimes
67137663Scharnier    in = BIO_new(BIO_s_file());
672121767Speter    out = BIO_new(BIO_s_file());
67331656Sguido    Sout = BIO_new(BIO_s_file());
67431656Sguido    Cout = BIO_new(BIO_s_file());
67574462Salfred    if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL)) {
67631656Sguido        ERR_print_errors(bio_err);
6771558Srgrimes        goto err;
67831656Sguido    }
67931656Sguido
68074462Salfred        /*****************************************************************/
68131656Sguido    /* report status of cert with serial number given on command line */
68228911Sguido    if (ser_status) {
683121556Speter        if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) {
684121556Speter            lookup_fail(section, ENV_DATABASE);
68537663Scharnier            goto err;
6869336Sdfr        }
6871558Srgrimes        db = load_index(dbfile, &db_attr);
6881558Srgrimes        if (db == NULL)
689121556Speter            goto err;
69037663Scharnier
691121767Speter        if (!index_index(db))
69231656Sguido            goto err;
69331656Sguido
69474462Salfred        if (get_certificate_status(ser_status, db) != 1)
6951558Srgrimes            BIO_printf(bio_err, "Error verifying serial %s!\n", ser_status);
6961558Srgrimes        goto err;
6979336Sdfr    }
69831656Sguido
69931656Sguido        /*****************************************************************/
70074462Salfred    /* we definitely need a private key, so let's get it */
7011558Srgrimes
7021558Srgrimes    if ((keyfile == NULL) && ((keyfile = NCONF_get_string(conf,
7031558Srgrimes                                                          section,
704121556Speter                                                          ENV_PRIVATE_KEY)) ==
70531656Sguido                              NULL)) {
70674462Salfred        lookup_fail(section, ENV_PRIVATE_KEY);
7071558Srgrimes        goto err;
7081558Srgrimes    }
7091558Srgrimes    if (!key) {
71051968Salfred        free_key = 1;
71151968Salfred        if (!app_passwd(bio_err, passargin, NULL, &key, NULL)) {
71251968Salfred            BIO_printf(bio_err, "Error getting password\n");
71374462Salfred            goto err;
71451968Salfred        }
715121556Speter    }
71637663Scharnier    pkey = load_key(bio_err, keyfile, keyform, 0, key, e, "CA private key");
71774462Salfred    if (key)
71875635Siedowse        OPENSSL_cleanse(key, strlen(key));
71975635Siedowse    if (pkey == NULL) {
720121767Speter        /* load_key() has already printed an appropriate message */
72131656Sguido        goto err;
72231656Sguido    }
72374462Salfred
7241558Srgrimes        /*****************************************************************/
7251558Srgrimes    /* we need a certificate */
7269336Sdfr    if (!selfsign || spkac_file || ss_cert_file || gencrl) {
72731656Sguido        if ((certfile == NULL)
72831656Sguido            && ((certfile = NCONF_get_string(conf,
72974462Salfred                                             section,
7301558Srgrimes                                             ENV_CERTIFICATE)) == NULL)) {
7311558Srgrimes            lookup_fail(section, ENV_CERTIFICATE);
7321558Srgrimes            goto err;
733121556Speter        }
73437663Scharnier        x509 = load_cert(bio_err, certfile, FORMAT_PEM, NULL, e,
73574462Salfred                         "CA certificate");
73675635Siedowse        if (x509 == NULL)
73775635Siedowse            goto err;
738121767Speter
73931656Sguido        if (!X509_check_private_key(x509, pkey)) {
74031656Sguido            BIO_printf(bio_err,
74174462Salfred                       "CA certificate and CA private key do not match\n");
7421558Srgrimes            goto err;
7431558Srgrimes        }
744121556Speter    }
745121556Speter    if (!selfsign)
746121556Speter        x509p = x509;
747100117Salfred
748121767Speter    f = NCONF_get_string(conf, BASE_SECTION, ENV_PRESERVE);
74931656Sguido    if (f == NULL)
75031656Sguido        ERR_clear_error();
75174462Salfred    if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
7521558Srgrimes        preserve = 1;
7531558Srgrimes    f = NCONF_get_string(conf, BASE_SECTION, ENV_MSIE_HACK);
7541558Srgrimes    if (f == NULL)
7551558Srgrimes        ERR_clear_error();
7561558Srgrimes    if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
7571558Srgrimes        msie_hack = 1;
7581558Srgrimes
7591558Srgrimes    f = NCONF_get_string(conf, section, ENV_NAMEOPT);
7601558Srgrimes
7611558Srgrimes    if (f) {
7621558Srgrimes        if (!set_name_ex(&nameopt, f)) {
7631558Srgrimes            BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f);
7641558Srgrimes            goto err;
7651558Srgrimes        }
7661558Srgrimes        default_op = 0;
7671558Srgrimes    } else
7681558Srgrimes        ERR_clear_error();
7691558Srgrimes
7701558Srgrimes    f = NCONF_get_string(conf, section, ENV_CERTOPT);
7719336Sdfr
7721558Srgrimes    if (f) {
7731558Srgrimes        if (!set_cert_ex(&certopt, f)) {
7749336Sdfr            BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f);
7751558Srgrimes            goto err;
7769336Sdfr        }
7771558Srgrimes        default_op = 0;
77892806Sobrien    } else
7799336Sdfr        ERR_clear_error();
7801558Srgrimes
7811558Srgrimes    f = NCONF_get_string(conf, section, ENV_EXTCOPY);
7821558Srgrimes
7839336Sdfr    if (f) {
7849336Sdfr        if (!set_ext_copy(&ext_copy, f)) {
7859336Sdfr            BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f);
7869336Sdfr            goto err;
7879336Sdfr        }
7889336Sdfr    } else
7899336Sdfr        ERR_clear_error();
7909336Sdfr
7919336Sdfr        /*****************************************************************/
79283653Speter    /* lookup where to write new certificates */
7939336Sdfr    if ((outdir == NULL) && (req)) {
7949336Sdfr
7959336Sdfr        if ((outdir = NCONF_get_string(conf, section, ENV_NEW_CERTS_DIR))
7969336Sdfr            == NULL) {
7979336Sdfr            BIO_printf(bio_err,
7989336Sdfr                       "there needs to be defined a directory for new certificate to be placed in\n");
7991558Srgrimes            goto err;
8001558Srgrimes        }
8011558Srgrimes#ifndef OPENSSL_SYS_VMS
8021558Srgrimes        /*
8031558Srgrimes         * outdir is a directory spec, but access() for VMS demands a
8041558Srgrimes         * filename.  In any case, stat(), below, will catch the problem if
8051558Srgrimes         * outdir is not a directory spec, and the fopen() or open() will
8061558Srgrimes         * catch an error if there is no write access.
8071558Srgrimes         *
8081558Srgrimes         * Presumably, this problem could also be solved by using the DEC C
8091558Srgrimes         * routines to convert the directory syntax to Unixly, and give that
8101558Srgrimes         * to access().  However, time's too short to do that just now.
8111558Srgrimes         */
8121558Srgrimes# ifndef _WIN32
8131558Srgrimes        if (access(outdir, R_OK | W_OK | X_OK) != 0)
8141558Srgrimes# else
8151558Srgrimes        if (_access(outdir, R_OK | W_OK | X_OK) != 0)
8161558Srgrimes# endif
8171558Srgrimes        {
8181558Srgrimes            BIO_printf(bio_err, "I am unable to access the %s directory\n",
8191558Srgrimes                       outdir);
8201558Srgrimes            perror(outdir);
8211558Srgrimes            goto err;
8221558Srgrimes        }
8231558Srgrimes
8241558Srgrimes        if (app_isdir(outdir) <= 0) {
8251558Srgrimes            BIO_printf(bio_err, "%s need to be a directory\n", outdir);
8261558Srgrimes            perror(outdir);
8271558Srgrimes            goto err;
8281558Srgrimes        }
8291558Srgrimes#endif
8301558Srgrimes    }
8311558Srgrimes
832100117Salfred        /*****************************************************************/
8331558Srgrimes    /* we need to load the database file */
8341558Srgrimes    if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) {
835100117Salfred        lookup_fail(section, ENV_DATABASE);
8361558Srgrimes        goto err;
8371558Srgrimes    }
8381558Srgrimes    db = load_index(dbfile, &db_attr);
8399336Sdfr    if (db == NULL)
8409336Sdfr        goto err;
8411558Srgrimes
8429336Sdfr    /* Lets check some fields */
8439336Sdfr    for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
8449336Sdfr        pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
8451558Srgrimes        if ((pp[DB_type][0] != DB_TYPE_REV) && (pp[DB_rev_date][0] != '\0')) {
8461558Srgrimes            BIO_printf(bio_err,
8471558Srgrimes                       "entry %d: not revoked yet, but has a revocation date\n",
848100117Salfred                       i + 1);
849100117Salfred            goto err;
8501558Srgrimes        }
8511558Srgrimes        if ((pp[DB_type][0] == DB_TYPE_REV) &&
8521558Srgrimes            !make_revoked(NULL, pp[DB_rev_date])) {
853100117Salfred            BIO_printf(bio_err, " in entry %d\n", i + 1);
8541558Srgrimes            goto err;
8551558Srgrimes        }
8561558Srgrimes        if (!check_time_format((char *)pp[DB_exp_date])) {
8579336Sdfr            BIO_printf(bio_err, "entry %d: invalid expiry date\n", i + 1);
8581558Srgrimes            goto err;
8591558Srgrimes        }
8601558Srgrimes        p = pp[DB_serial];
8611558Srgrimes        j = strlen(p);
8629336Sdfr        if (*p == '-') {
8631558Srgrimes            p++;
8641558Srgrimes            j--;
8651558Srgrimes        }
8661558Srgrimes        if ((j & 1) || (j < 2)) {
8671558Srgrimes            BIO_printf(bio_err, "entry %d: bad serial number length (%d)\n",
8681558Srgrimes                       i + 1, j);
8691558Srgrimes            goto err;
8701558Srgrimes        }
871100117Salfred        while (*p) {
8721558Srgrimes            if (!(((*p >= '0') && (*p <= '9')) ||
8731558Srgrimes                  ((*p >= 'A') && (*p <= 'F')) ||
8741558Srgrimes                  ((*p >= 'a') && (*p <= 'f')))) {
8751558Srgrimes                BIO_printf(bio_err,
876100117Salfred                           "entry %d: bad serial number characters, char pos %ld, char is '%c'\n",
8771558Srgrimes                           i + 1, (long)(p - pp[DB_serial]), *p);
8781558Srgrimes                goto err;
8791558Srgrimes            }
8801558Srgrimes            p++;
8811558Srgrimes        }
8821558Srgrimes    }
8831558Srgrimes    if (verbose) {
8841558Srgrimes        BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); /* cannot fail */
8851558Srgrimes#ifdef OPENSSL_SYS_VMS
886100117Salfred        {
8871558Srgrimes            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
8881558Srgrimes            out = BIO_push(tmpbio, out);
8891558Srgrimes        }
8901558Srgrimes#endif
8911558Srgrimes        TXT_DB_write(out, db->db);
8921558Srgrimes        BIO_printf(bio_err, "%d entries loaded from the database\n",
8931558Srgrimes                   sk_OPENSSL_PSTRING_num(db->db->data));
8941558Srgrimes        BIO_printf(bio_err, "generating index\n");
8951558Srgrimes    }
8961558Srgrimes
897100117Salfred    if (!index_index(db))
898100117Salfred        goto err;
899100117Salfred
900100117Salfred        /*****************************************************************/
901100117Salfred    /* Update the db file for expired certificates */
902100117Salfred    if (doupdatedb) {
903100117Salfred        if (verbose)
9041558Srgrimes            BIO_printf(bio_err, "Updating %s ...\n", dbfile);
9051558Srgrimes
9061558Srgrimes        i = do_updatedb(db);
9071558Srgrimes        if (i == -1) {
9081558Srgrimes            BIO_printf(bio_err, "Malloc failure\n");
9091558Srgrimes            goto err;
9101558Srgrimes        } else if (i == 0) {
91174462Salfred            if (verbose)
9128871Srgrimes                BIO_printf(bio_err, "No entries found to mark expired\n");
9131558Srgrimes        } else {
9141558Srgrimes            if (!save_index(dbfile, "new", db))
9151558Srgrimes                goto err;
9161558Srgrimes
9171558Srgrimes            if (!rotate_index(dbfile, "new", "old"))
9181558Srgrimes                goto err;
9198871Srgrimes
9201558Srgrimes            if (verbose)
9211558Srgrimes                BIO_printf(bio_err,
9221558Srgrimes                           "Done. %d entries marked as expired\n", i);
9231558Srgrimes        }
9241558Srgrimes    }
9251558Srgrimes
9261558Srgrimes        /*****************************************************************/
9271558Srgrimes    /* Read extentions config file                                   */
9281558Srgrimes    if (extfile) {
9291558Srgrimes        extconf = NCONF_new(NULL);
9301558Srgrimes        if (NCONF_load(extconf, extfile, &errorline) <= 0) {
9311558Srgrimes            if (errorline <= 0)
932100117Salfred                BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
9331558Srgrimes                           extfile);
9341558Srgrimes            else
9351558Srgrimes                BIO_printf(bio_err,
9361558Srgrimes                           "ERROR: on line %ld of config file '%s'\n",
9371558Srgrimes                           errorline, extfile);
938100117Salfred            ret = 1;
939100117Salfred            goto err;
940100117Salfred        }
941100117Salfred
942100117Salfred        if (verbose)
943100117Salfred            BIO_printf(bio_err, "Successfully loaded extensions file %s\n",
944100117Salfred                       extfile);
945100117Salfred
946100117Salfred        /* We can have sections in the ext file */
947100117Salfred        if (!extensions
948100117Salfred            && !(extensions =
949100117Salfred                 NCONF_get_string(extconf, "default", "extensions")))
950100117Salfred            extensions = "default";
951100117Salfred    }
952100117Salfred
953100117Salfred        /*****************************************************************/
954100117Salfred    if (req || gencrl) {
955100117Salfred        if (outfile != NULL) {
95696622Siedowse            if (BIO_write_filename(Sout, outfile) <= 0) {
95796622Siedowse                perror(outfile);
9581558Srgrimes                goto err;
9591558Srgrimes            }
9601558Srgrimes        } else {
9611558Srgrimes            BIO_set_fp(Sout, stdout, BIO_NOCLOSE | BIO_FP_TEXT);
9621558Srgrimes#ifdef OPENSSL_SYS_VMS
9631558Srgrimes            {
9641558Srgrimes                BIO *tmpbio = BIO_new(BIO_f_linebuffer());
9651558Srgrimes                Sout = BIO_push(tmpbio, Sout);
9661558Srgrimes            }
9671558Srgrimes#endif
9681558Srgrimes        }
9691558Srgrimes    }
9701558Srgrimes
97172650Sgreen    if ((md == NULL) && ((md = NCONF_get_string(conf,
9721558Srgrimes                                                section,
9731558Srgrimes                                                ENV_DEFAULT_MD)) == NULL)) {
9741558Srgrimes        lookup_fail(section, ENV_DEFAULT_MD);
97551968Salfred        goto err;
97651968Salfred    }
97751968Salfred
9781558Srgrimes    if (!strcmp(md, "default")) {
9791558Srgrimes        int def_nid;
9801558Srgrimes        if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0) {
9811558Srgrimes            BIO_puts(bio_err, "no default digest\n");
9821558Srgrimes            goto err;
9831558Srgrimes        }
9841558Srgrimes        md = (char *)OBJ_nid2sn(def_nid);
9851558Srgrimes    }
9861558Srgrimes
9871558Srgrimes    if ((dgst = EVP_get_digestbyname(md)) == NULL) {
9881558Srgrimes        BIO_printf(bio_err, "%s is an unsupported message digest type\n", md);
9891558Srgrimes        goto err;
9901558Srgrimes    }
9911558Srgrimes
9921558Srgrimes    if (req) {
9931558Srgrimes        if ((email_dn == 1) && ((tmp_email_dn = NCONF_get_string(conf,
9941558Srgrimes                                                                 section,
9951558Srgrimes                                                                 ENV_DEFAULT_EMAIL_DN))
9961558Srgrimes                                != NULL)) {
9971558Srgrimes            if (strcmp(tmp_email_dn, "no") == 0)
9981558Srgrimes                email_dn = 0;
99996707Strhodes        }
100096707Strhodes        if (verbose)
100123681Speter            BIO_printf(bio_err, "message digest is %s\n",
10021558Srgrimes                       OBJ_nid2ln(dgst->type));
10031558Srgrimes        if ((policy == NULL) && ((policy = NCONF_get_string(conf,
10041558Srgrimes                                                            section,
10051558Srgrimes                                                            ENV_POLICY)) ==
10061558Srgrimes                                 NULL)) {
10071558Srgrimes            lookup_fail(section, ENV_POLICY);
10089336Sdfr            goto err;
100954093Ssemenu        }
10101558Srgrimes        if (verbose)
10111558Srgrimes            BIO_printf(bio_err, "policy is %s\n", policy);
101277435Sphk
101377577Sru        if ((serialfile = NCONF_get_string(conf, section, ENV_SERIAL))
101454093Ssemenu            == NULL) {
101523681Speter            lookup_fail(section, ENV_SERIAL);
1016138680Sphk            goto err;
10179336Sdfr        }
10189336Sdfr
10199336Sdfr        if (!extconf) {
102077405Siedowse            /*
102177405Siedowse             * no '-extfile' option, so we look for extensions in the main
102277405Siedowse             * configuration file
102377405Siedowse             */
102474462Salfred            if (!extensions) {
10251558Srgrimes                extensions = NCONF_get_string(conf, section, ENV_EXTENSIONS);
10261558Srgrimes                if (!extensions)
10271558Srgrimes                    ERR_clear_error();
10281558Srgrimes            }
10291558Srgrimes            if (extensions) {
10301558Srgrimes                /* Check syntax of file */
10311558Srgrimes                X509V3_CTX ctx;
10321558Srgrimes                X509V3_set_ctx_test(&ctx);
10331558Srgrimes                X509V3_set_nconf(&ctx, conf);
103437663Scharnier                if (!X509V3_EXT_add_nconf(conf, &ctx, extensions, NULL)) {
10351558Srgrimes                    BIO_printf(bio_err,
10361558Srgrimes                               "Error Loading extension section %s\n",
10371558Srgrimes                               extensions);
10381558Srgrimes                    ret = 1;
10391558Srgrimes                    goto err;
104037663Scharnier                }
10411558Srgrimes            }
10421558Srgrimes        }
10431558Srgrimes
10441558Srgrimes        if (startdate == NULL) {
10451558Srgrimes            startdate = NCONF_get_string(conf, section,
10461558Srgrimes                                         ENV_DEFAULT_STARTDATE);
10471558Srgrimes            if (startdate == NULL)
10481558Srgrimes                ERR_clear_error();
10491558Srgrimes        }
10501558Srgrimes        if (startdate && !ASN1_TIME_set_string(NULL, startdate)) {
10511558Srgrimes            BIO_printf(bio_err,
10521558Srgrimes                       "start date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
10531558Srgrimes            goto err;
10541558Srgrimes        }
10551558Srgrimes        if (startdate == NULL)
10561558Srgrimes            startdate = "today";
10571558Srgrimes
10581558Srgrimes        if (enddate == NULL) {
10591558Srgrimes            enddate = NCONF_get_string(conf, section, ENV_DEFAULT_ENDDATE);
10601558Srgrimes            if (enddate == NULL)
10611558Srgrimes                ERR_clear_error();
10621558Srgrimes        }
10631558Srgrimes        if (enddate && !ASN1_TIME_set_string(NULL, enddate)) {
10641558Srgrimes            BIO_printf(bio_err,
10651558Srgrimes                       "end date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
10661558Srgrimes            goto err;
10671558Srgrimes        }
10681558Srgrimes
10691558Srgrimes        if (days == 0) {
10701558Srgrimes            if (!NCONF_get_number(conf, section, ENV_DEFAULT_DAYS, &days))
10711558Srgrimes                days = 0;
107237663Scharnier        }
10731558Srgrimes        if (!enddate && (days == 0)) {
10741558Srgrimes            BIO_printf(bio_err,
10751558Srgrimes                       "cannot lookup how many days to certify for\n");
10761558Srgrimes            goto err;
10771558Srgrimes        }
10781558Srgrimes
10791558Srgrimes        if ((serial = load_serial(serialfile, create_ser, NULL)) == NULL) {
10801558Srgrimes            BIO_printf(bio_err, "error while loading serial number\n");
10811558Srgrimes            goto err;
10821558Srgrimes        }
10831558Srgrimes        if (verbose) {
10841558Srgrimes            if (BN_is_zero(serial))
108537663Scharnier                BIO_printf(bio_err, "next serial number is 00\n");
10861558Srgrimes            else {
10871558Srgrimes                if ((f = BN_bn2hex(serial)) == NULL)
10881558Srgrimes                    goto err;
10891558Srgrimes                BIO_printf(bio_err, "next serial number is %s\n", f);
10901558Srgrimes                OPENSSL_free(f);
10911558Srgrimes            }
10921558Srgrimes        }
10931558Srgrimes
10941558Srgrimes        if ((attribs = NCONF_get_section(conf, policy)) == NULL) {
10951558Srgrimes            BIO_printf(bio_err, "unable to find 'section' for %s\n", policy);
10961558Srgrimes            goto err;
10971558Srgrimes        }
10981558Srgrimes
10991558Srgrimes        if ((cert_sk = sk_X509_new_null()) == NULL) {
11001558Srgrimes            BIO_printf(bio_err, "Memory allocation failure\n");
11011558Srgrimes            goto err;
11021558Srgrimes        }
11031558Srgrimes        if (spkac_file != NULL) {
11041558Srgrimes            total++;
11051558Srgrimes            j = certify_spkac(&x, spkac_file, pkey, x509, dgst, sigopts,
11061558Srgrimes                              attribs, db, serial, subj, chtype, multirdn,
11071558Srgrimes                              email_dn, startdate, enddate, days, extensions,
11081558Srgrimes                              conf, verbose, certopt, nameopt, default_op,
11091558Srgrimes                              ext_copy);
11101558Srgrimes            if (j < 0)
11111558Srgrimes                goto err;
111274462Salfred            if (j > 0) {
111374462Salfred                total_done++;
111474462Salfred                BIO_printf(bio_err, "\n");
11151558Srgrimes                if (!BN_add_word(serial, 1))
111637663Scharnier                    goto err;
11171558Srgrimes                if (!sk_X509_push(cert_sk, x)) {
11181558Srgrimes                    BIO_printf(bio_err, "Memory allocation failure\n");
11191558Srgrimes                    goto err;
11201558Srgrimes                }
11211558Srgrimes                if (outfile) {
11221558Srgrimes                    output_der = 1;
11231558Srgrimes                    batch = 1;
11241558Srgrimes                }
11251558Srgrimes            }
11261558Srgrimes        }
11271558Srgrimes        if (ss_cert_file != NULL) {
11281558Srgrimes            total++;
11291558Srgrimes            j = certify_cert(&x, ss_cert_file, pkey, x509, dgst, sigopts,
11301558Srgrimes                             attribs,
11311558Srgrimes                             db, serial, subj, chtype, multirdn, email_dn,
11321558Srgrimes                             startdate, enddate, days, batch, extensions,
11331558Srgrimes                             conf, verbose, certopt, nameopt, default_op,
11341558Srgrimes                             ext_copy, e);
11351558Srgrimes            if (j < 0)
11361558Srgrimes                goto err;
11371558Srgrimes            if (j > 0) {
11381558Srgrimes                total_done++;
11391558Srgrimes                BIO_printf(bio_err, "\n");
11401558Srgrimes                if (!BN_add_word(serial, 1))
11411558Srgrimes                    goto err;
11421558Srgrimes                if (!sk_X509_push(cert_sk, x)) {
11431558Srgrimes                    BIO_printf(bio_err, "Memory allocation failure\n");
11441558Srgrimes                    goto err;
11451558Srgrimes                }
11461558Srgrimes            }
11471558Srgrimes        }
11481558Srgrimes        if (infile != NULL) {
11491558Srgrimes            total++;
11501558Srgrimes            j = certify(&x, infile, pkey, x509p, dgst, sigopts, attribs, db,
115137003Sjoerg                        serial, subj, chtype, multirdn, email_dn, startdate,
115237663Scharnier                        enddate, days, batch, extensions, conf, verbose,
115337663Scharnier                        certopt, nameopt, default_op, ext_copy, selfsign);
115437004Sjoerg            if (j < 0)
115537003Sjoerg                goto err;
115637663Scharnier            if (j > 0) {
115737663Scharnier                total_done++;
115829317Sjlemon                BIO_printf(bio_err, "\n");
11591558Srgrimes                if (!BN_add_word(serial, 1))
11607401Swpaul                    goto err;
116137663Scharnier                if (!sk_X509_push(cert_sk, x)) {
116229317Sjlemon                    BIO_printf(bio_err, "Memory allocation failure\n");
11631558Srgrimes                    goto err;
11641558Srgrimes                }
11651558Srgrimes            }
11661558Srgrimes        }
11671558Srgrimes        for (i = 0; i < argc; i++) {
11681558Srgrimes            total++;
11691558Srgrimes            j = certify(&x, argv[i], pkey, x509p, dgst, sigopts, attribs, db,
11701558Srgrimes                        serial, subj, chtype, multirdn, email_dn, startdate,
11711558Srgrimes                        enddate, days, batch, extensions, conf, verbose,
11721558Srgrimes                        certopt, nameopt, default_op, ext_copy, selfsign);
11731558Srgrimes            if (j < 0)
11741558Srgrimes                goto err;
11751558Srgrimes            if (j > 0) {
11761558Srgrimes                total_done++;
11771558Srgrimes                BIO_printf(bio_err, "\n");
117875641Siedowse                if (!BN_add_word(serial, 1))
11791558Srgrimes                    goto err;
118037663Scharnier                if (!sk_X509_push(cert_sk, x)) {
11811558Srgrimes                    BIO_printf(bio_err, "Memory allocation failure\n");
11821558Srgrimes                    goto err;
11831558Srgrimes                }
11841558Srgrimes            }
11851558Srgrimes        }
11861558Srgrimes        /*
118775801Siedowse         * we have a stack of newly certified certificates and a data base
11881558Srgrimes         * and serial number that need updating
11891558Srgrimes         */
119029317Sjlemon
119174462Salfred        if (sk_X509_num(cert_sk) > 0) {
119274462Salfred            if (!batch) {
119329317Sjlemon                BIO_printf(bio_err,
119429317Sjlemon                           "\n%d out of %d certificate requests certified, commit? [y/n]",
119529317Sjlemon                           total_done, total);
119629317Sjlemon                (void)BIO_flush(bio_err);
119774462Salfred                buf[0][0] = '\0';
119829317Sjlemon                if (!fgets(buf[0], 10, stdin)) {
119929317Sjlemon                    BIO_printf(bio_err,
120029317Sjlemon                               "CERTIFICATION CANCELED: I/O error\n");
120129317Sjlemon                    ret = 0;
120229317Sjlemon                    goto err;
12031558Srgrimes                }
12041558Srgrimes                if ((buf[0][0] != 'y') && (buf[0][0] != 'Y')) {
12051558Srgrimes                    BIO_printf(bio_err, "CERTIFICATION CANCELED\n");
12061558Srgrimes                    ret = 0;
12071558Srgrimes                    goto err;
12081558Srgrimes                }
12091558Srgrimes            }
12101558Srgrimes
12111558Srgrimes            BIO_printf(bio_err, "Write out database with %d new entries\n",
121275635Siedowse                       sk_X509_num(cert_sk));
121375635Siedowse
121475635Siedowse            if (!save_serial(serialfile, "new", serial, NULL))
121575635Siedowse                goto err;
121675635Siedowse
12171558Srgrimes            if (!save_index(dbfile, "new", db))
12181558Srgrimes                goto err;
12191558Srgrimes        }
12201558Srgrimes
12211558Srgrimes        if (verbose)
12221558Srgrimes            BIO_printf(bio_err, "writing new certificates\n");
12239336Sdfr        for (i = 0; i < sk_X509_num(cert_sk); i++) {
12241558Srgrimes            int k;
12251558Srgrimes            char *n;
12261558Srgrimes
12271558Srgrimes            x = sk_X509_value(cert_sk, i);
12289336Sdfr
12291558Srgrimes            j = x->cert_info->serialNumber->length;
12301558Srgrimes            p = (const char *)x->cert_info->serialNumber->data;
12311558Srgrimes
12321558Srgrimes            if (strlen(outdir) >= (size_t)(j ? BSIZE - j * 2 - 6 : BSIZE - 8)) {
12331558Srgrimes                BIO_printf(bio_err, "certificate file name too long\n");
12341558Srgrimes                goto err;
12351558Srgrimes            }
12361558Srgrimes
12371558Srgrimes            strcpy(buf[2], outdir);
12381558Srgrimes
12391558Srgrimes#ifndef OPENSSL_SYS_VMS
12401558Srgrimes            BUF_strlcat(buf[2], "/", sizeof(buf[2]));
12411558Srgrimes#endif
12421558Srgrimes
12431558Srgrimes            n = (char *)&(buf[2][strlen(buf[2])]);
12441558Srgrimes            if (j > 0) {
12451558Srgrimes                for (k = 0; k < j; k++) {
12461558Srgrimes                    if (n >= &(buf[2][sizeof(buf[2])]))
12471558Srgrimes                        break;
12481558Srgrimes                    BIO_snprintf(n,
12491558Srgrimes                                 &buf[2][0] + sizeof(buf[2]) - n,
12501558Srgrimes                                 "%02X", (unsigned char)*(p++));
12511558Srgrimes                    n += 2;
12521558Srgrimes                }
12531558Srgrimes            } else {
12541558Srgrimes                *(n++) = '0';
12551558Srgrimes                *(n++) = '0';
12561558Srgrimes            }
12571558Srgrimes            *(n++) = '.';
12581558Srgrimes            *(n++) = 'p';
12591558Srgrimes            *(n++) = 'e';
12601558Srgrimes            *(n++) = 'm';
12611558Srgrimes            *n = '\0';
12621558Srgrimes            if (verbose)
12631558Srgrimes                BIO_printf(bio_err, "writing %s\n", buf[2]);
12641558Srgrimes
12651558Srgrimes            if (BIO_write_filename(Cout, buf[2]) <= 0) {
12661558Srgrimes                perror(buf[2]);
12671558Srgrimes                goto err;
126823681Speter            }
12691558Srgrimes            write_new_certificate(Cout, x, 0, notext);
12701558Srgrimes            write_new_certificate(Sout, x, output_der, notext);
12711558Srgrimes        }
12721558Srgrimes
12731558Srgrimes        if (sk_X509_num(cert_sk)) {
12741558Srgrimes            /* Rename the database and the serial file */
12751558Srgrimes            if (!rotate_serial(serialfile, "new", "old"))
12761558Srgrimes                goto err;
12771558Srgrimes
12781558Srgrimes            if (!rotate_index(dbfile, "new", "old"))
12791558Srgrimes                goto err;
12801558Srgrimes
12811558Srgrimes            BIO_printf(bio_err, "Data Base Updated\n");
12821558Srgrimes        }
128323681Speter    }
12841558Srgrimes
12851558Srgrimes        /*****************************************************************/
12861558Srgrimes    if (gencrl) {
12871558Srgrimes        int crl_v2 = 0;
12881558Srgrimes        if (!crl_ext) {
12891558Srgrimes            crl_ext = NCONF_get_string(conf, section, ENV_CRLEXT);
12901558Srgrimes            if (!crl_ext)
12911558Srgrimes                ERR_clear_error();
12921558Srgrimes        }
12931558Srgrimes        if (crl_ext) {
12941558Srgrimes            /* Check syntax of file */
12951558Srgrimes            X509V3_CTX ctx;
12961558Srgrimes            X509V3_set_ctx_test(&ctx);
1297100336Sjoerg            X509V3_set_nconf(&ctx, conf);
1298100336Sjoerg            if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL)) {
12991558Srgrimes                BIO_printf(bio_err,
13001558Srgrimes                           "Error Loading CRL extension section %s\n",
13011558Srgrimes                           crl_ext);
13021558Srgrimes                ret = 1;
13031558Srgrimes                goto err;
13041558Srgrimes            }
13051558Srgrimes        }
13061558Srgrimes
13071558Srgrimes        if ((crlnumberfile = NCONF_get_string(conf, section, ENV_CRLNUMBER))
13081558Srgrimes            != NULL)
13091558Srgrimes            if ((crlnumber = load_serial(crlnumberfile, 0, NULL)) == NULL) {
13101558Srgrimes                BIO_printf(bio_err, "error while loading CRL number\n");
13111558Srgrimes                goto err;
13121558Srgrimes            }
13131558Srgrimes
13141558Srgrimes        if (!crldays && !crlhours && !crlsec) {
13151558Srgrimes            if (!NCONF_get_number(conf, section,
13161558Srgrimes                                  ENV_DEFAULT_CRL_DAYS, &crldays))
13171558Srgrimes                crldays = 0;
13181558Srgrimes            if (!NCONF_get_number(conf, section,
13191558Srgrimes                                  ENV_DEFAULT_CRL_HOURS, &crlhours))
13201558Srgrimes                crlhours = 0;
13211558Srgrimes            ERR_clear_error();
13221558Srgrimes        }
13231558Srgrimes        if ((crldays == 0) && (crlhours == 0) && (crlsec == 0)) {
13241558Srgrimes            BIO_printf(bio_err,
13251558Srgrimes                       "cannot lookup how long until the next CRL is issued\n");
13261558Srgrimes            goto err;
13271558Srgrimes        }
13281558Srgrimes
13291558Srgrimes        if (verbose)
13301558Srgrimes            BIO_printf(bio_err, "making CRL\n");
13311558Srgrimes        if ((crl = X509_CRL_new()) == NULL)
13321558Srgrimes            goto err;
13331558Srgrimes        if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509)))
13341558Srgrimes            goto err;
13351558Srgrimes
13361558Srgrimes        tmptm = ASN1_TIME_new();
13371558Srgrimes        if (!tmptm)
13381558Srgrimes            goto err;
133937663Scharnier        X509_gmtime_adj(tmptm, 0);
134037663Scharnier        X509_CRL_set_lastUpdate(crl, tmptm);
13411558Srgrimes        if (!X509_time_adj_ex(tmptm, crldays, crlhours * 60 * 60 + crlsec,
13421558Srgrimes                              NULL)) {
13431558Srgrimes            BIO_puts(bio_err, "error setting CRL nextUpdate\n");
13441558Srgrimes            goto err;
13451558Srgrimes        }
13461558Srgrimes        X509_CRL_set_nextUpdate(crl, tmptm);
13471558Srgrimes
13481558Srgrimes        ASN1_TIME_free(tmptm);
13491558Srgrimes
13501558Srgrimes        for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
13511558Srgrimes            pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
13521558Srgrimes            if (pp[DB_type][0] == DB_TYPE_REV) {
13531558Srgrimes                if ((r = X509_REVOKED_new()) == NULL)
13541558Srgrimes                    goto err;
13559336Sdfr                j = make_revoked(r, pp[DB_rev_date]);
13561558Srgrimes                if (!j)
13571558Srgrimes                    goto err;
13581558Srgrimes                if (j == 2)
13599336Sdfr                    crl_v2 = 1;
13601558Srgrimes                if (!BN_hex2bn(&serial, pp[DB_serial]))
13611558Srgrimes                    goto err;
13621558Srgrimes                tmpser = BN_to_ASN1_INTEGER(serial, NULL);
13631558Srgrimes                BN_free(serial);
13649336Sdfr                serial = NULL;
13651558Srgrimes                if (!tmpser)
13661558Srgrimes                    goto err;
13671558Srgrimes                X509_REVOKED_set_serialNumber(r, tmpser);
13681558Srgrimes                ASN1_INTEGER_free(tmpser);
13699336Sdfr                X509_CRL_add0_revoked(crl, r);
13701558Srgrimes            }
13719336Sdfr        }
13721558Srgrimes
13731558Srgrimes        /*
13741558Srgrimes         * sort the data so it will be written in serial number order
13751558Srgrimes         */
13761558Srgrimes        X509_CRL_sort(crl);
13771558Srgrimes
13781558Srgrimes        /* we now have a CRL */
13791558Srgrimes        if (verbose)
13801558Srgrimes            BIO_printf(bio_err, "signing CRL\n");
138137663Scharnier
13821558Srgrimes        /* Add any extensions asked for */
13831558Srgrimes
13841558Srgrimes        if (crl_ext || crlnumberfile != NULL) {
13859336Sdfr            X509V3_CTX crlctx;
13861558Srgrimes            X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
13871558Srgrimes            X509V3_set_nconf(&crlctx, conf);
13881558Srgrimes
13891558Srgrimes            if (crl_ext)
13901558Srgrimes                if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl))
13911558Srgrimes                    goto err;
13921558Srgrimes            if (crlnumberfile != NULL) {
13931558Srgrimes                tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL);
13941558Srgrimes                if (!tmpser)
13951558Srgrimes                    goto err;
13969336Sdfr                X509_CRL_add1_ext_i2d(crl, NID_crl_number, tmpser, 0, 0);
13971558Srgrimes                ASN1_INTEGER_free(tmpser);
13981558Srgrimes                crl_v2 = 1;
13991558Srgrimes                if (!BN_add_word(crlnumber, 1))
14009336Sdfr                    goto err;
14011558Srgrimes            }
14021558Srgrimes        }
14031558Srgrimes        if (crl_ext || crl_v2) {
14041558Srgrimes            if (!X509_CRL_set_version(crl, 1))
14051558Srgrimes                goto err;       /* version 2 CRL */
14061558Srgrimes        }
14071558Srgrimes
14081558Srgrimes        /* we have a CRL number that need updating */
14091558Srgrimes        if (crlnumberfile != NULL)
14109336Sdfr            if (!save_serial(crlnumberfile, "new", crlnumber, NULL))
14111558Srgrimes                goto err;
14121558Srgrimes
14139336Sdfr        if (crlnumber) {
14141558Srgrimes            BN_free(crlnumber);
14151558Srgrimes            crlnumber = NULL;
14161558Srgrimes        }
14171558Srgrimes
14181558Srgrimes        if (!do_X509_CRL_sign(bio_err, crl, pkey, dgst, sigopts))
14191558Srgrimes            goto err;
14201558Srgrimes
14211558Srgrimes        PEM_write_bio_X509_CRL(Sout, crl);
14221558Srgrimes
14231558Srgrimes        if (crlnumberfile != NULL) /* Rename the crlnumber file */
14241558Srgrimes            if (!rotate_serial(crlnumberfile, "new", "old"))
14251558Srgrimes                goto err;
14261558Srgrimes
14271558Srgrimes    }
14281558Srgrimes        /*****************************************************************/
14291558Srgrimes    if (dorevoke) {
14301558Srgrimes        if (infile == NULL) {
14311558Srgrimes            BIO_printf(bio_err, "no input files\n");
14321558Srgrimes            goto err;
14331558Srgrimes        } else {
14349336Sdfr            X509 *revcert;
14351558Srgrimes            revcert = load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile);
14369336Sdfr            if (revcert == NULL)
14371558Srgrimes                goto err;
14381558Srgrimes            j = do_revoke(revcert, db, rev_type, rev_arg);
14391558Srgrimes            if (j <= 0)
14401558Srgrimes                goto err;
14411558Srgrimes            X509_free(revcert);
14421558Srgrimes
144374462Salfred            if (!save_index(dbfile, "new", db))
14441558Srgrimes                goto err;
144574462Salfred
14461558Srgrimes            if (!rotate_index(dbfile, "new", "old"))
14471558Srgrimes                goto err;
14481558Srgrimes
14491558Srgrimes            BIO_printf(bio_err, "Data Base Updated\n");
145074462Salfred        }
14511558Srgrimes    }
145274462Salfred        /*****************************************************************/
14531558Srgrimes    ret = 0;
145474462Salfred err:
14551558Srgrimes    if (tofree)
14561558Srgrimes        OPENSSL_free(tofree);
14571558Srgrimes    BIO_free_all(Cout);
14581558Srgrimes    BIO_free_all(Sout);
14591558Srgrimes    BIO_free_all(out);
14601558Srgrimes    BIO_free_all(in);
14611558Srgrimes
14621558Srgrimes    if (cert_sk)
14631558Srgrimes        sk_X509_pop_free(cert_sk, X509_free);
14641558Srgrimes
14659336Sdfr    if (ret)
14661558Srgrimes        ERR_print_errors(bio_err);
146774462Salfred    app_RAND_write_file(randfile, bio_err);
14681558Srgrimes    if (free_key && key)
14699336Sdfr        OPENSSL_free(key);
14701558Srgrimes    BN_free(serial);
14711558Srgrimes    BN_free(crlnumber);
14721558Srgrimes    free_index(db);
147374462Salfred    if (sigopts)
14741558Srgrimes        sk_OPENSSL_STRING_free(sigopts);
14751558Srgrimes    EVP_PKEY_free(pkey);
14761558Srgrimes    if (x509)
14779336Sdfr        X509_free(x509);
14781558Srgrimes    X509_CRL_free(crl);
14791558Srgrimes    NCONF_free(conf);
14801558Srgrimes    NCONF_free(extconf);
14811558Srgrimes    OBJ_cleanup();
14821558Srgrimes    apps_shutdown();
148374462Salfred    OPENSSL_EXIT(ret);
148474462Salfred}
148575801Siedowse
148674462Salfredstatic void lookup_fail(const char *name, const char *tag)
148774462Salfred{
148874462Salfred    BIO_printf(bio_err, "variable lookup failed for %s::%s\n", name, tag);
148974462Salfred}
14909336Sdfr
149175801Siedowsestatic int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
14921558Srgrimes                   const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
149375801Siedowse                   STACK_OF(CONF_VALUE) *policy, CA_DB *db,
149475801Siedowse                   BIGNUM *serial, char *subj, unsigned long chtype,
149575801Siedowse                   int multirdn, int email_dn, char *startdate, char *enddate,
149675801Siedowse                   long days, int batch, char *ext_sect, CONF *lconf,
149774462Salfred                   int verbose, unsigned long certopt, unsigned long nameopt,
149874462Salfred                   int default_op, int ext_copy, int selfsign)
149974462Salfred{
150075801Siedowse    X509_REQ *req = NULL;
150175801Siedowse    BIO *in = NULL;
15021558Srgrimes    EVP_PKEY *pktmp = NULL;
15031558Srgrimes    int ok = -1, i;
15041558Srgrimes
15051558Srgrimes    in = BIO_new(BIO_s_file());
15061558Srgrimes
15071558Srgrimes    if (BIO_read_filename(in, infile) <= 0) {
15081558Srgrimes        perror(infile);
15091558Srgrimes        goto err;
15101558Srgrimes    }
15111558Srgrimes    if ((req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL)) == NULL) {
15121558Srgrimes        BIO_printf(bio_err, "Error reading certificate request in %s\n",
15131558Srgrimes                   infile);
151474462Salfred        goto err;
15151558Srgrimes    }
15169336Sdfr    if (verbose)
15171558Srgrimes        X509_REQ_print(bio_err, req);
15181558Srgrimes
15191558Srgrimes    BIO_printf(bio_err, "Check that the request matches the signature\n");
15201558Srgrimes
15219336Sdfr    if (selfsign && !X509_REQ_check_private_key(req, pkey)) {
15221558Srgrimes        BIO_printf(bio_err,
15231558Srgrimes                   "Certificate request and CA private key do not match\n");
15241558Srgrimes        ok = 0;
15251558Srgrimes        goto err;
15261558Srgrimes    }
15271558Srgrimes    if ((pktmp = X509_REQ_get_pubkey(req)) == NULL) {
15281558Srgrimes        BIO_printf(bio_err, "error unpacking public key\n");
15291558Srgrimes        goto err;
15301558Srgrimes    }
15311558Srgrimes    i = X509_REQ_verify(req, pktmp);
15321558Srgrimes    EVP_PKEY_free(pktmp);
15331558Srgrimes    if (i < 0) {
15341558Srgrimes        ok = 0;
15351558Srgrimes        BIO_printf(bio_err, "Signature verification problems....\n");
15361558Srgrimes        ERR_print_errors(bio_err);
15371558Srgrimes        goto err;
15381558Srgrimes    }
15391558Srgrimes    if (i == 0) {
15401558Srgrimes        ok = 0;
15411558Srgrimes        BIO_printf(bio_err,
15421558Srgrimes                   "Signature did not match the certificate request\n");
15431558Srgrimes        ERR_print_errors(bio_err);
15441558Srgrimes        goto err;
15451558Srgrimes    } else
15461558Srgrimes        BIO_printf(bio_err, "Signature ok\n");
15471558Srgrimes
15481558Srgrimes    ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj,
15491558Srgrimes                 chtype, multirdn, email_dn, startdate, enddate, days, batch,
15501558Srgrimes                 verbose, req, ext_sect, lconf, certopt, nameopt, default_op,
15511558Srgrimes                 ext_copy, selfsign);
15521558Srgrimes
15531558Srgrimes err:
15541558Srgrimes    if (req != NULL)
15551558Srgrimes        X509_REQ_free(req);
15561558Srgrimes    if (in != NULL)
155772650Sgreen        BIO_free(in);
15581558Srgrimes    return (ok);
15591558Srgrimes}
15601558Srgrimes
15611558Srgrimesstatic int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
15621558Srgrimes                        const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
156351968Salfred                        STACK_OF(CONF_VALUE) *policy, CA_DB *db,
15641558Srgrimes                        BIGNUM *serial, char *subj, unsigned long chtype,
15651558Srgrimes                        int multirdn, int email_dn, char *startdate,
15661558Srgrimes                        char *enddate, long days, int batch, char *ext_sect,
15671558Srgrimes                        CONF *lconf, int verbose, unsigned long certopt,
15681558Srgrimes                        unsigned long nameopt, int default_op, int ext_copy,
15691558Srgrimes                        ENGINE *e)
15701558Srgrimes{
15711558Srgrimes    X509 *req = NULL;
157237663Scharnier    X509_REQ *rreq = NULL;
15731558Srgrimes    EVP_PKEY *pktmp = NULL;
157437663Scharnier    int ok = -1, i;
15751558Srgrimes
15761558Srgrimes    if ((req =
157737663Scharnier         load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL)
15781558Srgrimes        goto err;
15791558Srgrimes    if (verbose)
15801558Srgrimes        X509_print(bio_err, req);
15811558Srgrimes
15821558Srgrimes    BIO_printf(bio_err, "Check that the request matches the signature\n");
15831558Srgrimes
15841558Srgrimes    if ((pktmp = X509_get_pubkey(req)) == NULL) {
15851558Srgrimes        BIO_printf(bio_err, "error unpacking public key\n");
15861558Srgrimes        goto err;
15871558Srgrimes    }
15881558Srgrimes    i = X509_verify(req, pktmp);
15891558Srgrimes    EVP_PKEY_free(pktmp);
15901558Srgrimes    if (i < 0) {
15911558Srgrimes        ok = 0;
15921558Srgrimes        BIO_printf(bio_err, "Signature verification problems....\n");
15931558Srgrimes        goto err;
15941558Srgrimes    }
15951558Srgrimes    if (i == 0) {
15961558Srgrimes        ok = 0;
15971558Srgrimes        BIO_printf(bio_err, "Signature did not match the certificate\n");
15981558Srgrimes        goto err;
15991558Srgrimes    } else
16001558Srgrimes        BIO_printf(bio_err, "Signature ok\n");
16011558Srgrimes
16021558Srgrimes    if ((rreq = X509_to_X509_REQ(req, NULL, EVP_md5())) == NULL)
16031558Srgrimes        goto err;
160475801Siedowse
16051558Srgrimes    ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj,
160637663Scharnier                 chtype, multirdn, email_dn, startdate, enddate, days, batch,
16071558Srgrimes                 verbose, rreq, ext_sect, lconf, certopt, nameopt, default_op,
16081558Srgrimes                 ext_copy, 0);
16091558Srgrimes
16101558Srgrimes err:
16111558Srgrimes    if (rreq != NULL)
16121558Srgrimes        X509_REQ_free(rreq);
161374462Salfred    if (req != NULL)
161474462Salfred        X509_free(req);
161574462Salfred    return (ok);
161674462Salfred}
161774462Salfred
16181558Srgrimesstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
161937663Scharnier                   const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
16201558Srgrimes                   STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,
16211558Srgrimes                   char *subj, unsigned long chtype, int multirdn,
162237663Scharnier                   int email_dn, char *startdate, char *enddate, long days,
16231558Srgrimes                   int batch, int verbose, X509_REQ *req, char *ext_sect,
16241558Srgrimes                   CONF *lconf, unsigned long certopt, unsigned long nameopt,
16251558Srgrimes                   int default_op, int ext_copy, int selfsign)
16261558Srgrimes{
16271558Srgrimes    X509_NAME *name = NULL, *CAname = NULL, *subject = NULL, *dn_subject =
16281558Srgrimes        NULL;
16291558Srgrimes    ASN1_UTCTIME *tm, *tmptm;
16301558Srgrimes    ASN1_STRING *str, *str2;
163127447Sdfr    ASN1_OBJECT *obj;
163227447Sdfr    X509 *ret = NULL;
163327447Sdfr    X509_CINF *ci;
163427447Sdfr    X509_NAME_ENTRY *ne;
163527447Sdfr    X509_NAME_ENTRY *tne, *push;
163627447Sdfr    EVP_PKEY *pktmp;
163727447Sdfr    int ok = -1, i, j, last, nid;
1638100336Sjoerg    const char *p;
1639100336Sjoerg    CONF_VALUE *cv;
16401558Srgrimes    OPENSSL_STRING row[DB_NUMBER];
164137663Scharnier    OPENSSL_STRING *irow = NULL;
16421558Srgrimes    OPENSSL_STRING *rrow = NULL;
16431558Srgrimes    char buf[25];
16441558Srgrimes
16451558Srgrimes    tmptm = ASN1_UTCTIME_new();
16461558Srgrimes    if (tmptm == NULL) {
16471558Srgrimes        BIO_printf(bio_err, "malloc error\n");
16481558Srgrimes        return (0);
16491558Srgrimes    }
16501558Srgrimes
16511558Srgrimes    for (i = 0; i < DB_NUMBER; i++)
16521558Srgrimes        row[i] = NULL;
16531558Srgrimes
16541558Srgrimes    if (subj) {
16551558Srgrimes        X509_NAME *n = parse_name(subj, chtype, multirdn);
16561558Srgrimes
16571558Srgrimes        if (!n) {
16581558Srgrimes            ERR_print_errors(bio_err);
16591558Srgrimes            goto err;
16601558Srgrimes        }
16611558Srgrimes        X509_REQ_set_subject_name(req, n);
16621558Srgrimes        req->req_info->enc.modified = 1;
16631558Srgrimes        X509_NAME_free(n);
16647401Swpaul    }
16651558Srgrimes
16661558Srgrimes    if (default_op)
16677401Swpaul        BIO_printf(bio_err,
16681558Srgrimes                   "The Subject's Distinguished Name is as follows\n");
16697401Swpaul
167075635Siedowse    name = X509_REQ_get_subject_name(req);
167174462Salfred    for (i = 0; i < X509_NAME_entry_count(name); i++) {
167274462Salfred        ne = X509_NAME_get_entry(name, i);
16731558Srgrimes        str = X509_NAME_ENTRY_get_data(ne);
167474462Salfred        obj = X509_NAME_ENTRY_get_object(ne);
167574462Salfred
16761558Srgrimes        if (msie_hack) {
16771558Srgrimes            /* assume all type should be strings */
167874462Salfred            nid = OBJ_obj2nid(ne->object);
167974462Salfred
168074462Salfred            if (str->type == V_ASN1_UNIVERSALSTRING)
168174462Salfred                ASN1_UNIVERSALSTRING_to_string(str);
168274462Salfred
168375635Siedowse            if ((str->type == V_ASN1_IA5STRING) &&
168474462Salfred                (nid != NID_pkcs9_emailAddress))
168574462Salfred                str->type = V_ASN1_T61STRING;
168674462Salfred
168774462Salfred            if ((nid == NID_pkcs9_emailAddress) &&
168874462Salfred                (str->type == V_ASN1_PRINTABLESTRING))
168974462Salfred                str->type = V_ASN1_IA5STRING;
1690146187Sume        }
169174462Salfred
169274462Salfred        /* If no EMAIL is wanted in the subject */
169374462Salfred        if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn))
169475641Siedowse            continue;
169574462Salfred
169675635Siedowse        /* check some things */
169775635Siedowse        if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
169875635Siedowse            (str->type != V_ASN1_IA5STRING)) {
169975635Siedowse            BIO_printf(bio_err,
170075635Siedowse                       "\nemailAddress type needs to be of type IA5STRING\n");
170175635Siedowse            goto err;
170275635Siedowse        }
170375635Siedowse        if ((str->type != V_ASN1_BMPSTRING)
170475635Siedowse            && (str->type != V_ASN1_UTF8STRING)) {
170575635Siedowse            j = ASN1_PRINTABLE_type(str->data, str->length);
170675635Siedowse            if (((j == V_ASN1_T61STRING) &&
170775801Siedowse                 (str->type != V_ASN1_T61STRING)) ||
170875635Siedowse                ((j == V_ASN1_IA5STRING) &&
170975635Siedowse                 (str->type == V_ASN1_PRINTABLESTRING))) {
171075635Siedowse                BIO_printf(bio_err,
171175635Siedowse                           "\nThe string contains characters that are illegal for the ASN.1 type\n");
171275635Siedowse                goto err;
171375635Siedowse            }
171475635Siedowse        }
171575635Siedowse
171675635Siedowse        if (default_op)
171774462Salfred            old_entry_print(bio_err, obj, str);
17181558Srgrimes    }
171975635Siedowse
17201558Srgrimes    /* Ok, now we check the 'policy' stuff. */
17211558Srgrimes    if ((subject = X509_NAME_new()) == NULL) {
17221558Srgrimes        BIO_printf(bio_err, "Memory allocation failure\n");
17231558Srgrimes        goto err;
17241558Srgrimes    }
17251558Srgrimes
17261558Srgrimes    /* take a copy of the issuer name before we mess with it. */
17271558Srgrimes    if (selfsign)
17281558Srgrimes        CAname = X509_NAME_dup(name);
17291558Srgrimes    else
17301558Srgrimes        CAname = X509_NAME_dup(x509->cert_info->subject);
17311558Srgrimes    if (CAname == NULL)
17321558Srgrimes        goto err;
17331558Srgrimes    str = str2 = NULL;
17341558Srgrimes
17351558Srgrimes    for (i = 0; i < sk_CONF_VALUE_num(policy); i++) {
17361558Srgrimes        cv = sk_CONF_VALUE_value(policy, i); /* get the object id */
173727447Sdfr        if ((j = OBJ_txt2nid(cv->name)) == NID_undef) {
173827447Sdfr            BIO_printf(bio_err,
17391558Srgrimes                       "%s:unknown object type in 'policy' configuration\n",
17401558Srgrimes                       cv->name);
17411558Srgrimes            goto err;
17421558Srgrimes        }
17431558Srgrimes        obj = OBJ_nid2obj(j);
17441558Srgrimes
17451558Srgrimes        last = -1;
17461558Srgrimes        for (;;) {
17471558Srgrimes            /* lookup the object in the supplied name list */
17481558Srgrimes            j = X509_NAME_get_index_by_OBJ(name, obj, last);
17491558Srgrimes            if (j < 0) {
17501558Srgrimes                if (last != -1)
17511558Srgrimes                    break;
17521558Srgrimes                tne = NULL;
17531558Srgrimes            } else {
17541558Srgrimes                tne = X509_NAME_get_entry(name, j);
17551558Srgrimes            }
17561558Srgrimes            last = j;
17571558Srgrimes
17581558Srgrimes            /* depending on the 'policy', decide what to do. */
17591558Srgrimes            push = NULL;
17601558Srgrimes            if (strcmp(cv->value, "optional") == 0) {
17611558Srgrimes                if (tne != NULL)
17621558Srgrimes                    push = tne;
17631558Srgrimes            } else if (strcmp(cv->value, "supplied") == 0) {
17641558Srgrimes                if (tne == NULL) {
17651558Srgrimes                    BIO_printf(bio_err,
17661558Srgrimes                               "The %s field needed to be supplied and was missing\n",
17671558Srgrimes                               cv->name);
17689336Sdfr                    goto err;
17691558Srgrimes                } else
17701558Srgrimes                    push = tne;
17711558Srgrimes            } else if (strcmp(cv->value, "match") == 0) {
17721558Srgrimes                int last2;
17731558Srgrimes
17741558Srgrimes                if (tne == NULL) {
17751558Srgrimes                    BIO_printf(bio_err,
17761558Srgrimes                               "The mandatory %s field was missing\n",
17771558Srgrimes                               cv->name);
17781558Srgrimes                    goto err;
177937663Scharnier                }
17801558Srgrimes
17811558Srgrimes                last2 = -1;
17821558Srgrimes
17831558Srgrimes again2:
17841558Srgrimes                j = X509_NAME_get_index_by_OBJ(CAname, obj, last2);
17851558Srgrimes                if ((j < 0) && (last2 == -1)) {
17861558Srgrimes                    BIO_printf(bio_err,
17871558Srgrimes                               "The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",
17881558Srgrimes                               cv->name);
17891558Srgrimes                    goto err;
17901558Srgrimes                }
17911558Srgrimes                if (j >= 0) {
179272650Sgreen                    push = X509_NAME_get_entry(CAname, j);
17931558Srgrimes                    str = X509_NAME_ENTRY_get_data(tne);
17941558Srgrimes                    str2 = X509_NAME_ENTRY_get_data(push);
17951558Srgrimes                    last2 = j;
17961558Srgrimes                    if (ASN1_STRING_cmp(str, str2) != 0)
179775841Siedowse                        goto again2;
179874462Salfred                }
179975801Siedowse                if (j < 0) {
180074462Salfred                    BIO_printf(bio_err,
18011558Srgrimes                               "The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n",
18021558Srgrimes                               cv->name,
18031558Srgrimes                               ((str2 == NULL) ? "NULL" : (char *)str2->data),
18041558Srgrimes                               ((str == NULL) ? "NULL" : (char *)str->data));
18051558Srgrimes                    goto err;
18069336Sdfr                }
180754093Ssemenu            } else {
18081558Srgrimes                BIO_printf(bio_err,
18091558Srgrimes                           "%s:invalid type in 'policy' configuration\n",
181075801Siedowse                           cv->value);
181175801Siedowse                goto err;
18121558Srgrimes            }
181375801Siedowse
181475801Siedowse            if (push != NULL) {
181575801Siedowse                if (!X509_NAME_add_entry(subject, push, -1, 0)) {
181675801Siedowse                    if (push != NULL)
181775801Siedowse                        X509_NAME_ENTRY_free(push);
181875641Siedowse                    BIO_printf(bio_err, "Memory allocation failure\n");
181974462Salfred                    goto err;
182075641Siedowse                }
182175641Siedowse            }
18221558Srgrimes            if (j < 0)
18231558Srgrimes                break;
18241558Srgrimes        }
18251558Srgrimes    }
182675641Siedowse
182774462Salfred    if (preserve) {
182875801Siedowse        X509_NAME_free(subject);
182975801Siedowse        /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */
183075801Siedowse        subject = X509_NAME_dup(name);
18311558Srgrimes        if (subject == NULL)
18321558Srgrimes            goto err;
183375801Siedowse    }
183474462Salfred
183574462Salfred    if (verbose)
183675801Siedowse        BIO_printf(bio_err,
183775801Siedowse                   "The subject name appears to be ok, checking data base for clashes\n");
183875801Siedowse
183975801Siedowse    /* Build the correct Subject if no e-mail is wanted in the subject */
184075801Siedowse    /*
184175801Siedowse     * and add it later on because of the method extensions are added
18421558Srgrimes     * (altName)
184375641Siedowse     */
184475801Siedowse
184575801Siedowse    if (email_dn)
184675801Siedowse        dn_subject = subject;
184775801Siedowse    else {
184875641Siedowse        X509_NAME_ENTRY *tmpne;
18497401Swpaul        /*
18507401Swpaul         * Its best to dup the subject DN and then delete any email addresses
18517401Swpaul         * because this retains its structure.
18521558Srgrimes         */
185337663Scharnier        if (!(dn_subject = X509_NAME_dup(subject))) {
18541558Srgrimes            BIO_printf(bio_err, "Memory allocation failure\n");
18551558Srgrimes            goto err;
18561558Srgrimes        }
18571558Srgrimes        while ((i = X509_NAME_get_index_by_NID(dn_subject,
18581558Srgrimes                                               NID_pkcs9_emailAddress,
18591558Srgrimes                                               -1)) >= 0) {
18601558Srgrimes            tmpne = X509_NAME_get_entry(dn_subject, i);
18611558Srgrimes            X509_NAME_delete_entry(dn_subject, i);
18621558Srgrimes            X509_NAME_ENTRY_free(tmpne);
18631558Srgrimes        }
186496707Strhodes    }
18651558Srgrimes
18669336Sdfr    if (BN_is_zero(serial))
186774462Salfred        row[DB_serial] = BUF_strdup("00");
18681558Srgrimes    else
18691558Srgrimes        row[DB_serial] = BN_bn2hex(serial);
18701558Srgrimes    if (row[DB_serial] == NULL) {
18711558Srgrimes        BIO_printf(bio_err, "Memory allocation failure\n");
1872100336Sjoerg        goto err;
1873100336Sjoerg    }
18741558Srgrimes
187575635Siedowse    if (db->attributes.unique_subject) {
187675635Siedowse        OPENSSL_STRING *crow = row;
187775635Siedowse
18781558Srgrimes        rrow = TXT_DB_get_by_index(db->db, DB_name, crow);
187937663Scharnier        if (rrow != NULL) {
18801558Srgrimes            BIO_printf(bio_err,
18811558Srgrimes                       "ERROR:There is already a certificate for %s\n",
18821558Srgrimes                       row[DB_name]);
1883100336Sjoerg        }
1884100336Sjoerg    }
1885100336Sjoerg    if (rrow == NULL) {
1886100336Sjoerg        rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
1887100336Sjoerg        if (rrow != NULL) {
1888100336Sjoerg            BIO_printf(bio_err,
1889100336Sjoerg                       "ERROR:Serial number %s has already been issued,\n",
1890100336Sjoerg                       row[DB_serial]);
18911558Srgrimes            BIO_printf(bio_err,
18921558Srgrimes                       "      check the database/serial_file for corruption\n");
18931558Srgrimes        }
18941558Srgrimes    }
18951558Srgrimes
18961558Srgrimes    if (rrow != NULL) {
18971558Srgrimes        BIO_printf(bio_err, "The matching entry has the following details\n");
18981558Srgrimes        if (rrow[DB_type][0] == 'E')
18991558Srgrimes            p = "Expired";
190037663Scharnier        else if (rrow[DB_type][0] == 'R')
190137663Scharnier            p = "Revoked";
19021558Srgrimes        else if (rrow[DB_type][0] == 'V')
19031558Srgrimes            p = "Valid";
19041558Srgrimes        else
19051558Srgrimes            p = "\ninvalid type, Data base error\n";
190675841Siedowse        BIO_printf(bio_err, "Type          :%s\n", p);;
190775841Siedowse        if (rrow[DB_type][0] == 'R') {
190875841Siedowse            p = rrow[DB_exp_date];
190975841Siedowse            if (p == NULL)
191075841Siedowse                p = "undef";
191175841Siedowse            BIO_printf(bio_err, "Was revoked on:%s\n", p);
191275841Siedowse        }
19131558Srgrimes        p = rrow[DB_exp_date];
191474462Salfred        if (p == NULL)
191575641Siedowse            p = "undef";
191674462Salfred        BIO_printf(bio_err, "Expires on    :%s\n", p);
191775641Siedowse        p = rrow[DB_serial];
19181558Srgrimes        if (p == NULL)
19191558Srgrimes            p = "undef";
19201558Srgrimes        BIO_printf(bio_err, "Serial Number :%s\n", p);
19211558Srgrimes        p = rrow[DB_file];
19221558Srgrimes        if (p == NULL)
19231558Srgrimes            p = "undef";
19241558Srgrimes        BIO_printf(bio_err, "File name     :%s\n", p);
19251558Srgrimes        p = rrow[DB_name];
19261558Srgrimes        if (p == NULL)
192775801Siedowse            p = "undef";
192875801Siedowse        BIO_printf(bio_err, "Subject Name  :%s\n", p);
19291558Srgrimes        ok = -1;                /* This is now a 'bad' error. */
19301558Srgrimes        goto err;
19311558Srgrimes    }
19321558Srgrimes
19331558Srgrimes    /* We are now totally happy, lets make and sign the certificate */
19341558Srgrimes    if (verbose)
19351558Srgrimes        BIO_printf(bio_err,
193675861Siedowse                   "Everything appears to be ok, creating and signing the certificate\n");
193774462Salfred
193875801Siedowse    if ((ret = X509_new()) == NULL)
193975861Siedowse        goto err;
194074462Salfred    ci = ret->cert_info;
194174462Salfred
194274462Salfred#ifdef X509_V3
19431558Srgrimes    /* Make it an X509 v3 certificate. */
194475635Siedowse    if (!X509_set_version(ret, 2))
194574462Salfred        goto err;
194674462Salfred#endif
194774462Salfred
194874462Salfred    if (BN_to_ASN1_INTEGER(serial, ci->serialNumber) == NULL)
194974462Salfred        goto err;
195074462Salfred    if (selfsign) {
195175861Siedowse        if (!X509_set_issuer_name(ret, subject))
195275861Siedowse            goto err;
195375861Siedowse    } else {
195475861Siedowse        if (!X509_set_issuer_name(ret, X509_get_subject_name(x509)))
195575861Siedowse            goto err;
195674462Salfred    }
195775801Siedowse
195875801Siedowse    if (strcmp(startdate, "today") == 0)
195975801Siedowse        X509_gmtime_adj(X509_get_notBefore(ret), 0);
196075801Siedowse    else
196175801Siedowse        ASN1_TIME_set_string(X509_get_notBefore(ret), startdate);
196275801Siedowse
196375801Siedowse    if (enddate == NULL)
196474462Salfred        X509_time_adj_ex(X509_get_notAfter(ret), days, 0, NULL);
196575861Siedowse    else
196675861Siedowse        ASN1_TIME_set_string(X509_get_notAfter(ret), enddate);
196775861Siedowse
196874462Salfred    if (!X509_set_subject_name(ret, subject))
196975801Siedowse        goto err;
197075801Siedowse
197175801Siedowse    pktmp = X509_REQ_get_pubkey(req);
197274462Salfred    i = X509_set_pubkey(ret, pktmp);
197375801Siedowse    EVP_PKEY_free(pktmp);
197474462Salfred    if (!i)
197574462Salfred        goto err;
197675801Siedowse
197774462Salfred    /* Lets add the extensions, if there are any */
197875801Siedowse    if (ext_sect) {
197975801Siedowse        X509V3_CTX ctx;
198074462Salfred        if (ci->version == NULL)
198175861Siedowse            if ((ci->version = ASN1_INTEGER_new()) == NULL)
198275861Siedowse                goto err;
198375861Siedowse        ASN1_INTEGER_set(ci->version, 2); /* version 3 certificate */
198475861Siedowse
198575861Siedowse        /*
198675861Siedowse         * Free the current entries if any, there should not be any I believe
198775861Siedowse         */
198875861Siedowse        if (ci->extensions != NULL)
198975861Siedowse            sk_X509_EXTENSION_pop_free(ci->extensions, X509_EXTENSION_free);
199075861Siedowse
199174462Salfred        ci->extensions = NULL;
199225318Spst
199375801Siedowse        /* Initialize the context structure */
199475801Siedowse        if (selfsign)
199575801Siedowse            X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0);
199675801Siedowse        else
199775801Siedowse            X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
199875801Siedowse
199975801Siedowse        if (extconf) {
200075801Siedowse            if (verbose)
200175801Siedowse                BIO_printf(bio_err, "Extra configuration file found\n");
200274462Salfred
200375801Siedowse            /* Use the extconf configuration db LHASH */
200475801Siedowse            X509V3_set_nconf(&ctx, extconf);
200575801Siedowse
200675801Siedowse            /* Test the structure (needed?) */
2007146187Sume            /* X509V3_set_ctx_test(&ctx); */
200875801Siedowse
200975801Siedowse            /* Adds exts contained in the configuration file */
201075801Siedowse            if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect, ret)) {
201175801Siedowse                BIO_printf(bio_err,
201275801Siedowse                           "ERROR: adding extensions in section %s\n",
201375801Siedowse                           ext_sect);
201475801Siedowse                ERR_print_errors(bio_err);
201575801Siedowse                goto err;
201675801Siedowse            }
201775801Siedowse            if (verbose)
201875801Siedowse                BIO_printf(bio_err,
201974462Salfred                           "Successfully added extensions from file.\n");
202074462Salfred        } else if (ext_sect) {
202175801Siedowse            /* We found extensions to be set from config file */
202274462Salfred            X509V3_set_nconf(&ctx, lconf);
202375801Siedowse
202475801Siedowse            if (!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret)) {
202575801Siedowse                BIO_printf(bio_err,
202675801Siedowse                           "ERROR: adding extensions in section %s\n",
202774462Salfred                           ext_sect);
202875801Siedowse                ERR_print_errors(bio_err);
202975801Siedowse                goto err;
203075801Siedowse            }
203174462Salfred
203275801Siedowse            if (verbose)
203375801Siedowse                BIO_printf(bio_err,
203475801Siedowse                           "Successfully added extensions from config\n");
203575801Siedowse        }
203675801Siedowse    }
203775801Siedowse
203875801Siedowse    /* Copy extensions from request (if any) */
203975801Siedowse
204075801Siedowse    if (!copy_extensions(ret, req, ext_copy)) {
204175801Siedowse        BIO_printf(bio_err, "ERROR: adding extensions from request\n");
204275801Siedowse        ERR_print_errors(bio_err);
204375801Siedowse        goto err;
204475801Siedowse    }
204575801Siedowse
204675801Siedowse    /* Set the right value for the noemailDN option */
204774462Salfred    if (email_dn == 0) {
204874462Salfred        if (!X509_set_subject_name(ret, dn_subject))
204974462Salfred            goto err;
205074462Salfred    }
205174462Salfred
205274462Salfred    if (!default_op) {
205374462Salfred        BIO_printf(bio_err, "Certificate Details:\n");
205474462Salfred        /*
205574462Salfred         * Never print signature details because signature not present
205674462Salfred         */
205774462Salfred        certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
20581558Srgrimes        X509_print_ex(bio_err, ret, nameopt, certopt);
20591558Srgrimes    }
20601558Srgrimes
20611558Srgrimes    BIO_printf(bio_err, "Certificate is to be certified until ");
20621558Srgrimes    ASN1_TIME_print(bio_err, X509_get_notAfter(ret));
20631558Srgrimes    if (days)
20641558Srgrimes        BIO_printf(bio_err, " (%ld days)", days);
20651558Srgrimes    BIO_printf(bio_err, "\n");
20661558Srgrimes
20671558Srgrimes    if (!batch) {
20681558Srgrimes
20691558Srgrimes        BIO_printf(bio_err, "Sign the certificate? [y/n]:");
20701558Srgrimes        (void)BIO_flush(bio_err);
20711558Srgrimes        buf[0] = '\0';
20721558Srgrimes        if (!fgets(buf, sizeof(buf) - 1, stdin)) {
20731558Srgrimes            BIO_printf(bio_err,
20741558Srgrimes                       "CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n");
20751558Srgrimes            ok = 0;
20761558Srgrimes            goto err;
20771558Srgrimes        }
20781558Srgrimes        if (!((buf[0] == 'y') || (buf[0] == 'Y'))) {
20791558Srgrimes            BIO_printf(bio_err, "CERTIFICATE WILL NOT BE CERTIFIED\n");
20801558Srgrimes            ok = 0;
20811558Srgrimes            goto err;
20821558Srgrimes        }
20831558Srgrimes    }
20841558Srgrimes
20851558Srgrimes    pktmp = X509_get_pubkey(ret);
20861558Srgrimes    if (EVP_PKEY_missing_parameters(pktmp) &&
20871558Srgrimes        !EVP_PKEY_missing_parameters(pkey))
20881558Srgrimes        EVP_PKEY_copy_parameters(pktmp, pkey);
20891558Srgrimes    EVP_PKEY_free(pktmp);
20901558Srgrimes
209196622Siedowse    if (!do_X509_sign(bio_err, ret, pkey, dgst, sigopts))
20921558Srgrimes        goto err;
20931558Srgrimes
20941558Srgrimes    /* We now just add it to the database */
20951558Srgrimes    row[DB_type] = (char *)OPENSSL_malloc(2);
20961558Srgrimes
20971558Srgrimes    tm = X509_get_notAfter(ret);
20981558Srgrimes    row[DB_exp_date] = (char *)OPENSSL_malloc(tm->length + 1);
20991558Srgrimes    memcpy(row[DB_exp_date], tm->data, tm->length);
210096622Siedowse    row[DB_exp_date][tm->length] = '\0';
21011558Srgrimes
21021558Srgrimes    row[DB_rev_date] = NULL;
21031558Srgrimes
21041558Srgrimes    /* row[DB_serial] done already */
21051558Srgrimes    row[DB_file] = (char *)OPENSSL_malloc(8);
21061558Srgrimes    row[DB_name] = X509_NAME_oneline(X509_get_subject_name(ret), NULL, 0);
21071558Srgrimes
21081558Srgrimes    if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
21091558Srgrimes        (row[DB_file] == NULL) || (row[DB_name] == NULL)) {
21101558Srgrimes        BIO_printf(bio_err, "Memory allocation failure\n");
211179117Sdd        goto err;
211279117Sdd    }
211379117Sdd    BUF_strlcpy(row[DB_file], "unknown", 8);
211479117Sdd    row[DB_type][0] = 'V';
211596622Siedowse    row[DB_type][1] = '\0';
211696622Siedowse
211796622Siedowse    if ((irow =
211896622Siedowse         (char **)OPENSSL_malloc(sizeof(char *) * (DB_NUMBER + 1))) == NULL) {
211996622Siedowse        BIO_printf(bio_err, "Memory allocation failure\n");
21201558Srgrimes        goto err;
212196622Siedowse    }
212296622Siedowse
212396622Siedowse    for (i = 0; i < DB_NUMBER; i++) {
21241558Srgrimes        irow[i] = row[i];
21251558Srgrimes        row[i] = NULL;
21261558Srgrimes    }
21271558Srgrimes    irow[DB_NUMBER] = NULL;
21281558Srgrimes
21291558Srgrimes    if (!TXT_DB_insert(db->db, irow)) {
21301558Srgrimes        BIO_printf(bio_err, "failed to update database\n");
21311558Srgrimes        BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error);
21321558Srgrimes        goto err;
21331558Srgrimes    }
213472650Sgreen    ok = 1;
21351558Srgrimes err:
21361558Srgrimes    for (i = 0; i < DB_NUMBER; i++)
21371558Srgrimes        if (row[i] != NULL)
21381558Srgrimes            OPENSSL_free(row[i]);
21391558Srgrimes
21401558Srgrimes    if (CAname != NULL)
2141136051Sstefanf        X509_NAME_free(CAname);
2142136051Sstefanf    if (subject != NULL)
21431558Srgrimes        X509_NAME_free(subject);
214491354Sdd    if ((dn_subject != NULL) && !email_dn)
21451558Srgrimes        X509_NAME_free(dn_subject);
214637663Scharnier    if (tmptm != NULL)
21471558Srgrimes        ASN1_UTCTIME_free(tmptm);
21481558Srgrimes    if (ok <= 0) {
21491558Srgrimes        if (ret != NULL)
21501558Srgrimes            X509_free(ret);
21511558Srgrimes        ret = NULL;
21521558Srgrimes    } else
21531558Srgrimes        *xret = ret;
21541558Srgrimes    return (ok);
21551558Srgrimes}
21561558Srgrimes
21571558Srgrimesstatic void write_new_certificate(BIO *bp, X509 *x, int output_der,
21581558Srgrimes                                  int notext)
21591558Srgrimes{
21601558Srgrimes
21611558Srgrimes    if (output_der) {
21621558Srgrimes        (void)i2d_X509_bio(bp, x);
21631558Srgrimes        return;
21641558Srgrimes    }
216537663Scharnier#if 0
21661558Srgrimes    /* ??? Not needed since X509_print prints all this stuff anyway */
21671558Srgrimes    f = X509_NAME_oneline(X509_get_issuer_name(x), buf, 256);
21681558Srgrimes    BIO_printf(bp, "issuer :%s\n", f);
21691558Srgrimes
21701558Srgrimes    f = X509_NAME_oneline(X509_get_subject_name(x), buf, 256);
217137663Scharnier    BIO_printf(bp, "subject:%s\n", f);
21721558Srgrimes
2173136051Sstefanf    BIO_puts(bp, "serial :");
21741558Srgrimes    i2a_ASN1_INTEGER(bp, x->cert_info->serialNumber);
21751558Srgrimes    BIO_puts(bp, "\n\n");
21761558Srgrimes#endif
21771558Srgrimes    if (!notext)
21781558Srgrimes        X509_print(bp, x);
21791558Srgrimes    PEM_write_bio_X509(bp, x);
21801558Srgrimes}
21811558Srgrimes
21821558Srgrimesstatic int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey,
21831558Srgrimes                         X509 *x509, const EVP_MD *dgst,
21841558Srgrimes                         STACK_OF(OPENSSL_STRING) *sigopts,
21851558Srgrimes                         STACK_OF(CONF_VALUE) *policy, CA_DB *db,
21861558Srgrimes                         BIGNUM *serial, char *subj, unsigned long chtype,
21871558Srgrimes                         int multirdn, int email_dn, char *startdate,
21881558Srgrimes                         char *enddate, long days, char *ext_sect,
21891558Srgrimes                         CONF *lconf, int verbose, unsigned long certopt,
219037663Scharnier                         unsigned long nameopt, int default_op, int ext_copy)
21911558Srgrimes{
21921558Srgrimes    STACK_OF(CONF_VALUE) *sk = NULL;
21931558Srgrimes    LHASH_OF(CONF_VALUE) *parms = NULL;
21941558Srgrimes    X509_REQ *req = NULL;
21951558Srgrimes    CONF_VALUE *cv = NULL;
21961558Srgrimes    NETSCAPE_SPKI *spki = NULL;
21971558Srgrimes    X509_REQ_INFO *ri;
21981558Srgrimes    char *type, *buf;
21991558Srgrimes    EVP_PKEY *pktmp = NULL;
220037663Scharnier    X509_NAME *n = NULL;
22011558Srgrimes    X509_NAME_ENTRY *ne = NULL;
22021558Srgrimes    int ok = -1, i, j;
22031558Srgrimes    long errline;
22041558Srgrimes    int nid;
22051558Srgrimes
22061558Srgrimes    /*
220737663Scharnier     * Load input file into a hash table.  (This is just an easy
22081558Srgrimes     * way to read and parse the file, then put it into a convenient
22091558Srgrimes     * STACK format).
22101558Srgrimes     */
22111558Srgrimes    parms = CONF_load(NULL, infile, &errline);
22121558Srgrimes    if (parms == NULL) {
22131558Srgrimes        BIO_printf(bio_err, "error on line %ld of %s\n", errline, infile);
22141558Srgrimes        ERR_print_errors(bio_err);
22151558Srgrimes        goto err;
22161558Srgrimes    }
22171558Srgrimes
221823681Speter    sk = CONF_get_section(parms, "default");
22191558Srgrimes    if (sk_CONF_VALUE_num(sk) == 0) {
22201558Srgrimes        BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
22211558Srgrimes        CONF_free(parms);
22221558Srgrimes        goto err;
222353117Sbillf    }
222453117Sbillf
222553117Sbillf    /*
222653117Sbillf     * Now create a dummy X509 request structure.  We don't actually
222753117Sbillf     * have an X509 request, but we have many of the components
222853117Sbillf     * (a public key, various DN components).  The idea is that we
22291558Srgrimes     * put these components into the right X509 request structure
22301558Srgrimes     * and we can use the same code as if you had a real X509 request.
22311558Srgrimes     */
223223681Speter    req = X509_REQ_new();
223323681Speter    if (req == NULL) {
223423681Speter        ERR_print_errors(bio_err);
223523681Speter        goto err;
22361558Srgrimes    }
22371558Srgrimes
223837663Scharnier    /*
223937663Scharnier     * Build up the subject name set.
224023681Speter     */
224123681Speter    ri = req->req_info;
224223681Speter    n = ri->subject;
224323681Speter
22441558Srgrimes    for (i = 0;; i++) {
22451558Srgrimes        if (sk_CONF_VALUE_num(sk) <= i)
22461558Srgrimes            break;
22471558Srgrimes
22481558Srgrimes        cv = sk_CONF_VALUE_value(sk, i);
22491558Srgrimes        type = cv->name;
22501558Srgrimes        /*
225175635Siedowse         * Skip past any leading X. X: X, etc to allow for multiple instances
225275635Siedowse         */
22531558Srgrimes        for (buf = cv->name; *buf; buf++)
22541558Srgrimes            if ((*buf == ':') || (*buf == ',') || (*buf == '.')) {
22551558Srgrimes                buf++;
22561558Srgrimes                if (*buf)
22571558Srgrimes                    type = buf;
22581558Srgrimes                break;
22591558Srgrimes            }
22601558Srgrimes
22611558Srgrimes        buf = cv->value;
22621558Srgrimes        if ((nid = OBJ_txt2nid(type)) == NID_undef) {
22631558Srgrimes            if (strcmp(type, "SPKAC") == 0) {
22641558Srgrimes                spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
22651558Srgrimes                if (spki == NULL) {
22661558Srgrimes                    BIO_printf(bio_err,
22671558Srgrimes                               "unable to load Netscape SPKAC structure\n");
22681558Srgrimes                    ERR_print_errors(bio_err);
22691558Srgrimes                    goto err;
22701558Srgrimes                }
22711558Srgrimes            }
22721558Srgrimes            continue;
22731558Srgrimes        }
22741558Srgrimes
227537663Scharnier        if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
22761558Srgrimes                                        (unsigned char *)buf, -1, -1, 0))
22771558Srgrimes            goto err;
22781558Srgrimes    }
22791558Srgrimes    if (spki == NULL) {
22801558Srgrimes        BIO_printf(bio_err, "Netscape SPKAC structure not found in %s\n",
22811558Srgrimes                   infile);
22821558Srgrimes        goto err;
22831558Srgrimes    }
22841558Srgrimes
22851558Srgrimes    /*
22861558Srgrimes     * Now extract the key from the SPKI structure.
22871558Srgrimes     */
22881558Srgrimes
22891558Srgrimes    BIO_printf(bio_err,
22901558Srgrimes               "Check that the SPKAC request matches the signature\n");
22911558Srgrimes
22921558Srgrimes    if ((pktmp = NETSCAPE_SPKI_get_pubkey(spki)) == NULL) {
22931558Srgrimes        BIO_printf(bio_err, "error unpacking SPKAC public key\n");
22941558Srgrimes        goto err;
22951558Srgrimes    }
22961558Srgrimes
22971558Srgrimes    j = NETSCAPE_SPKI_verify(spki, pktmp);
22981558Srgrimes    if (j <= 0) {
22991558Srgrimes        BIO_printf(bio_err,
23001558Srgrimes                   "signature verification failed on SPKAC public key\n");
23011558Srgrimes        goto err;
23021558Srgrimes    }
230337663Scharnier    BIO_printf(bio_err, "Signature ok\n");
230437663Scharnier
23051558Srgrimes    X509_REQ_set_pubkey(req, pktmp);
23061558Srgrimes    EVP_PKEY_free(pktmp);
23071558Srgrimes    ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj,
23081558Srgrimes                 chtype, multirdn, email_dn, startdate, enddate, days, 1,
23091558Srgrimes                 verbose, req, ext_sect, lconf, certopt, nameopt, default_op,
23101558Srgrimes                 ext_copy, 0);
23111558Srgrimes err:
231237663Scharnier    if (req != NULL)
23131558Srgrimes        X509_REQ_free(req);
23141558Srgrimes    if (parms != NULL)
23151558Srgrimes        CONF_free(parms);
23161558Srgrimes    if (spki != NULL)
23171558Srgrimes        NETSCAPE_SPKI_free(spki);
23181558Srgrimes    if (ne != NULL)
23191558Srgrimes        X509_NAME_ENTRY_free(ne);
23201558Srgrimes
23211558Srgrimes    return (ok);
23221558Srgrimes}
23231558Srgrimes
23241558Srgrimesstatic int check_time_format(const char *str)
23251558Srgrimes{
23261558Srgrimes    return ASN1_TIME_set_string(NULL, str);
232774462Salfred}
232874462Salfred
23291558Srgrimesstatic int do_revoke(X509 *x509, CA_DB *db, int type, char *value)
23301558Srgrimes{
23311558Srgrimes    ASN1_UTCTIME *tm = NULL;
23321558Srgrimes    char *row[DB_NUMBER], **rrow, **irow;
23331558Srgrimes    char *rev_str = NULL;
23341558Srgrimes    BIGNUM *bn = NULL;
23351558Srgrimes    int ok = -1, i;
23361558Srgrimes
23371558Srgrimes    for (i = 0; i < DB_NUMBER; i++)
23381558Srgrimes        row[i] = NULL;
23391558Srgrimes    row[DB_name] = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0);
23401558Srgrimes    bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509), NULL);
23411558Srgrimes    if (!bn)
23421558Srgrimes        goto err;
23431558Srgrimes    if (BN_is_zero(bn))
23441558Srgrimes        row[DB_serial] = BUF_strdup("00");
23451558Srgrimes    else
23461558Srgrimes        row[DB_serial] = BN_bn2hex(bn);
23471558Srgrimes    BN_free(bn);
23481558Srgrimes    if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) {
23491558Srgrimes        BIO_printf(bio_err, "Memory allocation failure\n");
23501558Srgrimes        goto err;
23511558Srgrimes    }
23521558Srgrimes    /*
23531558Srgrimes     * We have to lookup by serial number because name lookup skips revoked
23541558Srgrimes     * certs
23551558Srgrimes     */
23561558Srgrimes    rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
23571558Srgrimes    if (rrow == NULL) {
235883653Speter        BIO_printf(bio_err,
235983653Speter                   "Adding Entry with serial number %s to DB for %s\n",
23601558Srgrimes                   row[DB_serial], row[DB_name]);
23611558Srgrimes
23621558Srgrimes        /* We now just add it to the database */
236375801Siedowse        row[DB_type] = (char *)OPENSSL_malloc(2);
236475801Siedowse
23651558Srgrimes        tm = X509_get_notAfter(x509);
236675801Siedowse        row[DB_exp_date] = (char *)OPENSSL_malloc(tm->length + 1);
236775801Siedowse        memcpy(row[DB_exp_date], tm->data, tm->length);
236875801Siedowse        row[DB_exp_date][tm->length] = '\0';
236975801Siedowse
237075801Siedowse        row[DB_rev_date] = NULL;
237175801Siedowse
237275801Siedowse        /* row[DB_serial] done already */
237375801Siedowse        row[DB_file] = (char *)OPENSSL_malloc(8);
23741558Srgrimes
237545927Salex        /* row[DB_name] done already */
23761558Srgrimes
23771558Srgrimes        if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
23781558Srgrimes            (row[DB_file] == NULL)) {
23791558Srgrimes            BIO_printf(bio_err, "Memory allocation failure\n");
23801558Srgrimes            goto err;
23811558Srgrimes        }
23821558Srgrimes        BUF_strlcpy(row[DB_file], "unknown", 8);
23831558Srgrimes        row[DB_type][0] = 'V';
23841558Srgrimes        row[DB_type][1] = '\0';
23851558Srgrimes
23861558Srgrimes        if ((irow =
23871558Srgrimes             (char **)OPENSSL_malloc(sizeof(char *) * (DB_NUMBER + 1))) ==
23881558Srgrimes            NULL) {
23891558Srgrimes            BIO_printf(bio_err, "Memory allocation failure\n");
23901558Srgrimes            goto err;
23911558Srgrimes        }
23921558Srgrimes
23931558Srgrimes        for (i = 0; i < DB_NUMBER; i++) {
23941558Srgrimes            irow[i] = row[i];
23951558Srgrimes            row[i] = NULL;
23969336Sdfr        }
23971558Srgrimes        irow[DB_NUMBER] = NULL;
23981558Srgrimes
23991558Srgrimes        if (!TXT_DB_insert(db->db, irow)) {
24001558Srgrimes            BIO_printf(bio_err, "failed to update database\n");
24011558Srgrimes            BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error);
24029336Sdfr            goto err;
24031558Srgrimes        }
24041558Srgrimes
24051558Srgrimes        /* Revoke Certificate */
24069336Sdfr        ok = do_revoke(x509, db, type, value);
240775801Siedowse
240875801Siedowse        goto err;
240975801Siedowse
241075801Siedowse    } else if (index_name_cmp_noconst(row, rrow)) {
241175801Siedowse        BIO_printf(bio_err, "ERROR:name does not match %s\n", row[DB_name]);
241275801Siedowse        goto err;
241374462Salfred    } else if (rrow[DB_type][0] == 'R') {
241475801Siedowse        BIO_printf(bio_err, "ERROR:Already revoked, serial number %s\n",
241575801Siedowse                   row[DB_serial]);
241674462Salfred        goto err;
241775801Siedowse    } else {
241875801Siedowse        BIO_printf(bio_err, "Revoking Certificate %s.\n", rrow[DB_serial]);
2419103949Smike        rev_str = make_revocation_str(type, value);
242075801Siedowse        if (!rev_str) {
242174462Salfred            BIO_printf(bio_err, "Error in revocation arguments\n");
242275801Siedowse            goto err;
2423103949Smike        }
242475801Siedowse        rrow[DB_type][0] = 'R';
242575801Siedowse        rrow[DB_type][1] = '\0';
242674462Salfred        rrow[DB_rev_date] = rev_str;
242775801Siedowse    }
242874462Salfred    ok = 1;
242974462Salfred err:
243075801Siedowse    for (i = 0; i < DB_NUMBER; i++) {
243175801Siedowse        if (row[i] != NULL)
243275801Siedowse            OPENSSL_free(row[i]);
243375801Siedowse    }
243475801Siedowse    return (ok);
243575801Siedowse}
243674462Salfred
243775801Siedowsestatic int get_certificate_status(const char *serial, CA_DB *db)
243875801Siedowse{
243974462Salfred    char *row[DB_NUMBER], **rrow;
244075801Siedowse    int ok = -1, i;
244175801Siedowse
244275801Siedowse    /* Free Resources */
244375801Siedowse    for (i = 0; i < DB_NUMBER; i++)
244475801Siedowse        row[i] = NULL;
244575801Siedowse
244675801Siedowse    /* Malloc needed char spaces */
244775801Siedowse    row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
244875801Siedowse    if (row[DB_serial] == NULL) {
244975801Siedowse        BIO_printf(bio_err, "Malloc failure\n");
245074462Salfred        goto err;
245175801Siedowse    }
245275801Siedowse
245375801Siedowse    if (strlen(serial) % 2) {
245475801Siedowse        /*
245574462Salfred         * Set the first char to 0
245674462Salfred         */ ;
245775801Siedowse        row[DB_serial][0] = '0';
245875801Siedowse
245975801Siedowse        /* Copy String from serial to row[DB_serial] */
246075801Siedowse        memcpy(row[DB_serial] + 1, serial, strlen(serial));
246175801Siedowse        row[DB_serial][strlen(serial) + 1] = '\0';
246275801Siedowse    } else {
246375801Siedowse        /* Copy String from serial to row[DB_serial] */
246474462Salfred        memcpy(row[DB_serial], serial, strlen(serial));
246575801Siedowse        row[DB_serial][strlen(serial)] = '\0';
246675801Siedowse    }
246774462Salfred
246875801Siedowse    /* Make it Upper Case */
246975801Siedowse    for (i = 0; row[DB_serial][i] != '\0'; i++)
247075801Siedowse        row[DB_serial][i] = toupper((unsigned char)row[DB_serial][i]);
247175801Siedowse
247275801Siedowse    ok = 1;
247375801Siedowse
247474462Salfred    /* Search for the certificate */
247575801Siedowse    rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
247675801Siedowse    if (rrow == NULL) {
247775801Siedowse        BIO_printf(bio_err, "Serial %s not present in db.\n", row[DB_serial]);
247874462Salfred        ok = -1;
247974462Salfred        goto err;
248074462Salfred    } else if (rrow[DB_type][0] == 'V') {
248175801Siedowse        BIO_printf(bio_err, "%s=Valid (%c)\n",
248275801Siedowse                   row[DB_serial], rrow[DB_type][0]);
248375801Siedowse        goto err;
248474462Salfred    } else if (rrow[DB_type][0] == 'R') {
248575801Siedowse        BIO_printf(bio_err, "%s=Revoked (%c)\n",
248675801Siedowse                   row[DB_serial], rrow[DB_type][0]);
248775801Siedowse        goto err;
248875801Siedowse    } else if (rrow[DB_type][0] == 'E') {
248974462Salfred        BIO_printf(bio_err, "%s=Expired (%c)\n",
249075801Siedowse                   row[DB_serial], rrow[DB_type][0]);
249175801Siedowse        goto err;
249275801Siedowse    } else if (rrow[DB_type][0] == 'S') {
249375801Siedowse        BIO_printf(bio_err, "%s=Suspended (%c)\n",
249474462Salfred                   row[DB_serial], rrow[DB_type][0]);
249574462Salfred        goto err;
249675801Siedowse    } else {
249775801Siedowse        BIO_printf(bio_err, "%s=Unknown (%c).\n",
249875801Siedowse                   row[DB_serial], rrow[DB_type][0]);
249975801Siedowse        ok = -1;
250075801Siedowse    }
250175801Siedowse err:
250275801Siedowse    for (i = 0; i < DB_NUMBER; i++) {
250375801Siedowse        if (row[i] != NULL)
250474462Salfred            OPENSSL_free(row[i]);
250574462Salfred    }
250675801Siedowse    return (ok);
250774462Salfred}
250875801Siedowse
250975801Siedowsestatic int do_updatedb(CA_DB *db)
251074462Salfred{
251174462Salfred    ASN1_UTCTIME *a_tm = NULL;
251275801Siedowse    int i, cnt = 0;
251375801Siedowse    int db_y2k, a_y2k;          /* flags = 1 if y >= 2000 */
251474462Salfred    char **rrow, *a_tm_s;
251574462Salfred
251675801Siedowse    a_tm = ASN1_UTCTIME_new();
251775801Siedowse    if (a_tm == NULL)
251874462Salfred        return -1;
251974462Salfred
252075801Siedowse    /* get actual time and make a string */
252175801Siedowse    a_tm = X509_gmtime_adj(a_tm, 0);
252275801Siedowse    a_tm_s = (char *)OPENSSL_malloc(a_tm->length + 1);
252374462Salfred    if (a_tm_s == NULL) {
252474462Salfred        cnt = -1;
252575754Siedowse        goto err;
252675754Siedowse    }
252775754Siedowse
252875754Siedowse    memcpy(a_tm_s, a_tm->data, a_tm->length);
252975754Siedowse    a_tm_s[a_tm->length] = '\0';
253075754Siedowse
253174462Salfred    if (strncmp(a_tm_s, "49", 2) <= 0)
253274462Salfred        a_y2k = 1;
253374462Salfred    else
253474462Salfred        a_y2k = 0;
253574462Salfred
253674792Salfred    for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
253774792Salfred        rrow = sk_OPENSSL_PSTRING_value(db->db->data, i);
253874462Salfred
253974462Salfred        if (rrow[DB_type][0] == 'V') {
2540            /* ignore entries that are not valid */
2541            if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2542                db_y2k = 1;
2543            else
2544                db_y2k = 0;
2545
2546            if (db_y2k == a_y2k) {
2547                /* all on the same y2k side */
2548                if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0) {
2549                    rrow[DB_type][0] = 'E';
2550                    rrow[DB_type][1] = '\0';
2551                    cnt++;
2552
2553                    BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]);
2554                }
2555            } else if (db_y2k < a_y2k) {
2556                rrow[DB_type][0] = 'E';
2557                rrow[DB_type][1] = '\0';
2558                cnt++;
2559
2560                BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]);
2561            }
2562
2563        }
2564    }
2565
2566 err:
2567
2568    ASN1_UTCTIME_free(a_tm);
2569    OPENSSL_free(a_tm_s);
2570
2571    return (cnt);
2572}
2573
2574static const char *crl_reasons[] = {
2575    /* CRL reason strings */
2576    "unspecified",
2577    "keyCompromise",
2578    "CACompromise",
2579    "affiliationChanged",
2580    "superseded",
2581    "cessationOfOperation",
2582    "certificateHold",
2583    "removeFromCRL",
2584    /* Additional pseudo reasons */
2585    "holdInstruction",
2586    "keyTime",
2587    "CAkeyTime"
2588};
2589
2590#define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2591
2592/*
2593 * Given revocation information convert to a DB string. The format of the
2594 * string is: revtime[,reason,extra]. Where 'revtime' is the revocation time
2595 * (the current time). 'reason' is the optional CRL reason and 'extra' is any
2596 * additional argument
2597 */
2598
2599char *make_revocation_str(int rev_type, char *rev_arg)
2600{
2601    char *other = NULL, *str;
2602    const char *reason = NULL;
2603    ASN1_OBJECT *otmp;
2604    ASN1_UTCTIME *revtm = NULL;
2605    int i;
2606    switch (rev_type) {
2607    case REV_NONE:
2608        break;
2609
2610    case REV_CRL_REASON:
2611        for (i = 0; i < 8; i++) {
2612            if (!strcasecmp(rev_arg, crl_reasons[i])) {
2613                reason = crl_reasons[i];
2614                break;
2615            }
2616        }
2617        if (reason == NULL) {
2618            BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2619            return NULL;
2620        }
2621        break;
2622
2623    case REV_HOLD:
2624        /* Argument is an OID */
2625
2626        otmp = OBJ_txt2obj(rev_arg, 0);
2627        ASN1_OBJECT_free(otmp);
2628
2629        if (otmp == NULL) {
2630            BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2631            return NULL;
2632        }
2633
2634        reason = "holdInstruction";
2635        other = rev_arg;
2636        break;
2637
2638    case REV_KEY_COMPROMISE:
2639    case REV_CA_COMPROMISE:
2640
2641        /* Argument is the key compromise time  */
2642        if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg)) {
2643            BIO_printf(bio_err,
2644                       "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n",
2645                       rev_arg);
2646            return NULL;
2647        }
2648        other = rev_arg;
2649        if (rev_type == REV_KEY_COMPROMISE)
2650            reason = "keyTime";
2651        else
2652            reason = "CAkeyTime";
2653
2654        break;
2655
2656    }
2657
2658    revtm = X509_gmtime_adj(NULL, 0);
2659
2660    if (!revtm)
2661        return NULL;
2662
2663    i = revtm->length + 1;
2664
2665    if (reason)
2666        i += strlen(reason) + 1;
2667    if (other)
2668        i += strlen(other) + 1;
2669
2670    str = OPENSSL_malloc(i);
2671
2672    if (!str)
2673        return NULL;
2674
2675    BUF_strlcpy(str, (char *)revtm->data, i);
2676    if (reason) {
2677        BUF_strlcat(str, ",", i);
2678        BUF_strlcat(str, reason, i);
2679    }
2680    if (other) {
2681        BUF_strlcat(str, ",", i);
2682        BUF_strlcat(str, other, i);
2683    }
2684    ASN1_UTCTIME_free(revtm);
2685    return str;
2686}
2687
2688/*-
2689 * Convert revocation field to X509_REVOKED entry
2690 * return code:
2691 * 0 error
2692 * 1 OK
2693 * 2 OK and some extensions added (i.e. V2 CRL)
2694 */
2695
2696int make_revoked(X509_REVOKED *rev, const char *str)
2697{
2698    char *tmp = NULL;
2699    int reason_code = -1;
2700    int i, ret = 0;
2701    ASN1_OBJECT *hold = NULL;
2702    ASN1_GENERALIZEDTIME *comp_time = NULL;
2703    ASN1_ENUMERATED *rtmp = NULL;
2704
2705    ASN1_TIME *revDate = NULL;
2706
2707    i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str);
2708
2709    if (i == 0)
2710        goto err;
2711
2712    if (rev && !X509_REVOKED_set_revocationDate(rev, revDate))
2713        goto err;
2714
2715    if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)) {
2716        rtmp = ASN1_ENUMERATED_new();
2717        if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
2718            goto err;
2719        if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
2720            goto err;
2721    }
2722
2723    if (rev && comp_time) {
2724        if (!X509_REVOKED_add1_ext_i2d
2725            (rev, NID_invalidity_date, comp_time, 0, 0))
2726            goto err;
2727    }
2728    if (rev && hold) {
2729        if (!X509_REVOKED_add1_ext_i2d
2730            (rev, NID_hold_instruction_code, hold, 0, 0))
2731            goto err;
2732    }
2733
2734    if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
2735        ret = 2;
2736    else
2737        ret = 1;
2738
2739 err:
2740
2741    if (tmp)
2742        OPENSSL_free(tmp);
2743    ASN1_OBJECT_free(hold);
2744    ASN1_GENERALIZEDTIME_free(comp_time);
2745    ASN1_ENUMERATED_free(rtmp);
2746    ASN1_TIME_free(revDate);
2747
2748    return ret;
2749}
2750
2751int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
2752{
2753    char buf[25], *pbuf, *p;
2754    int j;
2755    j = i2a_ASN1_OBJECT(bp, obj);
2756    pbuf = buf;
2757    for (j = 22 - j; j > 0; j--)
2758        *(pbuf++) = ' ';
2759    *(pbuf++) = ':';
2760    *(pbuf++) = '\0';
2761    BIO_puts(bp, buf);
2762
2763    if (str->type == V_ASN1_PRINTABLESTRING)
2764        BIO_printf(bp, "PRINTABLE:'");
2765    else if (str->type == V_ASN1_T61STRING)
2766        BIO_printf(bp, "T61STRING:'");
2767    else if (str->type == V_ASN1_IA5STRING)
2768        BIO_printf(bp, "IA5STRING:'");
2769    else if (str->type == V_ASN1_UNIVERSALSTRING)
2770        BIO_printf(bp, "UNIVERSALSTRING:'");
2771    else
2772        BIO_printf(bp, "ASN.1 %2d:'", str->type);
2773
2774    p = (char *)str->data;
2775    for (j = str->length; j > 0; j--) {
2776        if ((*p >= ' ') && (*p <= '~'))
2777            BIO_printf(bp, "%c", *p);
2778        else if (*p & 0x80)
2779            BIO_printf(bp, "\\0x%02X", *p);
2780        else if ((unsigned char)*p == 0xf7)
2781            BIO_printf(bp, "^?");
2782        else
2783            BIO_printf(bp, "^%c", *p + '@');
2784        p++;
2785    }
2786    BIO_printf(bp, "'\n");
2787    return 1;
2788}
2789
2790int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold,
2791                   ASN1_GENERALIZEDTIME **pinvtm, const char *str)
2792{
2793    char *tmp = NULL;
2794    char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
2795    int reason_code = -1;
2796    int ret = 0;
2797    unsigned int i;
2798    ASN1_OBJECT *hold = NULL;
2799    ASN1_GENERALIZEDTIME *comp_time = NULL;
2800    tmp = BUF_strdup(str);
2801
2802    if (!tmp) {
2803        BIO_printf(bio_err, "memory allocation failure\n");
2804        goto err;
2805    }
2806
2807    p = strchr(tmp, ',');
2808
2809    rtime_str = tmp;
2810
2811    if (p) {
2812        *p = '\0';
2813        p++;
2814        reason_str = p;
2815        p = strchr(p, ',');
2816        if (p) {
2817            *p = '\0';
2818            arg_str = p + 1;
2819        }
2820    }
2821
2822    if (prevtm) {
2823        *prevtm = ASN1_UTCTIME_new();
2824        if (!*prevtm) {
2825            BIO_printf(bio_err, "memory allocation failure\n");
2826            goto err;
2827        }
2828        if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str)) {
2829            BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
2830            goto err;
2831        }
2832    }
2833    if (reason_str) {
2834        for (i = 0; i < NUM_REASONS; i++) {
2835            if (!strcasecmp(reason_str, crl_reasons[i])) {
2836                reason_code = i;
2837                break;
2838            }
2839        }
2840        if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS) {
2841            BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
2842            goto err;
2843        }
2844
2845        if (reason_code == 7)
2846            reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
2847        else if (reason_code == 8) { /* Hold instruction */
2848            if (!arg_str) {
2849                BIO_printf(bio_err, "missing hold instruction\n");
2850                goto err;
2851            }
2852            reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
2853            hold = OBJ_txt2obj(arg_str, 0);
2854
2855            if (!hold) {
2856                BIO_printf(bio_err, "invalid object identifier %s\n",
2857                           arg_str);
2858                goto err;
2859            }
2860            if (phold)
2861                *phold = hold;
2862        } else if ((reason_code == 9) || (reason_code == 10)) {
2863            if (!arg_str) {
2864                BIO_printf(bio_err, "missing compromised time\n");
2865                goto err;
2866            }
2867            comp_time = ASN1_GENERALIZEDTIME_new();
2868            if (!comp_time) {
2869                BIO_printf(bio_err, "memory allocation failure\n");
2870                goto err;
2871            }
2872            if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str)) {
2873                BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
2874                goto err;
2875            }
2876            if (reason_code == 9)
2877                reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
2878            else
2879                reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
2880        }
2881    }
2882
2883    if (preason)
2884        *preason = reason_code;
2885    if (pinvtm)
2886        *pinvtm = comp_time;
2887    else
2888        ASN1_GENERALIZEDTIME_free(comp_time);
2889
2890    ret = 1;
2891
2892 err:
2893
2894    if (tmp)
2895        OPENSSL_free(tmp);
2896    if (!phold)
2897        ASN1_OBJECT_free(hold);
2898    if (!pinvtm)
2899        ASN1_GENERALIZEDTIME_free(comp_time);
2900
2901    return ret;
2902}
2903