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