[BACK]Return to ca.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / openssl

Annotation of src/usr.bin/openssl/ca.c, Revision 1.1

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