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