155714Skris/* apps/ca.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 8296465Sdelphij * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15296465Sdelphij * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 22296465Sdelphij * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 37296465Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40296465Sdelphij * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 52296465Sdelphij * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 5955714Skris/* The PPKI stuff has been donated by Jeff Barber <jeffb@issl.atl.hp.com> */ 6055714Skris 6155714Skris#include <stdio.h> 6255714Skris#include <stdlib.h> 6355714Skris#include <string.h> 64109998Smarkm#include <ctype.h> 6555714Skris#include <sys/types.h> 6655714Skris#include <sys/stat.h> 6755714Skris#include <openssl/conf.h> 6855714Skris#include <openssl/bio.h> 6955714Skris#include <openssl/err.h> 7055714Skris#include <openssl/bn.h> 7155714Skris#include <openssl/txt_db.h> 7255714Skris#include <openssl/evp.h> 7355714Skris#include <openssl/x509.h> 7455714Skris#include <openssl/x509v3.h> 7555714Skris#include <openssl/objects.h> 76109998Smarkm#include <openssl/ocsp.h> 7755714Skris#include <openssl/pem.h> 7855714Skris 7955714Skris#ifndef W_OK 80296465Sdelphij# ifdef OPENSSL_SYS_VMS 81296465Sdelphij# if defined(__DECC) 82296465Sdelphij# include <unistd.h> 83296465Sdelphij# else 84296465Sdelphij# include <unixlib.h> 8555714Skris# endif 86296465Sdelphij# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_NETWARE) && !defined(__TANDEM) 87296465Sdelphij# include <sys/file.h> 88296465Sdelphij# endif 8955714Skris#endif 9055714Skris 91109998Smarkm#include "apps.h" 92109998Smarkm 9355714Skris#ifndef W_OK 94296465Sdelphij# define F_OK 0 95296465Sdelphij# define X_OK 1 96296465Sdelphij# define W_OK 2 97296465Sdelphij# define R_OK 4 9855714Skris#endif 9955714Skris 10055714Skris#undef PROG 10155714Skris#define PROG ca_main 10255714Skris 103296465Sdelphij#define BASE_SECTION "ca" 10455714Skris#define CONFIG_FILE "openssl.cnf" 10555714Skris 106296465Sdelphij#define ENV_DEFAULT_CA "default_ca" 10755714Skris 108296465Sdelphij#define STRING_MASK "string_mask" 109296465Sdelphij#define UTF8_IN "utf8" 110160814Ssimon 111296465Sdelphij#define ENV_DIR "dir" 112296465Sdelphij#define ENV_CERTS "certs" 113296465Sdelphij#define ENV_CRL_DIR "crl_dir" 114296465Sdelphij#define ENV_CA_DB "CA_DB" 115296465Sdelphij#define ENV_NEW_CERTS_DIR "new_certs_dir" 116296465Sdelphij#define ENV_CERTIFICATE "certificate" 117296465Sdelphij#define ENV_SERIAL "serial" 118296465Sdelphij#define ENV_CRLNUMBER "crlnumber" 119296465Sdelphij#define ENV_CRL "crl" 120296465Sdelphij#define ENV_PRIVATE_KEY "private_key" 121296465Sdelphij#define ENV_RANDFILE "RANDFILE" 122296465Sdelphij#define ENV_DEFAULT_DAYS "default_days" 123296465Sdelphij#define ENV_DEFAULT_STARTDATE "default_startdate" 124296465Sdelphij#define ENV_DEFAULT_ENDDATE "default_enddate" 125296465Sdelphij#define ENV_DEFAULT_CRL_DAYS "default_crl_days" 126296465Sdelphij#define ENV_DEFAULT_CRL_HOURS "default_crl_hours" 127296465Sdelphij#define ENV_DEFAULT_MD "default_md" 128296465Sdelphij#define ENV_DEFAULT_EMAIL_DN "email_in_dn" 129296465Sdelphij#define ENV_PRESERVE "preserve" 130296465Sdelphij#define ENV_POLICY "policy" 131296465Sdelphij#define ENV_EXTENSIONS "x509_extensions" 132296465Sdelphij#define ENV_CRLEXT "crl_extensions" 133296465Sdelphij#define ENV_MSIE_HACK "msie_hack" 134296465Sdelphij#define ENV_NAMEOPT "name_opt" 135296465Sdelphij#define ENV_CERTOPT "cert_opt" 136296465Sdelphij#define ENV_EXTCOPY "copy_extensions" 137296465Sdelphij#define ENV_UNIQUE_SUBJECT "unique_subject" 13855714Skris 139296465Sdelphij#define ENV_DATABASE "database" 14055714Skris 141109998Smarkm/* Additional revocation information types */ 142109998Smarkm 143296465Sdelphij#define REV_NONE 0 /* No addditional information */ 144296465Sdelphij#define REV_CRL_REASON 1 /* Value is CRL reason code */ 145296465Sdelphij#define REV_HOLD 2 /* Value is hold instruction */ 146296465Sdelphij#define REV_KEY_COMPROMISE 3 /* Value is cert key compromise time */ 147296465Sdelphij#define REV_CA_COMPROMISE 4 /* Value is CA key compromise time */ 148109998Smarkm 149296465Sdelphijstatic const char *ca_usage[] = { 150296465Sdelphij "usage: ca args\n", 151296465Sdelphij "\n", 152296465Sdelphij " -verbose - Talk alot while doing things\n", 153296465Sdelphij " -config file - A config file\n", 154296465Sdelphij " -name arg - The particular CA definition to use\n", 155296465Sdelphij " -gencrl - Generate a new CRL\n", 156296465Sdelphij " -crldays days - Days is when the next CRL is due\n", 157296465Sdelphij " -crlhours hours - Hours is when the next CRL is due\n", 158296465Sdelphij " -startdate YYMMDDHHMMSSZ - certificate validity notBefore\n", 159296465Sdelphij " -enddate YYMMDDHHMMSSZ - certificate validity notAfter (overrides -days)\n", 160296465Sdelphij " -days arg - number of days to certify the certificate for\n", 161296465Sdelphij " -md arg - md to use, one of md2, md5, sha or sha1\n", 162296465Sdelphij " -policy arg - The CA 'policy' to support\n", 163296465Sdelphij " -keyfile arg - private key file\n", 164296465Sdelphij " -keyform arg - private key file format (PEM or ENGINE)\n", 165296465Sdelphij " -key arg - key to decode the private key if it is encrypted\n", 166296465Sdelphij " -cert file - The CA certificate\n", 167296465Sdelphij " -selfsign - sign a certificate with the key associated with it\n", 168296465Sdelphij " -in file - The input PEM encoded certificate request(s)\n", 169296465Sdelphij " -out file - Where to put the output file(s)\n", 170296465Sdelphij " -outdir dir - Where to put output certificates\n", 171296465Sdelphij " -infiles .... - The last argument, requests to process\n", 172296465Sdelphij " -spkac file - File contains DN and signed public key and challenge\n", 173296465Sdelphij " -ss_cert file - File contains a self signed cert to sign\n", 174296465Sdelphij " -preserveDN - Don't re-order the DN\n", 175296465Sdelphij " -noemailDN - Don't add the EMAIL field into certificate' subject\n", 176296465Sdelphij " -batch - Don't ask questions\n", 177296465Sdelphij " -msie_hack - msie modifications to handle all those universal strings\n", 178296465Sdelphij " -revoke file - Revoke a certificate (given in file)\n", 179296465Sdelphij " -subj arg - Use arg instead of request's subject\n", 180296465Sdelphij " -utf8 - input characters are UTF8 (default ASCII)\n", 181296465Sdelphij " -multivalue-rdn - enable support for multivalued RDNs\n", 182296465Sdelphij " -extensions .. - Extension section (override value in config file)\n", 183296465Sdelphij " -extfile file - Configuration file with X509v3 extentions to add\n", 184296465Sdelphij " -crlexts .. - CRL extension section (override value in config file)\n", 185111147Snectar#ifndef OPENSSL_NO_ENGINE 186296465Sdelphij " -engine e - use engine e, possibly a hardware device.\n", 187111147Snectar#endif 188296465Sdelphij " -status serial - Shows certificate status given the serial number\n", 189296465Sdelphij " -updatedb - Updates db for expired certificates\n", 190296465Sdelphij NULL 19155714Skris}; 19255714Skris 19355714Skris#ifdef EFENCE 19455714Skrisextern int EF_PROTECT_FREE; 19555714Skrisextern int EF_PROTECT_BELOW; 19655714Skrisextern int EF_ALIGNMENT; 19755714Skris#endif 19855714Skris 199160814Ssimonstatic void lookup_fail(const char *name, const char *tag); 200296465Sdelphijstatic int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 201296465Sdelphij const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, 202296465Sdelphij CA_DB *db, BIGNUM *serial, char *subj, 203296465Sdelphij unsigned long chtype, int multirdn, int email_dn, 204296465Sdelphij char *startdate, char *enddate, long days, int batch, 205296465Sdelphij char *ext_sect, CONF *conf, int verbose, 206296465Sdelphij unsigned long certopt, unsigned long nameopt, 207296465Sdelphij int default_op, int ext_copy, int selfsign); 208296465Sdelphijstatic int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 209296465Sdelphij const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, 210296465Sdelphij CA_DB *db, BIGNUM *serial, char *subj, 211296465Sdelphij unsigned long chtype, int multirdn, int email_dn, 212296465Sdelphij char *startdate, char *enddate, long days, int batch, 213296465Sdelphij char *ext_sect, CONF *conf, int verbose, 214296465Sdelphij unsigned long certopt, unsigned long nameopt, 215296465Sdelphij int default_op, int ext_copy, ENGINE *e); 216296465Sdelphijstatic int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, 217296465Sdelphij X509 *x509, const EVP_MD *dgst, 218296465Sdelphij STACK_OF(CONF_VALUE) *policy, CA_DB *db, 219296465Sdelphij BIGNUM *serial, char *subj, unsigned long chtype, 220296465Sdelphij int multirdn, int email_dn, char *startdate, 221296465Sdelphij char *enddate, long days, char *ext_sect, CONF *conf, 222296465Sdelphij int verbose, unsigned long certopt, 223296465Sdelphij unsigned long nameopt, int default_op, int ext_copy); 224296465Sdelphijstatic void write_new_certificate(BIO *bp, X509 *x, int output_der, 225296465Sdelphij int notext); 226296465Sdelphijstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, 227296465Sdelphij const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, 228296465Sdelphij CA_DB *db, BIGNUM *serial, char *subj, 229296465Sdelphij unsigned long chtype, int multirdn, int email_dn, 230296465Sdelphij char *startdate, char *enddate, long days, int batch, 231296465Sdelphij int verbose, X509_REQ *req, char *ext_sect, CONF *conf, 232296465Sdelphij unsigned long certopt, unsigned long nameopt, 233296465Sdelphij int default_op, int ext_copy, int selfsign); 234127128Snectarstatic int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval); 235127128Snectarstatic int get_certificate_status(const char *ser_status, CA_DB *db); 236127128Snectarstatic int do_updatedb(CA_DB *db); 237205128Ssimonstatic int check_time_format(const char *str); 238109998Smarkmchar *make_revocation_str(int rev_type, char *rev_arg); 239160814Ssimonint make_revoked(X509_REVOKED *rev, const char *str); 240109998Smarkmint old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str); 241296465Sdelphijstatic CONF *conf = NULL; 242296465Sdelphijstatic CONF *extconf = NULL; 243296465Sdelphijstatic char *section = NULL; 24455714Skris 245296465Sdelphijstatic int preserve = 0; 246296465Sdelphijstatic int msie_hack = 0; 24755714Skris 24859191Skrisint MAIN(int, char **); 24959191Skris 25055714Skrisint MAIN(int argc, char **argv) 251296465Sdelphij{ 252296465Sdelphij ENGINE *e = NULL; 253296465Sdelphij char *key = NULL, *passargin = NULL; 254296465Sdelphij int create_ser = 0; 255296465Sdelphij int free_key = 0; 256296465Sdelphij int total = 0; 257296465Sdelphij int total_done = 0; 258296465Sdelphij int badops = 0; 259296465Sdelphij int ret = 1; 260296465Sdelphij int email_dn = 1; 261296465Sdelphij int req = 0; 262296465Sdelphij int verbose = 0; 263296465Sdelphij int gencrl = 0; 264296465Sdelphij int dorevoke = 0; 265296465Sdelphij int doupdatedb = 0; 266296465Sdelphij long crldays = 0; 267296465Sdelphij long crlhours = 0; 268296465Sdelphij long errorline = -1; 269296465Sdelphij char *configfile = NULL; 270296465Sdelphij char *md = NULL; 271296465Sdelphij char *policy = NULL; 272296465Sdelphij char *keyfile = NULL; 273296465Sdelphij char *certfile = NULL; 274296465Sdelphij int keyform = FORMAT_PEM; 275296465Sdelphij char *infile = NULL; 276296465Sdelphij char *spkac_file = NULL; 277296465Sdelphij char *ss_cert_file = NULL; 278296465Sdelphij char *ser_status = NULL; 279296465Sdelphij EVP_PKEY *pkey = NULL; 280296465Sdelphij int output_der = 0; 281296465Sdelphij char *outfile = NULL; 282296465Sdelphij char *outdir = NULL; 283296465Sdelphij char *serialfile = NULL; 284296465Sdelphij char *crlnumberfile = NULL; 285296465Sdelphij char *extensions = NULL; 286296465Sdelphij char *extfile = NULL; 287296465Sdelphij char *subj = NULL; 288296465Sdelphij unsigned long chtype = MBSTRING_ASC; 289296465Sdelphij int multirdn = 0; 290296465Sdelphij char *tmp_email_dn = NULL; 291296465Sdelphij char *crl_ext = NULL; 292296465Sdelphij int rev_type = REV_NONE; 293296465Sdelphij char *rev_arg = NULL; 294296465Sdelphij BIGNUM *serial = NULL; 295296465Sdelphij BIGNUM *crlnumber = NULL; 296296465Sdelphij char *startdate = NULL; 297296465Sdelphij char *enddate = NULL; 298296465Sdelphij long days = 0; 299296465Sdelphij int batch = 0; 300296465Sdelphij int notext = 0; 301296465Sdelphij unsigned long nameopt = 0, certopt = 0; 302296465Sdelphij int default_op = 1; 303296465Sdelphij int ext_copy = EXT_COPY_NONE; 304296465Sdelphij int selfsign = 0; 305296465Sdelphij X509 *x509 = NULL, *x509p = NULL; 306296465Sdelphij X509 *x = NULL; 307296465Sdelphij BIO *in = NULL, *out = NULL, *Sout = NULL, *Cout = NULL; 308296465Sdelphij char *dbfile = NULL; 309296465Sdelphij CA_DB *db = NULL; 310296465Sdelphij X509_CRL *crl = NULL; 311296465Sdelphij X509_REVOKED *r = NULL; 312296465Sdelphij ASN1_TIME *tmptm; 313296465Sdelphij ASN1_INTEGER *tmpser; 314296465Sdelphij char *f; 315296465Sdelphij const char *p, **pp; 316296465Sdelphij int i, j; 317296465Sdelphij const EVP_MD *dgst = NULL; 318296465Sdelphij STACK_OF(CONF_VALUE) *attribs = NULL; 319296465Sdelphij STACK_OF(X509) *cert_sk = NULL; 32055714Skris#undef BSIZE 32155714Skris#define BSIZE 256 322296465Sdelphij MS_STATIC char buf[3][BSIZE]; 323296465Sdelphij char *randfile = NULL; 324111147Snectar#ifndef OPENSSL_NO_ENGINE 325296465Sdelphij char *engine = NULL; 326111147Snectar#endif 327296465Sdelphij char *tofree = NULL; 328296465Sdelphij DB_ATTR db_attr; 32955714Skris 33055714Skris#ifdef EFENCE 331296465Sdelphij EF_PROTECT_FREE = 1; 332296465Sdelphij EF_PROTECT_BELOW = 1; 333296465Sdelphij EF_ALIGNMENT = 0; 33455714Skris#endif 33555714Skris 336296465Sdelphij apps_startup(); 33755714Skris 338296465Sdelphij conf = NULL; 339296465Sdelphij key = NULL; 340296465Sdelphij section = NULL; 34155714Skris 342296465Sdelphij preserve = 0; 343296465Sdelphij msie_hack = 0; 344296465Sdelphij if (bio_err == NULL) 345296465Sdelphij if ((bio_err = BIO_new(BIO_s_file())) != NULL) 346296465Sdelphij BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); 34755714Skris 348296465Sdelphij argc--; 349296465Sdelphij argv++; 350296465Sdelphij while (argc >= 1) { 351296465Sdelphij if (strcmp(*argv, "-verbose") == 0) 352296465Sdelphij verbose = 1; 353296465Sdelphij else if (strcmp(*argv, "-config") == 0) { 354296465Sdelphij if (--argc < 1) 355296465Sdelphij goto bad; 356296465Sdelphij configfile = *(++argv); 357296465Sdelphij } else if (strcmp(*argv, "-name") == 0) { 358296465Sdelphij if (--argc < 1) 359296465Sdelphij goto bad; 360296465Sdelphij section = *(++argv); 361296465Sdelphij } else if (strcmp(*argv, "-subj") == 0) { 362296465Sdelphij if (--argc < 1) 363296465Sdelphij goto bad; 364296465Sdelphij subj = *(++argv); 365296465Sdelphij /* preserve=1; */ 366296465Sdelphij } else if (strcmp(*argv, "-utf8") == 0) 367296465Sdelphij chtype = MBSTRING_UTF8; 368296465Sdelphij else if (strcmp(*argv, "-create_serial") == 0) 369296465Sdelphij create_ser = 1; 370296465Sdelphij else if (strcmp(*argv, "-multivalue-rdn") == 0) 371296465Sdelphij multirdn = 1; 372296465Sdelphij else if (strcmp(*argv, "-startdate") == 0) { 373296465Sdelphij if (--argc < 1) 374296465Sdelphij goto bad; 375296465Sdelphij startdate = *(++argv); 376296465Sdelphij } else if (strcmp(*argv, "-enddate") == 0) { 377296465Sdelphij if (--argc < 1) 378296465Sdelphij goto bad; 379296465Sdelphij enddate = *(++argv); 380296465Sdelphij } else if (strcmp(*argv, "-days") == 0) { 381296465Sdelphij if (--argc < 1) 382296465Sdelphij goto bad; 383296465Sdelphij days = atoi(*(++argv)); 384296465Sdelphij } else if (strcmp(*argv, "-md") == 0) { 385296465Sdelphij if (--argc < 1) 386296465Sdelphij goto bad; 387296465Sdelphij md = *(++argv); 388296465Sdelphij } else if (strcmp(*argv, "-policy") == 0) { 389296465Sdelphij if (--argc < 1) 390296465Sdelphij goto bad; 391296465Sdelphij policy = *(++argv); 392296465Sdelphij } else if (strcmp(*argv, "-keyfile") == 0) { 393296465Sdelphij if (--argc < 1) 394296465Sdelphij goto bad; 395296465Sdelphij keyfile = *(++argv); 396296465Sdelphij } else if (strcmp(*argv, "-keyform") == 0) { 397296465Sdelphij if (--argc < 1) 398296465Sdelphij goto bad; 399296465Sdelphij keyform = str2fmt(*(++argv)); 400296465Sdelphij } else if (strcmp(*argv, "-passin") == 0) { 401296465Sdelphij if (--argc < 1) 402296465Sdelphij goto bad; 403296465Sdelphij passargin = *(++argv); 404296465Sdelphij } else if (strcmp(*argv, "-key") == 0) { 405296465Sdelphij if (--argc < 1) 406296465Sdelphij goto bad; 407296465Sdelphij key = *(++argv); 408296465Sdelphij } else if (strcmp(*argv, "-cert") == 0) { 409296465Sdelphij if (--argc < 1) 410296465Sdelphij goto bad; 411296465Sdelphij certfile = *(++argv); 412296465Sdelphij } else if (strcmp(*argv, "-selfsign") == 0) 413296465Sdelphij selfsign = 1; 414296465Sdelphij else if (strcmp(*argv, "-in") == 0) { 415296465Sdelphij if (--argc < 1) 416296465Sdelphij goto bad; 417296465Sdelphij infile = *(++argv); 418296465Sdelphij req = 1; 419296465Sdelphij } else if (strcmp(*argv, "-out") == 0) { 420296465Sdelphij if (--argc < 1) 421296465Sdelphij goto bad; 422296465Sdelphij outfile = *(++argv); 423296465Sdelphij } else if (strcmp(*argv, "-outdir") == 0) { 424296465Sdelphij if (--argc < 1) 425296465Sdelphij goto bad; 426296465Sdelphij outdir = *(++argv); 427296465Sdelphij } else if (strcmp(*argv, "-notext") == 0) 428296465Sdelphij notext = 1; 429296465Sdelphij else if (strcmp(*argv, "-batch") == 0) 430296465Sdelphij batch = 1; 431296465Sdelphij else if (strcmp(*argv, "-preserveDN") == 0) 432296465Sdelphij preserve = 1; 433296465Sdelphij else if (strcmp(*argv, "-noemailDN") == 0) 434296465Sdelphij email_dn = 0; 435296465Sdelphij else if (strcmp(*argv, "-gencrl") == 0) 436296465Sdelphij gencrl = 1; 437296465Sdelphij else if (strcmp(*argv, "-msie_hack") == 0) 438296465Sdelphij msie_hack = 1; 439296465Sdelphij else if (strcmp(*argv, "-crldays") == 0) { 440296465Sdelphij if (--argc < 1) 441296465Sdelphij goto bad; 442296465Sdelphij crldays = atol(*(++argv)); 443296465Sdelphij } else if (strcmp(*argv, "-crlhours") == 0) { 444296465Sdelphij if (--argc < 1) 445296465Sdelphij goto bad; 446296465Sdelphij crlhours = atol(*(++argv)); 447296465Sdelphij } else if (strcmp(*argv, "-infiles") == 0) { 448296465Sdelphij argc--; 449296465Sdelphij argv++; 450296465Sdelphij req = 1; 451296465Sdelphij break; 452296465Sdelphij } else if (strcmp(*argv, "-ss_cert") == 0) { 453296465Sdelphij if (--argc < 1) 454296465Sdelphij goto bad; 455296465Sdelphij ss_cert_file = *(++argv); 456296465Sdelphij req = 1; 457296465Sdelphij } else if (strcmp(*argv, "-spkac") == 0) { 458296465Sdelphij if (--argc < 1) 459296465Sdelphij goto bad; 460296465Sdelphij spkac_file = *(++argv); 461296465Sdelphij req = 1; 462296465Sdelphij } else if (strcmp(*argv, "-revoke") == 0) { 463296465Sdelphij if (--argc < 1) 464296465Sdelphij goto bad; 465296465Sdelphij infile = *(++argv); 466296465Sdelphij dorevoke = 1; 467296465Sdelphij } else if (strcmp(*argv, "-extensions") == 0) { 468296465Sdelphij if (--argc < 1) 469296465Sdelphij goto bad; 470296465Sdelphij extensions = *(++argv); 471296465Sdelphij } else if (strcmp(*argv, "-extfile") == 0) { 472296465Sdelphij if (--argc < 1) 473296465Sdelphij goto bad; 474296465Sdelphij extfile = *(++argv); 475296465Sdelphij } else if (strcmp(*argv, "-status") == 0) { 476296465Sdelphij if (--argc < 1) 477296465Sdelphij goto bad; 478296465Sdelphij ser_status = *(++argv); 479296465Sdelphij } else if (strcmp(*argv, "-updatedb") == 0) { 480296465Sdelphij doupdatedb = 1; 481296465Sdelphij } else if (strcmp(*argv, "-crlexts") == 0) { 482296465Sdelphij if (--argc < 1) 483296465Sdelphij goto bad; 484296465Sdelphij crl_ext = *(++argv); 485296465Sdelphij } else if (strcmp(*argv, "-crl_reason") == 0) { 486296465Sdelphij if (--argc < 1) 487296465Sdelphij goto bad; 488296465Sdelphij rev_arg = *(++argv); 489296465Sdelphij rev_type = REV_CRL_REASON; 490296465Sdelphij } else if (strcmp(*argv, "-crl_hold") == 0) { 491296465Sdelphij if (--argc < 1) 492296465Sdelphij goto bad; 493296465Sdelphij rev_arg = *(++argv); 494296465Sdelphij rev_type = REV_HOLD; 495296465Sdelphij } else if (strcmp(*argv, "-crl_compromise") == 0) { 496296465Sdelphij if (--argc < 1) 497296465Sdelphij goto bad; 498296465Sdelphij rev_arg = *(++argv); 499296465Sdelphij rev_type = REV_KEY_COMPROMISE; 500296465Sdelphij } else if (strcmp(*argv, "-crl_CA_compromise") == 0) { 501296465Sdelphij if (--argc < 1) 502296465Sdelphij goto bad; 503296465Sdelphij rev_arg = *(++argv); 504296465Sdelphij rev_type = REV_CA_COMPROMISE; 505296465Sdelphij } 506111147Snectar#ifndef OPENSSL_NO_ENGINE 507296465Sdelphij else if (strcmp(*argv, "-engine") == 0) { 508296465Sdelphij if (--argc < 1) 509296465Sdelphij goto bad; 510296465Sdelphij engine = *(++argv); 511296465Sdelphij } 512111147Snectar#endif 513296465Sdelphij else { 514296465Sdelphij bad: 515296465Sdelphij BIO_printf(bio_err, "unknown option %s\n", *argv); 516296465Sdelphij badops = 1; 517296465Sdelphij break; 518296465Sdelphij } 519296465Sdelphij argc--; 520296465Sdelphij argv++; 521296465Sdelphij } 52255714Skris 523296465Sdelphij if (badops) { 524296465Sdelphij for (pp = ca_usage; (*pp != NULL); pp++) 525296465Sdelphij BIO_printf(bio_err, "%s", *pp); 526296465Sdelphij goto err; 527296465Sdelphij } 52855714Skris 529296465Sdelphij ERR_load_crypto_strings(); 53055714Skris 531296465Sdelphij /*****************************************************************/ 532296465Sdelphij tofree = NULL; 533296465Sdelphij if (configfile == NULL) 534296465Sdelphij configfile = getenv("OPENSSL_CONF"); 535296465Sdelphij if (configfile == NULL) 536296465Sdelphij configfile = getenv("SSLEAY_CONF"); 537296465Sdelphij if (configfile == NULL) { 538296465Sdelphij const char *s = X509_get_default_cert_area(); 539296465Sdelphij size_t len; 540109998Smarkm 541109998Smarkm#ifdef OPENSSL_SYS_VMS 542296465Sdelphij len = strlen(s) + sizeof(CONFIG_FILE); 543296465Sdelphij tofree = OPENSSL_malloc(len); 544296465Sdelphij strcpy(tofree, s); 54555714Skris#else 546296465Sdelphij len = strlen(s) + sizeof(CONFIG_FILE) + 1; 547296465Sdelphij tofree = OPENSSL_malloc(len); 548296465Sdelphij BUF_strlcpy(tofree, s, len); 549296465Sdelphij BUF_strlcat(tofree, "/", len); 55055714Skris#endif 551296465Sdelphij BUF_strlcat(tofree, CONFIG_FILE, len); 552296465Sdelphij configfile = tofree; 553296465Sdelphij } 55455714Skris 555296465Sdelphij BIO_printf(bio_err, "Using configuration from %s\n", configfile); 556296465Sdelphij conf = NCONF_new(NULL); 557296465Sdelphij if (NCONF_load(conf, configfile, &errorline) <= 0) { 558296465Sdelphij if (errorline <= 0) 559296465Sdelphij BIO_printf(bio_err, "error loading the config file '%s'\n", 560296465Sdelphij configfile); 561296465Sdelphij else 562296465Sdelphij BIO_printf(bio_err, "error on line %ld of config file '%s'\n", 563296465Sdelphij errorline, configfile); 564296465Sdelphij goto err; 565296465Sdelphij } 566296465Sdelphij if (tofree) { 567296465Sdelphij OPENSSL_free(tofree); 568296465Sdelphij tofree = NULL; 569296465Sdelphij } 57055714Skris 571296465Sdelphij if (!load_config(bio_err, conf)) 572296465Sdelphij goto err; 573109998Smarkm 574142425Snectar#ifndef OPENSSL_NO_ENGINE 575296465Sdelphij e = setup_engine(bio_err, engine, 0); 576142425Snectar#endif 577142425Snectar 578296465Sdelphij /* Lets get the config section we are using */ 579296465Sdelphij if (section == NULL) { 580296465Sdelphij section = NCONF_get_string(conf, BASE_SECTION, ENV_DEFAULT_CA); 581296465Sdelphij if (section == NULL) { 582296465Sdelphij lookup_fail(BASE_SECTION, ENV_DEFAULT_CA); 583296465Sdelphij goto err; 584296465Sdelphij } 585296465Sdelphij } 58655714Skris 587296465Sdelphij if (conf != NULL) { 588296465Sdelphij p = NCONF_get_string(conf, NULL, "oid_file"); 589296465Sdelphij if (p == NULL) 590296465Sdelphij ERR_clear_error(); 591296465Sdelphij if (p != NULL) { 592296465Sdelphij BIO *oid_bio; 59355714Skris 594296465Sdelphij oid_bio = BIO_new_file(p, "r"); 595296465Sdelphij if (oid_bio == NULL) { 596296465Sdelphij /*- 597296465Sdelphij BIO_printf(bio_err,"problems opening %s for extra oid's\n",p); 598296465Sdelphij ERR_print_errors(bio_err); 599296465Sdelphij */ 600296465Sdelphij ERR_clear_error(); 601296465Sdelphij } else { 602296465Sdelphij OBJ_create_objects(oid_bio); 603296465Sdelphij BIO_free(oid_bio); 604296465Sdelphij } 605296465Sdelphij } 606296465Sdelphij if (!add_oid_section(bio_err, conf)) { 607296465Sdelphij ERR_print_errors(bio_err); 608296465Sdelphij goto err; 609296465Sdelphij } 610296465Sdelphij } 61155714Skris 612296465Sdelphij randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE"); 613296465Sdelphij if (randfile == NULL) 614296465Sdelphij ERR_clear_error(); 615296465Sdelphij app_RAND_load_file(randfile, bio_err, 0); 616127128Snectar 617296465Sdelphij f = NCONF_get_string(conf, section, STRING_MASK); 618296465Sdelphij if (!f) 619296465Sdelphij ERR_clear_error(); 620160814Ssimon 621296465Sdelphij if (f && !ASN1_STRING_set_default_mask_asc(f)) { 622296465Sdelphij BIO_printf(bio_err, "Invalid global string mask setting %s\n", f); 623296465Sdelphij goto err; 624296465Sdelphij } 625160814Ssimon 626296465Sdelphij if (chtype != MBSTRING_UTF8) { 627296465Sdelphij f = NCONF_get_string(conf, section, UTF8_IN); 628296465Sdelphij if (!f) 629296465Sdelphij ERR_clear_error(); 630296465Sdelphij else if (!strcmp(f, "yes")) 631296465Sdelphij chtype = MBSTRING_UTF8; 632296465Sdelphij } 633160814Ssimon 634296465Sdelphij db_attr.unique_subject = 1; 635296465Sdelphij p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT); 636296465Sdelphij if (p) { 637127128Snectar#ifdef RL_DEBUG 638296465Sdelphij BIO_printf(bio_err, "DEBUG: unique_subject = \"%s\"\n", p); 639127128Snectar#endif 640296465Sdelphij db_attr.unique_subject = parse_yesno(p, 1); 641296465Sdelphij } else 642296465Sdelphij ERR_clear_error(); 643127128Snectar#ifdef RL_DEBUG 644296465Sdelphij if (!p) 645296465Sdelphij BIO_printf(bio_err, "DEBUG: unique_subject undefined\n", p); 646127128Snectar#endif 647127128Snectar#ifdef RL_DEBUG 648296465Sdelphij BIO_printf(bio_err, "DEBUG: configured unique_subject is %d\n", 649296465Sdelphij db_attr.unique_subject); 650127128Snectar#endif 65155714Skris 652296465Sdelphij in = BIO_new(BIO_s_file()); 653296465Sdelphij out = BIO_new(BIO_s_file()); 654296465Sdelphij Sout = BIO_new(BIO_s_file()); 655296465Sdelphij Cout = BIO_new(BIO_s_file()); 656296465Sdelphij if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL)) { 657296465Sdelphij ERR_print_errors(bio_err); 658296465Sdelphij goto err; 659296465Sdelphij } 66055714Skris 661296465Sdelphij /*****************************************************************/ 662296465Sdelphij /* report status of cert with serial number given on command line */ 663296465Sdelphij if (ser_status) { 664296465Sdelphij if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) { 665296465Sdelphij lookup_fail(section, ENV_DATABASE); 666296465Sdelphij goto err; 667296465Sdelphij } 668296465Sdelphij db = load_index(dbfile, &db_attr); 669296465Sdelphij if (db == NULL) 670296465Sdelphij goto err; 671109998Smarkm 672296465Sdelphij if (!index_index(db)) 673296465Sdelphij goto err; 674109998Smarkm 675296465Sdelphij if (get_certificate_status(ser_status, db) != 1) 676296465Sdelphij BIO_printf(bio_err, "Error verifying serial %s!\n", ser_status); 677296465Sdelphij goto err; 678296465Sdelphij } 679109998Smarkm 680296465Sdelphij /*****************************************************************/ 681296465Sdelphij /* we definitely need a private key, so let's get it */ 68255714Skris 683296465Sdelphij if ((keyfile == NULL) && ((keyfile = NCONF_get_string(conf, 684296465Sdelphij section, 685296465Sdelphij ENV_PRIVATE_KEY)) == 686296465Sdelphij NULL)) { 687296465Sdelphij lookup_fail(section, ENV_PRIVATE_KEY); 688296465Sdelphij goto err; 689296465Sdelphij } 690296465Sdelphij if (!key) { 691296465Sdelphij free_key = 1; 692296465Sdelphij if (!app_passwd(bio_err, passargin, NULL, &key, NULL)) { 693296465Sdelphij BIO_printf(bio_err, "Error getting password\n"); 694296465Sdelphij goto err; 695296465Sdelphij } 696296465Sdelphij } 697296465Sdelphij pkey = load_key(bio_err, keyfile, keyform, 0, key, e, "CA private key"); 698296465Sdelphij if (key) 699296465Sdelphij OPENSSL_cleanse(key, strlen(key)); 700296465Sdelphij if (pkey == NULL) { 701296465Sdelphij /* load_key() has already printed an appropriate message */ 702296465Sdelphij goto err; 703296465Sdelphij } 70455714Skris 705296465Sdelphij /*****************************************************************/ 706296465Sdelphij /* we need a certificate */ 707296465Sdelphij if (!selfsign || spkac_file || ss_cert_file || gencrl) { 708296465Sdelphij if ((certfile == NULL) 709296465Sdelphij && ((certfile = NCONF_get_string(conf, 710296465Sdelphij section, 711296465Sdelphij ENV_CERTIFICATE)) == NULL)) { 712296465Sdelphij lookup_fail(section, ENV_CERTIFICATE); 713296465Sdelphij goto err; 714296465Sdelphij } 715296465Sdelphij x509 = load_cert(bio_err, certfile, FORMAT_PEM, NULL, e, 716296465Sdelphij "CA certificate"); 717296465Sdelphij if (x509 == NULL) 718296465Sdelphij goto err; 71955714Skris 720296465Sdelphij if (!X509_check_private_key(x509, pkey)) { 721296465Sdelphij BIO_printf(bio_err, 722296465Sdelphij "CA certificate and CA private key do not match\n"); 723296465Sdelphij goto err; 724296465Sdelphij } 725296465Sdelphij } 726296465Sdelphij if (!selfsign) 727296465Sdelphij x509p = x509; 72855714Skris 729296465Sdelphij f = NCONF_get_string(conf, BASE_SECTION, ENV_PRESERVE); 730296465Sdelphij if (f == NULL) 731296465Sdelphij ERR_clear_error(); 732296465Sdelphij if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) 733296465Sdelphij preserve = 1; 734296465Sdelphij f = NCONF_get_string(conf, BASE_SECTION, ENV_MSIE_HACK); 735296465Sdelphij if (f == NULL) 736296465Sdelphij ERR_clear_error(); 737296465Sdelphij if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) 738296465Sdelphij msie_hack = 1; 739109998Smarkm 740296465Sdelphij f = NCONF_get_string(conf, section, ENV_NAMEOPT); 741109998Smarkm 742296465Sdelphij if (f) { 743296465Sdelphij if (!set_name_ex(&nameopt, f)) { 744296465Sdelphij BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f); 745296465Sdelphij goto err; 746296465Sdelphij } 747296465Sdelphij default_op = 0; 748296465Sdelphij } else 749296465Sdelphij ERR_clear_error(); 750109998Smarkm 751296465Sdelphij f = NCONF_get_string(conf, section, ENV_CERTOPT); 752109998Smarkm 753296465Sdelphij if (f) { 754296465Sdelphij if (!set_cert_ex(&certopt, f)) { 755296465Sdelphij BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f); 756296465Sdelphij goto err; 757296465Sdelphij } 758296465Sdelphij default_op = 0; 759296465Sdelphij } else 760296465Sdelphij ERR_clear_error(); 761109998Smarkm 762296465Sdelphij f = NCONF_get_string(conf, section, ENV_EXTCOPY); 763109998Smarkm 764296465Sdelphij if (f) { 765296465Sdelphij if (!set_ext_copy(&ext_copy, f)) { 766296465Sdelphij BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f); 767296465Sdelphij goto err; 768296465Sdelphij } 769296465Sdelphij } else 770296465Sdelphij ERR_clear_error(); 77155714Skris 772296465Sdelphij /*****************************************************************/ 773296465Sdelphij /* lookup where to write new certificates */ 774296465Sdelphij if ((outdir == NULL) && (req)) { 775296465Sdelphij struct stat sb; 776296465Sdelphij 777296465Sdelphij if ((outdir = NCONF_get_string(conf, section, ENV_NEW_CERTS_DIR)) 778296465Sdelphij == NULL) { 779296465Sdelphij BIO_printf(bio_err, 780296465Sdelphij "there needs to be defined a directory for new certificate to be placed in\n"); 781296465Sdelphij goto err; 782296465Sdelphij } 783109998Smarkm#ifndef OPENSSL_SYS_VMS 784296465Sdelphij /* 785296465Sdelphij * outdir is a directory spec, but access() for VMS demands a 786296465Sdelphij * filename. In any case, stat(), below, will catch the problem if 787296465Sdelphij * outdir is not a directory spec, and the fopen() or open() will 788296465Sdelphij * catch an error if there is no write access. 789296465Sdelphij * 790296465Sdelphij * Presumably, this problem could also be solved by using the DEC C 791296465Sdelphij * routines to convert the directory syntax to Unixly, and give that 792296465Sdelphij * to access(). However, time's too short to do that just now. 793296465Sdelphij */ 794296465Sdelphij if (access(outdir, R_OK | W_OK | X_OK) != 0) { 795296465Sdelphij BIO_printf(bio_err, "I am unable to access the %s directory\n", 796296465Sdelphij outdir); 797296465Sdelphij perror(outdir); 798296465Sdelphij goto err; 799296465Sdelphij } 80059191Skris 801296465Sdelphij if (stat(outdir, &sb) != 0) { 802296465Sdelphij BIO_printf(bio_err, "unable to stat(%s)\n", outdir); 803296465Sdelphij perror(outdir); 804296465Sdelphij goto err; 805296465Sdelphij } 806296465Sdelphij# ifdef S_ISDIR 807296465Sdelphij if (!S_ISDIR(sb.st_mode)) { 808296465Sdelphij BIO_printf(bio_err, "%s need to be a directory\n", outdir); 809296465Sdelphij perror(outdir); 810296465Sdelphij goto err; 811296465Sdelphij } 812296465Sdelphij# endif 81359191Skris#endif 814296465Sdelphij } 81555714Skris 816296465Sdelphij /*****************************************************************/ 817296465Sdelphij /* we need to load the database file */ 818296465Sdelphij if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) { 819296465Sdelphij lookup_fail(section, ENV_DATABASE); 820296465Sdelphij goto err; 821296465Sdelphij } 822296465Sdelphij db = load_index(dbfile, &db_attr); 823296465Sdelphij if (db == NULL) 824296465Sdelphij goto err; 82555714Skris 826296465Sdelphij /* Lets check some fields */ 827296465Sdelphij for (i = 0; i < sk_num(db->db->data); i++) { 828296465Sdelphij pp = (const char **)sk_value(db->db->data, i); 829296465Sdelphij if ((pp[DB_type][0] != DB_TYPE_REV) && (pp[DB_rev_date][0] != '\0')) { 830296465Sdelphij BIO_printf(bio_err, 831296465Sdelphij "entry %d: not revoked yet, but has a revocation date\n", 832296465Sdelphij i + 1); 833296465Sdelphij goto err; 834296465Sdelphij } 835296465Sdelphij if ((pp[DB_type][0] == DB_TYPE_REV) && 836296465Sdelphij !make_revoked(NULL, pp[DB_rev_date])) { 837296465Sdelphij BIO_printf(bio_err, " in entry %d\n", i + 1); 838296465Sdelphij goto err; 839296465Sdelphij } 840296465Sdelphij if (!check_time_format(pp[DB_exp_date])) { 841296465Sdelphij BIO_printf(bio_err, "entry %d: invalid expiry date\n", i + 1); 842296465Sdelphij goto err; 843296465Sdelphij } 844296465Sdelphij p = pp[DB_serial]; 845296465Sdelphij j = strlen(p); 846296465Sdelphij if (*p == '-') { 847296465Sdelphij p++; 848296465Sdelphij j--; 849296465Sdelphij } 850296465Sdelphij if ((j & 1) || (j < 2)) { 851296465Sdelphij BIO_printf(bio_err, "entry %d: bad serial number length (%d)\n", 852296465Sdelphij i + 1, j); 853296465Sdelphij goto err; 854296465Sdelphij } 855296465Sdelphij while (*p) { 856296465Sdelphij if (!(((*p >= '0') && (*p <= '9')) || 857296465Sdelphij ((*p >= 'A') && (*p <= 'F')) || 858296465Sdelphij ((*p >= 'a') && (*p <= 'f')))) { 859296465Sdelphij BIO_printf(bio_err, 860296465Sdelphij "entry %d: bad serial number characters, char pos %ld, char is '%c'\n", 861296465Sdelphij i + 1, (long)(p - pp[DB_serial]), *p); 862296465Sdelphij goto err; 863296465Sdelphij } 864296465Sdelphij p++; 865296465Sdelphij } 866296465Sdelphij } 867296465Sdelphij if (verbose) { 868296465Sdelphij BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); /* cannot fail */ 869109998Smarkm#ifdef OPENSSL_SYS_VMS 870296465Sdelphij { 871296465Sdelphij BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 872296465Sdelphij out = BIO_push(tmpbio, out); 873296465Sdelphij } 87468651Skris#endif 875296465Sdelphij TXT_DB_write(out, db->db); 876296465Sdelphij BIO_printf(bio_err, "%d entries loaded from the database\n", 877296465Sdelphij db->db->data->num); 878296465Sdelphij BIO_printf(bio_err, "generating index\n"); 879296465Sdelphij } 88055714Skris 881296465Sdelphij if (!index_index(db)) 882296465Sdelphij goto err; 883109998Smarkm 884296465Sdelphij /*****************************************************************/ 885296465Sdelphij /* Update the db file for expired certificates */ 886296465Sdelphij if (doupdatedb) { 887296465Sdelphij if (verbose) 888296465Sdelphij BIO_printf(bio_err, "Updating %s ...\n", dbfile); 889109998Smarkm 890296465Sdelphij i = do_updatedb(db); 891296465Sdelphij if (i == -1) { 892296465Sdelphij BIO_printf(bio_err, "Malloc failure\n"); 893296465Sdelphij goto err; 894296465Sdelphij } else if (i == 0) { 895296465Sdelphij if (verbose) 896296465Sdelphij BIO_printf(bio_err, "No entries found to mark expired\n"); 897296465Sdelphij } else { 898296465Sdelphij if (!save_index(dbfile, "new", db)) 899296465Sdelphij goto err; 900109998Smarkm 901296465Sdelphij if (!rotate_index(dbfile, "new", "old")) 902296465Sdelphij goto err; 903109998Smarkm 904296465Sdelphij if (verbose) 905296465Sdelphij BIO_printf(bio_err, 906296465Sdelphij "Done. %d entries marked as expired\n", i); 907296465Sdelphij } 908296465Sdelphij } 909109998Smarkm 910296465Sdelphij /*****************************************************************/ 911296465Sdelphij /* Read extentions config file */ 912296465Sdelphij if (extfile) { 913296465Sdelphij extconf = NCONF_new(NULL); 914296465Sdelphij if (NCONF_load(extconf, extfile, &errorline) <= 0) { 915296465Sdelphij if (errorline <= 0) 916296465Sdelphij BIO_printf(bio_err, "ERROR: loading the config file '%s'\n", 917296465Sdelphij extfile); 918296465Sdelphij else 919296465Sdelphij BIO_printf(bio_err, 920296465Sdelphij "ERROR: on line %ld of config file '%s'\n", 921296465Sdelphij errorline, extfile); 922296465Sdelphij ret = 1; 923296465Sdelphij goto err; 924296465Sdelphij } 925296465Sdelphij 926296465Sdelphij if (verbose) 927296465Sdelphij BIO_printf(bio_err, "Successfully loaded extensions file %s\n", 928296465Sdelphij extfile); 929296465Sdelphij 930296465Sdelphij /* We can have sections in the ext file */ 931296465Sdelphij if (!extensions 932296465Sdelphij && !(extensions = 933296465Sdelphij NCONF_get_string(extconf, "default", "extensions"))) 934296465Sdelphij extensions = "default"; 935296465Sdelphij } 936296465Sdelphij 937296465Sdelphij /*****************************************************************/ 938296465Sdelphij if (req || gencrl) { 939296465Sdelphij if (outfile != NULL) { 940296465Sdelphij if (BIO_write_filename(Sout, outfile) <= 0) { 941296465Sdelphij perror(outfile); 942296465Sdelphij goto err; 943296465Sdelphij } 944296465Sdelphij } else { 945296465Sdelphij BIO_set_fp(Sout, stdout, BIO_NOCLOSE | BIO_FP_TEXT); 946109998Smarkm#ifdef OPENSSL_SYS_VMS 947296465Sdelphij { 948296465Sdelphij BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 949296465Sdelphij Sout = BIO_push(tmpbio, Sout); 950296465Sdelphij } 95168651Skris#endif 952296465Sdelphij } 953296465Sdelphij } 95455714Skris 955296465Sdelphij if ((md == NULL) && ((md = NCONF_get_string(conf, 956296465Sdelphij section, 957296465Sdelphij ENV_DEFAULT_MD)) == NULL)) { 958296465Sdelphij lookup_fail(section, ENV_DEFAULT_MD); 959296465Sdelphij goto err; 960296465Sdelphij } 961160814Ssimon 962296465Sdelphij if ((dgst = EVP_get_digestbyname(md)) == NULL) { 963296465Sdelphij BIO_printf(bio_err, "%s is an unsupported message digest type\n", md); 964296465Sdelphij goto err; 965296465Sdelphij } 966160814Ssimon 967296465Sdelphij if (req) { 968296465Sdelphij if ((email_dn == 1) && ((tmp_email_dn = NCONF_get_string(conf, 969296465Sdelphij section, 970296465Sdelphij ENV_DEFAULT_EMAIL_DN)) 971296465Sdelphij != NULL)) { 972296465Sdelphij if (strcmp(tmp_email_dn, "no") == 0) 973296465Sdelphij email_dn = 0; 974296465Sdelphij } 975296465Sdelphij if (verbose) 976296465Sdelphij BIO_printf(bio_err, "message digest is %s\n", 977296465Sdelphij OBJ_nid2ln(dgst->type)); 978296465Sdelphij if ((policy == NULL) && ((policy = NCONF_get_string(conf, 979296465Sdelphij section, 980296465Sdelphij ENV_POLICY)) == 981296465Sdelphij NULL)) { 982296465Sdelphij lookup_fail(section, ENV_POLICY); 983296465Sdelphij goto err; 984296465Sdelphij } 985296465Sdelphij if (verbose) 986296465Sdelphij BIO_printf(bio_err, "policy is %s\n", policy); 98755714Skris 988296465Sdelphij if ((serialfile = NCONF_get_string(conf, section, ENV_SERIAL)) 989296465Sdelphij == NULL) { 990296465Sdelphij lookup_fail(section, ENV_SERIAL); 991296465Sdelphij goto err; 992296465Sdelphij } 993109998Smarkm 994296465Sdelphij if (!extconf) { 995296465Sdelphij /* 996296465Sdelphij * no '-extfile' option, so we look for extensions in the main 997296465Sdelphij * configuration file 998296465Sdelphij */ 999296465Sdelphij if (!extensions) { 1000296465Sdelphij extensions = NCONF_get_string(conf, section, ENV_EXTENSIONS); 1001296465Sdelphij if (!extensions) 1002296465Sdelphij ERR_clear_error(); 1003296465Sdelphij } 1004296465Sdelphij if (extensions) { 1005296465Sdelphij /* Check syntax of file */ 1006296465Sdelphij X509V3_CTX ctx; 1007296465Sdelphij X509V3_set_ctx_test(&ctx); 1008296465Sdelphij X509V3_set_nconf(&ctx, conf); 1009296465Sdelphij if (!X509V3_EXT_add_nconf(conf, &ctx, extensions, NULL)) { 1010296465Sdelphij BIO_printf(bio_err, 1011296465Sdelphij "Error Loading extension section %s\n", 1012296465Sdelphij extensions); 1013296465Sdelphij ret = 1; 1014296465Sdelphij goto err; 1015296465Sdelphij } 1016296465Sdelphij } 1017296465Sdelphij } 101855714Skris 1019296465Sdelphij if (startdate == NULL) { 1020296465Sdelphij startdate = NCONF_get_string(conf, section, 1021296465Sdelphij ENV_DEFAULT_STARTDATE); 1022296465Sdelphij if (startdate == NULL) 1023296465Sdelphij ERR_clear_error(); 1024296465Sdelphij } 1025296465Sdelphij if (startdate && !ASN1_UTCTIME_set_string(NULL, startdate)) { 1026296465Sdelphij BIO_printf(bio_err, 1027296465Sdelphij "start date is invalid, it should be YYMMDDHHMMSSZ\n"); 1028296465Sdelphij goto err; 1029296465Sdelphij } 1030296465Sdelphij if (startdate == NULL) 1031296465Sdelphij startdate = "today"; 103255714Skris 1033296465Sdelphij if (enddate == NULL) { 1034296465Sdelphij enddate = NCONF_get_string(conf, section, ENV_DEFAULT_ENDDATE); 1035296465Sdelphij if (enddate == NULL) 1036296465Sdelphij ERR_clear_error(); 1037296465Sdelphij } 1038296465Sdelphij if (enddate && !ASN1_UTCTIME_set_string(NULL, enddate)) { 1039296465Sdelphij BIO_printf(bio_err, 1040296465Sdelphij "end date is invalid, it should be YYMMDDHHMMSSZ\n"); 1041296465Sdelphij goto err; 1042296465Sdelphij } 104355714Skris 1044296465Sdelphij if (days == 0) { 1045296465Sdelphij if (!NCONF_get_number(conf, section, ENV_DEFAULT_DAYS, &days)) 1046296465Sdelphij days = 0; 1047296465Sdelphij } 1048296465Sdelphij if (!enddate && (days == 0)) { 1049296465Sdelphij BIO_printf(bio_err, 1050296465Sdelphij "cannot lookup how many days to certify for\n"); 1051296465Sdelphij goto err; 1052296465Sdelphij } 105355714Skris 1054296465Sdelphij if ((serial = load_serial(serialfile, create_ser, NULL)) == NULL) { 1055296465Sdelphij BIO_printf(bio_err, "error while loading serial number\n"); 1056296465Sdelphij goto err; 1057296465Sdelphij } 1058296465Sdelphij if (verbose) { 1059296465Sdelphij if (BN_is_zero(serial)) 1060296465Sdelphij BIO_printf(bio_err, "next serial number is 00\n"); 1061296465Sdelphij else { 1062296465Sdelphij if ((f = BN_bn2hex(serial)) == NULL) 1063296465Sdelphij goto err; 1064296465Sdelphij BIO_printf(bio_err, "next serial number is %s\n", f); 1065296465Sdelphij OPENSSL_free(f); 1066296465Sdelphij } 1067296465Sdelphij } 106855714Skris 1069296465Sdelphij if ((attribs = NCONF_get_section(conf, policy)) == NULL) { 1070296465Sdelphij BIO_printf(bio_err, "unable to find 'section' for %s\n", policy); 1071296465Sdelphij goto err; 1072296465Sdelphij } 107355714Skris 1074296465Sdelphij if ((cert_sk = sk_X509_new_null()) == NULL) { 1075296465Sdelphij BIO_printf(bio_err, "Memory allocation failure\n"); 1076296465Sdelphij goto err; 1077296465Sdelphij } 1078296465Sdelphij if (spkac_file != NULL) { 1079296465Sdelphij total++; 1080296465Sdelphij j = certify_spkac(&x, spkac_file, pkey, x509, dgst, attribs, db, 1081296465Sdelphij serial, subj, chtype, multirdn, email_dn, 1082296465Sdelphij startdate, enddate, days, extensions, conf, 1083296465Sdelphij verbose, certopt, nameopt, default_op, 1084296465Sdelphij ext_copy); 1085296465Sdelphij if (j < 0) 1086296465Sdelphij goto err; 1087296465Sdelphij if (j > 0) { 1088296465Sdelphij total_done++; 1089296465Sdelphij BIO_printf(bio_err, "\n"); 1090296465Sdelphij if (!BN_add_word(serial, 1)) 1091296465Sdelphij goto err; 1092296465Sdelphij if (!sk_X509_push(cert_sk, x)) { 1093296465Sdelphij BIO_printf(bio_err, "Memory allocation failure\n"); 1094296465Sdelphij goto err; 1095296465Sdelphij } 1096296465Sdelphij if (outfile) { 1097296465Sdelphij output_der = 1; 1098296465Sdelphij batch = 1; 1099296465Sdelphij } 1100296465Sdelphij } 1101296465Sdelphij } 1102296465Sdelphij if (ss_cert_file != NULL) { 1103296465Sdelphij total++; 1104296465Sdelphij j = certify_cert(&x, ss_cert_file, pkey, x509, dgst, attribs, 1105296465Sdelphij db, serial, subj, chtype, multirdn, email_dn, 1106296465Sdelphij startdate, enddate, days, batch, extensions, 1107296465Sdelphij conf, verbose, certopt, nameopt, default_op, 1108296465Sdelphij ext_copy, e); 1109296465Sdelphij if (j < 0) 1110296465Sdelphij goto err; 1111296465Sdelphij if (j > 0) { 1112296465Sdelphij total_done++; 1113296465Sdelphij BIO_printf(bio_err, "\n"); 1114296465Sdelphij if (!BN_add_word(serial, 1)) 1115296465Sdelphij goto err; 1116296465Sdelphij if (!sk_X509_push(cert_sk, x)) { 1117296465Sdelphij BIO_printf(bio_err, "Memory allocation failure\n"); 1118296465Sdelphij goto err; 1119296465Sdelphij } 1120296465Sdelphij } 1121296465Sdelphij } 1122296465Sdelphij if (infile != NULL) { 1123296465Sdelphij total++; 1124296465Sdelphij j = certify(&x, infile, pkey, x509p, dgst, attribs, db, 1125296465Sdelphij serial, subj, chtype, multirdn, email_dn, startdate, 1126296465Sdelphij enddate, days, batch, extensions, conf, verbose, 1127296465Sdelphij certopt, nameopt, default_op, ext_copy, selfsign); 1128296465Sdelphij if (j < 0) 1129296465Sdelphij goto err; 1130296465Sdelphij if (j > 0) { 1131296465Sdelphij total_done++; 1132296465Sdelphij BIO_printf(bio_err, "\n"); 1133296465Sdelphij if (!BN_add_word(serial, 1)) 1134296465Sdelphij goto err; 1135296465Sdelphij if (!sk_X509_push(cert_sk, x)) { 1136296465Sdelphij BIO_printf(bio_err, "Memory allocation failure\n"); 1137296465Sdelphij goto err; 1138296465Sdelphij } 1139296465Sdelphij } 1140296465Sdelphij } 1141296465Sdelphij for (i = 0; i < argc; i++) { 1142296465Sdelphij total++; 1143296465Sdelphij j = certify(&x, argv[i], pkey, x509p, dgst, attribs, db, 1144296465Sdelphij serial, subj, chtype, multirdn, email_dn, startdate, 1145296465Sdelphij enddate, days, batch, extensions, conf, verbose, 1146296465Sdelphij certopt, nameopt, default_op, ext_copy, selfsign); 1147296465Sdelphij if (j < 0) 1148296465Sdelphij goto err; 1149296465Sdelphij if (j > 0) { 1150296465Sdelphij total_done++; 1151296465Sdelphij BIO_printf(bio_err, "\n"); 1152296465Sdelphij if (!BN_add_word(serial, 1)) 1153296465Sdelphij goto err; 1154296465Sdelphij if (!sk_X509_push(cert_sk, x)) { 1155296465Sdelphij BIO_printf(bio_err, "Memory allocation failure\n"); 1156296465Sdelphij goto err; 1157296465Sdelphij } 1158296465Sdelphij } 1159296465Sdelphij } 1160296465Sdelphij /* 1161296465Sdelphij * we have a stack of newly certified certificates and a data base 1162296465Sdelphij * and serial number that need updating 1163296465Sdelphij */ 116455714Skris 1165296465Sdelphij if (sk_X509_num(cert_sk) > 0) { 1166296465Sdelphij if (!batch) { 1167296465Sdelphij BIO_printf(bio_err, 1168296465Sdelphij "\n%d out of %d certificate requests certified, commit? [y/n]", 1169296465Sdelphij total_done, total); 1170296465Sdelphij (void)BIO_flush(bio_err); 1171296465Sdelphij buf[0][0] = '\0'; 1172296465Sdelphij if (!fgets(buf[0], 10, stdin)) { 1173296465Sdelphij BIO_printf(bio_err, 1174296465Sdelphij "CERTIFICATION CANCELED: I/O error\n"); 1175296465Sdelphij ret = 0; 1176296465Sdelphij goto err; 1177296465Sdelphij } 1178296465Sdelphij if ((buf[0][0] != 'y') && (buf[0][0] != 'Y')) { 1179296465Sdelphij BIO_printf(bio_err, "CERTIFICATION CANCELED\n"); 1180296465Sdelphij ret = 0; 1181296465Sdelphij goto err; 1182296465Sdelphij } 1183296465Sdelphij } 118455714Skris 1185296465Sdelphij BIO_printf(bio_err, "Write out database with %d new entries\n", 1186296465Sdelphij sk_X509_num(cert_sk)); 118755714Skris 1188296465Sdelphij if (!save_serial(serialfile, "new", serial, NULL)) 1189296465Sdelphij goto err; 119055714Skris 1191296465Sdelphij if (!save_index(dbfile, "new", db)) 1192296465Sdelphij goto err; 1193296465Sdelphij } 119455714Skris 1195296465Sdelphij if (verbose) 1196296465Sdelphij BIO_printf(bio_err, "writing new certificates\n"); 1197296465Sdelphij for (i = 0; i < sk_X509_num(cert_sk); i++) { 1198296465Sdelphij int k; 1199296465Sdelphij char *n; 120055714Skris 1201296465Sdelphij x = sk_X509_value(cert_sk, i); 120255714Skris 1203296465Sdelphij j = x->cert_info->serialNumber->length; 1204296465Sdelphij p = (const char *)x->cert_info->serialNumber->data; 1205109998Smarkm 1206296465Sdelphij if (strlen(outdir) >= (size_t)(j ? BSIZE - j * 2 - 6 : BSIZE - 8)) { 1207296465Sdelphij BIO_printf(bio_err, "certificate file name too long\n"); 1208296465Sdelphij goto err; 1209296465Sdelphij } 1210296465Sdelphij 1211296465Sdelphij strcpy(buf[2], outdir); 1212296465Sdelphij 1213109998Smarkm#ifndef OPENSSL_SYS_VMS 1214296465Sdelphij BUF_strlcat(buf[2], "/", sizeof(buf[2])); 121555714Skris#endif 121655714Skris 1217296465Sdelphij n = (char *)&(buf[2][strlen(buf[2])]); 1218296465Sdelphij if (j > 0) { 1219296465Sdelphij for (k = 0; k < j; k++) { 1220296465Sdelphij if (n >= &(buf[2][sizeof(buf[2])])) 1221296465Sdelphij break; 1222296465Sdelphij BIO_snprintf(n, 1223296465Sdelphij &buf[2][0] + sizeof(buf[2]) - n, 1224296465Sdelphij "%02X", (unsigned char)*(p++)); 1225296465Sdelphij n += 2; 1226296465Sdelphij } 1227296465Sdelphij } else { 1228296465Sdelphij *(n++) = '0'; 1229296465Sdelphij *(n++) = '0'; 1230296465Sdelphij } 1231296465Sdelphij *(n++) = '.'; 1232296465Sdelphij *(n++) = 'p'; 1233296465Sdelphij *(n++) = 'e'; 1234296465Sdelphij *(n++) = 'm'; 1235296465Sdelphij *n = '\0'; 1236296465Sdelphij if (verbose) 1237296465Sdelphij BIO_printf(bio_err, "writing %s\n", buf[2]); 123855714Skris 1239296465Sdelphij if (BIO_write_filename(Cout, buf[2]) <= 0) { 1240296465Sdelphij perror(buf[2]); 1241296465Sdelphij goto err; 1242296465Sdelphij } 1243296465Sdelphij write_new_certificate(Cout, x, 0, notext); 1244296465Sdelphij write_new_certificate(Sout, x, output_der, notext); 1245296465Sdelphij } 124655714Skris 1247296465Sdelphij if (sk_X509_num(cert_sk)) { 1248296465Sdelphij /* Rename the database and the serial file */ 1249296465Sdelphij if (!rotate_serial(serialfile, "new", "old")) 1250296465Sdelphij goto err; 125155714Skris 1252296465Sdelphij if (!rotate_index(dbfile, "new", "old")) 1253296465Sdelphij goto err; 125455714Skris 1255296465Sdelphij BIO_printf(bio_err, "Data Base Updated\n"); 1256296465Sdelphij } 1257296465Sdelphij } 125855714Skris 1259296465Sdelphij /*****************************************************************/ 1260296465Sdelphij if (gencrl) { 1261296465Sdelphij int crl_v2 = 0; 1262296465Sdelphij if (!crl_ext) { 1263296465Sdelphij crl_ext = NCONF_get_string(conf, section, ENV_CRLEXT); 1264296465Sdelphij if (!crl_ext) 1265296465Sdelphij ERR_clear_error(); 1266296465Sdelphij } 1267296465Sdelphij if (crl_ext) { 1268296465Sdelphij /* Check syntax of file */ 1269296465Sdelphij X509V3_CTX ctx; 1270296465Sdelphij X509V3_set_ctx_test(&ctx); 1271296465Sdelphij X509V3_set_nconf(&ctx, conf); 1272296465Sdelphij if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL)) { 1273296465Sdelphij BIO_printf(bio_err, 1274296465Sdelphij "Error Loading CRL extension section %s\n", 1275296465Sdelphij crl_ext); 1276296465Sdelphij ret = 1; 1277296465Sdelphij goto err; 1278296465Sdelphij } 1279296465Sdelphij } 1280127128Snectar 1281296465Sdelphij if ((crlnumberfile = NCONF_get_string(conf, section, ENV_CRLNUMBER)) 1282296465Sdelphij != NULL) 1283296465Sdelphij if ((crlnumber = load_serial(crlnumberfile, 0, NULL)) == NULL) { 1284296465Sdelphij BIO_printf(bio_err, "error while loading CRL number\n"); 1285296465Sdelphij goto err; 1286296465Sdelphij } 128755714Skris 1288296465Sdelphij if (!crldays && !crlhours) { 1289296465Sdelphij if (!NCONF_get_number(conf, section, 1290296465Sdelphij ENV_DEFAULT_CRL_DAYS, &crldays)) 1291296465Sdelphij crldays = 0; 1292296465Sdelphij if (!NCONF_get_number(conf, section, 1293296465Sdelphij ENV_DEFAULT_CRL_HOURS, &crlhours)) 1294296465Sdelphij crlhours = 0; 1295296465Sdelphij } 1296296465Sdelphij if ((crldays == 0) && (crlhours == 0)) { 1297296465Sdelphij BIO_printf(bio_err, 1298296465Sdelphij "cannot lookup how long until the next CRL is issued\n"); 1299296465Sdelphij goto err; 1300296465Sdelphij } 130155714Skris 1302296465Sdelphij if (verbose) 1303296465Sdelphij BIO_printf(bio_err, "making CRL\n"); 1304296465Sdelphij if ((crl = X509_CRL_new()) == NULL) 1305296465Sdelphij goto err; 1306296465Sdelphij if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) 1307296465Sdelphij goto err; 130855714Skris 1309296465Sdelphij tmptm = ASN1_TIME_new(); 1310296465Sdelphij if (!tmptm) 1311296465Sdelphij goto err; 1312296465Sdelphij X509_gmtime_adj(tmptm, 0); 1313296465Sdelphij X509_CRL_set_lastUpdate(crl, tmptm); 1314296465Sdelphij X509_gmtime_adj(tmptm, (crldays * 24 + crlhours) * 60 * 60); 1315296465Sdelphij X509_CRL_set_nextUpdate(crl, tmptm); 1316109998Smarkm 1317296465Sdelphij ASN1_TIME_free(tmptm); 1318109998Smarkm 1319296465Sdelphij for (i = 0; i < sk_num(db->db->data); i++) { 1320296465Sdelphij pp = (const char **)sk_value(db->db->data, i); 1321296465Sdelphij if (pp[DB_type][0] == DB_TYPE_REV) { 1322296465Sdelphij if ((r = X509_REVOKED_new()) == NULL) 1323296465Sdelphij goto err; 1324296465Sdelphij j = make_revoked(r, pp[DB_rev_date]); 1325296465Sdelphij if (!j) 1326296465Sdelphij goto err; 1327296465Sdelphij if (j == 2) 1328296465Sdelphij crl_v2 = 1; 1329296465Sdelphij if (!BN_hex2bn(&serial, pp[DB_serial])) 1330296465Sdelphij goto err; 1331296465Sdelphij tmpser = BN_to_ASN1_INTEGER(serial, NULL); 1332296465Sdelphij BN_free(serial); 1333296465Sdelphij serial = NULL; 1334296465Sdelphij if (!tmpser) 1335296465Sdelphij goto err; 1336296465Sdelphij X509_REVOKED_set_serialNumber(r, tmpser); 1337296465Sdelphij ASN1_INTEGER_free(tmpser); 1338296465Sdelphij X509_CRL_add0_revoked(crl, r); 1339296465Sdelphij } 1340296465Sdelphij } 134155714Skris 1342296465Sdelphij /* 1343296465Sdelphij * sort the data so it will be written in serial number order 1344296465Sdelphij */ 1345296465Sdelphij X509_CRL_sort(crl); 1346296465Sdelphij 1347296465Sdelphij /* we now have a CRL */ 1348296465Sdelphij if (verbose) 1349296465Sdelphij BIO_printf(bio_err, "signing CRL\n"); 1350160814Ssimon#ifndef OPENSSL_NO_DSA 1351296465Sdelphij if (pkey->type == EVP_PKEY_DSA) 1352296465Sdelphij dgst = EVP_dss1(); 1353296465Sdelphij else 135455714Skris#endif 1355160814Ssimon#ifndef OPENSSL_NO_ECDSA 1356296465Sdelphij if (pkey->type == EVP_PKEY_EC) 1357296465Sdelphij dgst = EVP_ecdsa(); 1358160814Ssimon#endif 135955714Skris 1360296465Sdelphij /* Add any extensions asked for */ 136155714Skris 1362296465Sdelphij if (crl_ext || crlnumberfile != NULL) { 1363296465Sdelphij X509V3_CTX crlctx; 1364296465Sdelphij X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0); 1365296465Sdelphij X509V3_set_nconf(&crlctx, conf); 136655714Skris 1367296465Sdelphij if (crl_ext) 1368296465Sdelphij if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl)) 1369296465Sdelphij goto err; 1370296465Sdelphij if (crlnumberfile != NULL) { 1371296465Sdelphij tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL); 1372296465Sdelphij if (!tmpser) 1373296465Sdelphij goto err; 1374296465Sdelphij X509_CRL_add1_ext_i2d(crl, NID_crl_number, tmpser, 0, 0); 1375296465Sdelphij ASN1_INTEGER_free(tmpser); 1376296465Sdelphij crl_v2 = 1; 1377296465Sdelphij if (!BN_add_word(crlnumber, 1)) 1378296465Sdelphij goto err; 1379296465Sdelphij } 1380296465Sdelphij } 1381296465Sdelphij if (crl_ext || crl_v2) { 1382296465Sdelphij if (!X509_CRL_set_version(crl, 1)) 1383296465Sdelphij goto err; /* version 2 CRL */ 1384296465Sdelphij } 138555714Skris 1386296465Sdelphij /* we have a CRL number that need updating */ 1387296465Sdelphij if (crlnumberfile != NULL) 1388296465Sdelphij if (!save_serial(crlnumberfile, "new", crlnumber, NULL)) 1389296465Sdelphij goto err; 1390127128Snectar 1391296465Sdelphij if (!X509_CRL_sign(crl, pkey, dgst)) 1392296465Sdelphij goto err; 139355714Skris 1394296465Sdelphij PEM_write_bio_X509_CRL(Sout, crl); 1395127128Snectar 1396296465Sdelphij if (crlnumberfile != NULL) /* Rename the crlnumber file */ 1397296465Sdelphij if (!rotate_serial(crlnumberfile, "new", "old")) 1398296465Sdelphij goto err; 1399127128Snectar 1400296465Sdelphij } 1401296465Sdelphij /*****************************************************************/ 1402296465Sdelphij if (dorevoke) { 1403296465Sdelphij if (infile == NULL) { 1404296465Sdelphij BIO_printf(bio_err, "no input files\n"); 1405296465Sdelphij goto err; 1406296465Sdelphij } else { 1407296465Sdelphij X509 *revcert; 1408296465Sdelphij revcert = load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile); 1409296465Sdelphij if (revcert == NULL) 1410296465Sdelphij goto err; 1411296465Sdelphij j = do_revoke(revcert, db, rev_type, rev_arg); 1412296465Sdelphij if (j <= 0) 1413296465Sdelphij goto err; 1414296465Sdelphij X509_free(revcert); 141555714Skris 1416296465Sdelphij if (!save_index(dbfile, "new", db)) 1417296465Sdelphij goto err; 1418109998Smarkm 1419296465Sdelphij if (!rotate_index(dbfile, "new", "old")) 1420296465Sdelphij goto err; 1421127128Snectar 1422296465Sdelphij BIO_printf(bio_err, "Data Base Updated\n"); 1423296465Sdelphij } 1424296465Sdelphij } 1425296465Sdelphij /*****************************************************************/ 1426296465Sdelphij ret = 0; 1427296465Sdelphij err: 1428296465Sdelphij if (tofree) 1429296465Sdelphij OPENSSL_free(tofree); 1430296465Sdelphij BIO_free_all(Cout); 1431296465Sdelphij BIO_free_all(Sout); 1432296465Sdelphij BIO_free_all(out); 1433296465Sdelphij BIO_free_all(in); 143455714Skris 1435296465Sdelphij if (cert_sk) 1436296465Sdelphij sk_X509_pop_free(cert_sk, X509_free); 143755714Skris 1438296465Sdelphij if (ret) 1439296465Sdelphij ERR_print_errors(bio_err); 1440296465Sdelphij app_RAND_write_file(randfile, bio_err); 1441296465Sdelphij if (free_key && key) 1442296465Sdelphij OPENSSL_free(key); 1443296465Sdelphij BN_free(serial); 1444296465Sdelphij free_index(db); 1445296465Sdelphij EVP_PKEY_free(pkey); 1446296465Sdelphij if (x509) 1447296465Sdelphij X509_free(x509); 1448296465Sdelphij X509_CRL_free(crl); 1449296465Sdelphij NCONF_free(conf); 1450296465Sdelphij NCONF_free(extconf); 1451296465Sdelphij OBJ_cleanup(); 1452296465Sdelphij apps_shutdown(); 1453296465Sdelphij OPENSSL_EXIT(ret); 1454296465Sdelphij} 145555714Skris 1456160814Ssimonstatic void lookup_fail(const char *name, const char *tag) 1457296465Sdelphij{ 1458296465Sdelphij BIO_printf(bio_err, "variable lookup failed for %s::%s\n", name, tag); 1459296465Sdelphij} 146055714Skris 146155714Skrisstatic int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 1462296465Sdelphij const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, 1463296465Sdelphij CA_DB *db, BIGNUM *serial, char *subj, 1464296465Sdelphij unsigned long chtype, int multirdn, int email_dn, 1465296465Sdelphij char *startdate, char *enddate, long days, int batch, 1466296465Sdelphij char *ext_sect, CONF *lconf, int verbose, 1467296465Sdelphij unsigned long certopt, unsigned long nameopt, 1468296465Sdelphij int default_op, int ext_copy, int selfsign) 1469296465Sdelphij{ 1470296465Sdelphij X509_REQ *req = NULL; 1471296465Sdelphij BIO *in = NULL; 1472296465Sdelphij EVP_PKEY *pktmp = NULL; 1473296465Sdelphij int ok = -1, i; 147455714Skris 1475296465Sdelphij in = BIO_new(BIO_s_file()); 147655714Skris 1477296465Sdelphij if (BIO_read_filename(in, infile) <= 0) { 1478296465Sdelphij perror(infile); 1479296465Sdelphij goto err; 1480296465Sdelphij } 1481296465Sdelphij if ((req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL)) == NULL) { 1482296465Sdelphij BIO_printf(bio_err, "Error reading certificate request in %s\n", 1483296465Sdelphij infile); 1484296465Sdelphij goto err; 1485296465Sdelphij } 1486296465Sdelphij if (verbose) 1487296465Sdelphij X509_REQ_print(bio_err, req); 148855714Skris 1489296465Sdelphij BIO_printf(bio_err, "Check that the request matches the signature\n"); 149055714Skris 1491296465Sdelphij if (selfsign && !X509_REQ_check_private_key(req, pkey)) { 1492296465Sdelphij BIO_printf(bio_err, 1493296465Sdelphij "Certificate request and CA private key do not match\n"); 1494296465Sdelphij ok = 0; 1495296465Sdelphij goto err; 1496296465Sdelphij } 1497296465Sdelphij if ((pktmp = X509_REQ_get_pubkey(req)) == NULL) { 1498296465Sdelphij BIO_printf(bio_err, "error unpacking public key\n"); 1499296465Sdelphij goto err; 1500296465Sdelphij } 1501296465Sdelphij i = X509_REQ_verify(req, pktmp); 1502296465Sdelphij EVP_PKEY_free(pktmp); 1503296465Sdelphij if (i < 0) { 1504296465Sdelphij ok = 0; 1505296465Sdelphij BIO_printf(bio_err, "Signature verification problems....\n"); 1506296465Sdelphij ERR_print_errors(bio_err); 1507296465Sdelphij goto err; 1508296465Sdelphij } 1509296465Sdelphij if (i == 0) { 1510296465Sdelphij ok = 0; 1511296465Sdelphij BIO_printf(bio_err, 1512296465Sdelphij "Signature did not match the certificate request\n"); 1513296465Sdelphij ERR_print_errors(bio_err); 1514296465Sdelphij goto err; 1515296465Sdelphij } else 1516296465Sdelphij BIO_printf(bio_err, "Signature ok\n"); 151755714Skris 1518296465Sdelphij ok = do_body(xret, pkey, x509, dgst, policy, db, serial, subj, chtype, 1519296465Sdelphij multirdn, email_dn, startdate, enddate, days, batch, verbose, 1520296465Sdelphij req, ext_sect, lconf, certopt, nameopt, default_op, ext_copy, 1521296465Sdelphij selfsign); 152255714Skris 1523296465Sdelphij err: 1524296465Sdelphij if (req != NULL) 1525296465Sdelphij X509_REQ_free(req); 1526296465Sdelphij if (in != NULL) 1527296465Sdelphij BIO_free(in); 1528296465Sdelphij return (ok); 1529296465Sdelphij} 153055714Skris 153155714Skrisstatic int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 1532296465Sdelphij const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, 1533296465Sdelphij CA_DB *db, BIGNUM *serial, char *subj, 1534296465Sdelphij unsigned long chtype, int multirdn, int email_dn, 1535296465Sdelphij char *startdate, char *enddate, long days, int batch, 1536296465Sdelphij char *ext_sect, CONF *lconf, int verbose, 1537296465Sdelphij unsigned long certopt, unsigned long nameopt, 1538296465Sdelphij int default_op, int ext_copy, ENGINE *e) 1539296465Sdelphij{ 1540296465Sdelphij X509 *req = NULL; 1541296465Sdelphij X509_REQ *rreq = NULL; 1542296465Sdelphij EVP_PKEY *pktmp = NULL; 1543296465Sdelphij int ok = -1, i; 154455714Skris 1545296465Sdelphij if ((req = 1546296465Sdelphij load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL) 1547296465Sdelphij goto err; 1548296465Sdelphij if (verbose) 1549296465Sdelphij X509_print(bio_err, req); 155055714Skris 1551296465Sdelphij BIO_printf(bio_err, "Check that the request matches the signature\n"); 155255714Skris 1553296465Sdelphij if ((pktmp = X509_get_pubkey(req)) == NULL) { 1554296465Sdelphij BIO_printf(bio_err, "error unpacking public key\n"); 1555296465Sdelphij goto err; 1556296465Sdelphij } 1557296465Sdelphij i = X509_verify(req, pktmp); 1558296465Sdelphij EVP_PKEY_free(pktmp); 1559296465Sdelphij if (i < 0) { 1560296465Sdelphij ok = 0; 1561296465Sdelphij BIO_printf(bio_err, "Signature verification problems....\n"); 1562296465Sdelphij goto err; 1563296465Sdelphij } 1564296465Sdelphij if (i == 0) { 1565296465Sdelphij ok = 0; 1566296465Sdelphij BIO_printf(bio_err, "Signature did not match the certificate\n"); 1567296465Sdelphij goto err; 1568296465Sdelphij } else 1569296465Sdelphij BIO_printf(bio_err, "Signature ok\n"); 157055714Skris 1571296465Sdelphij if ((rreq = X509_to_X509_REQ(req, NULL, EVP_md5())) == NULL) 1572296465Sdelphij goto err; 157355714Skris 1574296465Sdelphij ok = do_body(xret, pkey, x509, dgst, policy, db, serial, subj, chtype, 1575296465Sdelphij multirdn, email_dn, startdate, enddate, days, batch, verbose, 1576296465Sdelphij rreq, ext_sect, lconf, certopt, nameopt, default_op, 1577296465Sdelphij ext_copy, 0); 157855714Skris 1579296465Sdelphij err: 1580296465Sdelphij if (rreq != NULL) 1581296465Sdelphij X509_REQ_free(rreq); 1582296465Sdelphij if (req != NULL) 1583296465Sdelphij X509_free(req); 1584296465Sdelphij return (ok); 1585296465Sdelphij} 158655714Skris 1587296465Sdelphijstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, 1588296465Sdelphij const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, 1589296465Sdelphij CA_DB *db, BIGNUM *serial, char *subj, 1590296465Sdelphij unsigned long chtype, int multirdn, int email_dn, 1591296465Sdelphij char *startdate, char *enddate, long days, int batch, 1592296465Sdelphij int verbose, X509_REQ *req, char *ext_sect, CONF *lconf, 1593296465Sdelphij unsigned long certopt, unsigned long nameopt, 1594296465Sdelphij int default_op, int ext_copy, int selfsign) 1595296465Sdelphij{ 1596296465Sdelphij X509_NAME *name = NULL, *CAname = NULL, *subject = NULL, *dn_subject = 1597296465Sdelphij NULL; 1598296465Sdelphij ASN1_UTCTIME *tm, *tmptm; 1599296465Sdelphij ASN1_STRING *str, *str2; 1600296465Sdelphij ASN1_OBJECT *obj; 1601296465Sdelphij X509 *ret = NULL; 1602296465Sdelphij X509_CINF *ci; 1603296465Sdelphij X509_NAME_ENTRY *ne; 1604296465Sdelphij X509_NAME_ENTRY *tne, *push; 1605296465Sdelphij EVP_PKEY *pktmp; 1606296465Sdelphij int ok = -1, i, j, last, nid; 1607296465Sdelphij const char *p; 1608296465Sdelphij CONF_VALUE *cv; 1609296465Sdelphij char *row[DB_NUMBER], **rrow = NULL, **irow = NULL; 1610296465Sdelphij char buf[25]; 161155714Skris 1612296465Sdelphij tmptm = ASN1_UTCTIME_new(); 1613296465Sdelphij if (tmptm == NULL) { 1614296465Sdelphij BIO_printf(bio_err, "malloc error\n"); 1615296465Sdelphij return (0); 1616296465Sdelphij } 161755714Skris 1618296465Sdelphij for (i = 0; i < DB_NUMBER; i++) 1619296465Sdelphij row[i] = NULL; 162055714Skris 1621296465Sdelphij if (subj) { 1622296465Sdelphij X509_NAME *n = parse_name(subj, chtype, multirdn); 1623109998Smarkm 1624296465Sdelphij if (!n) { 1625296465Sdelphij ERR_print_errors(bio_err); 1626296465Sdelphij goto err; 1627296465Sdelphij } 1628296465Sdelphij X509_REQ_set_subject_name(req, n); 1629296465Sdelphij req->req_info->enc.modified = 1; 1630296465Sdelphij X509_NAME_free(n); 1631296465Sdelphij } 1632109998Smarkm 1633296465Sdelphij if (default_op) 1634296465Sdelphij BIO_printf(bio_err, 1635296465Sdelphij "The Subject's Distinguished Name is as follows\n"); 1636109998Smarkm 1637296465Sdelphij name = X509_REQ_get_subject_name(req); 1638296465Sdelphij for (i = 0; i < X509_NAME_entry_count(name); i++) { 1639296465Sdelphij ne = X509_NAME_get_entry(name, i); 1640296465Sdelphij str = X509_NAME_ENTRY_get_data(ne); 1641296465Sdelphij obj = X509_NAME_ENTRY_get_object(ne); 164255714Skris 1643296465Sdelphij if (msie_hack) { 1644296465Sdelphij /* assume all type should be strings */ 1645296465Sdelphij nid = OBJ_obj2nid(ne->object); 164655714Skris 1647296465Sdelphij if (str->type == V_ASN1_UNIVERSALSTRING) 1648296465Sdelphij ASN1_UNIVERSALSTRING_to_string(str); 164955714Skris 1650296465Sdelphij if ((str->type == V_ASN1_IA5STRING) && 1651296465Sdelphij (nid != NID_pkcs9_emailAddress)) 1652296465Sdelphij str->type = V_ASN1_T61STRING; 165355714Skris 1654296465Sdelphij if ((nid == NID_pkcs9_emailAddress) && 1655296465Sdelphij (str->type == V_ASN1_PRINTABLESTRING)) 1656296465Sdelphij str->type = V_ASN1_IA5STRING; 1657296465Sdelphij } 165855714Skris 1659296465Sdelphij /* If no EMAIL is wanted in the subject */ 1660296465Sdelphij if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn)) 1661296465Sdelphij continue; 166255714Skris 1663296465Sdelphij /* check some things */ 1664296465Sdelphij if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && 1665296465Sdelphij (str->type != V_ASN1_IA5STRING)) { 1666296465Sdelphij BIO_printf(bio_err, 1667296465Sdelphij "\nemailAddress type needs to be of type IA5STRING\n"); 1668296465Sdelphij goto err; 1669296465Sdelphij } 1670296465Sdelphij if ((str->type != V_ASN1_BMPSTRING) 1671296465Sdelphij && (str->type != V_ASN1_UTF8STRING)) { 1672296465Sdelphij j = ASN1_PRINTABLE_type(str->data, str->length); 1673296465Sdelphij if (((j == V_ASN1_T61STRING) && 1674296465Sdelphij (str->type != V_ASN1_T61STRING)) || 1675296465Sdelphij ((j == V_ASN1_IA5STRING) && 1676296465Sdelphij (str->type == V_ASN1_PRINTABLESTRING))) { 1677296465Sdelphij BIO_printf(bio_err, 1678296465Sdelphij "\nThe string contains characters that are illegal for the ASN.1 type\n"); 1679296465Sdelphij goto err; 1680296465Sdelphij } 1681296465Sdelphij } 1682109998Smarkm 1683296465Sdelphij if (default_op) 1684296465Sdelphij old_entry_print(bio_err, obj, str); 1685296465Sdelphij } 168655714Skris 1687296465Sdelphij /* Ok, now we check the 'policy' stuff. */ 1688296465Sdelphij if ((subject = X509_NAME_new()) == NULL) { 1689296465Sdelphij BIO_printf(bio_err, "Memory allocation failure\n"); 1690296465Sdelphij goto err; 1691296465Sdelphij } 169255714Skris 1693296465Sdelphij /* take a copy of the issuer name before we mess with it. */ 1694296465Sdelphij if (selfsign) 1695296465Sdelphij CAname = X509_NAME_dup(name); 1696296465Sdelphij else 1697296465Sdelphij CAname = X509_NAME_dup(x509->cert_info->subject); 1698296465Sdelphij if (CAname == NULL) 1699296465Sdelphij goto err; 1700296465Sdelphij str = str2 = NULL; 170155714Skris 1702296465Sdelphij for (i = 0; i < sk_CONF_VALUE_num(policy); i++) { 1703296465Sdelphij cv = sk_CONF_VALUE_value(policy, i); /* get the object id */ 1704296465Sdelphij if ((j = OBJ_txt2nid(cv->name)) == NID_undef) { 1705296465Sdelphij BIO_printf(bio_err, 1706296465Sdelphij "%s:unknown object type in 'policy' configuration\n", 1707296465Sdelphij cv->name); 1708296465Sdelphij goto err; 1709296465Sdelphij } 1710296465Sdelphij obj = OBJ_nid2obj(j); 171155714Skris 1712296465Sdelphij last = -1; 1713296465Sdelphij for (;;) { 1714296465Sdelphij /* lookup the object in the supplied name list */ 1715296465Sdelphij j = X509_NAME_get_index_by_OBJ(name, obj, last); 1716296465Sdelphij if (j < 0) { 1717296465Sdelphij if (last != -1) 1718296465Sdelphij break; 1719296465Sdelphij tne = NULL; 1720296465Sdelphij } else { 1721296465Sdelphij tne = X509_NAME_get_entry(name, j); 1722296465Sdelphij } 1723296465Sdelphij last = j; 172455714Skris 1725296465Sdelphij /* depending on the 'policy', decide what to do. */ 1726296465Sdelphij push = NULL; 1727296465Sdelphij if (strcmp(cv->value, "optional") == 0) { 1728296465Sdelphij if (tne != NULL) 1729296465Sdelphij push = tne; 1730296465Sdelphij } else if (strcmp(cv->value, "supplied") == 0) { 1731296465Sdelphij if (tne == NULL) { 1732296465Sdelphij BIO_printf(bio_err, 1733296465Sdelphij "The %s field needed to be supplied and was missing\n", 1734296465Sdelphij cv->name); 1735296465Sdelphij goto err; 1736296465Sdelphij } else 1737296465Sdelphij push = tne; 1738296465Sdelphij } else if (strcmp(cv->value, "match") == 0) { 1739296465Sdelphij int last2; 174055714Skris 1741296465Sdelphij if (tne == NULL) { 1742296465Sdelphij BIO_printf(bio_err, 1743296465Sdelphij "The mandatory %s field was missing\n", 1744296465Sdelphij cv->name); 1745296465Sdelphij goto err; 1746296465Sdelphij } 174755714Skris 1748296465Sdelphij last2 = -1; 174955714Skris 1750296465Sdelphij again2: 1751296465Sdelphij j = X509_NAME_get_index_by_OBJ(CAname, obj, last2); 1752296465Sdelphij if ((j < 0) && (last2 == -1)) { 1753296465Sdelphij BIO_printf(bio_err, 1754296465Sdelphij "The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n", 1755296465Sdelphij cv->name); 1756296465Sdelphij goto err; 1757296465Sdelphij } 1758296465Sdelphij if (j >= 0) { 1759296465Sdelphij push = X509_NAME_get_entry(CAname, j); 1760296465Sdelphij str = X509_NAME_ENTRY_get_data(tne); 1761296465Sdelphij str2 = X509_NAME_ENTRY_get_data(push); 1762296465Sdelphij last2 = j; 1763296465Sdelphij if (ASN1_STRING_cmp(str, str2) != 0) 1764296465Sdelphij goto again2; 1765296465Sdelphij } 1766296465Sdelphij if (j < 0) { 1767296465Sdelphij BIO_printf(bio_err, 1768296465Sdelphij "The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n", 1769296465Sdelphij cv->name, 1770296465Sdelphij ((str2 == NULL) ? "NULL" : (char *)str2->data), 1771296465Sdelphij ((str == NULL) ? "NULL" : (char *)str->data)); 1772296465Sdelphij goto err; 1773296465Sdelphij } 1774296465Sdelphij } else { 1775296465Sdelphij BIO_printf(bio_err, 1776296465Sdelphij "%s:invalid type in 'policy' configuration\n", 1777296465Sdelphij cv->value); 1778296465Sdelphij goto err; 1779296465Sdelphij } 178055714Skris 1781296465Sdelphij if (push != NULL) { 1782296465Sdelphij if (!X509_NAME_add_entry(subject, push, -1, 0)) { 1783296465Sdelphij if (push != NULL) 1784296465Sdelphij X509_NAME_ENTRY_free(push); 1785296465Sdelphij BIO_printf(bio_err, "Memory allocation failure\n"); 1786296465Sdelphij goto err; 1787296465Sdelphij } 1788296465Sdelphij } 1789296465Sdelphij if (j < 0) 1790296465Sdelphij break; 1791296465Sdelphij } 1792296465Sdelphij } 179355714Skris 1794296465Sdelphij if (preserve) { 1795296465Sdelphij X509_NAME_free(subject); 1796296465Sdelphij /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */ 1797296465Sdelphij subject = X509_NAME_dup(name); 1798296465Sdelphij if (subject == NULL) 1799296465Sdelphij goto err; 1800296465Sdelphij } 180155714Skris 1802296465Sdelphij if (verbose) 1803296465Sdelphij BIO_printf(bio_err, 1804296465Sdelphij "The subject name appears to be ok, checking data base for clashes\n"); 180555714Skris 1806296465Sdelphij /* Build the correct Subject if no e-mail is wanted in the subject */ 1807296465Sdelphij /* 1808296465Sdelphij * and add it later on because of the method extensions are added 1809296465Sdelphij * (altName) 1810296465Sdelphij */ 1811109998Smarkm 1812296465Sdelphij if (email_dn) 1813296465Sdelphij dn_subject = subject; 1814296465Sdelphij else { 1815296465Sdelphij X509_NAME_ENTRY *tmpne; 1816296465Sdelphij /* 1817296465Sdelphij * Its best to dup the subject DN and then delete any email addresses 1818296465Sdelphij * because this retains its structure. 1819296465Sdelphij */ 1820296465Sdelphij if (!(dn_subject = X509_NAME_dup(subject))) { 1821296465Sdelphij BIO_printf(bio_err, "Memory allocation failure\n"); 1822296465Sdelphij goto err; 1823296465Sdelphij } 1824296465Sdelphij while ((i = X509_NAME_get_index_by_NID(dn_subject, 1825296465Sdelphij NID_pkcs9_emailAddress, 1826296465Sdelphij -1)) >= 0) { 1827296465Sdelphij tmpne = X509_NAME_get_entry(dn_subject, i); 1828296465Sdelphij X509_NAME_delete_entry(dn_subject, i); 1829296465Sdelphij X509_NAME_ENTRY_free(tmpne); 1830296465Sdelphij } 1831296465Sdelphij } 183255714Skris 1833296465Sdelphij if (BN_is_zero(serial)) 1834296465Sdelphij row[DB_serial] = BUF_strdup("00"); 1835296465Sdelphij else 1836296465Sdelphij row[DB_serial] = BN_bn2hex(serial); 1837296465Sdelphij if (row[DB_serial] == NULL) { 1838296465Sdelphij BIO_printf(bio_err, "Memory allocation failure\n"); 1839296465Sdelphij goto err; 1840296465Sdelphij } 184155714Skris 1842296465Sdelphij if (db->attributes.unique_subject) { 1843296465Sdelphij rrow = TXT_DB_get_by_index(db->db, DB_name, row); 1844296465Sdelphij if (rrow != NULL) { 1845296465Sdelphij BIO_printf(bio_err, 1846296465Sdelphij "ERROR:There is already a certificate for %s\n", 1847296465Sdelphij row[DB_name]); 1848296465Sdelphij } 1849296465Sdelphij } 1850296465Sdelphij if (rrow == NULL) { 1851296465Sdelphij rrow = TXT_DB_get_by_index(db->db, DB_serial, row); 1852296465Sdelphij if (rrow != NULL) { 1853296465Sdelphij BIO_printf(bio_err, 1854296465Sdelphij "ERROR:Serial number %s has already been issued,\n", 1855296465Sdelphij row[DB_serial]); 1856296465Sdelphij BIO_printf(bio_err, 1857296465Sdelphij " check the database/serial_file for corruption\n"); 1858296465Sdelphij } 1859296465Sdelphij } 186055714Skris 1861296465Sdelphij if (rrow != NULL) { 1862296465Sdelphij BIO_printf(bio_err, "The matching entry has the following details\n"); 1863296465Sdelphij if (rrow[DB_type][0] == 'E') 1864296465Sdelphij p = "Expired"; 1865296465Sdelphij else if (rrow[DB_type][0] == 'R') 1866296465Sdelphij p = "Revoked"; 1867296465Sdelphij else if (rrow[DB_type][0] == 'V') 1868296465Sdelphij p = "Valid"; 1869296465Sdelphij else 1870296465Sdelphij p = "\ninvalid type, Data base error\n"; 1871296465Sdelphij BIO_printf(bio_err, "Type :%s\n", p);; 1872296465Sdelphij if (rrow[DB_type][0] == 'R') { 1873296465Sdelphij p = rrow[DB_exp_date]; 1874296465Sdelphij if (p == NULL) 1875296465Sdelphij p = "undef"; 1876296465Sdelphij BIO_printf(bio_err, "Was revoked on:%s\n", p); 1877296465Sdelphij } 1878296465Sdelphij p = rrow[DB_exp_date]; 1879296465Sdelphij if (p == NULL) 1880296465Sdelphij p = "undef"; 1881296465Sdelphij BIO_printf(bio_err, "Expires on :%s\n", p); 1882296465Sdelphij p = rrow[DB_serial]; 1883296465Sdelphij if (p == NULL) 1884296465Sdelphij p = "undef"; 1885296465Sdelphij BIO_printf(bio_err, "Serial Number :%s\n", p); 1886296465Sdelphij p = rrow[DB_file]; 1887296465Sdelphij if (p == NULL) 1888296465Sdelphij p = "undef"; 1889296465Sdelphij BIO_printf(bio_err, "File name :%s\n", p); 1890296465Sdelphij p = rrow[DB_name]; 1891296465Sdelphij if (p == NULL) 1892296465Sdelphij p = "undef"; 1893296465Sdelphij BIO_printf(bio_err, "Subject Name :%s\n", p); 1894296465Sdelphij ok = -1; /* This is now a 'bad' error. */ 1895296465Sdelphij goto err; 1896296465Sdelphij } 189755714Skris 1898296465Sdelphij /* We are now totally happy, lets make and sign the certificate */ 1899296465Sdelphij if (verbose) 1900296465Sdelphij BIO_printf(bio_err, 1901296465Sdelphij "Everything appears to be ok, creating and signing the certificate\n"); 190255714Skris 1903296465Sdelphij if ((ret = X509_new()) == NULL) 1904296465Sdelphij goto err; 1905296465Sdelphij ci = ret->cert_info; 1906296465Sdelphij 190755714Skris#ifdef X509_V3 1908296465Sdelphij /* Make it an X509 v3 certificate. */ 1909296465Sdelphij if (!X509_set_version(ret, 2)) 1910296465Sdelphij goto err; 191155714Skris#endif 191255714Skris 1913296465Sdelphij if (BN_to_ASN1_INTEGER(serial, ci->serialNumber) == NULL) 1914296465Sdelphij goto err; 1915296465Sdelphij if (selfsign) { 1916296465Sdelphij if (!X509_set_issuer_name(ret, subject)) 1917296465Sdelphij goto err; 1918296465Sdelphij } else { 1919296465Sdelphij if (!X509_set_issuer_name(ret, X509_get_subject_name(x509))) 1920296465Sdelphij goto err; 1921296465Sdelphij } 192255714Skris 1923296465Sdelphij if (strcmp(startdate, "today") == 0) 1924296465Sdelphij X509_gmtime_adj(X509_get_notBefore(ret), 0); 1925296465Sdelphij else 1926296465Sdelphij ASN1_UTCTIME_set_string(X509_get_notBefore(ret), startdate); 192755714Skris 1928296465Sdelphij if (enddate == NULL) 1929296465Sdelphij X509_gmtime_adj(X509_get_notAfter(ret), (long)60 * 60 * 24 * days); 1930296465Sdelphij else 1931296465Sdelphij ASN1_UTCTIME_set_string(X509_get_notAfter(ret), enddate); 193255714Skris 1933296465Sdelphij if (!X509_set_subject_name(ret, subject)) 1934296465Sdelphij goto err; 193555714Skris 1936296465Sdelphij pktmp = X509_REQ_get_pubkey(req); 1937296465Sdelphij i = X509_set_pubkey(ret, pktmp); 1938296465Sdelphij EVP_PKEY_free(pktmp); 1939296465Sdelphij if (!i) 1940296465Sdelphij goto err; 194155714Skris 1942296465Sdelphij /* Lets add the extensions, if there are any */ 1943296465Sdelphij if (ext_sect) { 1944296465Sdelphij X509V3_CTX ctx; 1945296465Sdelphij if (ci->version == NULL) 1946296465Sdelphij if ((ci->version = ASN1_INTEGER_new()) == NULL) 1947296465Sdelphij goto err; 1948296465Sdelphij ASN1_INTEGER_set(ci->version, 2); /* version 3 certificate */ 194955714Skris 1950296465Sdelphij /* 1951296465Sdelphij * Free the current entries if any, there should not be any I believe 1952296465Sdelphij */ 1953296465Sdelphij if (ci->extensions != NULL) 1954296465Sdelphij sk_X509_EXTENSION_pop_free(ci->extensions, X509_EXTENSION_free); 195555714Skris 1956296465Sdelphij ci->extensions = NULL; 195755714Skris 1958296465Sdelphij /* Initialize the context structure */ 1959296465Sdelphij if (selfsign) 1960296465Sdelphij X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0); 1961296465Sdelphij else 1962296465Sdelphij X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0); 196355714Skris 1964296465Sdelphij if (extconf) { 1965296465Sdelphij if (verbose) 1966296465Sdelphij BIO_printf(bio_err, "Extra configuration file found\n"); 196755714Skris 1968296465Sdelphij /* Use the extconf configuration db LHASH */ 1969296465Sdelphij X509V3_set_nconf(&ctx, extconf); 1970109998Smarkm 1971296465Sdelphij /* Test the structure (needed?) */ 1972296465Sdelphij /* X509V3_set_ctx_test(&ctx); */ 1973109998Smarkm 1974296465Sdelphij /* Adds exts contained in the configuration file */ 1975296465Sdelphij if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect, ret)) { 1976296465Sdelphij BIO_printf(bio_err, 1977296465Sdelphij "ERROR: adding extensions in section %s\n", 1978296465Sdelphij ext_sect); 1979296465Sdelphij ERR_print_errors(bio_err); 1980296465Sdelphij goto err; 1981296465Sdelphij } 1982296465Sdelphij if (verbose) 1983296465Sdelphij BIO_printf(bio_err, 1984296465Sdelphij "Successfully added extensions from file.\n"); 1985296465Sdelphij } else if (ext_sect) { 1986296465Sdelphij /* We found extensions to be set from config file */ 1987296465Sdelphij X509V3_set_nconf(&ctx, lconf); 198855714Skris 1989296465Sdelphij if (!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret)) { 1990296465Sdelphij BIO_printf(bio_err, 1991296465Sdelphij "ERROR: adding extensions in section %s\n", 1992296465Sdelphij ext_sect); 1993296465Sdelphij ERR_print_errors(bio_err); 1994296465Sdelphij goto err; 1995296465Sdelphij } 199655714Skris 1997296465Sdelphij if (verbose) 1998296465Sdelphij BIO_printf(bio_err, 1999296465Sdelphij "Successfully added extensions from config\n"); 2000296465Sdelphij } 2001296465Sdelphij } 2002109998Smarkm 2003296465Sdelphij /* Copy extensions from request (if any) */ 2004109998Smarkm 2005296465Sdelphij if (!copy_extensions(ret, req, ext_copy)) { 2006296465Sdelphij BIO_printf(bio_err, "ERROR: adding extensions from request\n"); 2007296465Sdelphij ERR_print_errors(bio_err); 2008296465Sdelphij goto err; 2009296465Sdelphij } 2010109998Smarkm 2011296465Sdelphij /* Set the right value for the noemailDN option */ 2012296465Sdelphij if (email_dn == 0) { 2013296465Sdelphij if (!X509_set_subject_name(ret, dn_subject)) 2014296465Sdelphij goto err; 2015296465Sdelphij } 2016109998Smarkm 2017296465Sdelphij if (!default_op) { 2018296465Sdelphij BIO_printf(bio_err, "Certificate Details:\n"); 2019296465Sdelphij /* 2020296465Sdelphij * Never print signature details because signature not present 2021296465Sdelphij */ 2022296465Sdelphij certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME; 2023296465Sdelphij X509_print_ex(bio_err, ret, nameopt, certopt); 2024296465Sdelphij } 2025109998Smarkm 2026296465Sdelphij BIO_printf(bio_err, "Certificate is to be certified until "); 2027296465Sdelphij ASN1_TIME_print(bio_err, X509_get_notAfter(ret)); 2028296465Sdelphij if (days) 2029296465Sdelphij BIO_printf(bio_err, " (%ld days)", days); 2030296465Sdelphij BIO_printf(bio_err, "\n"); 203155714Skris 2032296465Sdelphij if (!batch) { 203355714Skris 2034296465Sdelphij BIO_printf(bio_err, "Sign the certificate? [y/n]:"); 2035296465Sdelphij (void)BIO_flush(bio_err); 2036296465Sdelphij buf[0] = '\0'; 2037296465Sdelphij if (!fgets(buf, sizeof(buf) - 1, stdin)) { 2038296465Sdelphij BIO_printf(bio_err, 2039296465Sdelphij "CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n"); 2040296465Sdelphij ok = 0; 2041296465Sdelphij goto err; 2042296465Sdelphij } 2043296465Sdelphij if (!((buf[0] == 'y') || (buf[0] == 'Y'))) { 2044296465Sdelphij BIO_printf(bio_err, "CERTIFICATE WILL NOT BE CERTIFIED\n"); 2045296465Sdelphij ok = 0; 2046296465Sdelphij goto err; 2047296465Sdelphij } 2048296465Sdelphij } 2049109998Smarkm#ifndef OPENSSL_NO_DSA 2050296465Sdelphij if (pkey->type == EVP_PKEY_DSA) 2051296465Sdelphij dgst = EVP_dss1(); 2052296465Sdelphij pktmp = X509_get_pubkey(ret); 2053296465Sdelphij if (EVP_PKEY_missing_parameters(pktmp) && 2054296465Sdelphij !EVP_PKEY_missing_parameters(pkey)) 2055296465Sdelphij EVP_PKEY_copy_parameters(pktmp, pkey); 2056296465Sdelphij EVP_PKEY_free(pktmp); 205755714Skris#endif 2058160814Ssimon#ifndef OPENSSL_NO_ECDSA 2059296465Sdelphij if (pkey->type == EVP_PKEY_EC) 2060296465Sdelphij dgst = EVP_ecdsa(); 2061296465Sdelphij pktmp = X509_get_pubkey(ret); 2062296465Sdelphij if (EVP_PKEY_missing_parameters(pktmp) && 2063296465Sdelphij !EVP_PKEY_missing_parameters(pkey)) 2064296465Sdelphij EVP_PKEY_copy_parameters(pktmp, pkey); 2065296465Sdelphij EVP_PKEY_free(pktmp); 2066160814Ssimon#endif 206755714Skris 2068296465Sdelphij if (!X509_sign(ret, pkey, dgst)) 2069296465Sdelphij goto err; 2070160814Ssimon 2071296465Sdelphij /* We now just add it to the database */ 2072296465Sdelphij row[DB_type] = (char *)OPENSSL_malloc(2); 207355714Skris 2074296465Sdelphij tm = X509_get_notAfter(ret); 2075296465Sdelphij row[DB_exp_date] = (char *)OPENSSL_malloc(tm->length + 1); 2076296465Sdelphij memcpy(row[DB_exp_date], tm->data, tm->length); 2077296465Sdelphij row[DB_exp_date][tm->length] = '\0'; 207855714Skris 2079296465Sdelphij row[DB_rev_date] = NULL; 208055714Skris 2081296465Sdelphij /* row[DB_serial] done already */ 2082296465Sdelphij row[DB_file] = (char *)OPENSSL_malloc(8); 2083296465Sdelphij row[DB_name] = X509_NAME_oneline(X509_get_subject_name(ret), NULL, 0); 208455714Skris 2085296465Sdelphij if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || 2086296465Sdelphij (row[DB_file] == NULL) || (row[DB_name] == NULL)) { 2087296465Sdelphij BIO_printf(bio_err, "Memory allocation failure\n"); 2088296465Sdelphij goto err; 2089296465Sdelphij } 2090296465Sdelphij BUF_strlcpy(row[DB_file], "unknown", 8); 2091296465Sdelphij row[DB_type][0] = 'V'; 2092296465Sdelphij row[DB_type][1] = '\0'; 209355714Skris 2094296465Sdelphij if ((irow = 2095296465Sdelphij (char **)OPENSSL_malloc(sizeof(char *) * (DB_NUMBER + 1))) == NULL) { 2096296465Sdelphij BIO_printf(bio_err, "Memory allocation failure\n"); 2097296465Sdelphij goto err; 2098296465Sdelphij } 209955714Skris 2100296465Sdelphij for (i = 0; i < DB_NUMBER; i++) { 2101296465Sdelphij irow[i] = row[i]; 2102296465Sdelphij row[i] = NULL; 2103296465Sdelphij } 2104296465Sdelphij irow[DB_NUMBER] = NULL; 210555714Skris 2106296465Sdelphij if (!TXT_DB_insert(db->db, irow)) { 2107296465Sdelphij BIO_printf(bio_err, "failed to update database\n"); 2108296465Sdelphij BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error); 2109296465Sdelphij goto err; 2110296465Sdelphij } 2111296465Sdelphij ok = 1; 2112296465Sdelphij err: 2113296465Sdelphij for (i = 0; i < DB_NUMBER; i++) 2114296465Sdelphij if (row[i] != NULL) 2115296465Sdelphij OPENSSL_free(row[i]); 211655714Skris 2117296465Sdelphij if (CAname != NULL) 2118296465Sdelphij X509_NAME_free(CAname); 2119296465Sdelphij if (subject != NULL) 2120296465Sdelphij X509_NAME_free(subject); 2121296465Sdelphij if ((dn_subject != NULL) && !email_dn) 2122296465Sdelphij X509_NAME_free(dn_subject); 2123296465Sdelphij if (tmptm != NULL) 2124296465Sdelphij ASN1_UTCTIME_free(tmptm); 2125296465Sdelphij if (ok <= 0) { 2126296465Sdelphij if (ret != NULL) 2127296465Sdelphij X509_free(ret); 2128296465Sdelphij ret = NULL; 2129296465Sdelphij } else 2130296465Sdelphij *xret = ret; 2131296465Sdelphij return (ok); 2132296465Sdelphij} 213355714Skris 2134296465Sdelphijstatic void write_new_certificate(BIO *bp, X509 *x, int output_der, 2135296465Sdelphij int notext) 2136296465Sdelphij{ 213755714Skris 2138296465Sdelphij if (output_der) { 2139296465Sdelphij (void)i2d_X509_bio(bp, x); 2140296465Sdelphij return; 2141296465Sdelphij } 214259191Skris#if 0 2143296465Sdelphij /* ??? Not needed since X509_print prints all this stuff anyway */ 2144296465Sdelphij f = X509_NAME_oneline(X509_get_issuer_name(x), buf, 256); 2145296465Sdelphij BIO_printf(bp, "issuer :%s\n", f); 214655714Skris 2147296465Sdelphij f = X509_NAME_oneline(X509_get_subject_name(x), buf, 256); 2148296465Sdelphij BIO_printf(bp, "subject:%s\n", f); 214955714Skris 2150296465Sdelphij BIO_puts(bp, "serial :"); 2151296465Sdelphij i2a_ASN1_INTEGER(bp, x->cert_info->serialNumber); 2152296465Sdelphij BIO_puts(bp, "\n\n"); 215359191Skris#endif 2154296465Sdelphij if (!notext) 2155296465Sdelphij X509_print(bp, x); 2156296465Sdelphij PEM_write_bio_X509(bp, x); 2157296465Sdelphij} 215855714Skris 2159296465Sdelphijstatic int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, 2160296465Sdelphij X509 *x509, const EVP_MD *dgst, 2161296465Sdelphij STACK_OF(CONF_VALUE) *policy, CA_DB *db, 2162296465Sdelphij BIGNUM *serial, char *subj, unsigned long chtype, 2163296465Sdelphij int multirdn, int email_dn, char *startdate, 2164296465Sdelphij char *enddate, long days, char *ext_sect, 2165296465Sdelphij CONF *lconf, int verbose, unsigned long certopt, 2166296465Sdelphij unsigned long nameopt, int default_op, int ext_copy) 2167296465Sdelphij{ 2168296465Sdelphij STACK_OF(CONF_VALUE) *sk = NULL; 2169296465Sdelphij LHASH *parms = NULL; 2170296465Sdelphij X509_REQ *req = NULL; 2171296465Sdelphij CONF_VALUE *cv = NULL; 2172296465Sdelphij NETSCAPE_SPKI *spki = NULL; 2173296465Sdelphij X509_REQ_INFO *ri; 2174296465Sdelphij char *type, *buf; 2175296465Sdelphij EVP_PKEY *pktmp = NULL; 2176296465Sdelphij X509_NAME *n = NULL; 2177296465Sdelphij X509_NAME_ENTRY *ne = NULL; 2178296465Sdelphij int ok = -1, i, j; 2179296465Sdelphij long errline; 2180296465Sdelphij int nid; 218155714Skris 2182296465Sdelphij /* 2183296465Sdelphij * Load input file into a hash table. (This is just an easy 2184296465Sdelphij * way to read and parse the file, then put it into a convenient 2185296465Sdelphij * STACK format). 2186296465Sdelphij */ 2187296465Sdelphij parms = CONF_load(NULL, infile, &errline); 2188296465Sdelphij if (parms == NULL) { 2189296465Sdelphij BIO_printf(bio_err, "error on line %ld of %s\n", errline, infile); 2190296465Sdelphij ERR_print_errors(bio_err); 2191296465Sdelphij goto err; 2192296465Sdelphij } 219355714Skris 2194296465Sdelphij sk = CONF_get_section(parms, "default"); 2195296465Sdelphij if (sk_CONF_VALUE_num(sk) == 0) { 2196296465Sdelphij BIO_printf(bio_err, "no name/value pairs found in %s\n", infile); 2197296465Sdelphij CONF_free(parms); 2198296465Sdelphij goto err; 2199296465Sdelphij } 220055714Skris 2201296465Sdelphij /* 2202296465Sdelphij * Now create a dummy X509 request structure. We don't actually 2203296465Sdelphij * have an X509 request, but we have many of the components 2204296465Sdelphij * (a public key, various DN components). The idea is that we 2205296465Sdelphij * put these components into the right X509 request structure 2206296465Sdelphij * and we can use the same code as if you had a real X509 request. 2207296465Sdelphij */ 2208296465Sdelphij req = X509_REQ_new(); 2209296465Sdelphij if (req == NULL) { 2210296465Sdelphij ERR_print_errors(bio_err); 2211296465Sdelphij goto err; 2212296465Sdelphij } 221355714Skris 2214296465Sdelphij /* 2215296465Sdelphij * Build up the subject name set. 2216296465Sdelphij */ 2217296465Sdelphij ri = req->req_info; 2218296465Sdelphij n = ri->subject; 221955714Skris 2220296465Sdelphij for (i = 0;; i++) { 2221296465Sdelphij if (sk_CONF_VALUE_num(sk) <= i) 2222296465Sdelphij break; 222355714Skris 2224296465Sdelphij cv = sk_CONF_VALUE_value(sk, i); 2225296465Sdelphij type = cv->name; 2226296465Sdelphij /* 2227296465Sdelphij * Skip past any leading X. X: X, etc to allow for multiple instances 2228296465Sdelphij */ 2229296465Sdelphij for (buf = cv->name; *buf; buf++) 2230296465Sdelphij if ((*buf == ':') || (*buf == ',') || (*buf == '.')) { 2231296465Sdelphij buf++; 2232296465Sdelphij if (*buf) 2233296465Sdelphij type = buf; 2234296465Sdelphij break; 2235296465Sdelphij } 223659191Skris 2237296465Sdelphij buf = cv->value; 2238296465Sdelphij if ((nid = OBJ_txt2nid(type)) == NID_undef) { 2239296465Sdelphij if (strcmp(type, "SPKAC") == 0) { 2240296465Sdelphij spki = NETSCAPE_SPKI_b64_decode(cv->value, -1); 2241296465Sdelphij if (spki == NULL) { 2242296465Sdelphij BIO_printf(bio_err, 2243296465Sdelphij "unable to load Netscape SPKAC structure\n"); 2244296465Sdelphij ERR_print_errors(bio_err); 2245296465Sdelphij goto err; 2246296465Sdelphij } 2247296465Sdelphij } 2248296465Sdelphij continue; 2249296465Sdelphij } 225055714Skris 2251296465Sdelphij if (!X509_NAME_add_entry_by_NID(n, nid, chtype, 2252296465Sdelphij (unsigned char *)buf, -1, -1, 0)) 2253296465Sdelphij goto err; 2254296465Sdelphij } 2255296465Sdelphij if (spki == NULL) { 2256296465Sdelphij BIO_printf(bio_err, "Netscape SPKAC structure not found in %s\n", 2257296465Sdelphij infile); 2258296465Sdelphij goto err; 2259296465Sdelphij } 226055714Skris 2261296465Sdelphij /* 2262296465Sdelphij * Now extract the key from the SPKI structure. 2263296465Sdelphij */ 226455714Skris 2265296465Sdelphij BIO_printf(bio_err, 2266296465Sdelphij "Check that the SPKAC request matches the signature\n"); 226755714Skris 2268296465Sdelphij if ((pktmp = NETSCAPE_SPKI_get_pubkey(spki)) == NULL) { 2269296465Sdelphij BIO_printf(bio_err, "error unpacking SPKAC public key\n"); 2270296465Sdelphij goto err; 2271296465Sdelphij } 227255714Skris 2273296465Sdelphij j = NETSCAPE_SPKI_verify(spki, pktmp); 2274296465Sdelphij if (j <= 0) { 2275296465Sdelphij BIO_printf(bio_err, 2276296465Sdelphij "signature verification failed on SPKAC public key\n"); 2277296465Sdelphij goto err; 2278296465Sdelphij } 2279296465Sdelphij BIO_printf(bio_err, "Signature ok\n"); 228055714Skris 2281296465Sdelphij X509_REQ_set_pubkey(req, pktmp); 2282296465Sdelphij EVP_PKEY_free(pktmp); 2283296465Sdelphij ok = do_body(xret, pkey, x509, dgst, policy, db, serial, subj, chtype, 2284296465Sdelphij multirdn, email_dn, startdate, enddate, days, 1, verbose, 2285296465Sdelphij req, ext_sect, lconf, certopt, nameopt, default_op, ext_copy, 2286296465Sdelphij 0); 2287296465Sdelphij err: 2288296465Sdelphij if (req != NULL) 2289296465Sdelphij X509_REQ_free(req); 2290296465Sdelphij if (parms != NULL) 2291296465Sdelphij CONF_free(parms); 2292296465Sdelphij if (spki != NULL) 2293296465Sdelphij NETSCAPE_SPKI_free(spki); 2294296465Sdelphij if (ne != NULL) 2295296465Sdelphij X509_NAME_ENTRY_free(ne); 229655714Skris 2297296465Sdelphij return (ok); 2298296465Sdelphij} 229955714Skris 2300205128Ssimonstatic int check_time_format(const char *str) 2301296465Sdelphij{ 2302296465Sdelphij ASN1_TIME tm; 230355714Skris 2304296465Sdelphij tm.data = (unsigned char *)str; 2305296465Sdelphij tm.length = strlen(str); 2306296465Sdelphij tm.type = V_ASN1_UTCTIME; 2307296465Sdelphij if (ASN1_TIME_check(&tm)) 2308296465Sdelphij return 1; 2309296465Sdelphij tm.type = V_ASN1_GENERALIZEDTIME; 2310296465Sdelphij return ASN1_TIME_check(&tm); 2311296465Sdelphij} 231255714Skris 2313127128Snectarstatic int do_revoke(X509 *x509, CA_DB *db, int type, char *value) 2314296465Sdelphij{ 2315296465Sdelphij ASN1_UTCTIME *tm = NULL; 2316296465Sdelphij char *row[DB_NUMBER], **rrow, **irow; 2317296465Sdelphij char *rev_str = NULL; 2318296465Sdelphij BIGNUM *bn = NULL; 2319296465Sdelphij int ok = -1, i; 232055714Skris 2321296465Sdelphij for (i = 0; i < DB_NUMBER; i++) 2322296465Sdelphij row[i] = NULL; 2323296465Sdelphij row[DB_name] = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0); 2324296465Sdelphij bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509), NULL); 2325296465Sdelphij if (BN_is_zero(bn)) 2326296465Sdelphij row[DB_serial] = BUF_strdup("00"); 2327296465Sdelphij else 2328296465Sdelphij row[DB_serial] = BN_bn2hex(bn); 2329296465Sdelphij BN_free(bn); 2330296465Sdelphij if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) { 2331296465Sdelphij BIO_printf(bio_err, "Memory allocation failure\n"); 2332296465Sdelphij goto err; 2333296465Sdelphij } 2334296465Sdelphij /* 2335296465Sdelphij * We have to lookup by serial number because name lookup skips revoked 2336296465Sdelphij * certs 2337296465Sdelphij */ 2338296465Sdelphij rrow = TXT_DB_get_by_index(db->db, DB_serial, row); 2339296465Sdelphij if (rrow == NULL) { 2340296465Sdelphij BIO_printf(bio_err, 2341296465Sdelphij "Adding Entry with serial number %s to DB for %s\n", 2342296465Sdelphij row[DB_serial], row[DB_name]); 234355714Skris 2344296465Sdelphij /* We now just add it to the database */ 2345296465Sdelphij row[DB_type] = (char *)OPENSSL_malloc(2); 234655714Skris 2347296465Sdelphij tm = X509_get_notAfter(x509); 2348296465Sdelphij row[DB_exp_date] = (char *)OPENSSL_malloc(tm->length + 1); 2349296465Sdelphij memcpy(row[DB_exp_date], tm->data, tm->length); 2350296465Sdelphij row[DB_exp_date][tm->length] = '\0'; 235155714Skris 2352296465Sdelphij row[DB_rev_date] = NULL; 235355714Skris 2354296465Sdelphij /* row[DB_serial] done already */ 2355296465Sdelphij row[DB_file] = (char *)OPENSSL_malloc(8); 235655714Skris 2357296465Sdelphij /* row[DB_name] done already */ 235855714Skris 2359296465Sdelphij if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || 2360296465Sdelphij (row[DB_file] == NULL)) { 2361296465Sdelphij BIO_printf(bio_err, "Memory allocation failure\n"); 2362296465Sdelphij goto err; 2363296465Sdelphij } 2364296465Sdelphij BUF_strlcpy(row[DB_file], "unknown", 8); 2365296465Sdelphij row[DB_type][0] = 'V'; 2366296465Sdelphij row[DB_type][1] = '\0'; 236755714Skris 2368296465Sdelphij if ((irow = 2369296465Sdelphij (char **)OPENSSL_malloc(sizeof(char *) * (DB_NUMBER + 1))) == 2370296465Sdelphij NULL) { 2371296465Sdelphij BIO_printf(bio_err, "Memory allocation failure\n"); 2372296465Sdelphij goto err; 2373296465Sdelphij } 237455714Skris 2375296465Sdelphij for (i = 0; i < DB_NUMBER; i++) { 2376296465Sdelphij irow[i] = row[i]; 2377296465Sdelphij row[i] = NULL; 2378296465Sdelphij } 2379296465Sdelphij irow[DB_NUMBER] = NULL; 238055714Skris 2381296465Sdelphij if (!TXT_DB_insert(db->db, irow)) { 2382296465Sdelphij BIO_printf(bio_err, "failed to update database\n"); 2383296465Sdelphij BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error); 2384296465Sdelphij goto err; 2385296465Sdelphij } 238655714Skris 2387296465Sdelphij /* Revoke Certificate */ 2388296465Sdelphij ok = do_revoke(x509, db, type, value); 238955714Skris 2390296465Sdelphij goto err; 239155714Skris 2392296465Sdelphij } else if (index_name_cmp((const char **)row, (const char **)rrow)) { 2393296465Sdelphij BIO_printf(bio_err, "ERROR:name does not match %s\n", row[DB_name]); 2394296465Sdelphij goto err; 2395296465Sdelphij } else if (rrow[DB_type][0] == 'R') { 2396296465Sdelphij BIO_printf(bio_err, "ERROR:Already revoked, serial number %s\n", 2397296465Sdelphij row[DB_serial]); 2398296465Sdelphij goto err; 2399296465Sdelphij } else { 2400296465Sdelphij BIO_printf(bio_err, "Revoking Certificate %s.\n", rrow[DB_serial]); 2401296465Sdelphij rev_str = make_revocation_str(type, value); 2402296465Sdelphij if (!rev_str) { 2403296465Sdelphij BIO_printf(bio_err, "Error in revocation arguments\n"); 2404296465Sdelphij goto err; 2405296465Sdelphij } 2406296465Sdelphij rrow[DB_type][0] = 'R'; 2407296465Sdelphij rrow[DB_type][1] = '\0'; 2408296465Sdelphij rrow[DB_rev_date] = rev_str; 2409296465Sdelphij } 2410296465Sdelphij ok = 1; 2411296465Sdelphij err: 2412296465Sdelphij for (i = 0; i < DB_NUMBER; i++) { 2413296465Sdelphij if (row[i] != NULL) 2414296465Sdelphij OPENSSL_free(row[i]); 2415296465Sdelphij } 2416296465Sdelphij return (ok); 2417296465Sdelphij} 2418109998Smarkm 2419127128Snectarstatic int get_certificate_status(const char *serial, CA_DB *db) 2420296465Sdelphij{ 2421296465Sdelphij char *row[DB_NUMBER], **rrow; 2422296465Sdelphij int ok = -1, i; 2423109998Smarkm 2424296465Sdelphij /* Free Resources */ 2425296465Sdelphij for (i = 0; i < DB_NUMBER; i++) 2426296465Sdelphij row[i] = NULL; 2427109998Smarkm 2428296465Sdelphij /* Malloc needed char spaces */ 2429296465Sdelphij row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2); 2430296465Sdelphij if (row[DB_serial] == NULL) { 2431296465Sdelphij BIO_printf(bio_err, "Malloc failure\n"); 2432296465Sdelphij goto err; 2433296465Sdelphij } 2434109998Smarkm 2435296465Sdelphij if (strlen(serial) % 2) { 2436296465Sdelphij /* 2437296465Sdelphij * Set the first char to 0 2438296465Sdelphij */ ; 2439296465Sdelphij row[DB_serial][0] = '0'; 2440109998Smarkm 2441296465Sdelphij /* Copy String from serial to row[DB_serial] */ 2442296465Sdelphij memcpy(row[DB_serial] + 1, serial, strlen(serial)); 2443296465Sdelphij row[DB_serial][strlen(serial) + 1] = '\0'; 2444296465Sdelphij } else { 2445296465Sdelphij /* Copy String from serial to row[DB_serial] */ 2446296465Sdelphij memcpy(row[DB_serial], serial, strlen(serial)); 2447296465Sdelphij row[DB_serial][strlen(serial)] = '\0'; 2448296465Sdelphij } 2449109998Smarkm 2450296465Sdelphij /* Make it Upper Case */ 2451296465Sdelphij for (i = 0; row[DB_serial][i] != '\0'; i++) 2452296465Sdelphij row[DB_serial][i] = toupper(row[DB_serial][i]); 2453109998Smarkm 2454296465Sdelphij ok = 1; 2455109998Smarkm 2456296465Sdelphij /* Search for the certificate */ 2457296465Sdelphij rrow = TXT_DB_get_by_index(db->db, DB_serial, row); 2458296465Sdelphij if (rrow == NULL) { 2459296465Sdelphij BIO_printf(bio_err, "Serial %s not present in db.\n", row[DB_serial]); 2460296465Sdelphij ok = -1; 2461296465Sdelphij goto err; 2462296465Sdelphij } else if (rrow[DB_type][0] == 'V') { 2463296465Sdelphij BIO_printf(bio_err, "%s=Valid (%c)\n", 2464296465Sdelphij row[DB_serial], rrow[DB_type][0]); 2465296465Sdelphij goto err; 2466296465Sdelphij } else if (rrow[DB_type][0] == 'R') { 2467296465Sdelphij BIO_printf(bio_err, "%s=Revoked (%c)\n", 2468296465Sdelphij row[DB_serial], rrow[DB_type][0]); 2469296465Sdelphij goto err; 2470296465Sdelphij } else if (rrow[DB_type][0] == 'E') { 2471296465Sdelphij BIO_printf(bio_err, "%s=Expired (%c)\n", 2472296465Sdelphij row[DB_serial], rrow[DB_type][0]); 2473296465Sdelphij goto err; 2474296465Sdelphij } else if (rrow[DB_type][0] == 'S') { 2475296465Sdelphij BIO_printf(bio_err, "%s=Suspended (%c)\n", 2476296465Sdelphij row[DB_serial], rrow[DB_type][0]); 2477296465Sdelphij goto err; 2478296465Sdelphij } else { 2479296465Sdelphij BIO_printf(bio_err, "%s=Unknown (%c).\n", 2480296465Sdelphij row[DB_serial], rrow[DB_type][0]); 2481296465Sdelphij ok = -1; 2482296465Sdelphij } 2483296465Sdelphij err: 2484296465Sdelphij for (i = 0; i < DB_NUMBER; i++) { 2485296465Sdelphij if (row[i] != NULL) 2486296465Sdelphij OPENSSL_free(row[i]); 2487296465Sdelphij } 2488296465Sdelphij return (ok); 2489296465Sdelphij} 2490109998Smarkm 2491296465Sdelphijstatic int do_updatedb(CA_DB *db) 2492296465Sdelphij{ 2493296465Sdelphij ASN1_UTCTIME *a_tm = NULL; 2494296465Sdelphij int i, cnt = 0; 2495296465Sdelphij int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */ 2496296465Sdelphij char **rrow, *a_tm_s; 2497109998Smarkm 2498296465Sdelphij a_tm = ASN1_UTCTIME_new(); 2499109998Smarkm 2500296465Sdelphij /* get actual time and make a string */ 2501296465Sdelphij a_tm = X509_gmtime_adj(a_tm, 0); 2502296465Sdelphij a_tm_s = (char *)OPENSSL_malloc(a_tm->length + 1); 2503296465Sdelphij if (a_tm_s == NULL) { 2504296465Sdelphij cnt = -1; 2505296465Sdelphij goto err; 2506296465Sdelphij } 2507109998Smarkm 2508296465Sdelphij memcpy(a_tm_s, a_tm->data, a_tm->length); 2509296465Sdelphij a_tm_s[a_tm->length] = '\0'; 2510109998Smarkm 2511296465Sdelphij if (strncmp(a_tm_s, "49", 2) <= 0) 2512296465Sdelphij a_y2k = 1; 2513296465Sdelphij else 2514296465Sdelphij a_y2k = 0; 2515109998Smarkm 2516296465Sdelphij for (i = 0; i < sk_num(db->db->data); i++) { 2517296465Sdelphij rrow = (char **)sk_value(db->db->data, i); 2518109998Smarkm 2519296465Sdelphij if (rrow[DB_type][0] == 'V') { 2520296465Sdelphij /* ignore entries that are not valid */ 2521296465Sdelphij if (strncmp(rrow[DB_exp_date], "49", 2) <= 0) 2522296465Sdelphij db_y2k = 1; 2523296465Sdelphij else 2524296465Sdelphij db_y2k = 0; 2525109998Smarkm 2526296465Sdelphij if (db_y2k == a_y2k) { 2527296465Sdelphij /* all on the same y2k side */ 2528296465Sdelphij if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0) { 2529296465Sdelphij rrow[DB_type][0] = 'E'; 2530296465Sdelphij rrow[DB_type][1] = '\0'; 2531296465Sdelphij cnt++; 2532109998Smarkm 2533296465Sdelphij BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]); 2534296465Sdelphij } 2535296465Sdelphij } else if (db_y2k < a_y2k) { 2536296465Sdelphij rrow[DB_type][0] = 'E'; 2537296465Sdelphij rrow[DB_type][1] = '\0'; 2538296465Sdelphij cnt++; 2539109998Smarkm 2540296465Sdelphij BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]); 2541296465Sdelphij } 2542109998Smarkm 2543296465Sdelphij } 2544296465Sdelphij } 2545109998Smarkm 2546296465Sdelphij err: 2547109998Smarkm 2548296465Sdelphij ASN1_UTCTIME_free(a_tm); 2549296465Sdelphij OPENSSL_free(a_tm_s); 2550109998Smarkm 2551296465Sdelphij return (cnt); 2552296465Sdelphij} 2553296465Sdelphij 2554160814Ssimonstatic const char *crl_reasons[] = { 2555296465Sdelphij /* CRL reason strings */ 2556296465Sdelphij "unspecified", 2557296465Sdelphij "keyCompromise", 2558296465Sdelphij "CACompromise", 2559296465Sdelphij "affiliationChanged", 2560296465Sdelphij "superseded", 2561296465Sdelphij "cessationOfOperation", 2562296465Sdelphij "certificateHold", 2563296465Sdelphij "removeFromCRL", 2564296465Sdelphij /* Additional pseudo reasons */ 2565296465Sdelphij "holdInstruction", 2566296465Sdelphij "keyTime", 2567296465Sdelphij "CAkeyTime" 2568109998Smarkm}; 2569109998Smarkm 2570109998Smarkm#define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *)) 2571109998Smarkm 2572296465Sdelphij/* 2573296465Sdelphij * Given revocation information convert to a DB string. The format of the 2574296465Sdelphij * string is: revtime[,reason,extra]. Where 'revtime' is the revocation time 2575296465Sdelphij * (the current time). 'reason' is the optional CRL reason and 'extra' is any 2576296465Sdelphij * additional argument 2577109998Smarkm */ 2578109998Smarkm 2579109998Smarkmchar *make_revocation_str(int rev_type, char *rev_arg) 2580296465Sdelphij{ 2581296465Sdelphij char *other = NULL, *str; 2582296465Sdelphij const char *reason = NULL; 2583296465Sdelphij ASN1_OBJECT *otmp; 2584296465Sdelphij ASN1_UTCTIME *revtm = NULL; 2585296465Sdelphij int i; 2586296465Sdelphij switch (rev_type) { 2587296465Sdelphij case REV_NONE: 2588296465Sdelphij break; 2589109998Smarkm 2590296465Sdelphij case REV_CRL_REASON: 2591296465Sdelphij for (i = 0; i < 8; i++) { 2592296465Sdelphij if (!strcasecmp(rev_arg, crl_reasons[i])) { 2593296465Sdelphij reason = crl_reasons[i]; 2594296465Sdelphij break; 2595296465Sdelphij } 2596296465Sdelphij } 2597296465Sdelphij if (reason == NULL) { 2598296465Sdelphij BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg); 2599296465Sdelphij return NULL; 2600296465Sdelphij } 2601296465Sdelphij break; 2602109998Smarkm 2603296465Sdelphij case REV_HOLD: 2604296465Sdelphij /* Argument is an OID */ 2605109998Smarkm 2606296465Sdelphij otmp = OBJ_txt2obj(rev_arg, 0); 2607296465Sdelphij ASN1_OBJECT_free(otmp); 2608109998Smarkm 2609296465Sdelphij if (otmp == NULL) { 2610296465Sdelphij BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg); 2611296465Sdelphij return NULL; 2612296465Sdelphij } 2613109998Smarkm 2614296465Sdelphij reason = "holdInstruction"; 2615296465Sdelphij other = rev_arg; 2616296465Sdelphij break; 2617109998Smarkm 2618296465Sdelphij case REV_KEY_COMPROMISE: 2619296465Sdelphij case REV_CA_COMPROMISE: 2620109998Smarkm 2621296465Sdelphij /* Argument is the key compromise time */ 2622296465Sdelphij if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg)) { 2623296465Sdelphij BIO_printf(bio_err, 2624296465Sdelphij "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", 2625296465Sdelphij rev_arg); 2626296465Sdelphij return NULL; 2627296465Sdelphij } 2628296465Sdelphij other = rev_arg; 2629296465Sdelphij if (rev_type == REV_KEY_COMPROMISE) 2630296465Sdelphij reason = "keyTime"; 2631296465Sdelphij else 2632296465Sdelphij reason = "CAkeyTime"; 2633109998Smarkm 2634296465Sdelphij break; 2635109998Smarkm 2636296465Sdelphij } 2637109998Smarkm 2638296465Sdelphij revtm = X509_gmtime_adj(NULL, 0); 2639279265Sdelphij 2640296465Sdelphij if (!revtm) 2641296465Sdelphij return NULL; 2642109998Smarkm 2643296465Sdelphij i = revtm->length + 1; 2644109998Smarkm 2645296465Sdelphij if (reason) 2646296465Sdelphij i += strlen(reason) + 1; 2647296465Sdelphij if (other) 2648296465Sdelphij i += strlen(other) + 1; 2649109998Smarkm 2650296465Sdelphij str = OPENSSL_malloc(i); 2651109998Smarkm 2652296465Sdelphij if (!str) 2653296465Sdelphij return NULL; 2654109998Smarkm 2655296465Sdelphij BUF_strlcpy(str, (char *)revtm->data, i); 2656296465Sdelphij if (reason) { 2657296465Sdelphij BUF_strlcat(str, ",", i); 2658296465Sdelphij BUF_strlcat(str, reason, i); 2659296465Sdelphij } 2660296465Sdelphij if (other) { 2661296465Sdelphij BUF_strlcat(str, ",", i); 2662296465Sdelphij BUF_strlcat(str, other, i); 2663296465Sdelphij } 2664296465Sdelphij ASN1_UTCTIME_free(revtm); 2665296465Sdelphij return str; 2666296465Sdelphij} 2667296465Sdelphij 2668296465Sdelphij/*- 2669296465Sdelphij * Convert revocation field to X509_REVOKED entry 2670109998Smarkm * return code: 2671109998Smarkm * 0 error 2672109998Smarkm * 1 OK 2673109998Smarkm * 2 OK and some extensions added (i.e. V2 CRL) 2674109998Smarkm */ 2675109998Smarkm 2676160814Ssimonint make_revoked(X509_REVOKED *rev, const char *str) 2677296465Sdelphij{ 2678296465Sdelphij char *tmp = NULL; 2679296465Sdelphij int reason_code = -1; 2680296465Sdelphij int i, ret = 0; 2681296465Sdelphij ASN1_OBJECT *hold = NULL; 2682296465Sdelphij ASN1_GENERALIZEDTIME *comp_time = NULL; 2683296465Sdelphij ASN1_ENUMERATED *rtmp = NULL; 2684109998Smarkm 2685296465Sdelphij ASN1_TIME *revDate = NULL; 2686109998Smarkm 2687296465Sdelphij i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str); 2688109998Smarkm 2689296465Sdelphij if (i == 0) 2690296465Sdelphij goto err; 2691109998Smarkm 2692296465Sdelphij if (rev && !X509_REVOKED_set_revocationDate(rev, revDate)) 2693296465Sdelphij goto err; 2694109998Smarkm 2695296465Sdelphij if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)) { 2696296465Sdelphij rtmp = ASN1_ENUMERATED_new(); 2697296465Sdelphij if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code)) 2698296465Sdelphij goto err; 2699296465Sdelphij if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0)) 2700296465Sdelphij goto err; 2701296465Sdelphij } 2702109998Smarkm 2703296465Sdelphij if (rev && comp_time) { 2704296465Sdelphij if (!X509_REVOKED_add1_ext_i2d 2705296465Sdelphij (rev, NID_invalidity_date, comp_time, 0, 0)) 2706296465Sdelphij goto err; 2707296465Sdelphij } 2708296465Sdelphij if (rev && hold) { 2709296465Sdelphij if (!X509_REVOKED_add1_ext_i2d 2710296465Sdelphij (rev, NID_hold_instruction_code, hold, 0, 0)) 2711296465Sdelphij goto err; 2712296465Sdelphij } 2713109998Smarkm 2714296465Sdelphij if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS) 2715296465Sdelphij ret = 2; 2716296465Sdelphij else 2717296465Sdelphij ret = 1; 2718109998Smarkm 2719296465Sdelphij err: 2720109998Smarkm 2721296465Sdelphij if (tmp) 2722296465Sdelphij OPENSSL_free(tmp); 2723296465Sdelphij ASN1_OBJECT_free(hold); 2724296465Sdelphij ASN1_GENERALIZEDTIME_free(comp_time); 2725296465Sdelphij ASN1_ENUMERATED_free(rtmp); 2726296465Sdelphij ASN1_TIME_free(revDate); 2727109998Smarkm 2728296465Sdelphij return ret; 2729296465Sdelphij} 2730109998Smarkm 2731109998Smarkmint old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str) 2732296465Sdelphij{ 2733296465Sdelphij char buf[25], *pbuf, *p; 2734296465Sdelphij int j; 2735296465Sdelphij j = i2a_ASN1_OBJECT(bp, obj); 2736296465Sdelphij pbuf = buf; 2737296465Sdelphij for (j = 22 - j; j > 0; j--) 2738296465Sdelphij *(pbuf++) = ' '; 2739296465Sdelphij *(pbuf++) = ':'; 2740296465Sdelphij *(pbuf++) = '\0'; 2741296465Sdelphij BIO_puts(bp, buf); 2742109998Smarkm 2743296465Sdelphij if (str->type == V_ASN1_PRINTABLESTRING) 2744296465Sdelphij BIO_printf(bp, "PRINTABLE:'"); 2745296465Sdelphij else if (str->type == V_ASN1_T61STRING) 2746296465Sdelphij BIO_printf(bp, "T61STRING:'"); 2747296465Sdelphij else if (str->type == V_ASN1_IA5STRING) 2748296465Sdelphij BIO_printf(bp, "IA5STRING:'"); 2749296465Sdelphij else if (str->type == V_ASN1_UNIVERSALSTRING) 2750296465Sdelphij BIO_printf(bp, "UNIVERSALSTRING:'"); 2751296465Sdelphij else 2752296465Sdelphij BIO_printf(bp, "ASN.1 %2d:'", str->type); 2753296465Sdelphij 2754296465Sdelphij p = (char *)str->data; 2755296465Sdelphij for (j = str->length; j > 0; j--) { 2756194206Ssimon#ifdef CHARSET_EBCDIC 2757296465Sdelphij if ((*p >= 0x20) && (*p <= 0x7e)) 2758296465Sdelphij BIO_printf(bp, "%c", os_toebcdic[*p]); 2759194206Ssimon#else 2760296465Sdelphij if ((*p >= ' ') && (*p <= '~')) 2761296465Sdelphij BIO_printf(bp, "%c", *p); 2762194206Ssimon#endif 2763296465Sdelphij else if (*p & 0x80) 2764296465Sdelphij BIO_printf(bp, "\\0x%02X", *p); 2765296465Sdelphij else if ((unsigned char)*p == 0xf7) 2766296465Sdelphij BIO_printf(bp, "^?"); 2767194206Ssimon#ifdef CHARSET_EBCDIC 2768296465Sdelphij else 2769296465Sdelphij BIO_printf(bp, "^%c", os_toebcdic[*p + 0x40]); 2770194206Ssimon#else 2771296465Sdelphij else 2772296465Sdelphij BIO_printf(bp, "^%c", *p + '@'); 2773194206Ssimon#endif 2774296465Sdelphij p++; 2775296465Sdelphij } 2776296465Sdelphij BIO_printf(bp, "'\n"); 2777296465Sdelphij return 1; 2778296465Sdelphij} 2779109998Smarkm 2780296465Sdelphijint unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, 2781296465Sdelphij ASN1_GENERALIZEDTIME **pinvtm, const char *str) 2782296465Sdelphij{ 2783296465Sdelphij char *tmp = NULL; 2784296465Sdelphij char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p; 2785296465Sdelphij int reason_code = -1; 2786296465Sdelphij int ret = 0; 2787296465Sdelphij unsigned int i; 2788296465Sdelphij ASN1_OBJECT *hold = NULL; 2789296465Sdelphij ASN1_GENERALIZEDTIME *comp_time = NULL; 2790296465Sdelphij tmp = BUF_strdup(str); 2791109998Smarkm 2792296465Sdelphij p = strchr(tmp, ','); 2793109998Smarkm 2794296465Sdelphij rtime_str = tmp; 2795109998Smarkm 2796296465Sdelphij if (p) { 2797296465Sdelphij *p = '\0'; 2798296465Sdelphij p++; 2799296465Sdelphij reason_str = p; 2800296465Sdelphij p = strchr(p, ','); 2801296465Sdelphij if (p) { 2802296465Sdelphij *p = '\0'; 2803296465Sdelphij arg_str = p + 1; 2804296465Sdelphij } 2805296465Sdelphij } 2806109998Smarkm 2807296465Sdelphij if (prevtm) { 2808296465Sdelphij *prevtm = ASN1_UTCTIME_new(); 2809296465Sdelphij if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str)) { 2810296465Sdelphij BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str); 2811296465Sdelphij goto err; 2812296465Sdelphij } 2813296465Sdelphij } 2814296465Sdelphij if (reason_str) { 2815296465Sdelphij for (i = 0; i < NUM_REASONS; i++) { 2816296465Sdelphij if (!strcasecmp(reason_str, crl_reasons[i])) { 2817296465Sdelphij reason_code = i; 2818296465Sdelphij break; 2819296465Sdelphij } 2820296465Sdelphij } 2821296465Sdelphij if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS) { 2822296465Sdelphij BIO_printf(bio_err, "invalid reason code %s\n", reason_str); 2823296465Sdelphij goto err; 2824296465Sdelphij } 2825109998Smarkm 2826296465Sdelphij if (reason_code == 7) 2827296465Sdelphij reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL; 2828296465Sdelphij else if (reason_code == 8) { /* Hold instruction */ 2829296465Sdelphij if (!arg_str) { 2830296465Sdelphij BIO_printf(bio_err, "missing hold instruction\n"); 2831296465Sdelphij goto err; 2832296465Sdelphij } 2833296465Sdelphij reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD; 2834296465Sdelphij hold = OBJ_txt2obj(arg_str, 0); 2835109998Smarkm 2836296465Sdelphij if (!hold) { 2837296465Sdelphij BIO_printf(bio_err, "invalid object identifier %s\n", 2838296465Sdelphij arg_str); 2839296465Sdelphij goto err; 2840296465Sdelphij } 2841296465Sdelphij if (phold) 2842296465Sdelphij *phold = hold; 2843296465Sdelphij } else if ((reason_code == 9) || (reason_code == 10)) { 2844296465Sdelphij if (!arg_str) { 2845296465Sdelphij BIO_printf(bio_err, "missing compromised time\n"); 2846296465Sdelphij goto err; 2847296465Sdelphij } 2848296465Sdelphij comp_time = ASN1_GENERALIZEDTIME_new(); 2849296465Sdelphij if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str)) { 2850296465Sdelphij BIO_printf(bio_err, "invalid compromised time %s\n", arg_str); 2851296465Sdelphij goto err; 2852296465Sdelphij } 2853296465Sdelphij if (reason_code == 9) 2854296465Sdelphij reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE; 2855296465Sdelphij else 2856296465Sdelphij reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE; 2857296465Sdelphij } 2858296465Sdelphij } 2859109998Smarkm 2860296465Sdelphij if (preason) 2861296465Sdelphij *preason = reason_code; 2862296465Sdelphij if (pinvtm) 2863296465Sdelphij *pinvtm = comp_time; 2864296465Sdelphij else 2865296465Sdelphij ASN1_GENERALIZEDTIME_free(comp_time); 2866109998Smarkm 2867296465Sdelphij ret = 1; 2868109998Smarkm 2869296465Sdelphij err: 2870109998Smarkm 2871296465Sdelphij if (tmp) 2872296465Sdelphij OPENSSL_free(tmp); 2873296465Sdelphij if (!phold) 2874296465Sdelphij ASN1_OBJECT_free(hold); 2875296465Sdelphij if (!pinvtm) 2876296465Sdelphij ASN1_GENERALIZEDTIME_free(comp_time); 2877109998Smarkm 2878296465Sdelphij return ret; 2879296465Sdelphij} 2880