X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=apps%2Fca.c;h=9428c3018aff01c4a4abce14b8906c5e96db76ae;hp=814162d0b9dbf3d8e0433b0aa3b325af854a4b2d;hb=e627a13cd58a54df830e0fc2853f3ea8862699f2;hpb=918bb8652969fd53f0c390c1cd909265ed502c7e diff --git a/apps/ca.c b/apps/ca.c index 814162d0b9..9428c3018a 100644 --- a/apps/ca.c +++ b/apps/ca.c @@ -1,59 +1,10 @@ -/* apps/ca.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ /* The PPKI stuff has been donated by Jeff Barber */ @@ -77,12 +28,8 @@ #ifndef W_OK # ifdef OPENSSL_SYS_VMS -# if defined(__DECC) -# include -# else -# include -# endif -# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_NETWARE) +# include +# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) # include # endif #endif @@ -96,28 +43,27 @@ # define R_OK 4 #endif -#undef PROG -#define PROG ca_main +#ifndef PATH_MAX +# define PATH_MAX 4096 +#endif +#ifndef NAME_MAX +# define NAME_MAX 255 +#endif -#define BASE_SECTION "ca" -#define CONFIG_FILE "openssl.cnf" +#define CERT_MAX (PATH_MAX + NAME_MAX) + +#define BASE_SECTION "ca" #define ENV_DEFAULT_CA "default_ca" -#define STRING_MASK "string_mask" +#define STRING_MASK "string_mask" #define UTF8_IN "utf8" -#define ENV_DIR "dir" -#define ENV_CERTS "certs" -#define ENV_CRL_DIR "crl_dir" -#define ENV_CA_DB "CA_DB" #define ENV_NEW_CERTS_DIR "new_certs_dir" #define ENV_CERTIFICATE "certificate" #define ENV_SERIAL "serial" #define ENV_CRLNUMBER "crlnumber" -#define ENV_CRL "crl" #define ENV_PRIVATE_KEY "private_key" -#define ENV_RANDFILE "RANDFILE" #define ENV_DEFAULT_DAYS "default_days" #define ENV_DEFAULT_STARTDATE "default_startdate" #define ENV_DEFAULT_ENDDATE "default_enddate" @@ -138,481 +84,361 @@ #define ENV_DATABASE "database" /* Additional revocation information types */ - -#define REV_NONE 0 /* No addditional information */ -#define REV_CRL_REASON 1 /* Value is CRL reason code */ -#define REV_HOLD 2 /* Value is hold instruction */ -#define REV_KEY_COMPROMISE 3 /* Value is cert key compromise time */ -#define REV_CA_COMPROMISE 4 /* Value is CA key compromise time */ - -static const char *ca_usage[] = { - "usage: ca args\n", - "\n", - " -verbose - Talk a lot while doing things\n", - " -config file - A config file\n", - " -name arg - The particular CA definition to use\n", - " -gencrl - Generate a new CRL\n", - " -crldays days - Days is when the next CRL is due\n", - " -crlhours hours - Hours is when the next CRL is due\n", - " -startdate YYMMDDHHMMSSZ - certificate validity notBefore\n", - " -enddate YYMMDDHHMMSSZ - certificate validity notAfter (overrides -days)\n", - " -days arg - number of days to certify the certificate for\n", - " -md arg - md to use, one of md2, md5, sha or sha1\n", - " -policy arg - The CA 'policy' to support\n", - " -keyfile arg - private key file\n", - " -keyform arg - private key file format (PEM or ENGINE)\n", - " -key arg - key to decode the private key if it is encrypted\n", - " -cert file - The CA certificate\n", - " -selfsign - sign a certificate with the key associated with it\n", - " -in file - The input PEM encoded certificate request(s)\n", - " -out file - Where to put the output file(s)\n", - " -outdir dir - Where to put output certificates\n", - " -infiles .... - The last argument, requests to process\n", - " -spkac file - File contains DN and signed public key and challenge\n", - " -ss_cert file - File contains a self signed cert to sign\n", - " -preserveDN - Don't re-order the DN\n", - " -noemailDN - Don't add the EMAIL field into certificate' subject\n", - " -batch - Don't ask questions\n", - " -msie_hack - msie modifications to handle all those universal strings\n", - " -revoke file - Revoke a certificate (given in file)\n", - " -subj arg - Use arg instead of request's subject\n", - " -utf8 - input characters are UTF8 (default ASCII)\n", - " -multivalue-rdn - enable support for multivalued RDNs\n", - " -extensions .. - Extension section (override value in config file)\n", - " -extfile file - Configuration file with X509v3 extensions to add\n", - " -crlexts .. - CRL extension section (override value in config file)\n", -#ifndef OPENSSL_NO_ENGINE - " -engine e - use engine e, possibly a hardware device.\n", -#endif - " -status serial - Shows certificate status given the serial number\n", - " -updatedb - Updates db for expired certificates\n", - NULL -}; - -#ifdef EFENCE -extern int EF_PROTECT_FREE; -extern int EF_PROTECT_BELOW; -extern int EF_ALIGNMENT; -#endif - -static void lookup_fail(const char *name, const char *tag); -static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, +typedef enum { + REV_VALID = -1, /* Valid (not-revoked) status */ + REV_NONE = 0, /* No additional information */ + REV_CRL_REASON = 1, /* Value is CRL reason code */ + REV_HOLD = 2, /* Value is hold instruction */ + REV_KEY_COMPROMISE = 3, /* Value is cert key compromise time */ + REV_CA_COMPROMISE = 4 /* Value is CA key compromise time */ +} REVINFO_TYPE; + +static char *lookup_conf(const CONF *conf, const char *group, const char *tag); + +static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, char *enddate, - long days, int batch, char *ext_sect, CONF *conf, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, + long days, int batch, const char *ext_sect, CONF *conf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy, int selfsign); -static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, +static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, - char *enddate, long days, int batch, char *ext_sect, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, long days, int batch, const char *ext_sect, CONF *conf, int verbose, unsigned long certopt, - unsigned long nameopt, int default_op, int ext_copy, - ENGINE *e); -static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, + unsigned long nameopt, int default_op, int ext_copy); +static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, - char *enddate, long days, char *ext_sect, CONF *conf, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, long days, const char *ext_sect, CONF *conf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy); -static void write_new_certificate(BIO *bp, X509 *x, int output_der, - int notext); static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, - char *subj, unsigned long chtype, int multirdn, - int email_dn, char *startdate, char *enddate, long days, - int batch, int verbose, X509_REQ *req, char *ext_sect, + const char *subj, unsigned long chtype, int multirdn, + int email_dn, const char *startdate, const char *enddate, long days, + int batch, int verbose, X509_REQ *req, const char *ext_sect, CONF *conf, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy, int selfsign); -static int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval); static int get_certificate_status(const char *ser_status, CA_DB *db); static int do_updatedb(CA_DB *db); static int check_time_format(const char *str); -char *make_revocation_str(int rev_type, char *rev_arg); -int make_revoked(X509_REVOKED *rev, const char *str); -int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str); -static CONF *conf = NULL; -static CONF *extconf = NULL; -static char *section = NULL; +static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type, + const char *extval); +static char *make_revocation_str(REVINFO_TYPE rev_type, const char *rev_arg); +static int make_revoked(X509_REVOKED *rev, const char *str); +static int old_entry_print(const ASN1_OBJECT *obj, const ASN1_STRING *str); +static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext); +static CONF *extconf = NULL; static int preserve = 0; static int msie_hack = 0; -int MAIN(int, char **); +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ENGINE, OPT_VERBOSE, OPT_CONFIG, OPT_NAME, OPT_SUBJ, OPT_UTF8, + OPT_CREATE_SERIAL, OPT_MULTIVALUE_RDN, OPT_STARTDATE, OPT_ENDDATE, + OPT_DAYS, OPT_MD, OPT_POLICY, OPT_KEYFILE, OPT_KEYFORM, OPT_PASSIN, + OPT_KEY, OPT_CERT, OPT_SELFSIGN, OPT_IN, OPT_OUT, OPT_OUTDIR, + OPT_SIGOPT, OPT_NOTEXT, OPT_BATCH, OPT_PRESERVEDN, OPT_NOEMAILDN, + OPT_GENCRL, OPT_MSIE_HACK, OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC, + OPT_INFILES, OPT_SS_CERT, OPT_SPKAC, OPT_REVOKE, OPT_VALID, + OPT_EXTENSIONS, OPT_EXTFILE, OPT_STATUS, OPT_UPDATEDB, OPT_CRLEXTS, + /* Do not change the order here; see related case statements below */ + OPT_CRL_REASON, OPT_CRL_HOLD, OPT_CRL_COMPROMISE, OPT_CRL_CA_COMPROMISE +} OPTION_CHOICE; + +const OPTIONS ca_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"verbose", OPT_VERBOSE, '-', "Verbose output during processing"}, + {"config", OPT_CONFIG, 's', "A config file"}, + {"name", OPT_NAME, 's', "The particular CA definition to use"}, + {"subj", OPT_SUBJ, 's', "Use arg instead of request's subject"}, + {"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"}, + {"create_serial", OPT_CREATE_SERIAL, '-', + "If reading serial fails, create a new random serial"}, + {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-', + "Enable support for multivalued RDNs"}, + {"startdate", OPT_STARTDATE, 's', "Cert notBefore, YYMMDDHHMMSSZ"}, + {"enddate", OPT_ENDDATE, 's', + "YYMMDDHHMMSSZ cert notAfter (overrides -days)"}, + {"days", OPT_DAYS, 'p', "Number of days to certify the cert for"}, + {"md", OPT_MD, 's', "md to use; one of md2, md5, sha or sha1"}, + {"policy", OPT_POLICY, 's', "The CA 'policy' to support"}, + {"keyfile", OPT_KEYFILE, 's', "Private key"}, + {"keyform", OPT_KEYFORM, 'f', "Private key file format (PEM or ENGINE)"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"key", OPT_KEY, 's', "Key to decode the private key if it is encrypted"}, + {"cert", OPT_CERT, '<', "The CA cert"}, + {"selfsign", OPT_SELFSIGN, '-', + "Sign a cert with the key associated with it"}, + {"in", OPT_IN, '<', "The input PEM encoded cert request(s)"}, + {"out", OPT_OUT, '>', "Where to put the output file(s)"}, + {"outdir", OPT_OUTDIR, '/', "Where to put output cert"}, + {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, + {"notext", OPT_NOTEXT, '-', "Do not print the generated certificate"}, + {"batch", OPT_BATCH, '-', "Don't ask questions"}, + {"preserveDN", OPT_PRESERVEDN, '-', "Don't re-order the DN"}, + {"noemailDN", OPT_NOEMAILDN, '-', "Don't add the EMAIL field to the DN"}, + {"gencrl", OPT_GENCRL, '-', "Generate a new CRL"}, + {"msie_hack", OPT_MSIE_HACK, '-', + "msie modifications to handle all those universal strings"}, + {"crldays", OPT_CRLDAYS, 'p', "Days until the next CRL is due"}, + {"crlhours", OPT_CRLHOURS, 'p', "Hours until the next CRL is due"}, + {"crlsec", OPT_CRLSEC, 'p', "Seconds until the next CRL is due"}, + {"infiles", OPT_INFILES, '-', "The last argument, requests to process"}, + {"ss_cert", OPT_SS_CERT, '<', "File contains a self signed cert to sign"}, + {"spkac", OPT_SPKAC, '<', + "File contains DN and signed public key and challenge"}, + {"revoke", OPT_REVOKE, '<', "Revoke a cert (given in file)"}, + {"valid", OPT_VALID, 's', + "Add a Valid(not-revoked) DB entry about a cert (given in file)"}, + {"extensions", OPT_EXTENSIONS, 's', + "Extension section (override value in config file)"}, + {"extfile", OPT_EXTFILE, '<', + "Configuration file with X509v3 extensions to add"}, + {"status", OPT_STATUS, 's', "Shows cert status given the serial number"}, + {"updatedb", OPT_UPDATEDB, '-', "Updates db for expired cert"}, + {"crlexts", OPT_CRLEXTS, 's', + "CRL extension section (override value in config file)"}, + {"crl_reason", OPT_CRL_REASON, 's', "revocation reason"}, + {"crl_hold", OPT_CRL_HOLD, 's', + "the hold instruction, an OID. Sets revocation reason to certificateHold"}, + {"crl_compromise", OPT_CRL_COMPROMISE, 's', + "sets compromise time to val and the revocation reason to keyCompromise"}, + {"crl_CA_compromise", OPT_CRL_CA_COMPROMISE, 's', + "sets compromise time to val and the revocation reason to CACompromise"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {NULL} +}; -int MAIN(int argc, char **argv) +int ca_main(int argc, char **argv) { + CONF *conf = NULL; ENGINE *e = NULL; - char *key = NULL, *passargin = NULL; - int create_ser = 0; - int free_key = 0; - int total = 0; - int total_done = 0; - int badops = 0; - int ret = 1; - int email_dn = 1; - int req = 0; - int verbose = 0; - int gencrl = 0; - int dorevoke = 0; - int doupdatedb = 0; - long crldays = 0; - long crlhours = 0; - long crlsec = 0; - long errorline = -1; - char *configfile = NULL; - char *md = NULL; - char *policy = NULL; - char *keyfile = NULL; - char *certfile = NULL; - int keyform = FORMAT_PEM; - char *infile = NULL; - char *spkac_file = NULL; - char *ss_cert_file = NULL; - char *ser_status = NULL; + BIGNUM *crlnumber = NULL, *serial = NULL; EVP_PKEY *pkey = NULL; - int output_der = 0; - char *outfile = NULL; - char *outdir = NULL; - char *serialfile = NULL; - char *crlnumberfile = NULL; - char *extensions = NULL; - char *extfile = NULL; - char *subj = NULL; - unsigned long chtype = MBSTRING_ASC; - int multirdn = 0; - char *tmp_email_dn = NULL; - char *crl_ext = NULL; - int rev_type = REV_NONE; - char *rev_arg = NULL; - BIGNUM *serial = NULL; - BIGNUM *crlnumber = NULL; - char *startdate = NULL; - char *enddate = NULL; - long days = 0; - int batch = 0; - int notext = 0; - unsigned long nameopt = 0, certopt = 0; - int default_op = 1; - int ext_copy = EXT_COPY_NONE; - int selfsign = 0; - X509 *x509 = NULL, *x509p = NULL; - X509 *x = NULL; - BIO *in = NULL, *out = NULL, *Sout = NULL, *Cout = NULL; - char *dbfile = NULL; - CA_DB *db = NULL; - X509_CRL *crl = NULL; - X509_REVOKED *r = NULL; - ASN1_TIME *tmptm; + BIO *in = NULL, *out = NULL, *Sout = NULL; ASN1_INTEGER *tmpser; - char *f; - const char *p; - char *const *pp; - int i, j; - const EVP_MD *dgst = NULL; + ASN1_TIME *tmptm; + CA_DB *db = NULL; + DB_ATTR db_attr; STACK_OF(CONF_VALUE) *attribs = NULL; - STACK_OF(X509) *cert_sk = NULL; STACK_OF(OPENSSL_STRING) *sigopts = NULL; -#undef BSIZE -#define BSIZE 256 - char buf[3][BSIZE]; - char *randfile = NULL; -#ifndef OPENSSL_NO_ENGINE - char *engine = NULL; -#endif - char *tofree = NULL; - DB_ATTR db_attr; - -#ifdef EFENCE - EF_PROTECT_FREE = 1; - EF_PROTECT_BELOW = 1; - EF_ALIGNMENT = 0; -#endif - - apps_startup(); - - conf = NULL; - key = NULL; - section = NULL; - - preserve = 0; - msie_hack = 0; - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - argc--; - argv++; - while (argc >= 1) { - if (strcmp(*argv, "-verbose") == 0) + STACK_OF(X509) *cert_sk = NULL; + X509_CRL *crl = NULL; + const EVP_MD *dgst = NULL; + char *configfile = default_config_file, *section = NULL; + char *md = NULL, *policy = NULL, *keyfile = NULL; + char *certfile = NULL, *crl_ext = NULL, *crlnumberfile = NULL, *key = NULL; + const char *infile = NULL, *spkac_file = NULL, *ss_cert_file = NULL; + const char *extensions = NULL, *extfile = NULL, *passinarg = NULL; + char *outdir = NULL, *outfile = NULL, *rev_arg = NULL, *ser_status = NULL; + const char *serialfile = NULL, *subj = NULL; + char *prog, *startdate = NULL, *enddate = NULL; + char *dbfile = NULL, *f, *randfile = NULL; + char new_cert[CERT_MAX + 1]; + char tmp[10 + 1] = "\0"; + char *const *pp; + const char *p; + int create_ser = 0, free_key = 0, total = 0, total_done = 0; + int batch = 0, default_op = 1, doupdatedb = 0, ext_copy = EXT_COPY_NONE; + int keyformat = FORMAT_PEM, multirdn = 0, notext = 0, output_der = 0; + int ret = 1, email_dn = 1, req = 0, verbose = 0, gencrl = 0, dorevoke = 0; + int i, j, selfsign = 0; + long crldays = 0, crlhours = 0, crlsec = 0, days = 0; + unsigned long chtype = MBSTRING_ASC, nameopt = 0, certopt = 0; + X509 *x509 = NULL, *x509p = NULL, *x = NULL; + REVINFO_TYPE rev_type = REV_NONE; + X509_REVOKED *r = NULL; + OPTION_CHOICE o; + + new_cert[CERT_MAX] = '\0'; + + prog = opt_init(argc, argv, ca_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(ca_options); + ret = 0; + goto end; + case OPT_IN: + req = 1; + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_VERBOSE: verbose = 1; - else if (strcmp(*argv, "-config") == 0) { - if (--argc < 1) - goto bad; - configfile = *(++argv); - } else if (strcmp(*argv, "-name") == 0) { - if (--argc < 1) - goto bad; - section = *(++argv); - } else if (strcmp(*argv, "-subj") == 0) { - if (--argc < 1) - goto bad; - subj = *(++argv); + break; + case OPT_CONFIG: + configfile = opt_arg(); + break; + case OPT_NAME: + section = opt_arg(); + break; + case OPT_SUBJ: + subj = opt_arg(); /* preserve=1; */ - } else if (strcmp(*argv, "-utf8") == 0) + break; + case OPT_UTF8: chtype = MBSTRING_UTF8; - else if (strcmp(*argv, "-create_serial") == 0) + break; + case OPT_CREATE_SERIAL: create_ser = 1; - else if (strcmp(*argv, "-multivalue-rdn") == 0) + break; + case OPT_MULTIVALUE_RDN: multirdn = 1; - else if (strcmp(*argv, "-startdate") == 0) { - if (--argc < 1) - goto bad; - startdate = *(++argv); - } else if (strcmp(*argv, "-enddate") == 0) { - if (--argc < 1) - goto bad; - enddate = *(++argv); - } else if (strcmp(*argv, "-days") == 0) { - if (--argc < 1) - goto bad; - days = atoi(*(++argv)); - } else if (strcmp(*argv, "-md") == 0) { - if (--argc < 1) - goto bad; - md = *(++argv); - } else if (strcmp(*argv, "-policy") == 0) { - if (--argc < 1) - goto bad; - policy = *(++argv); - } else if (strcmp(*argv, "-keyfile") == 0) { - if (--argc < 1) - goto bad; - keyfile = *(++argv); - } else if (strcmp(*argv, "-keyform") == 0) { - if (--argc < 1) - goto bad; - keyform = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-passin") == 0) { - if (--argc < 1) - goto bad; - passargin = *(++argv); - } else if (strcmp(*argv, "-key") == 0) { - if (--argc < 1) - goto bad; - key = *(++argv); - } else if (strcmp(*argv, "-cert") == 0) { - if (--argc < 1) - goto bad; - certfile = *(++argv); - } else if (strcmp(*argv, "-selfsign") == 0) + break; + case OPT_STARTDATE: + startdate = opt_arg(); + break; + case OPT_ENDDATE: + enddate = opt_arg(); + break; + case OPT_DAYS: + days = atoi(opt_arg()); + break; + case OPT_MD: + md = opt_arg(); + break; + case OPT_POLICY: + policy = opt_arg(); + break; + case OPT_KEYFILE: + keyfile = opt_arg(); + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat)) + goto opthelp; + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_KEY: + key = opt_arg(); + break; + case OPT_CERT: + certfile = opt_arg(); + break; + case OPT_SELFSIGN: selfsign = 1; - else if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); - req = 1; - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } else if (strcmp(*argv, "-outdir") == 0) { - if (--argc < 1) - goto bad; - outdir = *(++argv); - } else if (strcmp(*argv, "-sigopt") == 0) { - if (--argc < 1) - goto bad; - if (!sigopts) + break; + case OPT_OUTDIR: + outdir = opt_arg(); + break; + case OPT_SIGOPT: + if (sigopts == NULL) sigopts = sk_OPENSSL_STRING_new_null(); - if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv))) - goto bad; - } else if (strcmp(*argv, "-notext") == 0) + if (sigopts == NULL + || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) + goto end; + break; + case OPT_NOTEXT: notext = 1; - else if (strcmp(*argv, "-batch") == 0) + break; + case OPT_BATCH: batch = 1; - else if (strcmp(*argv, "-preserveDN") == 0) + break; + case OPT_PRESERVEDN: preserve = 1; - else if (strcmp(*argv, "-noemailDN") == 0) + break; + case OPT_NOEMAILDN: email_dn = 0; - else if (strcmp(*argv, "-gencrl") == 0) + break; + case OPT_GENCRL: gencrl = 1; - else if (strcmp(*argv, "-msie_hack") == 0) + break; + case OPT_MSIE_HACK: msie_hack = 1; - else if (strcmp(*argv, "-crldays") == 0) { - if (--argc < 1) - goto bad; - crldays = atol(*(++argv)); - } else if (strcmp(*argv, "-crlhours") == 0) { - if (--argc < 1) - goto bad; - crlhours = atol(*(++argv)); - } else if (strcmp(*argv, "-crlsec") == 0) { - if (--argc < 1) - goto bad; - crlsec = atol(*(++argv)); - } else if (strcmp(*argv, "-infiles") == 0) { - argc--; - argv++; - req = 1; break; - } else if (strcmp(*argv, "-ss_cert") == 0) { - if (--argc < 1) - goto bad; - ss_cert_file = *(++argv); + case OPT_CRLDAYS: + crldays = atol(opt_arg()); + break; + case OPT_CRLHOURS: + crlhours = atol(opt_arg()); + break; + case OPT_CRLSEC: + crlsec = atol(opt_arg()); + break; + case OPT_INFILES: req = 1; - } else if (strcmp(*argv, "-spkac") == 0) { - if (--argc < 1) - goto bad; - spkac_file = *(++argv); + goto end_of_options; + case OPT_SS_CERT: + ss_cert_file = opt_arg(); + req = 1; + break; + case OPT_SPKAC: + spkac_file = opt_arg(); req = 1; - } else if (strcmp(*argv, "-revoke") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); + break; + case OPT_REVOKE: + infile = opt_arg(); dorevoke = 1; - } else if (strcmp(*argv, "-valid") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); + break; + case OPT_VALID: + infile = opt_arg(); dorevoke = 2; - } else if (strcmp(*argv, "-extensions") == 0) { - if (--argc < 1) - goto bad; - extensions = *(++argv); - } else if (strcmp(*argv, "-extfile") == 0) { - if (--argc < 1) - goto bad; - extfile = *(++argv); - } else if (strcmp(*argv, "-status") == 0) { - if (--argc < 1) - goto bad; - ser_status = *(++argv); - } else if (strcmp(*argv, "-updatedb") == 0) { + break; + case OPT_EXTENSIONS: + extensions = opt_arg(); + break; + case OPT_EXTFILE: + extfile = opt_arg(); + break; + case OPT_STATUS: + ser_status = opt_arg(); + break; + case OPT_UPDATEDB: doupdatedb = 1; - } else if (strcmp(*argv, "-crlexts") == 0) { - if (--argc < 1) - goto bad; - crl_ext = *(++argv); - } else if (strcmp(*argv, "-crl_reason") == 0) { - if (--argc < 1) - goto bad; - rev_arg = *(++argv); - rev_type = REV_CRL_REASON; - } else if (strcmp(*argv, "-crl_hold") == 0) { - if (--argc < 1) - goto bad; - rev_arg = *(++argv); - rev_type = REV_HOLD; - } else if (strcmp(*argv, "-crl_compromise") == 0) { - if (--argc < 1) - goto bad; - rev_arg = *(++argv); - rev_type = REV_KEY_COMPROMISE; - } else if (strcmp(*argv, "-crl_CA_compromise") == 0) { - if (--argc < 1) - goto bad; - rev_arg = *(++argv); - rev_type = REV_CA_COMPROMISE; - } -#ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); - } -#endif - else { - bad: - BIO_printf(bio_err, "unknown option %s\n", *argv); - badops = 1; + break; + case OPT_CRLEXTS: + crl_ext = opt_arg(); + break; + case OPT_CRL_REASON: /* := REV_CRL_REASON */ + case OPT_CRL_HOLD: + case OPT_CRL_COMPROMISE: + case OPT_CRL_CA_COMPROMISE: + rev_arg = opt_arg(); + rev_type = (o - OPT_CRL_REASON) + REV_CRL_REASON; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); break; } - argc--; - argv++; - } - - if (badops) { - const char **pp2; - - for (pp2 = ca_usage; (*pp2 != NULL); pp2++) - BIO_printf(bio_err, "%s", *pp2); - goto err; - } - - ERR_load_crypto_strings(); - - /*****************************************************************/ - tofree = NULL; - if (configfile == NULL) - configfile = getenv("OPENSSL_CONF"); - if (configfile == NULL) - configfile = getenv("SSLEAY_CONF"); - if (configfile == NULL) { - const char *s = X509_get_default_cert_area(); - size_t len; - -#ifdef OPENSSL_SYS_VMS - len = strlen(s) + sizeof(CONFIG_FILE); - tofree = OPENSSL_malloc(len); - if(!tofree) { - BIO_printf(bio_err, "Out of memory\n"); - goto err; - } - strcpy(tofree, s); -#else - len = strlen(s) + sizeof(CONFIG_FILE) + 1; - tofree = OPENSSL_malloc(len); - if(!tofree) { - BIO_printf(bio_err, "Out of memory\n"); - goto err; - } - BUF_strlcpy(tofree, s, len); - BUF_strlcat(tofree, "/", len); -#endif - BUF_strlcat(tofree, CONFIG_FILE, len); - configfile = tofree; } +end_of_options: + argc = opt_num_rest(); + argv = opt_rest(); BIO_printf(bio_err, "Using configuration from %s\n", configfile); - conf = NCONF_new(NULL); - if (NCONF_load(conf, configfile, &errorline) <= 0) { - if (errorline <= 0) - BIO_printf(bio_err, "error loading the config file '%s'\n", - configfile); - else - BIO_printf(bio_err, "error on line %ld of config file '%s'\n", - errorline, configfile); - goto err; - } - if (tofree) { - OPENSSL_free(tofree); - tofree = NULL; - } - if (!load_config(bio_err, conf)) - goto err; - -#ifndef OPENSSL_NO_ENGINE - e = setup_engine(bio_err, engine, 0); -#endif + if ((conf = app_load_config(configfile)) == NULL) + goto end; + if (configfile != default_config_file && !app_load_modules(conf)) + goto end; /* Lets get the config section we are using */ - if (section == NULL) { - section = NCONF_get_string(conf, BASE_SECTION, ENV_DEFAULT_CA); - if (section == NULL) { - lookup_fail(BASE_SECTION, ENV_DEFAULT_CA); - goto err; - } - } + if (section == NULL + && (section = lookup_conf(conf, BASE_SECTION, ENV_DEFAULT_CA)) == NULL) + goto end; if (conf != NULL) { p = NCONF_get_string(conf, NULL, "oid_file"); @@ -633,16 +459,16 @@ int MAIN(int argc, char **argv) BIO_free(oid_bio); } } - if (!add_oid_section(bio_err, conf)) { + if (!add_oid_section(conf)) { ERR_print_errors(bio_err); - goto err; + goto end; } } randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE"); if (randfile == NULL) ERR_clear_error(); - app_RAND_load_file(randfile, bio_err, 0); + app_RAND_load_file(randfile, 0); f = NCONF_get_string(conf, section, STRING_MASK); if (!f) @@ -650,107 +476,80 @@ int MAIN(int argc, char **argv) if (f && !ASN1_STRING_set_default_mask_asc(f)) { BIO_printf(bio_err, "Invalid global string mask setting %s\n", f); - goto err; + goto end; } if (chtype != MBSTRING_UTF8) { f = NCONF_get_string(conf, section, UTF8_IN); if (!f) ERR_clear_error(); - else if (!strcmp(f, "yes")) + else if (strcmp(f, "yes") == 0) chtype = MBSTRING_UTF8; } db_attr.unique_subject = 1; p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT); if (p) { -#ifdef RL_DEBUG - BIO_printf(bio_err, "DEBUG: unique_subject = \"%s\"\n", p); -#endif db_attr.unique_subject = parse_yesno(p, 1); } else ERR_clear_error(); -#ifdef RL_DEBUG - if (!p) - BIO_printf(bio_err, "DEBUG: unique_subject undefined\n"); -#endif -#ifdef RL_DEBUG - BIO_printf(bio_err, "DEBUG: configured unique_subject is %d\n", - db_attr.unique_subject); -#endif - - in = BIO_new(BIO_s_file()); - out = BIO_new(BIO_s_file()); - Sout = BIO_new(BIO_s_file()); - Cout = BIO_new(BIO_s_file()); - if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL)) { - ERR_print_errors(bio_err); - goto err; - } - /*****************************************************************/ + /*****************************************************************/ /* report status of cert with serial number given on command line */ if (ser_status) { - if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) { - lookup_fail(section, ENV_DATABASE); - goto err; - } + dbfile = lookup_conf(conf, section, ENV_DATABASE); + if (dbfile == NULL) + goto end; + db = load_index(dbfile, &db_attr); if (db == NULL) - goto err; + goto end; if (!index_index(db)) - goto err; + goto end; if (get_certificate_status(ser_status, db) != 1) BIO_printf(bio_err, "Error verifying serial %s!\n", ser_status); - goto err; + goto end; } - /*****************************************************************/ + /*****************************************************************/ /* we definitely need a private key, so let's get it */ - if ((keyfile == NULL) && ((keyfile = NCONF_get_string(conf, - section, - ENV_PRIVATE_KEY)) == - NULL)) { - lookup_fail(section, ENV_PRIVATE_KEY); - goto err; - } + if (keyfile == NULL + && (keyfile = lookup_conf(conf, section, ENV_PRIVATE_KEY)) == NULL) + goto end; + if (!key) { free_key = 1; - if (!app_passwd(bio_err, passargin, NULL, &key, NULL)) { + if (!app_passwd(passinarg, NULL, &key, NULL)) { BIO_printf(bio_err, "Error getting password\n"); - goto err; + goto end; } } - pkey = load_key(bio_err, keyfile, keyform, 0, key, e, "CA private key"); + pkey = load_key(keyfile, keyformat, 0, key, e, "CA private key"); if (key) OPENSSL_cleanse(key, strlen(key)); if (pkey == NULL) { /* load_key() has already printed an appropriate message */ - goto err; + goto end; } - /*****************************************************************/ + /*****************************************************************/ /* we need a certificate */ if (!selfsign || spkac_file || ss_cert_file || gencrl) { - if ((certfile == NULL) - && ((certfile = NCONF_get_string(conf, - section, - ENV_CERTIFICATE)) == NULL)) { - lookup_fail(section, ENV_CERTIFICATE); - goto err; - } - x509 = load_cert(bio_err, certfile, FORMAT_PEM, NULL, e, - "CA certificate"); + if (certfile == NULL + && (certfile = lookup_conf(conf, section, ENV_CERTIFICATE)) == NULL) + goto end; + + x509 = load_cert(certfile, FORMAT_PEM, "CA certificate"); if (x509 == NULL) - goto err; + goto end; if (!X509_check_private_key(x509, pkey)) { BIO_printf(bio_err, "CA certificate and CA private key do not match\n"); - goto err; + goto end; } } if (!selfsign) @@ -772,18 +571,20 @@ int MAIN(int argc, char **argv) if (f) { if (!set_name_ex(&nameopt, f)) { BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f); - goto err; + goto end; } default_op = 0; - } else + } else { + nameopt = XN_FLAG_ONELINE; ERR_clear_error(); + } f = NCONF_get_string(conf, section, ENV_CERTOPT); if (f) { if (!set_cert_ex(&certopt, f)) { BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f); - goto err; + goto end; } default_op = 0; } else @@ -794,61 +595,46 @@ int MAIN(int argc, char **argv) if (f) { if (!set_ext_copy(&ext_copy, f)) { BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f); - goto err; + goto end; } } else ERR_clear_error(); - /*****************************************************************/ + /*****************************************************************/ /* lookup where to write new certificates */ if ((outdir == NULL) && (req)) { - if ((outdir = NCONF_get_string(conf, section, ENV_NEW_CERTS_DIR)) - == NULL) { + outdir = NCONF_get_string(conf, section, ENV_NEW_CERTS_DIR); + if (outdir == NULL) { BIO_printf(bio_err, "there needs to be defined a directory for new certificate to be placed in\n"); - goto err; + goto end; } #ifndef OPENSSL_SYS_VMS /* * outdir is a directory spec, but access() for VMS demands a - * filename. In any case, stat(), below, will catch the problem if - * outdir is not a directory spec, and the fopen() or open() will - * catch an error if there is no write access. - * - * Presumably, this problem could also be solved by using the DEC C - * routines to convert the directory syntax to Unixly, and give that - * to access(). However, time's too short to do that just now. + * filename. We could use the DEC C routine to convert the + * directory syntax to Unixly, and give that to app_isdir, + * but for now the fopen will catch the error if it's not a + * directory */ -# ifndef _WIN32 - if (access(outdir, R_OK | W_OK | X_OK) != 0) -# else - if (_access(outdir, R_OK | W_OK | X_OK) != 0) -# endif - { - BIO_printf(bio_err, "I am unable to access the %s directory\n", - outdir); - perror(outdir); - goto err; - } - if (app_isdir(outdir) <= 0) { - BIO_printf(bio_err, "%s need to be a directory\n", outdir); + BIO_printf(bio_err, "%s: %s is not a directory\n", prog, outdir); perror(outdir); - goto err; + goto end; } #endif } - /*****************************************************************/ + /*****************************************************************/ /* we need to load the database file */ - if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) { - lookup_fail(section, ENV_DATABASE); - goto err; - } + dbfile = lookup_conf(conf, section, ENV_DATABASE); + if (dbfile == NULL) + goto end; + db = load_index(dbfile, &db_attr); if (db == NULL) - goto err; + goto end; /* Lets check some fields */ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { @@ -857,16 +643,16 @@ int MAIN(int argc, char **argv) BIO_printf(bio_err, "entry %d: not revoked yet, but has a revocation date\n", i + 1); - goto err; + goto end; } if ((pp[DB_type][0] == DB_TYPE_REV) && !make_revoked(NULL, pp[DB_rev_date])) { BIO_printf(bio_err, " in entry %d\n", i + 1); - goto err; + goto end; } if (!check_time_format((char *)pp[DB_exp_date])) { BIO_printf(bio_err, "entry %d: invalid expiry date\n", i + 1); - goto err; + goto end; } p = pp[DB_serial]; j = strlen(p); @@ -877,38 +663,28 @@ int MAIN(int argc, char **argv) if ((j & 1) || (j < 2)) { BIO_printf(bio_err, "entry %d: bad serial number length (%d)\n", i + 1, j); - goto err; + goto end; } - while (*p) { - if (!(((*p >= '0') && (*p <= '9')) || - ((*p >= 'A') && (*p <= 'F')) || - ((*p >= 'a') && (*p <= 'f')))) { + for ( ; *p; p++) { + if (!isxdigit(_UC(*p))) { 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); - goto err; + "entry %d: bad char 0%o '%c' in serial number\n", + i + 1, *p, *p); + goto end; } - p++; } } if (verbose) { - BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); /* cannot fail */ -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - TXT_DB_write(out, db->db); + TXT_DB_write(bio_out, db->db); BIO_printf(bio_err, "%d entries loaded from the database\n", sk_OPENSSL_PSTRING_num(db->db->data)); BIO_printf(bio_err, "generating index\n"); } if (!index_index(db)) - goto err; + goto end; - /*****************************************************************/ + /*****************************************************************/ /* Update the db file for expired certificates */ if (doupdatedb) { if (verbose) @@ -917,16 +693,16 @@ int MAIN(int argc, char **argv) i = do_updatedb(db); if (i == -1) { BIO_printf(bio_err, "Malloc failure\n"); - goto err; + goto end; } else if (i == 0) { if (verbose) BIO_printf(bio_err, "No entries found to mark expired\n"); } else { if (!save_index(dbfile, "new", db)) - goto err; + goto end; if (!rotate_index(dbfile, "new", "old")) - goto err; + goto end; if (verbose) BIO_printf(bio_err, @@ -934,20 +710,12 @@ int MAIN(int argc, char **argv) } } - /*****************************************************************/ + /*****************************************************************/ /* Read extensions config file */ if (extfile) { - extconf = NCONF_new(NULL); - if (NCONF_load(extconf, extfile, &errorline) <= 0) { - if (errorline <= 0) - BIO_printf(bio_err, "ERROR: loading the config file '%s'\n", - extfile); - else - BIO_printf(bio_err, - "ERROR: on line %ld of config file '%s'\n", - errorline, extfile); + if ((extconf = app_load_config(extfile)) == NULL) { ret = 1; - goto err; + goto end; } if (verbose) @@ -955,77 +723,59 @@ int MAIN(int argc, char **argv) extfile); /* We can have sections in the ext file */ - if (!extensions - && !(extensions = - NCONF_get_string(extconf, "default", "extensions"))) - extensions = "default"; + if (extensions == NULL) { + extensions = NCONF_get_string(extconf, "default", "extensions"); + if (extensions == NULL) + extensions = "default"; + } } - /*****************************************************************/ + /*****************************************************************/ if (req || gencrl) { - if (outfile != NULL) { - if (BIO_write_filename(Sout, outfile) <= 0) { - perror(outfile); - goto err; - } - } else { - BIO_set_fp(Sout, stdout, BIO_NOCLOSE | BIO_FP_TEXT); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - Sout = BIO_push(tmpbio, Sout); - } -#endif - } + /* FIXME: Is it really always text? */ + Sout = bio_open_default(outfile, 'w', FORMAT_TEXT); + if (Sout == NULL) + goto end; } - if ((md == NULL) && ((md = NCONF_get_string(conf, - section, - ENV_DEFAULT_MD)) == NULL)) { - lookup_fail(section, ENV_DEFAULT_MD); - goto err; - } + if (md == NULL + && (md = lookup_conf(conf, section, ENV_DEFAULT_MD)) == NULL) + goto end; - if (!strcmp(md, "default")) { + if (strcmp(md, "default") == 0) { int def_nid; if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0) { BIO_puts(bio_err, "no default digest\n"); - goto err; + goto end; } md = (char *)OBJ_nid2sn(def_nid); } - if ((dgst = EVP_get_digestbyname(md)) == NULL) { - BIO_printf(bio_err, "%s is an unsupported message digest type\n", md); - goto err; + if (!opt_md(md, &dgst)) { + goto end; } if (req) { - if ((email_dn == 1) && ((tmp_email_dn = NCONF_get_string(conf, - section, - ENV_DEFAULT_EMAIL_DN)) - != NULL)) { - if (strcmp(tmp_email_dn, "no") == 0) + if (email_dn == 1) { + char *tmp_email_dn = NULL; + + tmp_email_dn = NCONF_get_string(conf, section, ENV_DEFAULT_EMAIL_DN); + if (tmp_email_dn != NULL && strcmp(tmp_email_dn, "no") == 0) email_dn = 0; } if (verbose) BIO_printf(bio_err, "message digest is %s\n", - OBJ_nid2ln(dgst->type)); - if ((policy == NULL) && ((policy = NCONF_get_string(conf, - section, - ENV_POLICY)) == - NULL)) { - lookup_fail(section, ENV_POLICY); - goto err; - } + OBJ_nid2ln(EVP_MD_type(dgst))); + if (policy == NULL + && (policy = lookup_conf(conf, section, ENV_POLICY)) == NULL) + goto end; + if (verbose) BIO_printf(bio_err, "policy is %s\n", policy); - if ((serialfile = NCONF_get_string(conf, section, ENV_SERIAL)) - == NULL) { - lookup_fail(section, ENV_SERIAL); - goto err; - } + serialfile = lookup_conf(conf, section, ENV_SERIAL); + if (serialfile == NULL) + goto end; if (!extconf) { /* @@ -1047,7 +797,7 @@ int MAIN(int argc, char **argv) "Error Loading extension section %s\n", extensions); ret = 1; - goto err; + goto end; } } } @@ -1061,7 +811,7 @@ int MAIN(int argc, char **argv) if (startdate && !ASN1_TIME_set_string(NULL, startdate)) { BIO_printf(bio_err, "start date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n"); - goto err; + goto end; } if (startdate == NULL) startdate = "today"; @@ -1074,7 +824,7 @@ int MAIN(int argc, char **argv) if (enddate && !ASN1_TIME_set_string(NULL, enddate)) { BIO_printf(bio_err, "end date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n"); - goto err; + goto end; } if (days == 0) { @@ -1084,19 +834,19 @@ int MAIN(int argc, char **argv) if (!enddate && (days == 0)) { BIO_printf(bio_err, "cannot lookup how many days to certify for\n"); - goto err; + goto end; } if ((serial = load_serial(serialfile, create_ser, NULL)) == NULL) { BIO_printf(bio_err, "error while loading serial number\n"); - goto err; + goto end; } if (verbose) { if (BN_is_zero(serial)) BIO_printf(bio_err, "next serial number is 00\n"); else { if ((f = BN_bn2hex(serial)) == NULL) - goto err; + goto end; BIO_printf(bio_err, "next serial number is %s\n", f); OPENSSL_free(f); } @@ -1104,12 +854,12 @@ int MAIN(int argc, char **argv) if ((attribs = NCONF_get_section(conf, policy)) == NULL) { BIO_printf(bio_err, "unable to find 'section' for %s\n", policy); - goto err; + goto end; } if ((cert_sk = sk_X509_new_null()) == NULL) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } if (spkac_file != NULL) { total++; @@ -1119,15 +869,15 @@ int MAIN(int argc, char **argv) conf, verbose, certopt, nameopt, default_op, ext_copy); if (j < 0) - goto err; + goto end; if (j > 0) { total_done++; BIO_printf(bio_err, "\n"); if (!BN_add_word(serial, 1)) - goto err; + goto end; if (!sk_X509_push(cert_sk, x)) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } if (outfile) { output_der = 1; @@ -1142,17 +892,17 @@ int MAIN(int argc, char **argv) db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, extensions, conf, verbose, certopt, nameopt, default_op, - ext_copy, e); + ext_copy); if (j < 0) - goto err; + goto end; if (j > 0) { total_done++; BIO_printf(bio_err, "\n"); if (!BN_add_word(serial, 1)) - goto err; + goto end; if (!sk_X509_push(cert_sk, x)) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } } } @@ -1163,15 +913,15 @@ int MAIN(int argc, char **argv) enddate, days, batch, extensions, conf, verbose, certopt, nameopt, default_op, ext_copy, selfsign); if (j < 0) - goto err; + goto end; if (j > 0) { total_done++; BIO_printf(bio_err, "\n"); if (!BN_add_word(serial, 1)) - goto err; + goto end; if (!sk_X509_push(cert_sk, x)) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } } } @@ -1182,15 +932,15 @@ int MAIN(int argc, char **argv) enddate, days, batch, extensions, conf, verbose, certopt, nameopt, default_op, ext_copy, selfsign); if (j < 0) - goto err; + goto end; if (j > 0) { total_done++; BIO_printf(bio_err, "\n"); if (!BN_add_word(serial, 1)) - goto err; + goto end; if (!sk_X509_push(cert_sk, x)) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } } } @@ -1205,17 +955,17 @@ int MAIN(int argc, char **argv) "\n%d out of %d certificate requests certified, commit? [y/n]", total_done, total); (void)BIO_flush(bio_err); - buf[0][0] = '\0'; - if (!fgets(buf[0], 10, stdin)) { + tmp[0] = '\0'; + if (fgets(tmp, sizeof(tmp), stdin) == NULL) { BIO_printf(bio_err, "CERTIFICATION CANCELED: I/O error\n"); ret = 0; - goto err; + goto end; } - if ((buf[0][0] != 'y') && (buf[0][0] != 'Y')) { + if (tmp[0] != 'y' && tmp[0] != 'Y') { BIO_printf(bio_err, "CERTIFICATION CANCELED\n"); ret = 0; - goto err; + goto end; } } @@ -1223,41 +973,41 @@ int MAIN(int argc, char **argv) sk_X509_num(cert_sk)); if (!save_serial(serialfile, "new", serial, NULL)) - goto err; + goto end; if (!save_index(dbfile, "new", db)) - goto err; + goto end; } if (verbose) BIO_printf(bio_err, "writing new certificates\n"); for (i = 0; i < sk_X509_num(cert_sk); i++) { + BIO *Cout = NULL; + X509 *xi = sk_X509_value(cert_sk, i); + ASN1_INTEGER *serialNumber = X509_get_serialNumber(xi); int k; char *n; - x = sk_X509_value(cert_sk, i); + j = ASN1_STRING_length(serialNumber); + p = (const char *)ASN1_STRING_get0_data(serialNumber); - j = x->cert_info->serialNumber->length; - p = (const char *)x->cert_info->serialNumber->data; - - if (strlen(outdir) >= (size_t)(j ? BSIZE - j * 2 - 6 : BSIZE - 8)) { + if (strlen(outdir) >= (size_t)(j ? CERT_MAX - j * 2 - 6 : CERT_MAX - 8)) { BIO_printf(bio_err, "certificate file name too long\n"); - goto err; + goto end; } - strcpy(buf[2], outdir); - + strcpy(new_cert, outdir); #ifndef OPENSSL_SYS_VMS - BUF_strlcat(buf[2], "/", sizeof(buf[2])); + OPENSSL_strlcat(new_cert, "/", sizeof(new_cert)); #endif - n = (char *)&(buf[2][strlen(buf[2])]); + n = (char *)&(new_cert[strlen(new_cert)]); if (j > 0) { for (k = 0; k < j; k++) { - if (n >= &(buf[2][sizeof(buf[2])])) + if (n >= &(new_cert[sizeof(new_cert)])) break; BIO_snprintf(n, - &buf[2][0] + sizeof(buf[2]) - n, + &new_cert[0] + sizeof(new_cert) - n, "%02X", (unsigned char)*(p++)); n += 2; } @@ -1271,29 +1021,31 @@ int MAIN(int argc, char **argv) *(n++) = 'm'; *n = '\0'; if (verbose) - BIO_printf(bio_err, "writing %s\n", buf[2]); + BIO_printf(bio_err, "writing %s\n", new_cert); - if (BIO_write_filename(Cout, buf[2]) <= 0) { - perror(buf[2]); - goto err; + Cout = BIO_new_file(new_cert, "w"); + if (Cout == NULL) { + perror(new_cert); + goto end; } - write_new_certificate(Cout, x, 0, notext); - write_new_certificate(Sout, x, output_der, notext); + write_new_certificate(Cout, xi, 0, notext); + write_new_certificate(Sout, xi, output_der, notext); + BIO_free_all(Cout); } if (sk_X509_num(cert_sk)) { /* Rename the database and the serial file */ if (!rotate_serial(serialfile, "new", "old")) - goto err; + goto end; if (!rotate_index(dbfile, "new", "old")) - goto err; + goto end; BIO_printf(bio_err, "Data Base Updated\n"); } } - /*****************************************************************/ + /*****************************************************************/ if (gencrl) { int crl_v2 = 0; if (!crl_ext) { @@ -1311,7 +1063,7 @@ int MAIN(int argc, char **argv) "Error Loading CRL extension section %s\n", crl_ext); ret = 1; - goto err; + goto end; } } @@ -1319,7 +1071,7 @@ int MAIN(int argc, char **argv) != NULL) if ((crlnumber = load_serial(crlnumberfile, 0, NULL)) == NULL) { BIO_printf(bio_err, "error while loading CRL number\n"); - goto err; + goto end; } if (!crldays && !crlhours && !crlsec) { @@ -1334,27 +1086,27 @@ int MAIN(int argc, char **argv) if ((crldays == 0) && (crlhours == 0) && (crlsec == 0)) { BIO_printf(bio_err, "cannot lookup how long until the next CRL is issued\n"); - goto err; + goto end; } if (verbose) BIO_printf(bio_err, "making CRL\n"); if ((crl = X509_CRL_new()) == NULL) - goto err; + goto end; if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) - goto err; + goto end; tmptm = ASN1_TIME_new(); - if (!tmptm) - goto err; + if (tmptm == NULL) + goto end; X509_gmtime_adj(tmptm, 0); - X509_CRL_set_lastUpdate(crl, tmptm); + X509_CRL_set1_lastUpdate(crl, tmptm); if (!X509_time_adj_ex(tmptm, crldays, crlhours * 60 * 60 + crlsec, NULL)) { BIO_puts(bio_err, "error setting CRL nextUpdate\n"); - goto err; + goto end; } - X509_CRL_set_nextUpdate(crl, tmptm); + X509_CRL_set1_nextUpdate(crl, tmptm); ASN1_TIME_free(tmptm); @@ -1362,19 +1114,19 @@ int MAIN(int argc, char **argv) pp = sk_OPENSSL_PSTRING_value(db->db->data, i); if (pp[DB_type][0] == DB_TYPE_REV) { if ((r = X509_REVOKED_new()) == NULL) - goto err; + goto end; j = make_revoked(r, pp[DB_rev_date]); if (!j) - goto err; + goto end; if (j == 2) crl_v2 = 1; if (!BN_hex2bn(&serial, pp[DB_serial])) - goto err; + goto end; tmpser = BN_to_ASN1_INTEGER(serial, NULL); BN_free(serial); serial = NULL; if (!tmpser) - goto err; + goto end; X509_REVOKED_set_serialNumber(r, tmpser); ASN1_INTEGER_free(tmpser); X509_CRL_add0_revoked(crl, r); @@ -1399,114 +1151,108 @@ int MAIN(int argc, char **argv) if (crl_ext) if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl)) - goto err; + goto end; if (crlnumberfile != NULL) { tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL); if (!tmpser) - goto err; + goto end; X509_CRL_add1_ext_i2d(crl, NID_crl_number, tmpser, 0, 0); ASN1_INTEGER_free(tmpser); crl_v2 = 1; if (!BN_add_word(crlnumber, 1)) - goto err; + goto end; } } if (crl_ext || crl_v2) { if (!X509_CRL_set_version(crl, 1)) - goto err; /* version 2 CRL */ + goto end; /* version 2 CRL */ } /* we have a CRL number that need updating */ if (crlnumberfile != NULL) if (!save_serial(crlnumberfile, "new", crlnumber, NULL)) - goto err; + goto end; - if (crlnumber) { - BN_free(crlnumber); - crlnumber = NULL; - } + BN_free(crlnumber); + crlnumber = NULL; - if (!do_X509_CRL_sign(bio_err, crl, pkey, dgst, sigopts)) - goto err; + if (!do_X509_CRL_sign(crl, pkey, dgst, sigopts)) + goto end; PEM_write_bio_X509_CRL(Sout, crl); if (crlnumberfile != NULL) /* Rename the crlnumber file */ if (!rotate_serial(crlnumberfile, "new", "old")) - goto err; + goto end; } - /*****************************************************************/ + /*****************************************************************/ if (dorevoke) { if (infile == NULL) { BIO_printf(bio_err, "no input files\n"); - goto err; + goto end; } else { X509 *revcert; - revcert = load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile); + revcert = load_cert(infile, FORMAT_PEM, infile); if (revcert == NULL) - goto err; + goto end; if (dorevoke == 2) - rev_type = -1; + rev_type = REV_VALID; j = do_revoke(revcert, db, rev_type, rev_arg); if (j <= 0) - goto err; + goto end; X509_free(revcert); if (!save_index(dbfile, "new", db)) - goto err; + goto end; if (!rotate_index(dbfile, "new", "old")) - goto err; + goto end; BIO_printf(bio_err, "Data Base Updated\n"); } } - /*****************************************************************/ + /*****************************************************************/ ret = 0; - err: - if (tofree) - OPENSSL_free(tofree); - BIO_free_all(Cout); + end: BIO_free_all(Sout); BIO_free_all(out); BIO_free_all(in); - - if (cert_sk) - sk_X509_pop_free(cert_sk, X509_free); + sk_X509_pop_free(cert_sk, X509_free); if (ret) ERR_print_errors(bio_err); - app_RAND_write_file(randfile, bio_err); - if (free_key && key) + app_RAND_write_file(randfile); + if (free_key) OPENSSL_free(key); BN_free(serial); BN_free(crlnumber); free_index(db); - if (sigopts) - sk_OPENSSL_STRING_free(sigopts); + sk_OPENSSL_STRING_free(sigopts); EVP_PKEY_free(pkey); - if (x509) - X509_free(x509); + X509_free(x509); X509_CRL_free(crl); NCONF_free(conf); NCONF_free(extconf); - OBJ_cleanup(); - apps_shutdown(); - OPENSSL_EXIT(ret); + release_engine(e); + return (ret); } -static void lookup_fail(const char *name, const char *tag) +static char *lookup_conf(const CONF *conf, const char *section, const char *tag) { - BIO_printf(bio_err, "variable lookup failed for %s::%s\n", name, tag); + char *entry = NCONF_get_string(conf, section, tag); + if (entry == NULL) + BIO_printf(bio_err, "variable lookup failed for %s::%s\n", section, tag); + return entry; } -static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, +static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, char *enddate, - long days, int batch, char *ext_sect, CONF *lconf, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, + long days, int batch, const char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy, int selfsign) { @@ -1515,16 +1261,15 @@ static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, EVP_PKEY *pktmp = NULL; int ok = -1, i; - in = BIO_new(BIO_s_file()); - - if (BIO_read_filename(in, infile) <= 0) { - perror(infile); - goto err; + in = BIO_new_file(infile, "r"); + if (in == NULL) { + ERR_print_errors(bio_err); + goto end; } if ((req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL)) == NULL) { BIO_printf(bio_err, "Error reading certificate request in %s\n", infile); - goto err; + goto end; } if (verbose) X509_REQ_print(bio_err, req); @@ -1535,26 +1280,26 @@ static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, BIO_printf(bio_err, "Certificate request and CA private key do not match\n"); ok = 0; - goto err; + goto end; } - if ((pktmp = X509_REQ_get_pubkey(req)) == NULL) { + if ((pktmp = X509_REQ_get0_pubkey(req)) == NULL) { BIO_printf(bio_err, "error unpacking public key\n"); - goto err; + goto end; } i = X509_REQ_verify(req, pktmp); - EVP_PKEY_free(pktmp); + pktmp = NULL; if (i < 0) { ok = 0; BIO_printf(bio_err, "Signature verification problems....\n"); ERR_print_errors(bio_err); - goto err; + goto end; } if (i == 0) { ok = 0; BIO_printf(bio_err, "Signature did not match the certificate request\n"); ERR_print_errors(bio_err); - goto err; + goto end; } else BIO_printf(bio_err, "Signature ok\n"); @@ -1563,89 +1308,80 @@ static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, verbose, req, ext_sect, lconf, certopt, nameopt, default_op, ext_copy, selfsign); - err: - if (req != NULL) - X509_REQ_free(req); - if (in != NULL) - BIO_free(in); + end: + X509_REQ_free(req); + BIO_free(in); return (ok); } -static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, +static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, - char *enddate, long days, int batch, char *ext_sect, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, long days, int batch, const char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, - unsigned long nameopt, int default_op, int ext_copy, - ENGINE *e) + unsigned long nameopt, int default_op, int ext_copy) { X509 *req = NULL; X509_REQ *rreq = NULL; EVP_PKEY *pktmp = NULL; int ok = -1, i; - if ((req = - load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL) - goto err; + if ((req = load_cert(infile, FORMAT_PEM, infile)) == NULL) + goto end; if (verbose) X509_print(bio_err, req); BIO_printf(bio_err, "Check that the request matches the signature\n"); - if ((pktmp = X509_get_pubkey(req)) == NULL) { + if ((pktmp = X509_get0_pubkey(req)) == NULL) { BIO_printf(bio_err, "error unpacking public key\n"); - goto err; + goto end; } i = X509_verify(req, pktmp); - EVP_PKEY_free(pktmp); if (i < 0) { ok = 0; BIO_printf(bio_err, "Signature verification problems....\n"); - goto err; + goto end; } if (i == 0) { ok = 0; BIO_printf(bio_err, "Signature did not match the certificate\n"); - goto err; + goto end; } else BIO_printf(bio_err, "Signature ok\n"); - if ((rreq = X509_to_X509_REQ(req, NULL, EVP_md5())) == NULL) - goto err; + if ((rreq = X509_to_X509_REQ(req, NULL, NULL)) == NULL) + goto end; ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, verbose, rreq, ext_sect, lconf, certopt, nameopt, default_op, ext_copy, 0); - err: - if (rreq != NULL) - X509_REQ_free(rreq); - if (req != NULL) - X509_free(req); + end: + X509_REQ_free(rreq); + X509_free(req); return (ok); } static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, - char *subj, unsigned long chtype, int multirdn, - int email_dn, char *startdate, char *enddate, long days, - int batch, int verbose, X509_REQ *req, char *ext_sect, + const char *subj, unsigned long chtype, int multirdn, + int email_dn, const char *startdate, const char *enddate, long days, + int batch, int verbose, X509_REQ *req, const char *ext_sect, CONF *lconf, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy, int selfsign) { X509_NAME *name = NULL, *CAname = NULL, *subject = NULL, *dn_subject = NULL; - ASN1_UTCTIME *tm, *tmptm; + const ASN1_TIME *tm; ASN1_STRING *str, *str2; ASN1_OBJECT *obj; X509 *ret = NULL; - X509_CINF *ci; - X509_NAME_ENTRY *ne; - X509_NAME_ENTRY *tne, *push; + X509_NAME_ENTRY *ne, *tne; EVP_PKEY *pktmp; int ok = -1, i, j, last, nid; const char *p; @@ -1655,12 +1391,6 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, OPENSSL_STRING *rrow = NULL; char buf[25]; - tmptm = ASN1_UTCTIME_new(); - if (tmptm == NULL) { - BIO_printf(bio_err, "malloc error\n"); - return (0); - } - for (i = 0; i < DB_NUMBER; i++) row[i] = NULL; @@ -1669,10 +1399,9 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, if (!n) { ERR_print_errors(bio_err); - goto err; + goto end; } X509_REQ_set_subject_name(req, n); - req->req_info->enc.modified = 1; X509_NAME_free(n); } @@ -1685,64 +1414,60 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, ne = X509_NAME_get_entry(name, i); str = X509_NAME_ENTRY_get_data(ne); obj = X509_NAME_ENTRY_get_object(ne); + nid = OBJ_obj2nid(obj); if (msie_hack) { /* assume all type should be strings */ - nid = OBJ_obj2nid(ne->object); if (str->type == V_ASN1_UNIVERSALSTRING) ASN1_UNIVERSALSTRING_to_string(str); - if ((str->type == V_ASN1_IA5STRING) && - (nid != NID_pkcs9_emailAddress)) + if (str->type == V_ASN1_IA5STRING && nid != NID_pkcs9_emailAddress) str->type = V_ASN1_T61STRING; - if ((nid == NID_pkcs9_emailAddress) && - (str->type == V_ASN1_PRINTABLESTRING)) + if (nid == NID_pkcs9_emailAddress + && str->type == V_ASN1_PRINTABLESTRING) str->type = V_ASN1_IA5STRING; } /* If no EMAIL is wanted in the subject */ - if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn)) + if (nid == NID_pkcs9_emailAddress && !email_dn) continue; /* check some things */ - if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && - (str->type != V_ASN1_IA5STRING)) { + if (nid == NID_pkcs9_emailAddress && str->type != V_ASN1_IA5STRING) { BIO_printf(bio_err, "\nemailAddress type needs to be of type IA5STRING\n"); - goto err; + goto end; } - if ((str->type != V_ASN1_BMPSTRING) - && (str->type != V_ASN1_UTF8STRING)) { + if (str->type != V_ASN1_BMPSTRING && str->type != V_ASN1_UTF8STRING) { j = ASN1_PRINTABLE_type(str->data, str->length); - if (((j == V_ASN1_T61STRING) && - (str->type != V_ASN1_T61STRING)) || - ((j == V_ASN1_IA5STRING) && - (str->type == V_ASN1_PRINTABLESTRING))) { + if ((j == V_ASN1_T61STRING && str->type != V_ASN1_T61STRING) || + (j == V_ASN1_IA5STRING && str->type == V_ASN1_PRINTABLESTRING)) + { BIO_printf(bio_err, "\nThe string contains characters that are illegal for the ASN.1 type\n"); - goto err; + goto end; } } if (default_op) - old_entry_print(bio_err, obj, str); + old_entry_print(obj, str); } /* Ok, now we check the 'policy' stuff. */ if ((subject = X509_NAME_new()) == NULL) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } /* take a copy of the issuer name before we mess with it. */ if (selfsign) CAname = X509_NAME_dup(name); else - CAname = X509_NAME_dup(x509->cert_info->subject); + CAname = X509_NAME_dup(X509_get_subject_name(x509)); if (CAname == NULL) - goto err; + goto end; str = str2 = NULL; for (i = 0; i < sk_CONF_VALUE_num(policy); i++) { @@ -1751,12 +1476,14 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, BIO_printf(bio_err, "%s:unknown object type in 'policy' configuration\n", cv->name); - goto err; + goto end; } obj = OBJ_nid2obj(j); last = -1; for (;;) { + X509_NAME_ENTRY *push = NULL; + /* lookup the object in the supplied name list */ j = X509_NAME_get_index_by_OBJ(name, obj, last); if (j < 0) { @@ -1769,7 +1496,6 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, last = j; /* depending on the 'policy', decide what to do. */ - push = NULL; if (strcmp(cv->value, "optional") == 0) { if (tne != NULL) push = tne; @@ -1778,7 +1504,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, BIO_printf(bio_err, "The %s field needed to be supplied and was missing\n", cv->name); - goto err; + goto end; } else push = tne; } else if (strcmp(cv->value, "match") == 0) { @@ -1788,7 +1514,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, BIO_printf(bio_err, "The mandatory %s field was missing\n", cv->name); - goto err; + goto end; } last2 = -1; @@ -1797,9 +1523,10 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, j = X509_NAME_get_index_by_OBJ(CAname, obj, last2); if ((j < 0) && (last2 == -1)) { BIO_printf(bio_err, - "The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n", + "The %s field does not exist in the CA certificate,\n" + "the 'policy' is misconfigured\n", cv->name); - goto err; + goto end; } if (j >= 0) { push = X509_NAME_get_entry(CAname, j); @@ -1811,25 +1538,25 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, } if (j < 0) { BIO_printf(bio_err, - "The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n", + "The %s field is different between\n" + "CA certificate (%s) and the request (%s)\n", cv->name, ((str2 == NULL) ? "NULL" : (char *)str2->data), ((str == NULL) ? "NULL" : (char *)str->data)); - goto err; + goto end; } } else { BIO_printf(bio_err, "%s:invalid type in 'policy' configuration\n", cv->value); - goto err; + goto end; } if (push != NULL) { if (!X509_NAME_add_entry(subject, push, -1, 0)) { - if (push != NULL) - X509_NAME_ENTRY_free(push); + X509_NAME_ENTRY_free(push); BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } } if (j < 0) @@ -1842,17 +1569,16 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */ subject = X509_NAME_dup(name); if (subject == NULL) - goto err; + goto end; } if (verbose) BIO_printf(bio_err, "The subject name appears to be ok, checking data base for clashes\n"); - /* Build the correct Subject if no e-mail is wanted in the subject */ - /* - * and add it later on because of the method extensions are added - * (altName) + /* + * Build the correct Subject if no e-mail is wanted in the subject. + * And add it later on because of the method extensions are added (altName) */ if (email_dn) @@ -1863,9 +1589,9 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, * Its best to dup the subject DN and then delete any email addresses * because this retains its structure. */ - if (!(dn_subject = X509_NAME_dup(subject))) { + if ((dn_subject = X509_NAME_dup(subject)) == NULL) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } while ((i = X509_NAME_get_index_by_NID(dn_subject, NID_pkcs9_emailAddress, @@ -1877,12 +1603,12 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, } if (BN_is_zero(serial)) - row[DB_serial] = BUF_strdup("00"); + row[DB_serial] = OPENSSL_strdup("00"); else row[DB_serial] = BN_bn2hex(serial); if (row[DB_serial] == NULL) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } if (db->attributes.unique_subject) { @@ -1908,16 +1634,16 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, if (rrow != NULL) { BIO_printf(bio_err, "The matching entry has the following details\n"); - if (rrow[DB_type][0] == 'E') + if (rrow[DB_type][0] == DB_TYPE_EXP) p = "Expired"; - else if (rrow[DB_type][0] == 'R') + else if (rrow[DB_type][0] == DB_TYPE_REV) p = "Revoked"; - else if (rrow[DB_type][0] == 'V') + else if (rrow[DB_type][0] == DB_TYPE_VAL) p = "Valid"; else p = "\ninvalid type, Data base error\n"; BIO_printf(bio_err, "Type :%s\n", p);; - if (rrow[DB_type][0] == 'R') { + if (rrow[DB_type][0] == DB_TYPE_REV) { p = rrow[DB_exp_date]; if (p == NULL) p = "undef"; @@ -1940,7 +1666,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, p = "undef"; BIO_printf(bio_err, "Subject Name :%s\n", p); ok = -1; /* This is now a 'bad' error. */ - goto err; + goto end; } /* We are now totally happy, lets make and sign the certificate */ @@ -1949,63 +1675,45 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, "Everything appears to be ok, creating and signing the certificate\n"); if ((ret = X509_new()) == NULL) - goto err; - ci = ret->cert_info; + goto end; #ifdef X509_V3 /* Make it an X509 v3 certificate. */ if (!X509_set_version(ret, 2)) - goto err; + goto end; #endif - if (BN_to_ASN1_INTEGER(serial, ci->serialNumber) == NULL) - goto err; + if (BN_to_ASN1_INTEGER(serial, X509_get_serialNumber(ret)) == NULL) + goto end; if (selfsign) { if (!X509_set_issuer_name(ret, subject)) - goto err; + goto end; } else { if (!X509_set_issuer_name(ret, X509_get_subject_name(x509))) - goto err; + goto end; } - if (strcmp(startdate, "today") == 0) - X509_gmtime_adj(X509_get_notBefore(ret), 0); - else - ASN1_TIME_set_string(X509_get_notBefore(ret), startdate); + if (!set_cert_times(ret, startdate, enddate, days)) + goto end; - if (enddate == NULL) - X509_time_adj_ex(X509_get_notAfter(ret), days, 0, NULL); - else { + if (enddate != NULL) { int tdays; - ASN1_TIME_set_string(X509_get_notAfter(ret), enddate); - ASN1_TIME_diff(&tdays, NULL, NULL, X509_get_notAfter(ret)); + ASN1_TIME_diff(&tdays, NULL, NULL, X509_get0_notAfter(ret)); days = tdays; } if (!X509_set_subject_name(ret, subject)) - goto err; + goto end; - pktmp = X509_REQ_get_pubkey(req); + pktmp = X509_REQ_get0_pubkey(req); i = X509_set_pubkey(ret, pktmp); - EVP_PKEY_free(pktmp); if (!i) - goto err; + goto end; /* Lets add the extensions, if there are any */ if (ext_sect) { X509V3_CTX ctx; - if (ci->version == NULL) - if ((ci->version = ASN1_INTEGER_new()) == NULL) - goto err; - ASN1_INTEGER_set(ci->version, 2); /* version 3 certificate */ - - /* - * Free the current entries if any, there should not be any I believe - */ - if (ci->extensions != NULL) - sk_X509_EXTENSION_pop_free(ci->extensions, X509_EXTENSION_free); - - ci->extensions = NULL; + X509_set_version(ret, 2); /* Initialize the context structure */ if (selfsign) @@ -2029,7 +1737,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, "ERROR: adding extensions in section %s\n", ext_sect); ERR_print_errors(bio_err); - goto err; + goto end; } if (verbose) BIO_printf(bio_err, @@ -2043,7 +1751,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, "ERROR: adding extensions in section %s\n", ext_sect); ERR_print_errors(bio_err); - goto err; + goto end; } if (verbose) @@ -2057,13 +1765,13 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, if (!copy_extensions(ret, req, ext_copy)) { BIO_printf(bio_err, "ERROR: adding extensions from request\n"); ERR_print_errors(bio_err); - goto err; + goto end; } /* Set the right value for the noemailDN option */ if (email_dn == 0) { if (!X509_set_subject_name(ret, dn_subject)) - goto err; + goto end; } if (!default_op) { @@ -2076,7 +1784,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, } BIO_printf(bio_err, "Certificate is to be certified until "); - ASN1_TIME_print(bio_err, X509_get_notAfter(ret)); + ASN1_TIME_print(bio_err, X509_get0_notAfter(ret)); if (days) BIO_printf(bio_err, " (%ld days)", days); BIO_printf(bio_err, "\n"); @@ -2086,87 +1794,69 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, BIO_printf(bio_err, "Sign the certificate? [y/n]:"); (void)BIO_flush(bio_err); buf[0] = '\0'; - if (!fgets(buf, sizeof(buf) - 1, stdin)) { + if (fgets(buf, sizeof(buf), stdin) == NULL) { BIO_printf(bio_err, "CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n"); ok = 0; - goto err; + goto end; } - if (!((buf[0] == 'y') || (buf[0] == 'Y'))) { + if (!(buf[0] == 'y' || buf[0] == 'Y')) { BIO_printf(bio_err, "CERTIFICATE WILL NOT BE CERTIFIED\n"); ok = 0; - goto err; + goto end; } } - pktmp = X509_get_pubkey(ret); + pktmp = X509_get0_pubkey(ret); if (EVP_PKEY_missing_parameters(pktmp) && !EVP_PKEY_missing_parameters(pkey)) EVP_PKEY_copy_parameters(pktmp, pkey); - EVP_PKEY_free(pktmp); - if (!do_X509_sign(bio_err, ret, pkey, dgst, sigopts)) - goto err; + if (!do_X509_sign(ret, pkey, dgst, sigopts)) + goto end; - /* We now just add it to the database */ - row[DB_type] = (char *)OPENSSL_malloc(2); - - tm = X509_get_notAfter(ret); - row[DB_exp_date] = (char *)OPENSSL_malloc(tm->length + 1); + /* We now just add it to the database as DB_TYPE_VAL('V') */ + row[DB_type] = OPENSSL_strdup("V"); + tm = X509_get0_notAfter(ret); + row[DB_exp_date] = app_malloc(tm->length + 1, "row expdate"); memcpy(row[DB_exp_date], tm->data, tm->length); row[DB_exp_date][tm->length] = '\0'; - row[DB_rev_date] = NULL; - - /* row[DB_serial] done already */ - row[DB_file] = (char *)OPENSSL_malloc(8); + row[DB_file] = OPENSSL_strdup("unknown"); row[DB_name] = X509_NAME_oneline(X509_get_subject_name(ret), NULL, 0); if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || (row[DB_file] == NULL) || (row[DB_name] == NULL)) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; - } - BUF_strlcpy(row[DB_file], "unknown", 8); - row[DB_type][0] = 'V'; - row[DB_type][1] = '\0'; - - if ((irow = - (char **)OPENSSL_malloc(sizeof(char *) * (DB_NUMBER + 1))) == NULL) { - BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } - for (i = 0; i < DB_NUMBER; i++) { + irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row space"); + for (i = 0; i < DB_NUMBER; i++) irow[i] = row[i]; - row[i] = NULL; - } irow[DB_NUMBER] = NULL; if (!TXT_DB_insert(db->db, irow)) { BIO_printf(bio_err, "failed to update database\n"); BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error); - goto err; + goto end; } + irow = NULL; ok = 1; - err: - for (i = 0; i < DB_NUMBER; i++) - if (row[i] != NULL) + end: + if (irow != NULL) { + for (i = 0; i < DB_NUMBER; i++) OPENSSL_free(row[i]); + OPENSSL_free(irow); + } - if (CAname != NULL) - X509_NAME_free(CAname); - if (subject != NULL) - X509_NAME_free(subject); - if ((dn_subject != NULL) && !email_dn) + X509_NAME_free(CAname); + X509_NAME_free(subject); + if (dn_subject != subject) X509_NAME_free(dn_subject); - if (tmptm != NULL) - ASN1_UTCTIME_free(tmptm); - if (ok <= 0) { - if (ret != NULL) - X509_free(ret); - ret = NULL; - } else + if (ok <= 0) + X509_free(ret); + else *xret = ret; return (ok); } @@ -2184,13 +1874,13 @@ static void write_new_certificate(BIO *bp, X509 *x, int output_der, PEM_write_bio_X509(bp, x); } -static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, +static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, - char *enddate, long days, char *ext_sect, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, long days, const char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy) { @@ -2199,7 +1889,6 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509_REQ *req = NULL; CONF_VALUE *cv = NULL; NETSCAPE_SPKI *spki = NULL; - X509_REQ_INFO *ri; char *type, *buf; EVP_PKEY *pktmp = NULL; X509_NAME *n = NULL; @@ -2217,14 +1906,13 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, if (parms == NULL) { BIO_printf(bio_err, "error on line %ld of %s\n", errline, infile); ERR_print_errors(bio_err); - goto err; + goto end; } sk = CONF_get_section(parms, "default"); if (sk_CONF_VALUE_num(sk) == 0) { BIO_printf(bio_err, "no name/value pairs found in %s\n", infile); - CONF_free(parms); - goto err; + goto end; } /* @@ -2237,14 +1925,13 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, req = X509_REQ_new(); if (req == NULL) { ERR_print_errors(bio_err); - goto err; + goto end; } /* * Build up the subject name set. */ - ri = req->req_info; - n = ri->subject; + n = X509_REQ_get_subject_name(req); for (i = 0;; i++) { if (sk_CONF_VALUE_num(sk) <= i) @@ -2271,7 +1958,7 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, BIO_printf(bio_err, "unable to load Netscape SPKAC structure\n"); ERR_print_errors(bio_err); - goto err; + goto end; } } continue; @@ -2279,12 +1966,12 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char *)buf, -1, -1, 0)) - goto err; + goto end; } if (spki == NULL) { BIO_printf(bio_err, "Netscape SPKAC structure not found in %s\n", infile); - goto err; + goto end; } /* @@ -2296,14 +1983,15 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, if ((pktmp = NETSCAPE_SPKI_get_pubkey(spki)) == NULL) { BIO_printf(bio_err, "error unpacking SPKAC public key\n"); - goto err; + goto end; } j = NETSCAPE_SPKI_verify(spki, pktmp); if (j <= 0) { + EVP_PKEY_free(pktmp); BIO_printf(bio_err, "signature verification failed on SPKAC public key\n"); - goto err; + goto end; } BIO_printf(bio_err, "Signature ok\n"); @@ -2313,15 +2001,11 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, chtype, multirdn, email_dn, startdate, enddate, days, 1, verbose, req, ext_sect, lconf, certopt, nameopt, default_op, ext_copy, 0); - err: - if (req != NULL) - X509_REQ_free(req); - if (parms != NULL) - CONF_free(parms); - if (spki != NULL) - NETSCAPE_SPKI_free(spki); - if (ne != NULL) - X509_NAME_ENTRY_free(ne); + end: + X509_REQ_free(req); + CONF_free(parms); + NETSCAPE_SPKI_free(spki); + X509_NAME_ENTRY_free(ne); return (ok); } @@ -2331,9 +2015,10 @@ static int check_time_format(const char *str) return ASN1_TIME_set_string(NULL, str); } -static int do_revoke(X509 *x509, CA_DB *db, int type, char *value) +static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type, + const char *value) { - ASN1_UTCTIME *tm = NULL; + const ASN1_TIME *tm = NULL; char *row[DB_NUMBER], **rrow, **irow; char *rev_str = NULL; BIGNUM *bn = NULL; @@ -2344,15 +2029,15 @@ static int do_revoke(X509 *x509, CA_DB *db, int type, char *value) row[DB_name] = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0); bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509), NULL); if (!bn) - goto err; + goto end; if (BN_is_zero(bn)) - row[DB_serial] = BUF_strdup("00"); + row[DB_serial] = OPENSSL_strdup("00"); else row[DB_serial] = BN_bn2hex(bn); BN_free(bn); if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } /* * We have to lookup by serial number because name lookup skips revoked @@ -2364,85 +2049,70 @@ static int do_revoke(X509 *x509, CA_DB *db, int type, char *value) "Adding Entry with serial number %s to DB for %s\n", row[DB_serial], row[DB_name]); - /* We now just add it to the database */ - row[DB_type] = (char *)OPENSSL_malloc(2); - - tm = X509_get_notAfter(x509); - row[DB_exp_date] = (char *)OPENSSL_malloc(tm->length + 1); + /* We now just add it to the database as DB_TYPE_REV('V') */ + row[DB_type] = OPENSSL_strdup("V"); + tm = X509_get0_notAfter(x509); + row[DB_exp_date] = app_malloc(tm->length + 1, "row exp_data"); memcpy(row[DB_exp_date], tm->data, tm->length); row[DB_exp_date][tm->length] = '\0'; - row[DB_rev_date] = NULL; + row[DB_file] = OPENSSL_strdup("unknown"); - /* row[DB_serial] done already */ - row[DB_file] = (char *)OPENSSL_malloc(8); - - /* row[DB_name] done already */ - - if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || - (row[DB_file] == NULL)) { + if (row[DB_type] == NULL || row[DB_file] == NULL) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } - BUF_strlcpy(row[DB_file], "unknown", 8); - row[DB_type][0] = 'V'; - row[DB_type][1] = '\0'; - if ((irow = - (char **)OPENSSL_malloc(sizeof(char *) * (DB_NUMBER + 1))) == - NULL) { - BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; - } - - for (i = 0; i < DB_NUMBER; i++) { + irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row ptr"); + for (i = 0; i < DB_NUMBER; i++) irow[i] = row[i]; - row[i] = NULL; - } irow[DB_NUMBER] = NULL; if (!TXT_DB_insert(db->db, irow)) { BIO_printf(bio_err, "failed to update database\n"); BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error); - goto err; + OPENSSL_free(irow); + goto end; } + for (i = 0; i < DB_NUMBER; i++) + row[i] = NULL; + /* Revoke Certificate */ - if (type == -1) + if (rev_type == REV_VALID) ok = 1; else - ok = do_revoke(x509, db, type, value); + /* Retry revocation after DB insertion */ + ok = do_revoke(x509, db, rev_type, value); - goto err; + goto end; } else if (index_name_cmp_noconst(row, rrow)) { BIO_printf(bio_err, "ERROR:name does not match %s\n", row[DB_name]); - goto err; - } else if (type == -1) { + goto end; + } else if (rev_type == REV_VALID) { BIO_printf(bio_err, "ERROR:Already present, serial number %s\n", row[DB_serial]); - goto err; - } else if (rrow[DB_type][0] == 'R') { + goto end; + } else if (rrow[DB_type][0] == DB_TYPE_REV) { BIO_printf(bio_err, "ERROR:Already revoked, serial number %s\n", row[DB_serial]); - goto err; + goto end; } else { BIO_printf(bio_err, "Revoking Certificate %s.\n", rrow[DB_serial]); - rev_str = make_revocation_str(type, value); + rev_str = make_revocation_str(rev_type, value); if (!rev_str) { BIO_printf(bio_err, "Error in revocation arguments\n"); - goto err; + goto end; } - rrow[DB_type][0] = 'R'; + rrow[DB_type][0] = DB_TYPE_REV; rrow[DB_type][1] = '\0'; rrow[DB_rev_date] = rev_str; } ok = 1; - err: - for (i = 0; i < DB_NUMBER; i++) { - if (row[i] != NULL) - OPENSSL_free(row[i]); - } + end: + for (i = 0; i < DB_NUMBER; i++) + OPENSSL_free(row[i]); return (ok); } @@ -2450,36 +2120,32 @@ static int get_certificate_status(const char *serial, CA_DB *db) { char *row[DB_NUMBER], **rrow; int ok = -1, i; + size_t serial_len = strlen(serial); /* Free Resources */ for (i = 0; i < DB_NUMBER; i++) row[i] = NULL; /* Malloc needed char spaces */ - row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2); - if (row[DB_serial] == NULL) { - BIO_printf(bio_err, "Malloc failure\n"); - goto err; - } + row[DB_serial] = app_malloc(serial_len + 2, "row serial#"); - if (strlen(serial) % 2) { + if (serial_len % 2) { /* * Set the first char to 0 */ ; row[DB_serial][0] = '0'; /* Copy String from serial to row[DB_serial] */ - memcpy(row[DB_serial] + 1, serial, strlen(serial)); - row[DB_serial][strlen(serial) + 1] = '\0'; + memcpy(row[DB_serial] + 1, serial, serial_len); + row[DB_serial][serial_len + 1] = '\0'; } else { /* Copy String from serial to row[DB_serial] */ - memcpy(row[DB_serial], serial, strlen(serial)); - row[DB_serial][strlen(serial)] = '\0'; + memcpy(row[DB_serial], serial, serial_len); + row[DB_serial][serial_len] = '\0'; } /* Make it Upper Case */ - for (i = 0; row[DB_serial][i] != '\0'; i++) - row[DB_serial][i] = toupper((unsigned char)row[DB_serial][i]); + make_uppercase(row[DB_serial]); ok = 1; @@ -2488,32 +2154,31 @@ static int get_certificate_status(const char *serial, CA_DB *db) if (rrow == NULL) { BIO_printf(bio_err, "Serial %s not present in db.\n", row[DB_serial]); ok = -1; - goto err; - } else if (rrow[DB_type][0] == 'V') { + goto end; + } else if (rrow[DB_type][0] == DB_TYPE_VAL) { BIO_printf(bio_err, "%s=Valid (%c)\n", row[DB_serial], rrow[DB_type][0]); - goto err; - } else if (rrow[DB_type][0] == 'R') { + goto end; + } else if (rrow[DB_type][0] == DB_TYPE_REV) { BIO_printf(bio_err, "%s=Revoked (%c)\n", row[DB_serial], rrow[DB_type][0]); - goto err; - } else if (rrow[DB_type][0] == 'E') { + goto end; + } else if (rrow[DB_type][0] == DB_TYPE_EXP) { BIO_printf(bio_err, "%s=Expired (%c)\n", row[DB_serial], rrow[DB_type][0]); - goto err; - } else if (rrow[DB_type][0] == 'S') { + goto end; + } else if (rrow[DB_type][0] == DB_TYPE_SUSP) { BIO_printf(bio_err, "%s=Suspended (%c)\n", row[DB_serial], rrow[DB_type][0]); - goto err; + goto end; } else { BIO_printf(bio_err, "%s=Unknown (%c).\n", row[DB_serial], rrow[DB_type][0]); ok = -1; } - err: + end: for (i = 0; i < DB_NUMBER; i++) { - if (row[i] != NULL) - OPENSSL_free(row[i]); + OPENSSL_free(row[i]); } return (ok); } @@ -2526,14 +2191,12 @@ static int do_updatedb(CA_DB *db) char **rrow, *a_tm_s; a_tm = ASN1_UTCTIME_new(); + if (a_tm == NULL) + return -1; /* get actual time and make a string */ a_tm = X509_gmtime_adj(a_tm, 0); - a_tm_s = (char *)OPENSSL_malloc(a_tm->length + 1); - if (a_tm_s == NULL) { - cnt = -1; - goto err; - } + a_tm_s = app_malloc(a_tm->length + 1, "time string"); memcpy(a_tm_s, a_tm->data, a_tm->length); a_tm_s[a_tm->length] = '\0'; @@ -2546,7 +2209,7 @@ static int do_updatedb(CA_DB *db) for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { rrow = sk_OPENSSL_PSTRING_value(db->db->data, i); - if (rrow[DB_type][0] == 'V') { + if (rrow[DB_type][0] == DB_TYPE_VAL) { /* ignore entries that are not valid */ if (strncmp(rrow[DB_exp_date], "49", 2) <= 0) db_y2k = 1; @@ -2556,14 +2219,14 @@ static int do_updatedb(CA_DB *db) if (db_y2k == a_y2k) { /* all on the same y2k side */ if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0) { - rrow[DB_type][0] = 'E'; + rrow[DB_type][0] = DB_TYPE_EXP; rrow[DB_type][1] = '\0'; cnt++; BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]); } } else if (db_y2k < a_y2k) { - rrow[DB_type][0] = 'E'; + rrow[DB_type][0] = DB_TYPE_EXP; rrow[DB_type][1] = '\0'; cnt++; @@ -2573,11 +2236,8 @@ static int do_updatedb(CA_DB *db) } } - err: - ASN1_UTCTIME_free(a_tm); OPENSSL_free(a_tm_s); - return (cnt); } @@ -2597,7 +2257,7 @@ static const char *crl_reasons[] = { "CAkeyTime" }; -#define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *)) +#define NUM_REASONS OSSL_NELEM(crl_reasons) /* * Given revocation information convert to a DB string. The format of the @@ -2606,20 +2266,22 @@ static const char *crl_reasons[] = { * additional argument */ -char *make_revocation_str(int rev_type, char *rev_arg) +static char *make_revocation_str(REVINFO_TYPE rev_type, const char *rev_arg) { - char *other = NULL, *str; - const char *reason = NULL; + char *str; + const char *reason = NULL, *other = NULL; ASN1_OBJECT *otmp; ASN1_UTCTIME *revtm = NULL; int i; + switch (rev_type) { case REV_NONE: + case REV_VALID: break; case REV_CRL_REASON: for (i = 0; i < 8; i++) { - if (!strcasecmp(rev_arg, crl_reasons[i])) { + if (strcasecmp(rev_arg, crl_reasons[i]) == 0) { reason = crl_reasons[i]; break; } @@ -2632,7 +2294,6 @@ char *make_revocation_str(int rev_type, char *rev_arg) case REV_HOLD: /* Argument is an OID */ - otmp = OBJ_txt2obj(rev_arg, 0); ASN1_OBJECT_free(otmp); @@ -2647,7 +2308,6 @@ char *make_revocation_str(int rev_type, char *rev_arg) case REV_KEY_COMPROMISE: case REV_CA_COMPROMISE: - /* Argument is the key compromise time */ if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg)) { BIO_printf(bio_err, @@ -2662,7 +2322,6 @@ char *make_revocation_str(int rev_type, char *rev_arg) reason = "CAkeyTime"; break; - } revtm = X509_gmtime_adj(NULL, 0); @@ -2677,19 +2336,15 @@ char *make_revocation_str(int rev_type, char *rev_arg) if (other) i += strlen(other) + 1; - str = OPENSSL_malloc(i); - - if (!str) - return NULL; - - BUF_strlcpy(str, (char *)revtm->data, i); + str = app_malloc(i, "revocation reason"); + OPENSSL_strlcpy(str, (char *)revtm->data, i); if (reason) { - BUF_strlcat(str, ",", i); - BUF_strlcat(str, reason, i); + OPENSSL_strlcat(str, ",", i); + OPENSSL_strlcat(str, reason, i); } if (other) { - BUF_strlcat(str, ",", i); - BUF_strlcat(str, other, i); + OPENSSL_strlcat(str, ",", i); + OPENSSL_strlcat(str, other, i); } ASN1_UTCTIME_free(revtm); return str; @@ -2703,7 +2358,7 @@ char *make_revocation_str(int rev_type, char *rev_arg) * 2 OK and some extensions added (i.e. V2 CRL) */ -int make_revoked(X509_REVOKED *rev, const char *str) +static int make_revoked(X509_REVOKED *rev, const char *str) { char *tmp = NULL; int reason_code = -1; @@ -2717,28 +2372,28 @@ int make_revoked(X509_REVOKED *rev, const char *str) i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str); if (i == 0) - goto err; + goto end; if (rev && !X509_REVOKED_set_revocationDate(rev, revDate)) - goto err; + goto end; if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)) { rtmp = ASN1_ENUMERATED_new(); - if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code)) - goto err; + if (rtmp == NULL || !ASN1_ENUMERATED_set(rtmp, reason_code)) + goto end; if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0)) - goto err; + goto end; } if (rev && comp_time) { if (!X509_REVOKED_add1_ext_i2d (rev, NID_invalidity_date, comp_time, 0, 0)) - goto err; + goto end; } if (rev && hold) { if (!X509_REVOKED_add1_ext_i2d (rev, NID_hold_instruction_code, hold, 0, 0)) - goto err; + goto end; } if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS) @@ -2746,10 +2401,9 @@ int make_revoked(X509_REVOKED *rev, const char *str) else ret = 1; - err: + end: - if (tmp) - OPENSSL_free(tmp); + OPENSSL_free(tmp); ASN1_OBJECT_free(hold); ASN1_GENERALIZEDTIME_free(comp_time); ASN1_ENUMERATED_free(rtmp); @@ -2758,56 +2412,63 @@ int make_revoked(X509_REVOKED *rev, const char *str) return ret; } -int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str) +static int old_entry_print(const ASN1_OBJECT *obj, const ASN1_STRING *str) { - char buf[25], *pbuf, *p; + char buf[25], *pbuf; + const char *p; int j; - j = i2a_ASN1_OBJECT(bp, obj); + + j = i2a_ASN1_OBJECT(bio_err, obj); pbuf = buf; for (j = 22 - j; j > 0; j--) *(pbuf++) = ' '; *(pbuf++) = ':'; *(pbuf++) = '\0'; - BIO_puts(bp, buf); + BIO_puts(bio_err, buf); if (str->type == V_ASN1_PRINTABLESTRING) - BIO_printf(bp, "PRINTABLE:'"); + BIO_printf(bio_err, "PRINTABLE:'"); else if (str->type == V_ASN1_T61STRING) - BIO_printf(bp, "T61STRING:'"); + BIO_printf(bio_err, "T61STRING:'"); else if (str->type == V_ASN1_IA5STRING) - BIO_printf(bp, "IA5STRING:'"); + BIO_printf(bio_err, "IA5STRING:'"); else if (str->type == V_ASN1_UNIVERSALSTRING) - BIO_printf(bp, "UNIVERSALSTRING:'"); + BIO_printf(bio_err, "UNIVERSALSTRING:'"); else - BIO_printf(bp, "ASN.1 %2d:'", str->type); + BIO_printf(bio_err, "ASN.1 %2d:'", str->type); - p = (char *)str->data; + p = (const char *)str->data; for (j = str->length; j > 0; j--) { if ((*p >= ' ') && (*p <= '~')) - BIO_printf(bp, "%c", *p); + BIO_printf(bio_err, "%c", *p); else if (*p & 0x80) - BIO_printf(bp, "\\0x%02X", *p); + BIO_printf(bio_err, "\\0x%02X", *p); else if ((unsigned char)*p == 0xf7) - BIO_printf(bp, "^?"); + BIO_printf(bio_err, "^?"); else - BIO_printf(bp, "^%c", *p + '@'); + BIO_printf(bio_err, "^%c", *p + '@'); p++; } - BIO_printf(bp, "'\n"); + BIO_printf(bio_err, "'\n"); return 1; } int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, const char *str) { - char *tmp = NULL; + char *tmp; char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p; int reason_code = -1; int ret = 0; unsigned int i; ASN1_OBJECT *hold = NULL; ASN1_GENERALIZEDTIME *comp_time = NULL; - tmp = BUF_strdup(str); + + tmp = OPENSSL_strdup(str); + if (!tmp) { + BIO_printf(bio_err, "memory allocation failure\n"); + goto end; + } p = strchr(tmp, ','); @@ -2826,21 +2487,25 @@ int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, if (prevtm) { *prevtm = ASN1_UTCTIME_new(); + if (*prevtm == NULL) { + BIO_printf(bio_err, "memory allocation failure\n"); + goto end; + } if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str)) { BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str); - goto err; + goto end; } } if (reason_str) { for (i = 0; i < NUM_REASONS; i++) { - if (!strcasecmp(reason_str, crl_reasons[i])) { + if (strcasecmp(reason_str, crl_reasons[i]) == 0) { reason_code = i; break; } } if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS) { BIO_printf(bio_err, "invalid reason code %s\n", reason_str); - goto err; + goto end; } if (reason_code == 7) @@ -2848,7 +2513,7 @@ int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, else if (reason_code == 8) { /* Hold instruction */ if (!arg_str) { BIO_printf(bio_err, "missing hold instruction\n"); - goto err; + goto end; } reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD; hold = OBJ_txt2obj(arg_str, 0); @@ -2856,19 +2521,25 @@ int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, if (!hold) { BIO_printf(bio_err, "invalid object identifier %s\n", arg_str); - goto err; + goto end; } if (phold) *phold = hold; + else + ASN1_OBJECT_free(hold); } else if ((reason_code == 9) || (reason_code == 10)) { if (!arg_str) { BIO_printf(bio_err, "missing compromised time\n"); - goto err; + goto end; } comp_time = ASN1_GENERALIZEDTIME_new(); + if (comp_time == NULL) { + BIO_printf(bio_err, "memory allocation failure\n"); + goto end; + } if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str)) { BIO_printf(bio_err, "invalid compromised time %s\n", arg_str); - goto err; + goto end; } if (reason_code == 9) reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE; @@ -2879,21 +2550,17 @@ int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, if (preason) *preason = reason_code; - if (pinvtm) + if (pinvtm) { *pinvtm = comp_time; - else - ASN1_GENERALIZEDTIME_free(comp_time); + comp_time = NULL; + } ret = 1; - err: + end: - if (tmp) - OPENSSL_free(tmp); - if (!phold) - ASN1_OBJECT_free(hold); - if (!pinvtm) - ASN1_GENERALIZEDTIME_free(comp_time); + OPENSSL_free(tmp); + ASN1_GENERALIZEDTIME_free(comp_time); return ret; }