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