11558Srgrimes/* apps/ca.c */ 21558Srgrimes/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 31558Srgrimes * All rights reserved. 41558Srgrimes * 51558Srgrimes * This package is an SSL implementation written 61558Srgrimes * by Eric Young (eay@cryptsoft.com). 71558Srgrimes * The implementation was written so as to conform with Netscapes SSL. 81558Srgrimes * 91558Srgrimes * This library is free for commercial and non-commercial use as long as 101558Srgrimes * the following conditions are aheared to. The following conditions 111558Srgrimes * apply to all code found in this distribution, be it the RC4, RSA, 121558Srgrimes * lhash, DES, etc., code; not just the SSL code. The SSL documentation 131558Srgrimes * included with this distribution is covered by the same copyright terms 141558Srgrimes * except that the holder is Tim Hudson (tjh@cryptsoft.com). 151558Srgrimes * 161558Srgrimes * Copyright remains Eric Young's, and as such any Copyright notices in 171558Srgrimes * the code are not to be removed. 181558Srgrimes * If this package is used in a product, Eric Young should be given attribution 191558Srgrimes * as the author of the parts of the library used. 201558Srgrimes * This can be in the form of a textual message at program startup or 211558Srgrimes * in documentation (online or textual) provided with the package. 221558Srgrimes * 231558Srgrimes * Redistribution and use in source and binary forms, with or without 241558Srgrimes * modification, are permitted provided that the following conditions 251558Srgrimes * are met: 261558Srgrimes * 1. Redistributions of source code must retain the copyright 271558Srgrimes * notice, this list of conditions and the following disclaimer. 281558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 291558Srgrimes * notice, this list of conditions and the following disclaimer in the 301558Srgrimes * documentation and/or other materials provided with the distribution. 311558Srgrimes * 3. All advertising materials mentioning features or use of this software 321558Srgrimes * must display the following acknowledgement: 331558Srgrimes * "This product includes cryptographic software written by 3437663Scharnier * Eric Young (eay@cryptsoft.com)" 351558Srgrimes * The word 'cryptographic' can be left out if the rouines from the library 361558Srgrimes * being used are not cryptographic related :-). 372999Swollman * 4. If you include any Windows specific code (or a derivative thereof) from 381558Srgrimes * the apps directory (application code) you must include an acknowledgement: 39105267Scharnier * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 401558Srgrimes * 4137663Scharnier * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42105267Scharnier * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4337663Scharnier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 441558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45105267Scharnier * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46105267Scharnier * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47105267Scharnier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 481558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 491558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5074462Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 511558Srgrimes * SUCH DAMAGE. 521558Srgrimes * 5324330Sguido * The licence and distribution terms for any publically available version or 5496622Siedowse * derivative of this code cannot be changed. i.e. this code cannot simply be 5596622Siedowse * copied and put under another distribution licence 561558Srgrimes * [including the GNU Public Licence.] 571558Srgrimes */ 58109363Smbr 591558Srgrimes/* The PPKI stuff has been donated by Jeff Barber <jeffb@issl.atl.hp.com> */ 6074462Salfred 6174462Salfred#include <stdio.h> 621558Srgrimes#include <stdlib.h> 639336Sdfr#include <string.h> 6483653Speter#include <ctype.h> 6523681Speter#include <sys/types.h> 6677162Sru#include <openssl/conf.h> 6777223Sru#include <openssl/bio.h> 6823681Speter#include <openssl/err.h> 691558Srgrimes#include <openssl/bn.h> 701558Srgrimes#include <openssl/txt_db.h> 711558Srgrimes#include <openssl/evp.h> 721558Srgrimes#include <openssl/x509.h> 7337663Scharnier#include <openssl/x509v3.h> 741558Srgrimes#include <openssl/objects.h> 751558Srgrimes#include <openssl/ocsp.h> 76103949Smike#include <openssl/pem.h> 771558Srgrimes 781558Srgrimes#ifndef W_OK 791558Srgrimes# ifdef OPENSSL_SYS_VMS 801558Srgrimes# if defined(__DECC) 811558Srgrimes# include <unistd.h> 821558Srgrimes# else 831558Srgrimes# include <unixlib.h> 841558Srgrimes# endif 851558Srgrimes# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_NETWARE) 861558Srgrimes# include <sys/file.h> 871558Srgrimes# endif 881558Srgrimes#endif 891558Srgrimes 9074462Salfred#include "apps.h" 9174462Salfred 9274462Salfred#ifndef W_OK 9374462Salfred# define F_OK 0 941558Srgrimes# define X_OK 1 951558Srgrimes# define W_OK 2 961558Srgrimes# define R_OK 4 971558Srgrimes#endif 981558Srgrimes 991558Srgrimes#undef PROG 1001558Srgrimes#define PROG ca_main 1011558Srgrimes 1021558Srgrimes#define BASE_SECTION "ca" 1031558Srgrimes#define CONFIG_FILE "openssl.cnf" 1041558Srgrimes 1051558Srgrimes#define ENV_DEFAULT_CA "default_ca" 1061558Srgrimes 1071558Srgrimes#define STRING_MASK "string_mask" 1081558Srgrimes#define UTF8_IN "utf8" 1091558Srgrimes 1101558Srgrimes#define ENV_NEW_CERTS_DIR "new_certs_dir" 1111558Srgrimes#define ENV_CERTIFICATE "certificate" 1129336Sdfr#define ENV_SERIAL "serial" 1131558Srgrimes#define ENV_CRLNUMBER "crlnumber" 1141558Srgrimes#define ENV_PRIVATE_KEY "private_key" 1151558Srgrimes#define ENV_DEFAULT_DAYS "default_days" 1161558Srgrimes#define ENV_DEFAULT_STARTDATE "default_startdate" 1171558Srgrimes#define ENV_DEFAULT_ENDDATE "default_enddate" 1181558Srgrimes#define ENV_DEFAULT_CRL_DAYS "default_crl_days" 1191558Srgrimes#define ENV_DEFAULT_CRL_HOURS "default_crl_hours" 1201558Srgrimes#define ENV_DEFAULT_MD "default_md" 12127447Sdfr#define ENV_DEFAULT_EMAIL_DN "email_in_dn" 1221558Srgrimes#define ENV_PRESERVE "preserve" 1231558Srgrimes#define ENV_POLICY "policy" 1241558Srgrimes#define ENV_EXTENSIONS "x509_extensions" 1251558Srgrimes#define ENV_CRLEXT "crl_extensions" 1261558Srgrimes#define ENV_MSIE_HACK "msie_hack" 12774462Salfred#define ENV_NAMEOPT "name_opt" 12875801Siedowse#define ENV_CERTOPT "cert_opt" 12942144Sdfr#define ENV_EXTCOPY "copy_extensions" 1301558Srgrimes#define ENV_UNIQUE_SUBJECT "unique_subject" 1311558Srgrimes 1321558Srgrimes#define ENV_DATABASE "database" 13374462Salfred 1341558Srgrimes/* Additional revocation information types */ 1351558Srgrimes 1361558Srgrimes#define REV_NONE 0 /* No addditional information */ 1371558Srgrimes#define REV_CRL_REASON 1 /* Value is CRL reason code */ 1381558Srgrimes#define REV_HOLD 2 /* Value is hold instruction */ 1391558Srgrimes#define REV_KEY_COMPROMISE 3 /* Value is cert key compromise time */ 1401558Srgrimes#define REV_CA_COMPROMISE 4 /* Value is CA key compromise time */ 1411558Srgrimes 1421558Srgrimesstatic const char *ca_usage[] = { 1431558Srgrimes "usage: ca args\n", 1441558Srgrimes "\n", 1451558Srgrimes " -verbose - Talk alot while doing things\n", 14675641Siedowse " -config file - A config file\n", 1477401Swpaul " -name arg - The particular CA definition to use\n", 1481558Srgrimes " -gencrl - Generate a new CRL\n", 1491558Srgrimes " -crldays days - Days is when the next CRL is due\n", 1509336Sdfr " -crlhours hours - Hours is when the next CRL is due\n", 1511558Srgrimes " -startdate YYMMDDHHMMSSZ - certificate validity notBefore\n", 1521558Srgrimes " -enddate YYMMDDHHMMSSZ - certificate validity notAfter (overrides -days)\n", 1531558Srgrimes " -days arg - number of days to certify the certificate for\n", 1541558Srgrimes " -md arg - md to use, one of md2, md5, sha or sha1\n", 1559336Sdfr " -policy arg - The CA 'policy' to support\n", 1569336Sdfr " -keyfile arg - private key file\n", 1579336Sdfr " -keyform arg - private key file format (PEM or ENGINE)\n", 1589336Sdfr " -key arg - key to decode the private key if it is encrypted\n", 1599336Sdfr " -cert file - The CA certificate\n", 1609336Sdfr " -selfsign - sign a certificate with the key associated with it\n", 1611558Srgrimes " -in file - The input PEM encoded certificate request(s)\n", 16292882Simp " -out file - Where to put the output file(s)\n", 16392882Simp " -outdir dir - Where to put output certificates\n", 16492882Simp " -infiles .... - The last argument, requests to process\n", 16592882Simp " -spkac file - File contains DN and signed public key and challenge\n", 16692882Simp " -ss_cert file - File contains a self signed cert to sign\n", 16792882Simp " -preserveDN - Don't re-order the DN\n", 16875801Siedowse " -noemailDN - Don't add the EMAIL field into certificate' subject\n", 16992882Simp " -batch - Don't ask questions\n", 17075635Siedowse " -msie_hack - msie modifications to handle all those universal strings\n", 17192882Simp " -revoke file - Revoke a certificate (given in file)\n", 17292882Simp " -subj arg - Use arg instead of request's subject\n", 17392882Simp " -utf8 - input characters are UTF8 (default ASCII)\n", 17492882Simp " -multivalue-rdn - enable support for multivalued RDNs\n", 17592882Simp " -extensions .. - Extension section (override value in config file)\n", 17692882Simp " -extfile file - Configuration file with X509v3 extentions to add\n", 17792882Simp " -crlexts .. - CRL extension section (override value in config file)\n", 17892882Simp#ifndef OPENSSL_NO_ENGINE 17992882Simp " -engine e - use engine e, possibly a hardware device.\n", 18092882Simp#endif 18192882Simp " -status serial - Shows certificate status given the serial number\n", 18292882Simp " -updatedb - Updates db for expired certificates\n", 18392882Simp NULL 18492882Simp}; 18592882Simp 18692882Simp#ifdef EFENCE 18792882Simpextern int EF_PROTECT_FREE; 18892882Simpextern int EF_PROTECT_BELOW; 18992882Simpextern int EF_ALIGNMENT; 19092882Simp#endif 19192882Simp 19275754Siedowsestatic void lookup_fail(const char *name, const char *tag); 19375801Siedowsestatic int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 19492882Simp const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, 19592882Simp STACK_OF(CONF_VALUE) *policy, CA_DB *db, 19692882Simp BIGNUM *serial, char *subj, unsigned long chtype, 19792882Simp int multirdn, int email_dn, char *startdate, char *enddate, 198100117Salfred long days, int batch, char *ext_sect, CONF *conf, 19975801Siedowse int verbose, unsigned long certopt, unsigned long nameopt, 20075801Siedowse int default_op, int ext_copy, int selfsign); 20175801Siedowsestatic int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 20292882Simp const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, 20392882Simp STACK_OF(CONF_VALUE) *policy, CA_DB *db, 20492882Simp BIGNUM *serial, char *subj, unsigned long chtype, 20592882Simp int multirdn, int email_dn, char *startdate, 206100117Salfred char *enddate, long days, int batch, char *ext_sect, 20792882Simp CONF *conf, int verbose, unsigned long certopt, 20892882Simp unsigned long nameopt, int default_op, int ext_copy, 20992882Simp ENGINE *e); 2101558Srgrimesstatic int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, 2111558Srgrimes X509 *x509, const EVP_MD *dgst, 2121558Srgrimes STACK_OF(OPENSSL_STRING) *sigopts, 2131558Srgrimes STACK_OF(CONF_VALUE) *policy, CA_DB *db, 2141558Srgrimes BIGNUM *serial, char *subj, unsigned long chtype, 21572650Sgreen int multirdn, int email_dn, char *startdate, 21691354Sdd char *enddate, long days, char *ext_sect, CONF *conf, 21772650Sgreen int verbose, unsigned long certopt, 2181558Srgrimes unsigned long nameopt, int default_op, int ext_copy); 21972650Sgreenstatic void write_new_certificate(BIO *bp, X509 *x, int output_der, 22072650Sgreen int notext); 2211558Srgrimesstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, 22225087Sdfr const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, 2239336Sdfr STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, 2249336Sdfr char *subj, unsigned long chtype, int multirdn, 225121767Speter int email_dn, char *startdate, char *enddate, long days, 22675754Siedowse int batch, int verbose, X509_REQ *req, char *ext_sect, 22774462Salfred CONF *conf, unsigned long certopt, unsigned long nameopt, 2281558Srgrimes int default_op, int ext_copy, int selfsign); 22974462Salfredstatic int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval); 23074462Salfredstatic int get_certificate_status(const char *ser_status, CA_DB *db); 23174462Salfredstatic int do_updatedb(CA_DB *db); 23275801Siedowsestatic int check_time_format(const char *str); 2331558Srgrimeschar *make_revocation_str(int rev_type, char *rev_arg); 2341558Srgrimesint make_revoked(X509_REVOKED *rev, const char *str); 23583653Speterint old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str); 2361558Srgrimesstatic CONF *conf = NULL; 2371558Srgrimesstatic CONF *extconf = NULL; 2381558Srgrimesstatic char *section = NULL; 23975801Siedowse 240100336Sjoergstatic int preserve = 0; 24174462Salfredstatic int msie_hack = 0; 2421558Srgrimes 2431558Srgrimesint MAIN(int, char **); 2441558Srgrimes 24592882Simpint MAIN(int argc, char **argv) 2461558Srgrimes{ 2471558Srgrimes ENGINE *e = NULL; 2481558Srgrimes char *key = NULL, *passargin = NULL; 2491558Srgrimes int create_ser = 0; 2501558Srgrimes int free_key = 0; 2511558Srgrimes int total = 0; 2521558Srgrimes int total_done = 0; 2531558Srgrimes int badops = 0; 2541558Srgrimes int ret = 1; 2551558Srgrimes int email_dn = 1; 2561558Srgrimes int req = 0; 2571558Srgrimes int verbose = 0; 2581558Srgrimes int gencrl = 0; 2591558Srgrimes int dorevoke = 0; 2601558Srgrimes int doupdatedb = 0; 2611558Srgrimes long crldays = 0; 2621558Srgrimes long crlhours = 0; 26375754Siedowse long crlsec = 0; 264126572Sbms long errorline = -1; 265126572Sbms char *configfile = NULL; 266126572Sbms char *md = NULL; 26774462Salfred char *policy = NULL; 26874462Salfred char *keyfile = NULL; 26974462Salfred char *certfile = NULL; 27074462Salfred int keyform = FORMAT_PEM; 271109363Smbr char *infile = NULL; 27274462Salfred char *spkac_file = NULL; 273126572Sbms char *ss_cert_file = NULL; 274126572Sbms char *ser_status = NULL; 2751558Srgrimes EVP_PKEY *pkey = NULL; 27675635Siedowse int output_der = 0; 277126643Smarkm char *outfile = NULL; 27875635Siedowse char *outdir = NULL; 27974462Salfred char *serialfile = NULL; 28074462Salfred char *crlnumberfile = NULL; 28174462Salfred char *extensions = NULL; 28274462Salfred char *extfile = NULL; 28374462Salfred char *subj = NULL; 284105267Scharnier unsigned long chtype = MBSTRING_ASC; 28574462Salfred int multirdn = 0; 28674462Salfred char *tmp_email_dn = NULL; 28774462Salfred char *crl_ext = NULL; 28874462Salfred int rev_type = REV_NONE; 28974462Salfred char *rev_arg = NULL; 29083687Speter BIGNUM *serial = NULL; 29183687Speter BIGNUM *crlnumber = NULL; 29283687Speter char *startdate = NULL; 29383687Speter char *enddate = NULL; 2942999Swollman long days = 0; 2952999Swollman int batch = 0; 296126572Sbms int notext = 0; 2971558Srgrimes unsigned long nameopt = 0, certopt = 0; 29825087Sdfr int default_op = 1; 29925087Sdfr int ext_copy = EXT_COPY_NONE; 30025087Sdfr int selfsign = 0; 3019336Sdfr X509 *x509 = NULL, *x509p = NULL; 3029336Sdfr X509 *x = NULL; 3039336Sdfr BIO *in = NULL, *out = NULL, *Sout = NULL, *Cout = NULL; 3049336Sdfr char *dbfile = NULL; 3059336Sdfr CA_DB *db = NULL; 3069336Sdfr X509_CRL *crl = NULL; 3078688Sphk X509_REVOKED *r = NULL; 3088688Sphk ASN1_TIME *tmptm; 3098688Sphk ASN1_INTEGER *tmpser; 31031656Sguido char *f; 311121767Speter const char *p; 31231656Sguido char *const *pp; 313126572Sbms int i, j; 314126572Sbms const EVP_MD *dgst = NULL; 315126572Sbms STACK_OF(CONF_VALUE) *attribs = NULL; 316126572Sbms STACK_OF(X509) *cert_sk = NULL; 317126572Sbms STACK_OF(OPENSSL_STRING) *sigopts = NULL; 318126572Sbms#undef BSIZE 319126572Sbms#define BSIZE 256 3201558Srgrimes MS_STATIC char buf[3][BSIZE]; 32137663Scharnier char *randfile = NULL; 3221558Srgrimes#ifndef OPENSSL_NO_ENGINE 3231558Srgrimes char *engine = NULL; 3241558Srgrimes#endif 3251558Srgrimes char *tofree = NULL; 3261558Srgrimes DB_ATTR db_attr; 3271558Srgrimes 3281558Srgrimes#ifdef EFENCE 3291558Srgrimes EF_PROTECT_FREE = 1; 3301558Srgrimes EF_PROTECT_BELOW = 1; 3311558Srgrimes EF_ALIGNMENT = 0; 3321558Srgrimes#endif 3331558Srgrimes 3341558Srgrimes apps_startup(); 33537663Scharnier 3361558Srgrimes conf = NULL; 3371558Srgrimes key = NULL; 33837663Scharnier section = NULL; 3391558Srgrimes 3401558Srgrimes preserve = 0; 34137663Scharnier msie_hack = 0; 3421558Srgrimes if (bio_err == NULL) 3431558Srgrimes if ((bio_err = BIO_new(BIO_s_file())) != NULL) 3441558Srgrimes BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); 3451558Srgrimes 3461558Srgrimes argc--; 34775754Siedowse argv++; 34874462Salfred while (argc >= 1) { 3491558Srgrimes if (strcmp(*argv, "-verbose") == 0) 3501558Srgrimes verbose = 1; 3511558Srgrimes else if (strcmp(*argv, "-config") == 0) { 3521558Srgrimes if (--argc < 1) 3531558Srgrimes goto bad; 3541558Srgrimes configfile = *(++argv); 35574462Salfred } else if (strcmp(*argv, "-name") == 0) { 35674462Salfred if (--argc < 1) 35774462Salfred goto bad; 35874462Salfred section = *(++argv); 35974791Salfred } else if (strcmp(*argv, "-subj") == 0) { 36074791Salfred if (--argc < 1) 361109363Smbr goto bad; 362109363Smbr subj = *(++argv); 363109363Smbr /* preserve=1; */ 36474791Salfred } else if (strcmp(*argv, "-utf8") == 0) 36574791Salfred chtype = MBSTRING_UTF8; 36674462Salfred else if (strcmp(*argv, "-create_serial") == 0) 36774462Salfred create_ser = 1; 36874462Salfred else if (strcmp(*argv, "-multivalue-rdn") == 0) 36974462Salfred multirdn = 1; 37074462Salfred else if (strcmp(*argv, "-startdate") == 0) { 37174462Salfred if (--argc < 1) 37274462Salfred goto bad; 37374462Salfred startdate = *(++argv); 374117684Srwatson } else if (strcmp(*argv, "-enddate") == 0) { 37574462Salfred if (--argc < 1) 37674462Salfred goto bad; 37774462Salfred enddate = *(++argv); 37874462Salfred } else if (strcmp(*argv, "-days") == 0) { 379117684Srwatson if (--argc < 1) 380117684Srwatson goto bad; 38174462Salfred days = atoi(*(++argv)); 38274462Salfred } else if (strcmp(*argv, "-md") == 0) { 38374462Salfred if (--argc < 1) 38474462Salfred goto bad; 38574791Salfred md = *(++argv); 38674791Salfred } else if (strcmp(*argv, "-policy") == 0) { 38724759Sguido if (--argc < 1) 38883687Speter goto bad; 38983687Speter policy = *(++argv); 39083687Speter } else if (strcmp(*argv, "-keyfile") == 0) { 39124759Sguido if (--argc < 1) 39224759Sguido goto bad; 39324759Sguido keyfile = *(++argv); 39424330Sguido } else if (strcmp(*argv, "-keyform") == 0) { 395126572Sbms if (--argc < 1) 396126572Sbms goto bad; 397126572Sbms keyform = str2fmt(*(++argv)); 398126572Sbms } else if (strcmp(*argv, "-passin") == 0) { 399126572Sbms if (--argc < 1) 400126572Sbms goto bad; 401126572Sbms passargin = *(++argv); 402126572Sbms } else if (strcmp(*argv, "-key") == 0) { 403126572Sbms if (--argc < 1) 404126572Sbms goto bad; 405126572Sbms key = *(++argv); 40674462Salfred } else if (strcmp(*argv, "-cert") == 0) { 407126572Sbms if (--argc < 1) 408126572Sbms goto bad; 409126572Sbms certfile = *(++argv); 410126572Sbms } else if (strcmp(*argv, "-selfsign") == 0) 411126572Sbms selfsign = 1; 412126572Sbms else if (strcmp(*argv, "-in") == 0) { 413126572Sbms if (--argc < 1) 414126572Sbms goto bad; 41574462Salfred infile = *(++argv); 41674462Salfred req = 1; 41774462Salfred } else if (strcmp(*argv, "-out") == 0) { 41874462Salfred if (--argc < 1) 41974462Salfred goto bad; 42074462Salfred outfile = *(++argv); 42174462Salfred } else if (strcmp(*argv, "-outdir") == 0) { 42274462Salfred if (--argc < 1) 42374462Salfred goto bad; 42474462Salfred outdir = *(++argv); 42574462Salfred } else if (strcmp(*argv, "-sigopt") == 0) { 42674462Salfred if (--argc < 1) 42774462Salfred goto bad; 42874462Salfred if (!sigopts) 42974462Salfred sigopts = sk_OPENSSL_STRING_new_null(); 43074462Salfred if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv))) 43174462Salfred goto bad; 43274462Salfred } else if (strcmp(*argv, "-notext") == 0) 43374462Salfred notext = 1; 434126572Sbms else if (strcmp(*argv, "-batch") == 0) 435126572Sbms batch = 1; 436126572Sbms else if (strcmp(*argv, "-preserveDN") == 0) 437126572Sbms preserve = 1; 438126572Sbms else if (strcmp(*argv, "-noemailDN") == 0) 439126572Sbms email_dn = 0; 440126572Sbms else if (strcmp(*argv, "-gencrl") == 0) 441126572Sbms gencrl = 1; 44274462Salfred else if (strcmp(*argv, "-msie_hack") == 0) 443109363Smbr msie_hack = 1; 44474462Salfred else if (strcmp(*argv, "-crldays") == 0) { 44574462Salfred if (--argc < 1) 44674462Salfred goto bad; 44774462Salfred crldays = atol(*(++argv)); 44874462Salfred } else if (strcmp(*argv, "-crlhours") == 0) { 44974462Salfred if (--argc < 1) 45074462Salfred goto bad; 45174462Salfred crlhours = atol(*(++argv)); 45274462Salfred } else if (strcmp(*argv, "-crlsec") == 0) { 45374462Salfred if (--argc < 1) 45474462Salfred goto bad; 45574462Salfred crlsec = atol(*(++argv)); 45674462Salfred } else if (strcmp(*argv, "-infiles") == 0) { 45774462Salfred argc--; 45874462Salfred argv++; 45974462Salfred req = 1; 46074462Salfred break; 46174791Salfred } else if (strcmp(*argv, "-ss_cert") == 0) { 462126572Sbms if (--argc < 1) 463126572Sbms goto bad; 464126572Sbms ss_cert_file = *(++argv); 465126572Sbms req = 1; 466126572Sbms } else if (strcmp(*argv, "-spkac") == 0) { 467126572Sbms if (--argc < 1) 468126572Sbms goto bad; 469126572Sbms spkac_file = *(++argv); 470126572Sbms req = 1; 47174462Salfred } else if (strcmp(*argv, "-revoke") == 0) { 47274462Salfred if (--argc < 1) 47374462Salfred goto bad; 47474462Salfred infile = *(++argv); 47574462Salfred dorevoke = 1; 47674462Salfred } else if (strcmp(*argv, "-extensions") == 0) { 47774462Salfred if (--argc < 1) 47874462Salfred goto bad; 47974462Salfred extensions = *(++argv); 48074462Salfred } else if (strcmp(*argv, "-extfile") == 0) { 48174462Salfred if (--argc < 1) 48274462Salfred goto bad; 48374462Salfred extfile = *(++argv); 48474462Salfred } else if (strcmp(*argv, "-status") == 0) { 48574462Salfred if (--argc < 1) 48674462Salfred goto bad; 48774462Salfred ser_status = *(++argv); 48874462Salfred } else if (strcmp(*argv, "-updatedb") == 0) { 48974791Salfred doupdatedb = 1; 490126572Sbms } else if (strcmp(*argv, "-crlexts") == 0) { 491126572Sbms if (--argc < 1) 492126572Sbms goto bad; 493126572Sbms crl_ext = *(++argv); 494126572Sbms } else if (strcmp(*argv, "-crl_reason") == 0) { 495126572Sbms if (--argc < 1) 496126572Sbms goto bad; 497126572Sbms rev_arg = *(++argv); 498126572Sbms rev_type = REV_CRL_REASON; 49974462Salfred } else if (strcmp(*argv, "-crl_hold") == 0) { 500109363Smbr if (--argc < 1) 50174462Salfred goto bad; 50274462Salfred rev_arg = *(++argv); 50374462Salfred rev_type = REV_HOLD; 50474462Salfred } else if (strcmp(*argv, "-crl_compromise") == 0) { 50574462Salfred if (--argc < 1) 50674462Salfred goto bad; 50774462Salfred rev_arg = *(++argv); 50874462Salfred rev_type = REV_KEY_COMPROMISE; 50974462Salfred } else if (strcmp(*argv, "-crl_CA_compromise") == 0) { 51074462Salfred if (--argc < 1) 51174462Salfred goto bad; 51274462Salfred rev_arg = *(++argv); 51374462Salfred rev_type = REV_CA_COMPROMISE; 51474462Salfred } 51574462Salfred#ifndef OPENSSL_NO_ENGINE 51674462Salfred else if (strcmp(*argv, "-engine") == 0) { 51774462Salfred if (--argc < 1) 51874462Salfred goto bad; 51974462Salfred engine = *(++argv); 5201558Srgrimes } 5211558Srgrimes#endif 52275754Siedowse else { 52375754Siedowse bad: 52475754Siedowse BIO_printf(bio_err, "unknown option %s\n", *argv); 52575754Siedowse badops = 1; 52675754Siedowse break; 52775754Siedowse } 52875754Siedowse argc--; 52975754Siedowse argv++; 53075754Siedowse } 53175754Siedowse 53275754Siedowse if (badops) { 53375754Siedowse const char **pp2; 53475754Siedowse 53575754Siedowse for (pp2 = ca_usage; (*pp2 != NULL); pp2++) 53675754Siedowse BIO_printf(bio_err, "%s", *pp2); 53775754Siedowse goto err; 53875754Siedowse } 53975754Siedowse 54075754Siedowse ERR_load_crypto_strings(); 54175754Siedowse 5421558Srgrimes /*****************************************************************/ 5431558Srgrimes tofree = NULL; 54437663Scharnier if (configfile == NULL) 54537663Scharnier configfile = getenv("OPENSSL_CONF"); 54637663Scharnier if (configfile == NULL) 54737663Scharnier configfile = getenv("SSLEAY_CONF"); 548126572Sbms if (configfile == NULL) { 549126572Sbms const char *s = X509_get_default_cert_area(); 55037663Scharnier size_t len; 55137663Scharnier 55237663Scharnier#ifdef OPENSSL_SYS_VMS 5531558Srgrimes len = strlen(s) + sizeof(CONFIG_FILE); 5541558Srgrimes tofree = OPENSSL_malloc(len); 5551558Srgrimes if (!tofree) { 5561558Srgrimes BIO_printf(bio_err, "Out of memory\n"); 5571558Srgrimes goto err; 5581558Srgrimes } 5591558Srgrimes strcpy(tofree, s); 5601558Srgrimes#else 5611558Srgrimes len = strlen(s) + sizeof(CONFIG_FILE) + 1; 5621558Srgrimes tofree = OPENSSL_malloc(len); 5639336Sdfr if (!tofree) { 5641558Srgrimes BIO_printf(bio_err, "Out of memory\n"); 5651558Srgrimes goto err; 56674462Salfred } 56774462Salfred BUF_strlcpy(tofree, s, len); 56874462Salfred BUF_strlcat(tofree, "/", len); 5699336Sdfr#endif 57023681Speter BUF_strlcat(tofree, CONFIG_FILE, len); 57128911Sguido configfile = tofree; 5729336Sdfr } 5731558Srgrimes 5749336Sdfr BIO_printf(bio_err, "Using configuration from %s\n", configfile); 5759336Sdfr conf = NCONF_new(NULL); 57674462Salfred if (NCONF_load(conf, configfile, &errorline) <= 0) { 57774462Salfred if (errorline <= 0) 57874462Salfred BIO_printf(bio_err, "error loading the config file '%s'\n", 57975635Siedowse configfile); 58074462Salfred else 58174462Salfred BIO_printf(bio_err, "error on line %ld of config file '%s'\n", 58275635Siedowse errorline, configfile); 58374462Salfred goto err; 58474462Salfred } 58574462Salfred if (tofree) { 58674462Salfred OPENSSL_free(tofree); 58774462Salfred tofree = NULL; 58874462Salfred } 58974462Salfred 59074462Salfred if (!load_config(bio_err, conf)) 59174462Salfred goto err; 5921558Srgrimes 5931558Srgrimes#ifndef OPENSSL_NO_ENGINE 594121556Speter e = setup_engine(bio_err, engine, 0); 59537663Scharnier#endif 5961558Srgrimes 5971558Srgrimes /* Lets get the config section we are using */ 5989336Sdfr if (section == NULL) { 59931656Sguido section = NCONF_get_string(conf, BASE_SECTION, ENV_DEFAULT_CA); 60031656Sguido if (section == NULL) { 60174462Salfred lookup_fail(BASE_SECTION, ENV_DEFAULT_CA); 6021558Srgrimes goto err; 6031558Srgrimes } 6041558Srgrimes } 605121556Speter 60631656Sguido if (conf != NULL) { 60774462Salfred p = NCONF_get_string(conf, NULL, "oid_file"); 6081558Srgrimes if (p == NULL) 6091558Srgrimes ERR_clear_error(); 6101558Srgrimes if (p != NULL) { 6111558Srgrimes BIO *oid_bio; 6121558Srgrimes 6131558Srgrimes oid_bio = BIO_new_file(p, "r"); 6149336Sdfr if (oid_bio == NULL) { 6159336Sdfr /*- 6161558Srgrimes BIO_printf(bio_err,"problems opening %s for extra oid's\n",p); 61751968Salfred ERR_print_errors(bio_err); 6181558Srgrimes */ 6199336Sdfr ERR_clear_error(); 62074462Salfred } else { 6211558Srgrimes OBJ_create_objects(oid_bio); 6221558Srgrimes BIO_free(oid_bio); 62331656Sguido } 62437663Scharnier } 62574462Salfred if (!add_oid_section(bio_err, conf)) { 6261558Srgrimes ERR_print_errors(bio_err); 62737663Scharnier goto err; 62828911Sguido } 6291558Srgrimes } 6301558Srgrimes 6311558Srgrimes randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE"); 6329336Sdfr if (randfile == NULL) 6331558Srgrimes ERR_clear_error(); 6349336Sdfr app_RAND_load_file(randfile, bio_err, 0); 6359336Sdfr 6361558Srgrimes f = NCONF_get_string(conf, section, STRING_MASK); 63774462Salfred if (!f) 63874462Salfred ERR_clear_error(); 63974462Salfred 64028911Sguido if (f && !ASN1_STRING_set_default_mask_asc(f)) { 641121556Speter BIO_printf(bio_err, "Invalid global string mask setting %s\n", f); 64228911Sguido goto err; 64337663Scharnier } 64428911Sguido 64528911Sguido if (chtype != MBSTRING_UTF8) { 64628911Sguido f = NCONF_get_string(conf, section, UTF8_IN); 6479336Sdfr if (!f) 6489336Sdfr ERR_clear_error(); 6499336Sdfr else if (!strcmp(f, "yes")) 6509336Sdfr chtype = MBSTRING_UTF8; 6519336Sdfr } 6521558Srgrimes 65323681Speter db_attr.unique_subject = 1; 6549336Sdfr p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT); 6551558Srgrimes if (p) { 65637663Scharnier#ifdef RL_DEBUG 657121556Speter BIO_printf(bio_err, "DEBUG: unique_subject = \"%s\"\n", p); 6581558Srgrimes#endif 65937663Scharnier db_attr.unique_subject = parse_yesno(p, 1); 6609336Sdfr } else 6611558Srgrimes ERR_clear_error(); 6621558Srgrimes#ifdef RL_DEBUG 663121556Speter if (!p) 664121556Speter BIO_printf(bio_err, "DEBUG: unique_subject undefined\n"); 66537663Scharnier#endif 66674462Salfred#ifdef RL_DEBUG 66774462Salfred BIO_printf(bio_err, "DEBUG: configured unique_subject is %d\n", 6681558Srgrimes db_attr.unique_subject); 66974462Salfred#endif 6701558Srgrimes 67137663Scharnier in = BIO_new(BIO_s_file()); 672121767Speter out = BIO_new(BIO_s_file()); 67331656Sguido Sout = BIO_new(BIO_s_file()); 67431656Sguido Cout = BIO_new(BIO_s_file()); 67574462Salfred if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL)) { 67631656Sguido ERR_print_errors(bio_err); 6771558Srgrimes goto err; 67831656Sguido } 67931656Sguido 68074462Salfred /*****************************************************************/ 68131656Sguido /* report status of cert with serial number given on command line */ 68228911Sguido if (ser_status) { 683121556Speter if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) { 684121556Speter lookup_fail(section, ENV_DATABASE); 68537663Scharnier goto err; 6869336Sdfr } 6871558Srgrimes db = load_index(dbfile, &db_attr); 6881558Srgrimes if (db == NULL) 689121556Speter goto err; 69037663Scharnier 691121767Speter if (!index_index(db)) 69231656Sguido goto err; 69331656Sguido 69474462Salfred if (get_certificate_status(ser_status, db) != 1) 6951558Srgrimes BIO_printf(bio_err, "Error verifying serial %s!\n", ser_status); 6961558Srgrimes goto err; 6979336Sdfr } 69831656Sguido 69931656Sguido /*****************************************************************/ 70074462Salfred /* we definitely need a private key, so let's get it */ 7011558Srgrimes 7021558Srgrimes if ((keyfile == NULL) && ((keyfile = NCONF_get_string(conf, 7031558Srgrimes section, 704121556Speter ENV_PRIVATE_KEY)) == 70531656Sguido NULL)) { 70674462Salfred lookup_fail(section, ENV_PRIVATE_KEY); 7071558Srgrimes goto err; 7081558Srgrimes } 7091558Srgrimes if (!key) { 71051968Salfred free_key = 1; 71151968Salfred if (!app_passwd(bio_err, passargin, NULL, &key, NULL)) { 71251968Salfred BIO_printf(bio_err, "Error getting password\n"); 71374462Salfred goto err; 71451968Salfred } 715121556Speter } 71637663Scharnier pkey = load_key(bio_err, keyfile, keyform, 0, key, e, "CA private key"); 71774462Salfred if (key) 71875635Siedowse OPENSSL_cleanse(key, strlen(key)); 71975635Siedowse if (pkey == NULL) { 720121767Speter /* load_key() has already printed an appropriate message */ 72131656Sguido goto err; 72231656Sguido } 72374462Salfred 7241558Srgrimes /*****************************************************************/ 7251558Srgrimes /* we need a certificate */ 7269336Sdfr if (!selfsign || spkac_file || ss_cert_file || gencrl) { 72731656Sguido if ((certfile == NULL) 72831656Sguido && ((certfile = NCONF_get_string(conf, 72974462Salfred section, 7301558Srgrimes ENV_CERTIFICATE)) == NULL)) { 7311558Srgrimes lookup_fail(section, ENV_CERTIFICATE); 7321558Srgrimes goto err; 733121556Speter } 73437663Scharnier x509 = load_cert(bio_err, certfile, FORMAT_PEM, NULL, e, 73574462Salfred "CA certificate"); 73675635Siedowse if (x509 == NULL) 73775635Siedowse goto err; 738121767Speter 73931656Sguido if (!X509_check_private_key(x509, pkey)) { 74031656Sguido BIO_printf(bio_err, 74174462Salfred "CA certificate and CA private key do not match\n"); 7421558Srgrimes goto err; 7431558Srgrimes } 744121556Speter } 745121556Speter if (!selfsign) 746121556Speter x509p = x509; 747100117Salfred 748121767Speter f = NCONF_get_string(conf, BASE_SECTION, ENV_PRESERVE); 74931656Sguido if (f == NULL) 75031656Sguido ERR_clear_error(); 75174462Salfred if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) 7521558Srgrimes preserve = 1; 7531558Srgrimes f = NCONF_get_string(conf, BASE_SECTION, ENV_MSIE_HACK); 7541558Srgrimes if (f == NULL) 7551558Srgrimes ERR_clear_error(); 7561558Srgrimes if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) 7571558Srgrimes msie_hack = 1; 7581558Srgrimes 7591558Srgrimes f = NCONF_get_string(conf, section, ENV_NAMEOPT); 7601558Srgrimes 7611558Srgrimes if (f) { 7621558Srgrimes if (!set_name_ex(&nameopt, f)) { 7631558Srgrimes BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f); 7641558Srgrimes goto err; 7651558Srgrimes } 7661558Srgrimes default_op = 0; 7671558Srgrimes } else 7681558Srgrimes ERR_clear_error(); 7691558Srgrimes 7701558Srgrimes f = NCONF_get_string(conf, section, ENV_CERTOPT); 7719336Sdfr 7721558Srgrimes if (f) { 7731558Srgrimes if (!set_cert_ex(&certopt, f)) { 7749336Sdfr BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f); 7751558Srgrimes goto err; 7769336Sdfr } 7771558Srgrimes default_op = 0; 77892806Sobrien } else 7799336Sdfr ERR_clear_error(); 7801558Srgrimes 7811558Srgrimes f = NCONF_get_string(conf, section, ENV_EXTCOPY); 7821558Srgrimes 7839336Sdfr if (f) { 7849336Sdfr if (!set_ext_copy(&ext_copy, f)) { 7859336Sdfr BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f); 7869336Sdfr goto err; 7879336Sdfr } 7889336Sdfr } else 7899336Sdfr ERR_clear_error(); 7909336Sdfr 7919336Sdfr /*****************************************************************/ 79283653Speter /* lookup where to write new certificates */ 7939336Sdfr if ((outdir == NULL) && (req)) { 7949336Sdfr 7959336Sdfr if ((outdir = NCONF_get_string(conf, section, ENV_NEW_CERTS_DIR)) 7969336Sdfr == NULL) { 7979336Sdfr BIO_printf(bio_err, 7989336Sdfr "there needs to be defined a directory for new certificate to be placed in\n"); 7991558Srgrimes goto err; 8001558Srgrimes } 8011558Srgrimes#ifndef OPENSSL_SYS_VMS 8021558Srgrimes /* 8031558Srgrimes * outdir is a directory spec, but access() for VMS demands a 8041558Srgrimes * filename. In any case, stat(), below, will catch the problem if 8051558Srgrimes * outdir is not a directory spec, and the fopen() or open() will 8061558Srgrimes * catch an error if there is no write access. 8071558Srgrimes * 8081558Srgrimes * Presumably, this problem could also be solved by using the DEC C 8091558Srgrimes * routines to convert the directory syntax to Unixly, and give that 8101558Srgrimes * to access(). However, time's too short to do that just now. 8111558Srgrimes */ 8121558Srgrimes# ifndef _WIN32 8131558Srgrimes if (access(outdir, R_OK | W_OK | X_OK) != 0) 8141558Srgrimes# else 8151558Srgrimes if (_access(outdir, R_OK | W_OK | X_OK) != 0) 8161558Srgrimes# endif 8171558Srgrimes { 8181558Srgrimes BIO_printf(bio_err, "I am unable to access the %s directory\n", 8191558Srgrimes outdir); 8201558Srgrimes perror(outdir); 8211558Srgrimes goto err; 8221558Srgrimes } 8231558Srgrimes 8241558Srgrimes if (app_isdir(outdir) <= 0) { 8251558Srgrimes BIO_printf(bio_err, "%s need to be a directory\n", outdir); 8261558Srgrimes perror(outdir); 8271558Srgrimes goto err; 8281558Srgrimes } 8291558Srgrimes#endif 8301558Srgrimes } 8311558Srgrimes 832100117Salfred /*****************************************************************/ 8331558Srgrimes /* we need to load the database file */ 8341558Srgrimes if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) { 835100117Salfred lookup_fail(section, ENV_DATABASE); 8361558Srgrimes goto err; 8371558Srgrimes } 8381558Srgrimes db = load_index(dbfile, &db_attr); 8399336Sdfr if (db == NULL) 8409336Sdfr goto err; 8411558Srgrimes 8429336Sdfr /* Lets check some fields */ 8439336Sdfr for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { 8449336Sdfr pp = sk_OPENSSL_PSTRING_value(db->db->data, i); 8451558Srgrimes if ((pp[DB_type][0] != DB_TYPE_REV) && (pp[DB_rev_date][0] != '\0')) { 8461558Srgrimes BIO_printf(bio_err, 8471558Srgrimes "entry %d: not revoked yet, but has a revocation date\n", 848100117Salfred i + 1); 849100117Salfred goto err; 8501558Srgrimes } 8511558Srgrimes if ((pp[DB_type][0] == DB_TYPE_REV) && 8521558Srgrimes !make_revoked(NULL, pp[DB_rev_date])) { 853100117Salfred BIO_printf(bio_err, " in entry %d\n", i + 1); 8541558Srgrimes goto err; 8551558Srgrimes } 8561558Srgrimes if (!check_time_format((char *)pp[DB_exp_date])) { 8579336Sdfr BIO_printf(bio_err, "entry %d: invalid expiry date\n", i + 1); 8581558Srgrimes goto err; 8591558Srgrimes } 8601558Srgrimes p = pp[DB_serial]; 8611558Srgrimes j = strlen(p); 8629336Sdfr if (*p == '-') { 8631558Srgrimes p++; 8641558Srgrimes j--; 8651558Srgrimes } 8661558Srgrimes if ((j & 1) || (j < 2)) { 8671558Srgrimes BIO_printf(bio_err, "entry %d: bad serial number length (%d)\n", 8681558Srgrimes i + 1, j); 8691558Srgrimes goto err; 8701558Srgrimes } 871100117Salfred while (*p) { 8721558Srgrimes if (!(((*p >= '0') && (*p <= '9')) || 8731558Srgrimes ((*p >= 'A') && (*p <= 'F')) || 8741558Srgrimes ((*p >= 'a') && (*p <= 'f')))) { 8751558Srgrimes BIO_printf(bio_err, 876100117Salfred "entry %d: bad serial number characters, char pos %ld, char is '%c'\n", 8771558Srgrimes i + 1, (long)(p - pp[DB_serial]), *p); 8781558Srgrimes goto err; 8791558Srgrimes } 8801558Srgrimes p++; 8811558Srgrimes } 8821558Srgrimes } 8831558Srgrimes if (verbose) { 8841558Srgrimes BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); /* cannot fail */ 8851558Srgrimes#ifdef OPENSSL_SYS_VMS 886100117Salfred { 8871558Srgrimes BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 8881558Srgrimes out = BIO_push(tmpbio, out); 8891558Srgrimes } 8901558Srgrimes#endif 8911558Srgrimes TXT_DB_write(out, db->db); 8921558Srgrimes BIO_printf(bio_err, "%d entries loaded from the database\n", 8931558Srgrimes sk_OPENSSL_PSTRING_num(db->db->data)); 8941558Srgrimes BIO_printf(bio_err, "generating index\n"); 8951558Srgrimes } 8961558Srgrimes 897100117Salfred if (!index_index(db)) 898100117Salfred goto err; 899100117Salfred 900100117Salfred /*****************************************************************/ 901100117Salfred /* Update the db file for expired certificates */ 902100117Salfred if (doupdatedb) { 903100117Salfred if (verbose) 9041558Srgrimes BIO_printf(bio_err, "Updating %s ...\n", dbfile); 9051558Srgrimes 9061558Srgrimes i = do_updatedb(db); 9071558Srgrimes if (i == -1) { 9081558Srgrimes BIO_printf(bio_err, "Malloc failure\n"); 9091558Srgrimes goto err; 9101558Srgrimes } else if (i == 0) { 91174462Salfred if (verbose) 9128871Srgrimes BIO_printf(bio_err, "No entries found to mark expired\n"); 9131558Srgrimes } else { 9141558Srgrimes if (!save_index(dbfile, "new", db)) 9151558Srgrimes goto err; 9161558Srgrimes 9171558Srgrimes if (!rotate_index(dbfile, "new", "old")) 9181558Srgrimes goto err; 9198871Srgrimes 9201558Srgrimes if (verbose) 9211558Srgrimes BIO_printf(bio_err, 9221558Srgrimes "Done. %d entries marked as expired\n", i); 9231558Srgrimes } 9241558Srgrimes } 9251558Srgrimes 9261558Srgrimes /*****************************************************************/ 9271558Srgrimes /* Read extentions config file */ 9281558Srgrimes if (extfile) { 9291558Srgrimes extconf = NCONF_new(NULL); 9301558Srgrimes if (NCONF_load(extconf, extfile, &errorline) <= 0) { 9311558Srgrimes if (errorline <= 0) 932100117Salfred BIO_printf(bio_err, "ERROR: loading the config file '%s'\n", 9331558Srgrimes extfile); 9341558Srgrimes else 9351558Srgrimes BIO_printf(bio_err, 9361558Srgrimes "ERROR: on line %ld of config file '%s'\n", 9371558Srgrimes errorline, extfile); 938100117Salfred ret = 1; 939100117Salfred goto err; 940100117Salfred } 941100117Salfred 942100117Salfred if (verbose) 943100117Salfred BIO_printf(bio_err, "Successfully loaded extensions file %s\n", 944100117Salfred extfile); 945100117Salfred 946100117Salfred /* We can have sections in the ext file */ 947100117Salfred if (!extensions 948100117Salfred && !(extensions = 949100117Salfred NCONF_get_string(extconf, "default", "extensions"))) 950100117Salfred extensions = "default"; 951100117Salfred } 952100117Salfred 953100117Salfred /*****************************************************************/ 954100117Salfred if (req || gencrl) { 955100117Salfred if (outfile != NULL) { 95696622Siedowse if (BIO_write_filename(Sout, outfile) <= 0) { 95796622Siedowse perror(outfile); 9581558Srgrimes goto err; 9591558Srgrimes } 9601558Srgrimes } else { 9611558Srgrimes BIO_set_fp(Sout, stdout, BIO_NOCLOSE | BIO_FP_TEXT); 9621558Srgrimes#ifdef OPENSSL_SYS_VMS 9631558Srgrimes { 9641558Srgrimes BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 9651558Srgrimes Sout = BIO_push(tmpbio, Sout); 9661558Srgrimes } 9671558Srgrimes#endif 9681558Srgrimes } 9691558Srgrimes } 9701558Srgrimes 97172650Sgreen if ((md == NULL) && ((md = NCONF_get_string(conf, 9721558Srgrimes section, 9731558Srgrimes ENV_DEFAULT_MD)) == NULL)) { 9741558Srgrimes lookup_fail(section, ENV_DEFAULT_MD); 97551968Salfred goto err; 97651968Salfred } 97751968Salfred 9781558Srgrimes if (!strcmp(md, "default")) { 9791558Srgrimes int def_nid; 9801558Srgrimes if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0) { 9811558Srgrimes BIO_puts(bio_err, "no default digest\n"); 9821558Srgrimes goto err; 9831558Srgrimes } 9841558Srgrimes md = (char *)OBJ_nid2sn(def_nid); 9851558Srgrimes } 9861558Srgrimes 9871558Srgrimes if ((dgst = EVP_get_digestbyname(md)) == NULL) { 9881558Srgrimes BIO_printf(bio_err, "%s is an unsupported message digest type\n", md); 9891558Srgrimes goto err; 9901558Srgrimes } 9911558Srgrimes 9921558Srgrimes if (req) { 9931558Srgrimes if ((email_dn == 1) && ((tmp_email_dn = NCONF_get_string(conf, 9941558Srgrimes section, 9951558Srgrimes ENV_DEFAULT_EMAIL_DN)) 9961558Srgrimes != NULL)) { 9971558Srgrimes if (strcmp(tmp_email_dn, "no") == 0) 9981558Srgrimes email_dn = 0; 99996707Strhodes } 100096707Strhodes if (verbose) 100123681Speter BIO_printf(bio_err, "message digest is %s\n", 10021558Srgrimes OBJ_nid2ln(dgst->type)); 10031558Srgrimes if ((policy == NULL) && ((policy = NCONF_get_string(conf, 10041558Srgrimes section, 10051558Srgrimes ENV_POLICY)) == 10061558Srgrimes NULL)) { 10071558Srgrimes lookup_fail(section, ENV_POLICY); 10089336Sdfr goto err; 100954093Ssemenu } 10101558Srgrimes if (verbose) 10111558Srgrimes BIO_printf(bio_err, "policy is %s\n", policy); 101277435Sphk 101377577Sru if ((serialfile = NCONF_get_string(conf, section, ENV_SERIAL)) 101454093Ssemenu == NULL) { 101523681Speter lookup_fail(section, ENV_SERIAL); 1016138680Sphk goto err; 10179336Sdfr } 10189336Sdfr 10199336Sdfr if (!extconf) { 102077405Siedowse /* 102177405Siedowse * no '-extfile' option, so we look for extensions in the main 102277405Siedowse * configuration file 102377405Siedowse */ 102474462Salfred if (!extensions) { 10251558Srgrimes extensions = NCONF_get_string(conf, section, ENV_EXTENSIONS); 10261558Srgrimes if (!extensions) 10271558Srgrimes ERR_clear_error(); 10281558Srgrimes } 10291558Srgrimes if (extensions) { 10301558Srgrimes /* Check syntax of file */ 10311558Srgrimes X509V3_CTX ctx; 10321558Srgrimes X509V3_set_ctx_test(&ctx); 10331558Srgrimes X509V3_set_nconf(&ctx, conf); 103437663Scharnier if (!X509V3_EXT_add_nconf(conf, &ctx, extensions, NULL)) { 10351558Srgrimes BIO_printf(bio_err, 10361558Srgrimes "Error Loading extension section %s\n", 10371558Srgrimes extensions); 10381558Srgrimes ret = 1; 10391558Srgrimes goto err; 104037663Scharnier } 10411558Srgrimes } 10421558Srgrimes } 10431558Srgrimes 10441558Srgrimes if (startdate == NULL) { 10451558Srgrimes startdate = NCONF_get_string(conf, section, 10461558Srgrimes ENV_DEFAULT_STARTDATE); 10471558Srgrimes if (startdate == NULL) 10481558Srgrimes ERR_clear_error(); 10491558Srgrimes } 10501558Srgrimes if (startdate && !ASN1_TIME_set_string(NULL, startdate)) { 10511558Srgrimes BIO_printf(bio_err, 10521558Srgrimes "start date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n"); 10531558Srgrimes goto err; 10541558Srgrimes } 10551558Srgrimes if (startdate == NULL) 10561558Srgrimes startdate = "today"; 10571558Srgrimes 10581558Srgrimes if (enddate == NULL) { 10591558Srgrimes enddate = NCONF_get_string(conf, section, ENV_DEFAULT_ENDDATE); 10601558Srgrimes if (enddate == NULL) 10611558Srgrimes ERR_clear_error(); 10621558Srgrimes } 10631558Srgrimes if (enddate && !ASN1_TIME_set_string(NULL, enddate)) { 10641558Srgrimes BIO_printf(bio_err, 10651558Srgrimes "end date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n"); 10661558Srgrimes goto err; 10671558Srgrimes } 10681558Srgrimes 10691558Srgrimes if (days == 0) { 10701558Srgrimes if (!NCONF_get_number(conf, section, ENV_DEFAULT_DAYS, &days)) 10711558Srgrimes days = 0; 107237663Scharnier } 10731558Srgrimes if (!enddate && (days == 0)) { 10741558Srgrimes BIO_printf(bio_err, 10751558Srgrimes "cannot lookup how many days to certify for\n"); 10761558Srgrimes goto err; 10771558Srgrimes } 10781558Srgrimes 10791558Srgrimes if ((serial = load_serial(serialfile, create_ser, NULL)) == NULL) { 10801558Srgrimes BIO_printf(bio_err, "error while loading serial number\n"); 10811558Srgrimes goto err; 10821558Srgrimes } 10831558Srgrimes if (verbose) { 10841558Srgrimes if (BN_is_zero(serial)) 108537663Scharnier BIO_printf(bio_err, "next serial number is 00\n"); 10861558Srgrimes else { 10871558Srgrimes if ((f = BN_bn2hex(serial)) == NULL) 10881558Srgrimes goto err; 10891558Srgrimes BIO_printf(bio_err, "next serial number is %s\n", f); 10901558Srgrimes OPENSSL_free(f); 10911558Srgrimes } 10921558Srgrimes } 10931558Srgrimes 10941558Srgrimes if ((attribs = NCONF_get_section(conf, policy)) == NULL) { 10951558Srgrimes BIO_printf(bio_err, "unable to find 'section' for %s\n", policy); 10961558Srgrimes goto err; 10971558Srgrimes } 10981558Srgrimes 10991558Srgrimes if ((cert_sk = sk_X509_new_null()) == NULL) { 11001558Srgrimes BIO_printf(bio_err, "Memory allocation failure\n"); 11011558Srgrimes goto err; 11021558Srgrimes } 11031558Srgrimes if (spkac_file != NULL) { 11041558Srgrimes total++; 11051558Srgrimes j = certify_spkac(&x, spkac_file, pkey, x509, dgst, sigopts, 11061558Srgrimes attribs, db, serial, subj, chtype, multirdn, 11071558Srgrimes email_dn, startdate, enddate, days, extensions, 11081558Srgrimes conf, verbose, certopt, nameopt, default_op, 11091558Srgrimes ext_copy); 11101558Srgrimes if (j < 0) 11111558Srgrimes goto err; 111274462Salfred if (j > 0) { 111374462Salfred total_done++; 111474462Salfred BIO_printf(bio_err, "\n"); 11151558Srgrimes if (!BN_add_word(serial, 1)) 111637663Scharnier goto err; 11171558Srgrimes if (!sk_X509_push(cert_sk, x)) { 11181558Srgrimes BIO_printf(bio_err, "Memory allocation failure\n"); 11191558Srgrimes goto err; 11201558Srgrimes } 11211558Srgrimes if (outfile) { 11221558Srgrimes output_der = 1; 11231558Srgrimes batch = 1; 11241558Srgrimes } 11251558Srgrimes } 11261558Srgrimes } 11271558Srgrimes if (ss_cert_file != NULL) { 11281558Srgrimes total++; 11291558Srgrimes j = certify_cert(&x, ss_cert_file, pkey, x509, dgst, sigopts, 11301558Srgrimes attribs, 11311558Srgrimes db, serial, subj, chtype, multirdn, email_dn, 11321558Srgrimes startdate, enddate, days, batch, extensions, 11331558Srgrimes conf, verbose, certopt, nameopt, default_op, 11341558Srgrimes ext_copy, e); 11351558Srgrimes if (j < 0) 11361558Srgrimes goto err; 11371558Srgrimes if (j > 0) { 11381558Srgrimes total_done++; 11391558Srgrimes BIO_printf(bio_err, "\n"); 11401558Srgrimes if (!BN_add_word(serial, 1)) 11411558Srgrimes goto err; 11421558Srgrimes if (!sk_X509_push(cert_sk, x)) { 11431558Srgrimes BIO_printf(bio_err, "Memory allocation failure\n"); 11441558Srgrimes goto err; 11451558Srgrimes } 11461558Srgrimes } 11471558Srgrimes } 11481558Srgrimes if (infile != NULL) { 11491558Srgrimes total++; 11501558Srgrimes j = certify(&x, infile, pkey, x509p, dgst, sigopts, attribs, db, 115137003Sjoerg serial, subj, chtype, multirdn, email_dn, startdate, 115237663Scharnier enddate, days, batch, extensions, conf, verbose, 115337663Scharnier certopt, nameopt, default_op, ext_copy, selfsign); 115437004Sjoerg if (j < 0) 115537003Sjoerg goto err; 115637663Scharnier if (j > 0) { 115737663Scharnier total_done++; 115829317Sjlemon BIO_printf(bio_err, "\n"); 11591558Srgrimes if (!BN_add_word(serial, 1)) 11607401Swpaul goto err; 116137663Scharnier if (!sk_X509_push(cert_sk, x)) { 116229317Sjlemon BIO_printf(bio_err, "Memory allocation failure\n"); 11631558Srgrimes goto err; 11641558Srgrimes } 11651558Srgrimes } 11661558Srgrimes } 11671558Srgrimes for (i = 0; i < argc; i++) { 11681558Srgrimes total++; 11691558Srgrimes j = certify(&x, argv[i], pkey, x509p, dgst, sigopts, attribs, db, 11701558Srgrimes serial, subj, chtype, multirdn, email_dn, startdate, 11711558Srgrimes enddate, days, batch, extensions, conf, verbose, 11721558Srgrimes certopt, nameopt, default_op, ext_copy, selfsign); 11731558Srgrimes if (j < 0) 11741558Srgrimes goto err; 11751558Srgrimes if (j > 0) { 11761558Srgrimes total_done++; 11771558Srgrimes BIO_printf(bio_err, "\n"); 117875641Siedowse if (!BN_add_word(serial, 1)) 11791558Srgrimes goto err; 118037663Scharnier if (!sk_X509_push(cert_sk, x)) { 11811558Srgrimes BIO_printf(bio_err, "Memory allocation failure\n"); 11821558Srgrimes goto err; 11831558Srgrimes } 11841558Srgrimes } 11851558Srgrimes } 11861558Srgrimes /* 118775801Siedowse * we have a stack of newly certified certificates and a data base 11881558Srgrimes * and serial number that need updating 11891558Srgrimes */ 119029317Sjlemon 119174462Salfred if (sk_X509_num(cert_sk) > 0) { 119274462Salfred if (!batch) { 119329317Sjlemon BIO_printf(bio_err, 119429317Sjlemon "\n%d out of %d certificate requests certified, commit? [y/n]", 119529317Sjlemon total_done, total); 119629317Sjlemon (void)BIO_flush(bio_err); 119774462Salfred buf[0][0] = '\0'; 119829317Sjlemon if (!fgets(buf[0], 10, stdin)) { 119929317Sjlemon BIO_printf(bio_err, 120029317Sjlemon "CERTIFICATION CANCELED: I/O error\n"); 120129317Sjlemon ret = 0; 120229317Sjlemon goto err; 12031558Srgrimes } 12041558Srgrimes if ((buf[0][0] != 'y') && (buf[0][0] != 'Y')) { 12051558Srgrimes BIO_printf(bio_err, "CERTIFICATION CANCELED\n"); 12061558Srgrimes ret = 0; 12071558Srgrimes goto err; 12081558Srgrimes } 12091558Srgrimes } 12101558Srgrimes 12111558Srgrimes BIO_printf(bio_err, "Write out database with %d new entries\n", 121275635Siedowse sk_X509_num(cert_sk)); 121375635Siedowse 121475635Siedowse if (!save_serial(serialfile, "new", serial, NULL)) 121575635Siedowse goto err; 121675635Siedowse 12171558Srgrimes if (!save_index(dbfile, "new", db)) 12181558Srgrimes goto err; 12191558Srgrimes } 12201558Srgrimes 12211558Srgrimes if (verbose) 12221558Srgrimes BIO_printf(bio_err, "writing new certificates\n"); 12239336Sdfr for (i = 0; i < sk_X509_num(cert_sk); i++) { 12241558Srgrimes int k; 12251558Srgrimes char *n; 12261558Srgrimes 12271558Srgrimes x = sk_X509_value(cert_sk, i); 12289336Sdfr 12291558Srgrimes j = x->cert_info->serialNumber->length; 12301558Srgrimes p = (const char *)x->cert_info->serialNumber->data; 12311558Srgrimes 12321558Srgrimes if (strlen(outdir) >= (size_t)(j ? BSIZE - j * 2 - 6 : BSIZE - 8)) { 12331558Srgrimes BIO_printf(bio_err, "certificate file name too long\n"); 12341558Srgrimes goto err; 12351558Srgrimes } 12361558Srgrimes 12371558Srgrimes strcpy(buf[2], outdir); 12381558Srgrimes 12391558Srgrimes#ifndef OPENSSL_SYS_VMS 12401558Srgrimes BUF_strlcat(buf[2], "/", sizeof(buf[2])); 12411558Srgrimes#endif 12421558Srgrimes 12431558Srgrimes n = (char *)&(buf[2][strlen(buf[2])]); 12441558Srgrimes if (j > 0) { 12451558Srgrimes for (k = 0; k < j; k++) { 12461558Srgrimes if (n >= &(buf[2][sizeof(buf[2])])) 12471558Srgrimes break; 12481558Srgrimes BIO_snprintf(n, 12491558Srgrimes &buf[2][0] + sizeof(buf[2]) - n, 12501558Srgrimes "%02X", (unsigned char)*(p++)); 12511558Srgrimes n += 2; 12521558Srgrimes } 12531558Srgrimes } else { 12541558Srgrimes *(n++) = '0'; 12551558Srgrimes *(n++) = '0'; 12561558Srgrimes } 12571558Srgrimes *(n++) = '.'; 12581558Srgrimes *(n++) = 'p'; 12591558Srgrimes *(n++) = 'e'; 12601558Srgrimes *(n++) = 'm'; 12611558Srgrimes *n = '\0'; 12621558Srgrimes if (verbose) 12631558Srgrimes BIO_printf(bio_err, "writing %s\n", buf[2]); 12641558Srgrimes 12651558Srgrimes if (BIO_write_filename(Cout, buf[2]) <= 0) { 12661558Srgrimes perror(buf[2]); 12671558Srgrimes goto err; 126823681Speter } 12691558Srgrimes write_new_certificate(Cout, x, 0, notext); 12701558Srgrimes write_new_certificate(Sout, x, output_der, notext); 12711558Srgrimes } 12721558Srgrimes 12731558Srgrimes if (sk_X509_num(cert_sk)) { 12741558Srgrimes /* Rename the database and the serial file */ 12751558Srgrimes if (!rotate_serial(serialfile, "new", "old")) 12761558Srgrimes goto err; 12771558Srgrimes 12781558Srgrimes if (!rotate_index(dbfile, "new", "old")) 12791558Srgrimes goto err; 12801558Srgrimes 12811558Srgrimes BIO_printf(bio_err, "Data Base Updated\n"); 12821558Srgrimes } 128323681Speter } 12841558Srgrimes 12851558Srgrimes /*****************************************************************/ 12861558Srgrimes if (gencrl) { 12871558Srgrimes int crl_v2 = 0; 12881558Srgrimes if (!crl_ext) { 12891558Srgrimes crl_ext = NCONF_get_string(conf, section, ENV_CRLEXT); 12901558Srgrimes if (!crl_ext) 12911558Srgrimes ERR_clear_error(); 12921558Srgrimes } 12931558Srgrimes if (crl_ext) { 12941558Srgrimes /* Check syntax of file */ 12951558Srgrimes X509V3_CTX ctx; 12961558Srgrimes X509V3_set_ctx_test(&ctx); 1297100336Sjoerg X509V3_set_nconf(&ctx, conf); 1298100336Sjoerg if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL)) { 12991558Srgrimes BIO_printf(bio_err, 13001558Srgrimes "Error Loading CRL extension section %s\n", 13011558Srgrimes crl_ext); 13021558Srgrimes ret = 1; 13031558Srgrimes goto err; 13041558Srgrimes } 13051558Srgrimes } 13061558Srgrimes 13071558Srgrimes if ((crlnumberfile = NCONF_get_string(conf, section, ENV_CRLNUMBER)) 13081558Srgrimes != NULL) 13091558Srgrimes if ((crlnumber = load_serial(crlnumberfile, 0, NULL)) == NULL) { 13101558Srgrimes BIO_printf(bio_err, "error while loading CRL number\n"); 13111558Srgrimes goto err; 13121558Srgrimes } 13131558Srgrimes 13141558Srgrimes if (!crldays && !crlhours && !crlsec) { 13151558Srgrimes if (!NCONF_get_number(conf, section, 13161558Srgrimes ENV_DEFAULT_CRL_DAYS, &crldays)) 13171558Srgrimes crldays = 0; 13181558Srgrimes if (!NCONF_get_number(conf, section, 13191558Srgrimes ENV_DEFAULT_CRL_HOURS, &crlhours)) 13201558Srgrimes crlhours = 0; 13211558Srgrimes ERR_clear_error(); 13221558Srgrimes } 13231558Srgrimes if ((crldays == 0) && (crlhours == 0) && (crlsec == 0)) { 13241558Srgrimes BIO_printf(bio_err, 13251558Srgrimes "cannot lookup how long until the next CRL is issued\n"); 13261558Srgrimes goto err; 13271558Srgrimes } 13281558Srgrimes 13291558Srgrimes if (verbose) 13301558Srgrimes BIO_printf(bio_err, "making CRL\n"); 13311558Srgrimes if ((crl = X509_CRL_new()) == NULL) 13321558Srgrimes goto err; 13331558Srgrimes if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) 13341558Srgrimes goto err; 13351558Srgrimes 13361558Srgrimes tmptm = ASN1_TIME_new(); 13371558Srgrimes if (!tmptm) 13381558Srgrimes goto err; 133937663Scharnier X509_gmtime_adj(tmptm, 0); 134037663Scharnier X509_CRL_set_lastUpdate(crl, tmptm); 13411558Srgrimes if (!X509_time_adj_ex(tmptm, crldays, crlhours * 60 * 60 + crlsec, 13421558Srgrimes NULL)) { 13431558Srgrimes BIO_puts(bio_err, "error setting CRL nextUpdate\n"); 13441558Srgrimes goto err; 13451558Srgrimes } 13461558Srgrimes X509_CRL_set_nextUpdate(crl, tmptm); 13471558Srgrimes 13481558Srgrimes ASN1_TIME_free(tmptm); 13491558Srgrimes 13501558Srgrimes for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { 13511558Srgrimes pp = sk_OPENSSL_PSTRING_value(db->db->data, i); 13521558Srgrimes if (pp[DB_type][0] == DB_TYPE_REV) { 13531558Srgrimes if ((r = X509_REVOKED_new()) == NULL) 13541558Srgrimes goto err; 13559336Sdfr j = make_revoked(r, pp[DB_rev_date]); 13561558Srgrimes if (!j) 13571558Srgrimes goto err; 13581558Srgrimes if (j == 2) 13599336Sdfr crl_v2 = 1; 13601558Srgrimes if (!BN_hex2bn(&serial, pp[DB_serial])) 13611558Srgrimes goto err; 13621558Srgrimes tmpser = BN_to_ASN1_INTEGER(serial, NULL); 13631558Srgrimes BN_free(serial); 13649336Sdfr serial = NULL; 13651558Srgrimes if (!tmpser) 13661558Srgrimes goto err; 13671558Srgrimes X509_REVOKED_set_serialNumber(r, tmpser); 13681558Srgrimes ASN1_INTEGER_free(tmpser); 13699336Sdfr X509_CRL_add0_revoked(crl, r); 13701558Srgrimes } 13719336Sdfr } 13721558Srgrimes 13731558Srgrimes /* 13741558Srgrimes * sort the data so it will be written in serial number order 13751558Srgrimes */ 13761558Srgrimes X509_CRL_sort(crl); 13771558Srgrimes 13781558Srgrimes /* we now have a CRL */ 13791558Srgrimes if (verbose) 13801558Srgrimes BIO_printf(bio_err, "signing CRL\n"); 138137663Scharnier 13821558Srgrimes /* Add any extensions asked for */ 13831558Srgrimes 13841558Srgrimes if (crl_ext || crlnumberfile != NULL) { 13859336Sdfr X509V3_CTX crlctx; 13861558Srgrimes X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0); 13871558Srgrimes X509V3_set_nconf(&crlctx, conf); 13881558Srgrimes 13891558Srgrimes if (crl_ext) 13901558Srgrimes if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl)) 13911558Srgrimes goto err; 13921558Srgrimes if (crlnumberfile != NULL) { 13931558Srgrimes tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL); 13941558Srgrimes if (!tmpser) 13951558Srgrimes goto err; 13969336Sdfr X509_CRL_add1_ext_i2d(crl, NID_crl_number, tmpser, 0, 0); 13971558Srgrimes ASN1_INTEGER_free(tmpser); 13981558Srgrimes crl_v2 = 1; 13991558Srgrimes if (!BN_add_word(crlnumber, 1)) 14009336Sdfr goto err; 14011558Srgrimes } 14021558Srgrimes } 14031558Srgrimes if (crl_ext || crl_v2) { 14041558Srgrimes if (!X509_CRL_set_version(crl, 1)) 14051558Srgrimes goto err; /* version 2 CRL */ 14061558Srgrimes } 14071558Srgrimes 14081558Srgrimes /* we have a CRL number that need updating */ 14091558Srgrimes if (crlnumberfile != NULL) 14109336Sdfr if (!save_serial(crlnumberfile, "new", crlnumber, NULL)) 14111558Srgrimes goto err; 14121558Srgrimes 14139336Sdfr if (crlnumber) { 14141558Srgrimes BN_free(crlnumber); 14151558Srgrimes crlnumber = NULL; 14161558Srgrimes } 14171558Srgrimes 14181558Srgrimes if (!do_X509_CRL_sign(bio_err, crl, pkey, dgst, sigopts)) 14191558Srgrimes goto err; 14201558Srgrimes 14211558Srgrimes PEM_write_bio_X509_CRL(Sout, crl); 14221558Srgrimes 14231558Srgrimes if (crlnumberfile != NULL) /* Rename the crlnumber file */ 14241558Srgrimes if (!rotate_serial(crlnumberfile, "new", "old")) 14251558Srgrimes goto err; 14261558Srgrimes 14271558Srgrimes } 14281558Srgrimes /*****************************************************************/ 14291558Srgrimes if (dorevoke) { 14301558Srgrimes if (infile == NULL) { 14311558Srgrimes BIO_printf(bio_err, "no input files\n"); 14321558Srgrimes goto err; 14331558Srgrimes } else { 14349336Sdfr X509 *revcert; 14351558Srgrimes revcert = load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile); 14369336Sdfr if (revcert == NULL) 14371558Srgrimes goto err; 14381558Srgrimes j = do_revoke(revcert, db, rev_type, rev_arg); 14391558Srgrimes if (j <= 0) 14401558Srgrimes goto err; 14411558Srgrimes X509_free(revcert); 14421558Srgrimes 144374462Salfred if (!save_index(dbfile, "new", db)) 14441558Srgrimes goto err; 144574462Salfred 14461558Srgrimes if (!rotate_index(dbfile, "new", "old")) 14471558Srgrimes goto err; 14481558Srgrimes 14491558Srgrimes BIO_printf(bio_err, "Data Base Updated\n"); 145074462Salfred } 14511558Srgrimes } 145274462Salfred /*****************************************************************/ 14531558Srgrimes ret = 0; 145474462Salfred err: 14551558Srgrimes if (tofree) 14561558Srgrimes OPENSSL_free(tofree); 14571558Srgrimes BIO_free_all(Cout); 14581558Srgrimes BIO_free_all(Sout); 14591558Srgrimes BIO_free_all(out); 14601558Srgrimes BIO_free_all(in); 14611558Srgrimes 14621558Srgrimes if (cert_sk) 14631558Srgrimes sk_X509_pop_free(cert_sk, X509_free); 14641558Srgrimes 14659336Sdfr if (ret) 14661558Srgrimes ERR_print_errors(bio_err); 146774462Salfred app_RAND_write_file(randfile, bio_err); 14681558Srgrimes if (free_key && key) 14699336Sdfr OPENSSL_free(key); 14701558Srgrimes BN_free(serial); 14711558Srgrimes BN_free(crlnumber); 14721558Srgrimes free_index(db); 147374462Salfred if (sigopts) 14741558Srgrimes sk_OPENSSL_STRING_free(sigopts); 14751558Srgrimes EVP_PKEY_free(pkey); 14761558Srgrimes if (x509) 14779336Sdfr X509_free(x509); 14781558Srgrimes X509_CRL_free(crl); 14791558Srgrimes NCONF_free(conf); 14801558Srgrimes NCONF_free(extconf); 14811558Srgrimes OBJ_cleanup(); 14821558Srgrimes apps_shutdown(); 148374462Salfred OPENSSL_EXIT(ret); 148474462Salfred} 148575801Siedowse 148674462Salfredstatic void lookup_fail(const char *name, const char *tag) 148774462Salfred{ 148874462Salfred BIO_printf(bio_err, "variable lookup failed for %s::%s\n", name, tag); 148974462Salfred} 14909336Sdfr 149175801Siedowsestatic int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 14921558Srgrimes const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, 149375801Siedowse STACK_OF(CONF_VALUE) *policy, CA_DB *db, 149475801Siedowse BIGNUM *serial, char *subj, unsigned long chtype, 149575801Siedowse int multirdn, int email_dn, char *startdate, char *enddate, 149675801Siedowse long days, int batch, char *ext_sect, CONF *lconf, 149774462Salfred int verbose, unsigned long certopt, unsigned long nameopt, 149874462Salfred int default_op, int ext_copy, int selfsign) 149974462Salfred{ 150075801Siedowse X509_REQ *req = NULL; 150175801Siedowse BIO *in = NULL; 15021558Srgrimes EVP_PKEY *pktmp = NULL; 15031558Srgrimes int ok = -1, i; 15041558Srgrimes 15051558Srgrimes in = BIO_new(BIO_s_file()); 15061558Srgrimes 15071558Srgrimes if (BIO_read_filename(in, infile) <= 0) { 15081558Srgrimes perror(infile); 15091558Srgrimes goto err; 15101558Srgrimes } 15111558Srgrimes if ((req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL)) == NULL) { 15121558Srgrimes BIO_printf(bio_err, "Error reading certificate request in %s\n", 15131558Srgrimes infile); 151474462Salfred goto err; 15151558Srgrimes } 15169336Sdfr if (verbose) 15171558Srgrimes X509_REQ_print(bio_err, req); 15181558Srgrimes 15191558Srgrimes BIO_printf(bio_err, "Check that the request matches the signature\n"); 15201558Srgrimes 15219336Sdfr if (selfsign && !X509_REQ_check_private_key(req, pkey)) { 15221558Srgrimes BIO_printf(bio_err, 15231558Srgrimes "Certificate request and CA private key do not match\n"); 15241558Srgrimes ok = 0; 15251558Srgrimes goto err; 15261558Srgrimes } 15271558Srgrimes if ((pktmp = X509_REQ_get_pubkey(req)) == NULL) { 15281558Srgrimes BIO_printf(bio_err, "error unpacking public key\n"); 15291558Srgrimes goto err; 15301558Srgrimes } 15311558Srgrimes i = X509_REQ_verify(req, pktmp); 15321558Srgrimes EVP_PKEY_free(pktmp); 15331558Srgrimes if (i < 0) { 15341558Srgrimes ok = 0; 15351558Srgrimes BIO_printf(bio_err, "Signature verification problems....\n"); 15361558Srgrimes ERR_print_errors(bio_err); 15371558Srgrimes goto err; 15381558Srgrimes } 15391558Srgrimes if (i == 0) { 15401558Srgrimes ok = 0; 15411558Srgrimes BIO_printf(bio_err, 15421558Srgrimes "Signature did not match the certificate request\n"); 15431558Srgrimes ERR_print_errors(bio_err); 15441558Srgrimes goto err; 15451558Srgrimes } else 15461558Srgrimes BIO_printf(bio_err, "Signature ok\n"); 15471558Srgrimes 15481558Srgrimes ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj, 15491558Srgrimes chtype, multirdn, email_dn, startdate, enddate, days, batch, 15501558Srgrimes verbose, req, ext_sect, lconf, certopt, nameopt, default_op, 15511558Srgrimes ext_copy, selfsign); 15521558Srgrimes 15531558Srgrimes err: 15541558Srgrimes if (req != NULL) 15551558Srgrimes X509_REQ_free(req); 15561558Srgrimes if (in != NULL) 155772650Sgreen BIO_free(in); 15581558Srgrimes return (ok); 15591558Srgrimes} 15601558Srgrimes 15611558Srgrimesstatic int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 15621558Srgrimes const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, 156351968Salfred STACK_OF(CONF_VALUE) *policy, CA_DB *db, 15641558Srgrimes BIGNUM *serial, char *subj, unsigned long chtype, 15651558Srgrimes int multirdn, int email_dn, char *startdate, 15661558Srgrimes char *enddate, long days, int batch, char *ext_sect, 15671558Srgrimes CONF *lconf, int verbose, unsigned long certopt, 15681558Srgrimes unsigned long nameopt, int default_op, int ext_copy, 15691558Srgrimes ENGINE *e) 15701558Srgrimes{ 15711558Srgrimes X509 *req = NULL; 157237663Scharnier X509_REQ *rreq = NULL; 15731558Srgrimes EVP_PKEY *pktmp = NULL; 157437663Scharnier int ok = -1, i; 15751558Srgrimes 15761558Srgrimes if ((req = 157737663Scharnier load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL) 15781558Srgrimes goto err; 15791558Srgrimes if (verbose) 15801558Srgrimes X509_print(bio_err, req); 15811558Srgrimes 15821558Srgrimes BIO_printf(bio_err, "Check that the request matches the signature\n"); 15831558Srgrimes 15841558Srgrimes if ((pktmp = X509_get_pubkey(req)) == NULL) { 15851558Srgrimes BIO_printf(bio_err, "error unpacking public key\n"); 15861558Srgrimes goto err; 15871558Srgrimes } 15881558Srgrimes i = X509_verify(req, pktmp); 15891558Srgrimes EVP_PKEY_free(pktmp); 15901558Srgrimes if (i < 0) { 15911558Srgrimes ok = 0; 15921558Srgrimes BIO_printf(bio_err, "Signature verification problems....\n"); 15931558Srgrimes goto err; 15941558Srgrimes } 15951558Srgrimes if (i == 0) { 15961558Srgrimes ok = 0; 15971558Srgrimes BIO_printf(bio_err, "Signature did not match the certificate\n"); 15981558Srgrimes goto err; 15991558Srgrimes } else 16001558Srgrimes BIO_printf(bio_err, "Signature ok\n"); 16011558Srgrimes 16021558Srgrimes if ((rreq = X509_to_X509_REQ(req, NULL, EVP_md5())) == NULL) 16031558Srgrimes goto err; 160475801Siedowse 16051558Srgrimes ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj, 160637663Scharnier chtype, multirdn, email_dn, startdate, enddate, days, batch, 16071558Srgrimes verbose, rreq, ext_sect, lconf, certopt, nameopt, default_op, 16081558Srgrimes ext_copy, 0); 16091558Srgrimes 16101558Srgrimes err: 16111558Srgrimes if (rreq != NULL) 16121558Srgrimes X509_REQ_free(rreq); 161374462Salfred if (req != NULL) 161474462Salfred X509_free(req); 161574462Salfred return (ok); 161674462Salfred} 161774462Salfred 16181558Srgrimesstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, 161937663Scharnier const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, 16201558Srgrimes STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, 16211558Srgrimes char *subj, unsigned long chtype, int multirdn, 162237663Scharnier int email_dn, char *startdate, char *enddate, long days, 16231558Srgrimes int batch, int verbose, X509_REQ *req, char *ext_sect, 16241558Srgrimes CONF *lconf, unsigned long certopt, unsigned long nameopt, 16251558Srgrimes int default_op, int ext_copy, int selfsign) 16261558Srgrimes{ 16271558Srgrimes X509_NAME *name = NULL, *CAname = NULL, *subject = NULL, *dn_subject = 16281558Srgrimes NULL; 16291558Srgrimes ASN1_UTCTIME *tm, *tmptm; 16301558Srgrimes ASN1_STRING *str, *str2; 163127447Sdfr ASN1_OBJECT *obj; 163227447Sdfr X509 *ret = NULL; 163327447Sdfr X509_CINF *ci; 163427447Sdfr X509_NAME_ENTRY *ne; 163527447Sdfr X509_NAME_ENTRY *tne, *push; 163627447Sdfr EVP_PKEY *pktmp; 163727447Sdfr int ok = -1, i, j, last, nid; 1638100336Sjoerg const char *p; 1639100336Sjoerg CONF_VALUE *cv; 16401558Srgrimes OPENSSL_STRING row[DB_NUMBER]; 164137663Scharnier OPENSSL_STRING *irow = NULL; 16421558Srgrimes OPENSSL_STRING *rrow = NULL; 16431558Srgrimes char buf[25]; 16441558Srgrimes 16451558Srgrimes tmptm = ASN1_UTCTIME_new(); 16461558Srgrimes if (tmptm == NULL) { 16471558Srgrimes BIO_printf(bio_err, "malloc error\n"); 16481558Srgrimes return (0); 16491558Srgrimes } 16501558Srgrimes 16511558Srgrimes for (i = 0; i < DB_NUMBER; i++) 16521558Srgrimes row[i] = NULL; 16531558Srgrimes 16541558Srgrimes if (subj) { 16551558Srgrimes X509_NAME *n = parse_name(subj, chtype, multirdn); 16561558Srgrimes 16571558Srgrimes if (!n) { 16581558Srgrimes ERR_print_errors(bio_err); 16591558Srgrimes goto err; 16601558Srgrimes } 16611558Srgrimes X509_REQ_set_subject_name(req, n); 16621558Srgrimes req->req_info->enc.modified = 1; 16631558Srgrimes X509_NAME_free(n); 16647401Swpaul } 16651558Srgrimes 16661558Srgrimes if (default_op) 16677401Swpaul BIO_printf(bio_err, 16681558Srgrimes "The Subject's Distinguished Name is as follows\n"); 16697401Swpaul 167075635Siedowse name = X509_REQ_get_subject_name(req); 167174462Salfred for (i = 0; i < X509_NAME_entry_count(name); i++) { 167274462Salfred ne = X509_NAME_get_entry(name, i); 16731558Srgrimes str = X509_NAME_ENTRY_get_data(ne); 167474462Salfred obj = X509_NAME_ENTRY_get_object(ne); 167574462Salfred 16761558Srgrimes if (msie_hack) { 16771558Srgrimes /* assume all type should be strings */ 167874462Salfred nid = OBJ_obj2nid(ne->object); 167974462Salfred 168074462Salfred if (str->type == V_ASN1_UNIVERSALSTRING) 168174462Salfred ASN1_UNIVERSALSTRING_to_string(str); 168274462Salfred 168375635Siedowse if ((str->type == V_ASN1_IA5STRING) && 168474462Salfred (nid != NID_pkcs9_emailAddress)) 168574462Salfred str->type = V_ASN1_T61STRING; 168674462Salfred 168774462Salfred if ((nid == NID_pkcs9_emailAddress) && 168874462Salfred (str->type == V_ASN1_PRINTABLESTRING)) 168974462Salfred str->type = V_ASN1_IA5STRING; 1690146187Sume } 169174462Salfred 169274462Salfred /* If no EMAIL is wanted in the subject */ 169374462Salfred if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn)) 169475641Siedowse continue; 169574462Salfred 169675635Siedowse /* check some things */ 169775635Siedowse if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && 169875635Siedowse (str->type != V_ASN1_IA5STRING)) { 169975635Siedowse BIO_printf(bio_err, 170075635Siedowse "\nemailAddress type needs to be of type IA5STRING\n"); 170175635Siedowse goto err; 170275635Siedowse } 170375635Siedowse if ((str->type != V_ASN1_BMPSTRING) 170475635Siedowse && (str->type != V_ASN1_UTF8STRING)) { 170575635Siedowse j = ASN1_PRINTABLE_type(str->data, str->length); 170675635Siedowse if (((j == V_ASN1_T61STRING) && 170775801Siedowse (str->type != V_ASN1_T61STRING)) || 170875635Siedowse ((j == V_ASN1_IA5STRING) && 170975635Siedowse (str->type == V_ASN1_PRINTABLESTRING))) { 171075635Siedowse BIO_printf(bio_err, 171175635Siedowse "\nThe string contains characters that are illegal for the ASN.1 type\n"); 171275635Siedowse goto err; 171375635Siedowse } 171475635Siedowse } 171575635Siedowse 171675635Siedowse if (default_op) 171774462Salfred old_entry_print(bio_err, obj, str); 17181558Srgrimes } 171975635Siedowse 17201558Srgrimes /* Ok, now we check the 'policy' stuff. */ 17211558Srgrimes if ((subject = X509_NAME_new()) == NULL) { 17221558Srgrimes BIO_printf(bio_err, "Memory allocation failure\n"); 17231558Srgrimes goto err; 17241558Srgrimes } 17251558Srgrimes 17261558Srgrimes /* take a copy of the issuer name before we mess with it. */ 17271558Srgrimes if (selfsign) 17281558Srgrimes CAname = X509_NAME_dup(name); 17291558Srgrimes else 17301558Srgrimes CAname = X509_NAME_dup(x509->cert_info->subject); 17311558Srgrimes if (CAname == NULL) 17321558Srgrimes goto err; 17331558Srgrimes str = str2 = NULL; 17341558Srgrimes 17351558Srgrimes for (i = 0; i < sk_CONF_VALUE_num(policy); i++) { 17361558Srgrimes cv = sk_CONF_VALUE_value(policy, i); /* get the object id */ 173727447Sdfr if ((j = OBJ_txt2nid(cv->name)) == NID_undef) { 173827447Sdfr BIO_printf(bio_err, 17391558Srgrimes "%s:unknown object type in 'policy' configuration\n", 17401558Srgrimes cv->name); 17411558Srgrimes goto err; 17421558Srgrimes } 17431558Srgrimes obj = OBJ_nid2obj(j); 17441558Srgrimes 17451558Srgrimes last = -1; 17461558Srgrimes for (;;) { 17471558Srgrimes /* lookup the object in the supplied name list */ 17481558Srgrimes j = X509_NAME_get_index_by_OBJ(name, obj, last); 17491558Srgrimes if (j < 0) { 17501558Srgrimes if (last != -1) 17511558Srgrimes break; 17521558Srgrimes tne = NULL; 17531558Srgrimes } else { 17541558Srgrimes tne = X509_NAME_get_entry(name, j); 17551558Srgrimes } 17561558Srgrimes last = j; 17571558Srgrimes 17581558Srgrimes /* depending on the 'policy', decide what to do. */ 17591558Srgrimes push = NULL; 17601558Srgrimes if (strcmp(cv->value, "optional") == 0) { 17611558Srgrimes if (tne != NULL) 17621558Srgrimes push = tne; 17631558Srgrimes } else if (strcmp(cv->value, "supplied") == 0) { 17641558Srgrimes if (tne == NULL) { 17651558Srgrimes BIO_printf(bio_err, 17661558Srgrimes "The %s field needed to be supplied and was missing\n", 17671558Srgrimes cv->name); 17689336Sdfr goto err; 17691558Srgrimes } else 17701558Srgrimes push = tne; 17711558Srgrimes } else if (strcmp(cv->value, "match") == 0) { 17721558Srgrimes int last2; 17731558Srgrimes 17741558Srgrimes if (tne == NULL) { 17751558Srgrimes BIO_printf(bio_err, 17761558Srgrimes "The mandatory %s field was missing\n", 17771558Srgrimes cv->name); 17781558Srgrimes goto err; 177937663Scharnier } 17801558Srgrimes 17811558Srgrimes last2 = -1; 17821558Srgrimes 17831558Srgrimes again2: 17841558Srgrimes j = X509_NAME_get_index_by_OBJ(CAname, obj, last2); 17851558Srgrimes if ((j < 0) && (last2 == -1)) { 17861558Srgrimes BIO_printf(bio_err, 17871558Srgrimes "The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n", 17881558Srgrimes cv->name); 17891558Srgrimes goto err; 17901558Srgrimes } 17911558Srgrimes if (j >= 0) { 179272650Sgreen push = X509_NAME_get_entry(CAname, j); 17931558Srgrimes str = X509_NAME_ENTRY_get_data(tne); 17941558Srgrimes str2 = X509_NAME_ENTRY_get_data(push); 17951558Srgrimes last2 = j; 17961558Srgrimes if (ASN1_STRING_cmp(str, str2) != 0) 179775841Siedowse goto again2; 179874462Salfred } 179975801Siedowse if (j < 0) { 180074462Salfred BIO_printf(bio_err, 18011558Srgrimes "The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n", 18021558Srgrimes cv->name, 18031558Srgrimes ((str2 == NULL) ? "NULL" : (char *)str2->data), 18041558Srgrimes ((str == NULL) ? "NULL" : (char *)str->data)); 18051558Srgrimes goto err; 18069336Sdfr } 180754093Ssemenu } else { 18081558Srgrimes BIO_printf(bio_err, 18091558Srgrimes "%s:invalid type in 'policy' configuration\n", 181075801Siedowse cv->value); 181175801Siedowse goto err; 18121558Srgrimes } 181375801Siedowse 181475801Siedowse if (push != NULL) { 181575801Siedowse if (!X509_NAME_add_entry(subject, push, -1, 0)) { 181675801Siedowse if (push != NULL) 181775801Siedowse X509_NAME_ENTRY_free(push); 181875641Siedowse BIO_printf(bio_err, "Memory allocation failure\n"); 181974462Salfred goto err; 182075641Siedowse } 182175641Siedowse } 18221558Srgrimes if (j < 0) 18231558Srgrimes break; 18241558Srgrimes } 18251558Srgrimes } 182675641Siedowse 182774462Salfred if (preserve) { 182875801Siedowse X509_NAME_free(subject); 182975801Siedowse /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */ 183075801Siedowse subject = X509_NAME_dup(name); 18311558Srgrimes if (subject == NULL) 18321558Srgrimes goto err; 183375801Siedowse } 183474462Salfred 183574462Salfred if (verbose) 183675801Siedowse BIO_printf(bio_err, 183775801Siedowse "The subject name appears to be ok, checking data base for clashes\n"); 183875801Siedowse 183975801Siedowse /* Build the correct Subject if no e-mail is wanted in the subject */ 184075801Siedowse /* 184175801Siedowse * and add it later on because of the method extensions are added 18421558Srgrimes * (altName) 184375641Siedowse */ 184475801Siedowse 184575801Siedowse if (email_dn) 184675801Siedowse dn_subject = subject; 184775801Siedowse else { 184875641Siedowse X509_NAME_ENTRY *tmpne; 18497401Swpaul /* 18507401Swpaul * Its best to dup the subject DN and then delete any email addresses 18517401Swpaul * because this retains its structure. 18521558Srgrimes */ 185337663Scharnier if (!(dn_subject = X509_NAME_dup(subject))) { 18541558Srgrimes BIO_printf(bio_err, "Memory allocation failure\n"); 18551558Srgrimes goto err; 18561558Srgrimes } 18571558Srgrimes while ((i = X509_NAME_get_index_by_NID(dn_subject, 18581558Srgrimes NID_pkcs9_emailAddress, 18591558Srgrimes -1)) >= 0) { 18601558Srgrimes tmpne = X509_NAME_get_entry(dn_subject, i); 18611558Srgrimes X509_NAME_delete_entry(dn_subject, i); 18621558Srgrimes X509_NAME_ENTRY_free(tmpne); 18631558Srgrimes } 186496707Strhodes } 18651558Srgrimes 18669336Sdfr if (BN_is_zero(serial)) 186774462Salfred row[DB_serial] = BUF_strdup("00"); 18681558Srgrimes else 18691558Srgrimes row[DB_serial] = BN_bn2hex(serial); 18701558Srgrimes if (row[DB_serial] == NULL) { 18711558Srgrimes BIO_printf(bio_err, "Memory allocation failure\n"); 1872100336Sjoerg goto err; 1873100336Sjoerg } 18741558Srgrimes 187575635Siedowse if (db->attributes.unique_subject) { 187675635Siedowse OPENSSL_STRING *crow = row; 187775635Siedowse 18781558Srgrimes rrow = TXT_DB_get_by_index(db->db, DB_name, crow); 187937663Scharnier if (rrow != NULL) { 18801558Srgrimes BIO_printf(bio_err, 18811558Srgrimes "ERROR:There is already a certificate for %s\n", 18821558Srgrimes row[DB_name]); 1883100336Sjoerg } 1884100336Sjoerg } 1885100336Sjoerg if (rrow == NULL) { 1886100336Sjoerg rrow = TXT_DB_get_by_index(db->db, DB_serial, row); 1887100336Sjoerg if (rrow != NULL) { 1888100336Sjoerg BIO_printf(bio_err, 1889100336Sjoerg "ERROR:Serial number %s has already been issued,\n", 1890100336Sjoerg row[DB_serial]); 18911558Srgrimes BIO_printf(bio_err, 18921558Srgrimes " check the database/serial_file for corruption\n"); 18931558Srgrimes } 18941558Srgrimes } 18951558Srgrimes 18961558Srgrimes if (rrow != NULL) { 18971558Srgrimes BIO_printf(bio_err, "The matching entry has the following details\n"); 18981558Srgrimes if (rrow[DB_type][0] == 'E') 18991558Srgrimes p = "Expired"; 190037663Scharnier else if (rrow[DB_type][0] == 'R') 190137663Scharnier p = "Revoked"; 19021558Srgrimes else if (rrow[DB_type][0] == 'V') 19031558Srgrimes p = "Valid"; 19041558Srgrimes else 19051558Srgrimes p = "\ninvalid type, Data base error\n"; 190675841Siedowse BIO_printf(bio_err, "Type :%s\n", p);; 190775841Siedowse if (rrow[DB_type][0] == 'R') { 190875841Siedowse p = rrow[DB_exp_date]; 190975841Siedowse if (p == NULL) 191075841Siedowse p = "undef"; 191175841Siedowse BIO_printf(bio_err, "Was revoked on:%s\n", p); 191275841Siedowse } 19131558Srgrimes p = rrow[DB_exp_date]; 191474462Salfred if (p == NULL) 191575641Siedowse p = "undef"; 191674462Salfred BIO_printf(bio_err, "Expires on :%s\n", p); 191775641Siedowse p = rrow[DB_serial]; 19181558Srgrimes if (p == NULL) 19191558Srgrimes p = "undef"; 19201558Srgrimes BIO_printf(bio_err, "Serial Number :%s\n", p); 19211558Srgrimes p = rrow[DB_file]; 19221558Srgrimes if (p == NULL) 19231558Srgrimes p = "undef"; 19241558Srgrimes BIO_printf(bio_err, "File name :%s\n", p); 19251558Srgrimes p = rrow[DB_name]; 19261558Srgrimes if (p == NULL) 192775801Siedowse p = "undef"; 192875801Siedowse BIO_printf(bio_err, "Subject Name :%s\n", p); 19291558Srgrimes ok = -1; /* This is now a 'bad' error. */ 19301558Srgrimes goto err; 19311558Srgrimes } 19321558Srgrimes 19331558Srgrimes /* We are now totally happy, lets make and sign the certificate */ 19341558Srgrimes if (verbose) 19351558Srgrimes BIO_printf(bio_err, 193675861Siedowse "Everything appears to be ok, creating and signing the certificate\n"); 193774462Salfred 193875801Siedowse if ((ret = X509_new()) == NULL) 193975861Siedowse goto err; 194074462Salfred ci = ret->cert_info; 194174462Salfred 194274462Salfred#ifdef X509_V3 19431558Srgrimes /* Make it an X509 v3 certificate. */ 194475635Siedowse if (!X509_set_version(ret, 2)) 194574462Salfred goto err; 194674462Salfred#endif 194774462Salfred 194874462Salfred if (BN_to_ASN1_INTEGER(serial, ci->serialNumber) == NULL) 194974462Salfred goto err; 195074462Salfred if (selfsign) { 195175861Siedowse if (!X509_set_issuer_name(ret, subject)) 195275861Siedowse goto err; 195375861Siedowse } else { 195475861Siedowse if (!X509_set_issuer_name(ret, X509_get_subject_name(x509))) 195575861Siedowse goto err; 195674462Salfred } 195775801Siedowse 195875801Siedowse if (strcmp(startdate, "today") == 0) 195975801Siedowse X509_gmtime_adj(X509_get_notBefore(ret), 0); 196075801Siedowse else 196175801Siedowse ASN1_TIME_set_string(X509_get_notBefore(ret), startdate); 196275801Siedowse 196375801Siedowse if (enddate == NULL) 196474462Salfred X509_time_adj_ex(X509_get_notAfter(ret), days, 0, NULL); 196575861Siedowse else 196675861Siedowse ASN1_TIME_set_string(X509_get_notAfter(ret), enddate); 196775861Siedowse 196874462Salfred if (!X509_set_subject_name(ret, subject)) 196975801Siedowse goto err; 197075801Siedowse 197175801Siedowse pktmp = X509_REQ_get_pubkey(req); 197274462Salfred i = X509_set_pubkey(ret, pktmp); 197375801Siedowse EVP_PKEY_free(pktmp); 197474462Salfred if (!i) 197574462Salfred goto err; 197675801Siedowse 197774462Salfred /* Lets add the extensions, if there are any */ 197875801Siedowse if (ext_sect) { 197975801Siedowse X509V3_CTX ctx; 198074462Salfred if (ci->version == NULL) 198175861Siedowse if ((ci->version = ASN1_INTEGER_new()) == NULL) 198275861Siedowse goto err; 198375861Siedowse ASN1_INTEGER_set(ci->version, 2); /* version 3 certificate */ 198475861Siedowse 198575861Siedowse /* 198675861Siedowse * Free the current entries if any, there should not be any I believe 198775861Siedowse */ 198875861Siedowse if (ci->extensions != NULL) 198975861Siedowse sk_X509_EXTENSION_pop_free(ci->extensions, X509_EXTENSION_free); 199075861Siedowse 199174462Salfred ci->extensions = NULL; 199225318Spst 199375801Siedowse /* Initialize the context structure */ 199475801Siedowse if (selfsign) 199575801Siedowse X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0); 199675801Siedowse else 199775801Siedowse X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0); 199875801Siedowse 199975801Siedowse if (extconf) { 200075801Siedowse if (verbose) 200175801Siedowse BIO_printf(bio_err, "Extra configuration file found\n"); 200274462Salfred 200375801Siedowse /* Use the extconf configuration db LHASH */ 200475801Siedowse X509V3_set_nconf(&ctx, extconf); 200575801Siedowse 200675801Siedowse /* Test the structure (needed?) */ 2007146187Sume /* X509V3_set_ctx_test(&ctx); */ 200875801Siedowse 200975801Siedowse /* Adds exts contained in the configuration file */ 201075801Siedowse if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect, ret)) { 201175801Siedowse BIO_printf(bio_err, 201275801Siedowse "ERROR: adding extensions in section %s\n", 201375801Siedowse ext_sect); 201475801Siedowse ERR_print_errors(bio_err); 201575801Siedowse goto err; 201675801Siedowse } 201775801Siedowse if (verbose) 201875801Siedowse BIO_printf(bio_err, 201974462Salfred "Successfully added extensions from file.\n"); 202074462Salfred } else if (ext_sect) { 202175801Siedowse /* We found extensions to be set from config file */ 202274462Salfred X509V3_set_nconf(&ctx, lconf); 202375801Siedowse 202475801Siedowse if (!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret)) { 202575801Siedowse BIO_printf(bio_err, 202675801Siedowse "ERROR: adding extensions in section %s\n", 202774462Salfred ext_sect); 202875801Siedowse ERR_print_errors(bio_err); 202975801Siedowse goto err; 203075801Siedowse } 203174462Salfred 203275801Siedowse if (verbose) 203375801Siedowse BIO_printf(bio_err, 203475801Siedowse "Successfully added extensions from config\n"); 203575801Siedowse } 203675801Siedowse } 203775801Siedowse 203875801Siedowse /* Copy extensions from request (if any) */ 203975801Siedowse 204075801Siedowse if (!copy_extensions(ret, req, ext_copy)) { 204175801Siedowse BIO_printf(bio_err, "ERROR: adding extensions from request\n"); 204275801Siedowse ERR_print_errors(bio_err); 204375801Siedowse goto err; 204475801Siedowse } 204575801Siedowse 204675801Siedowse /* Set the right value for the noemailDN option */ 204774462Salfred if (email_dn == 0) { 204874462Salfred if (!X509_set_subject_name(ret, dn_subject)) 204974462Salfred goto err; 205074462Salfred } 205174462Salfred 205274462Salfred if (!default_op) { 205374462Salfred BIO_printf(bio_err, "Certificate Details:\n"); 205474462Salfred /* 205574462Salfred * Never print signature details because signature not present 205674462Salfred */ 205774462Salfred certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME; 20581558Srgrimes X509_print_ex(bio_err, ret, nameopt, certopt); 20591558Srgrimes } 20601558Srgrimes 20611558Srgrimes BIO_printf(bio_err, "Certificate is to be certified until "); 20621558Srgrimes ASN1_TIME_print(bio_err, X509_get_notAfter(ret)); 20631558Srgrimes if (days) 20641558Srgrimes BIO_printf(bio_err, " (%ld days)", days); 20651558Srgrimes BIO_printf(bio_err, "\n"); 20661558Srgrimes 20671558Srgrimes if (!batch) { 20681558Srgrimes 20691558Srgrimes BIO_printf(bio_err, "Sign the certificate? [y/n]:"); 20701558Srgrimes (void)BIO_flush(bio_err); 20711558Srgrimes buf[0] = '\0'; 20721558Srgrimes if (!fgets(buf, sizeof(buf) - 1, stdin)) { 20731558Srgrimes BIO_printf(bio_err, 20741558Srgrimes "CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n"); 20751558Srgrimes ok = 0; 20761558Srgrimes goto err; 20771558Srgrimes } 20781558Srgrimes if (!((buf[0] == 'y') || (buf[0] == 'Y'))) { 20791558Srgrimes BIO_printf(bio_err, "CERTIFICATE WILL NOT BE CERTIFIED\n"); 20801558Srgrimes ok = 0; 20811558Srgrimes goto err; 20821558Srgrimes } 20831558Srgrimes } 20841558Srgrimes 20851558Srgrimes pktmp = X509_get_pubkey(ret); 20861558Srgrimes if (EVP_PKEY_missing_parameters(pktmp) && 20871558Srgrimes !EVP_PKEY_missing_parameters(pkey)) 20881558Srgrimes EVP_PKEY_copy_parameters(pktmp, pkey); 20891558Srgrimes EVP_PKEY_free(pktmp); 20901558Srgrimes 209196622Siedowse if (!do_X509_sign(bio_err, ret, pkey, dgst, sigopts)) 20921558Srgrimes goto err; 20931558Srgrimes 20941558Srgrimes /* We now just add it to the database */ 20951558Srgrimes row[DB_type] = (char *)OPENSSL_malloc(2); 20961558Srgrimes 20971558Srgrimes tm = X509_get_notAfter(ret); 20981558Srgrimes row[DB_exp_date] = (char *)OPENSSL_malloc(tm->length + 1); 20991558Srgrimes memcpy(row[DB_exp_date], tm->data, tm->length); 210096622Siedowse row[DB_exp_date][tm->length] = '\0'; 21011558Srgrimes 21021558Srgrimes row[DB_rev_date] = NULL; 21031558Srgrimes 21041558Srgrimes /* row[DB_serial] done already */ 21051558Srgrimes row[DB_file] = (char *)OPENSSL_malloc(8); 21061558Srgrimes row[DB_name] = X509_NAME_oneline(X509_get_subject_name(ret), NULL, 0); 21071558Srgrimes 21081558Srgrimes if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || 21091558Srgrimes (row[DB_file] == NULL) || (row[DB_name] == NULL)) { 21101558Srgrimes BIO_printf(bio_err, "Memory allocation failure\n"); 211179117Sdd goto err; 211279117Sdd } 211379117Sdd BUF_strlcpy(row[DB_file], "unknown", 8); 211479117Sdd row[DB_type][0] = 'V'; 211596622Siedowse row[DB_type][1] = '\0'; 211696622Siedowse 211796622Siedowse if ((irow = 211896622Siedowse (char **)OPENSSL_malloc(sizeof(char *) * (DB_NUMBER + 1))) == NULL) { 211996622Siedowse BIO_printf(bio_err, "Memory allocation failure\n"); 21201558Srgrimes goto err; 212196622Siedowse } 212296622Siedowse 212396622Siedowse for (i = 0; i < DB_NUMBER; i++) { 21241558Srgrimes irow[i] = row[i]; 21251558Srgrimes row[i] = NULL; 21261558Srgrimes } 21271558Srgrimes irow[DB_NUMBER] = NULL; 21281558Srgrimes 21291558Srgrimes if (!TXT_DB_insert(db->db, irow)) { 21301558Srgrimes BIO_printf(bio_err, "failed to update database\n"); 21311558Srgrimes BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error); 21321558Srgrimes goto err; 21331558Srgrimes } 213472650Sgreen ok = 1; 21351558Srgrimes err: 21361558Srgrimes for (i = 0; i < DB_NUMBER; i++) 21371558Srgrimes if (row[i] != NULL) 21381558Srgrimes OPENSSL_free(row[i]); 21391558Srgrimes 21401558Srgrimes if (CAname != NULL) 2141136051Sstefanf X509_NAME_free(CAname); 2142136051Sstefanf if (subject != NULL) 21431558Srgrimes X509_NAME_free(subject); 214491354Sdd if ((dn_subject != NULL) && !email_dn) 21451558Srgrimes X509_NAME_free(dn_subject); 214637663Scharnier if (tmptm != NULL) 21471558Srgrimes ASN1_UTCTIME_free(tmptm); 21481558Srgrimes if (ok <= 0) { 21491558Srgrimes if (ret != NULL) 21501558Srgrimes X509_free(ret); 21511558Srgrimes ret = NULL; 21521558Srgrimes } else 21531558Srgrimes *xret = ret; 21541558Srgrimes return (ok); 21551558Srgrimes} 21561558Srgrimes 21571558Srgrimesstatic void write_new_certificate(BIO *bp, X509 *x, int output_der, 21581558Srgrimes int notext) 21591558Srgrimes{ 21601558Srgrimes 21611558Srgrimes if (output_der) { 21621558Srgrimes (void)i2d_X509_bio(bp, x); 21631558Srgrimes return; 21641558Srgrimes } 216537663Scharnier#if 0 21661558Srgrimes /* ??? Not needed since X509_print prints all this stuff anyway */ 21671558Srgrimes f = X509_NAME_oneline(X509_get_issuer_name(x), buf, 256); 21681558Srgrimes BIO_printf(bp, "issuer :%s\n", f); 21691558Srgrimes 21701558Srgrimes f = X509_NAME_oneline(X509_get_subject_name(x), buf, 256); 217137663Scharnier BIO_printf(bp, "subject:%s\n", f); 21721558Srgrimes 2173136051Sstefanf BIO_puts(bp, "serial :"); 21741558Srgrimes i2a_ASN1_INTEGER(bp, x->cert_info->serialNumber); 21751558Srgrimes BIO_puts(bp, "\n\n"); 21761558Srgrimes#endif 21771558Srgrimes if (!notext) 21781558Srgrimes X509_print(bp, x); 21791558Srgrimes PEM_write_bio_X509(bp, x); 21801558Srgrimes} 21811558Srgrimes 21821558Srgrimesstatic int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, 21831558Srgrimes X509 *x509, const EVP_MD *dgst, 21841558Srgrimes STACK_OF(OPENSSL_STRING) *sigopts, 21851558Srgrimes STACK_OF(CONF_VALUE) *policy, CA_DB *db, 21861558Srgrimes BIGNUM *serial, char *subj, unsigned long chtype, 21871558Srgrimes int multirdn, int email_dn, char *startdate, 21881558Srgrimes char *enddate, long days, char *ext_sect, 21891558Srgrimes CONF *lconf, int verbose, unsigned long certopt, 219037663Scharnier unsigned long nameopt, int default_op, int ext_copy) 21911558Srgrimes{ 21921558Srgrimes STACK_OF(CONF_VALUE) *sk = NULL; 21931558Srgrimes LHASH_OF(CONF_VALUE) *parms = NULL; 21941558Srgrimes X509_REQ *req = NULL; 21951558Srgrimes CONF_VALUE *cv = NULL; 21961558Srgrimes NETSCAPE_SPKI *spki = NULL; 21971558Srgrimes X509_REQ_INFO *ri; 21981558Srgrimes char *type, *buf; 21991558Srgrimes EVP_PKEY *pktmp = NULL; 220037663Scharnier X509_NAME *n = NULL; 22011558Srgrimes X509_NAME_ENTRY *ne = NULL; 22021558Srgrimes int ok = -1, i, j; 22031558Srgrimes long errline; 22041558Srgrimes int nid; 22051558Srgrimes 22061558Srgrimes /* 220737663Scharnier * Load input file into a hash table. (This is just an easy 22081558Srgrimes * way to read and parse the file, then put it into a convenient 22091558Srgrimes * STACK format). 22101558Srgrimes */ 22111558Srgrimes parms = CONF_load(NULL, infile, &errline); 22121558Srgrimes if (parms == NULL) { 22131558Srgrimes BIO_printf(bio_err, "error on line %ld of %s\n", errline, infile); 22141558Srgrimes ERR_print_errors(bio_err); 22151558Srgrimes goto err; 22161558Srgrimes } 22171558Srgrimes 221823681Speter sk = CONF_get_section(parms, "default"); 22191558Srgrimes if (sk_CONF_VALUE_num(sk) == 0) { 22201558Srgrimes BIO_printf(bio_err, "no name/value pairs found in %s\n", infile); 22211558Srgrimes CONF_free(parms); 22221558Srgrimes goto err; 222353117Sbillf } 222453117Sbillf 222553117Sbillf /* 222653117Sbillf * Now create a dummy X509 request structure. We don't actually 222753117Sbillf * have an X509 request, but we have many of the components 222853117Sbillf * (a public key, various DN components). The idea is that we 22291558Srgrimes * put these components into the right X509 request structure 22301558Srgrimes * and we can use the same code as if you had a real X509 request. 22311558Srgrimes */ 223223681Speter req = X509_REQ_new(); 223323681Speter if (req == NULL) { 223423681Speter ERR_print_errors(bio_err); 223523681Speter goto err; 22361558Srgrimes } 22371558Srgrimes 223837663Scharnier /* 223937663Scharnier * Build up the subject name set. 224023681Speter */ 224123681Speter ri = req->req_info; 224223681Speter n = ri->subject; 224323681Speter 22441558Srgrimes for (i = 0;; i++) { 22451558Srgrimes if (sk_CONF_VALUE_num(sk) <= i) 22461558Srgrimes break; 22471558Srgrimes 22481558Srgrimes cv = sk_CONF_VALUE_value(sk, i); 22491558Srgrimes type = cv->name; 22501558Srgrimes /* 225175635Siedowse * Skip past any leading X. X: X, etc to allow for multiple instances 225275635Siedowse */ 22531558Srgrimes for (buf = cv->name; *buf; buf++) 22541558Srgrimes if ((*buf == ':') || (*buf == ',') || (*buf == '.')) { 22551558Srgrimes buf++; 22561558Srgrimes if (*buf) 22571558Srgrimes type = buf; 22581558Srgrimes break; 22591558Srgrimes } 22601558Srgrimes 22611558Srgrimes buf = cv->value; 22621558Srgrimes if ((nid = OBJ_txt2nid(type)) == NID_undef) { 22631558Srgrimes if (strcmp(type, "SPKAC") == 0) { 22641558Srgrimes spki = NETSCAPE_SPKI_b64_decode(cv->value, -1); 22651558Srgrimes if (spki == NULL) { 22661558Srgrimes BIO_printf(bio_err, 22671558Srgrimes "unable to load Netscape SPKAC structure\n"); 22681558Srgrimes ERR_print_errors(bio_err); 22691558Srgrimes goto err; 22701558Srgrimes } 22711558Srgrimes } 22721558Srgrimes continue; 22731558Srgrimes } 22741558Srgrimes 227537663Scharnier if (!X509_NAME_add_entry_by_NID(n, nid, chtype, 22761558Srgrimes (unsigned char *)buf, -1, -1, 0)) 22771558Srgrimes goto err; 22781558Srgrimes } 22791558Srgrimes if (spki == NULL) { 22801558Srgrimes BIO_printf(bio_err, "Netscape SPKAC structure not found in %s\n", 22811558Srgrimes infile); 22821558Srgrimes goto err; 22831558Srgrimes } 22841558Srgrimes 22851558Srgrimes /* 22861558Srgrimes * Now extract the key from the SPKI structure. 22871558Srgrimes */ 22881558Srgrimes 22891558Srgrimes BIO_printf(bio_err, 22901558Srgrimes "Check that the SPKAC request matches the signature\n"); 22911558Srgrimes 22921558Srgrimes if ((pktmp = NETSCAPE_SPKI_get_pubkey(spki)) == NULL) { 22931558Srgrimes BIO_printf(bio_err, "error unpacking SPKAC public key\n"); 22941558Srgrimes goto err; 22951558Srgrimes } 22961558Srgrimes 22971558Srgrimes j = NETSCAPE_SPKI_verify(spki, pktmp); 22981558Srgrimes if (j <= 0) { 22991558Srgrimes BIO_printf(bio_err, 23001558Srgrimes "signature verification failed on SPKAC public key\n"); 23011558Srgrimes goto err; 23021558Srgrimes } 230337663Scharnier BIO_printf(bio_err, "Signature ok\n"); 230437663Scharnier 23051558Srgrimes X509_REQ_set_pubkey(req, pktmp); 23061558Srgrimes EVP_PKEY_free(pktmp); 23071558Srgrimes ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj, 23081558Srgrimes chtype, multirdn, email_dn, startdate, enddate, days, 1, 23091558Srgrimes verbose, req, ext_sect, lconf, certopt, nameopt, default_op, 23101558Srgrimes ext_copy, 0); 23111558Srgrimes err: 231237663Scharnier if (req != NULL) 23131558Srgrimes X509_REQ_free(req); 23141558Srgrimes if (parms != NULL) 23151558Srgrimes CONF_free(parms); 23161558Srgrimes if (spki != NULL) 23171558Srgrimes NETSCAPE_SPKI_free(spki); 23181558Srgrimes if (ne != NULL) 23191558Srgrimes X509_NAME_ENTRY_free(ne); 23201558Srgrimes 23211558Srgrimes return (ok); 23221558Srgrimes} 23231558Srgrimes 23241558Srgrimesstatic int check_time_format(const char *str) 23251558Srgrimes{ 23261558Srgrimes return ASN1_TIME_set_string(NULL, str); 232774462Salfred} 232874462Salfred 23291558Srgrimesstatic int do_revoke(X509 *x509, CA_DB *db, int type, char *value) 23301558Srgrimes{ 23311558Srgrimes ASN1_UTCTIME *tm = NULL; 23321558Srgrimes char *row[DB_NUMBER], **rrow, **irow; 23331558Srgrimes char *rev_str = NULL; 23341558Srgrimes BIGNUM *bn = NULL; 23351558Srgrimes int ok = -1, i; 23361558Srgrimes 23371558Srgrimes for (i = 0; i < DB_NUMBER; i++) 23381558Srgrimes row[i] = NULL; 23391558Srgrimes row[DB_name] = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0); 23401558Srgrimes bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509), NULL); 23411558Srgrimes if (!bn) 23421558Srgrimes goto err; 23431558Srgrimes if (BN_is_zero(bn)) 23441558Srgrimes row[DB_serial] = BUF_strdup("00"); 23451558Srgrimes else 23461558Srgrimes row[DB_serial] = BN_bn2hex(bn); 23471558Srgrimes BN_free(bn); 23481558Srgrimes if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) { 23491558Srgrimes BIO_printf(bio_err, "Memory allocation failure\n"); 23501558Srgrimes goto err; 23511558Srgrimes } 23521558Srgrimes /* 23531558Srgrimes * We have to lookup by serial number because name lookup skips revoked 23541558Srgrimes * certs 23551558Srgrimes */ 23561558Srgrimes rrow = TXT_DB_get_by_index(db->db, DB_serial, row); 23571558Srgrimes if (rrow == NULL) { 235883653Speter BIO_printf(bio_err, 235983653Speter "Adding Entry with serial number %s to DB for %s\n", 23601558Srgrimes row[DB_serial], row[DB_name]); 23611558Srgrimes 23621558Srgrimes /* We now just add it to the database */ 236375801Siedowse row[DB_type] = (char *)OPENSSL_malloc(2); 236475801Siedowse 23651558Srgrimes tm = X509_get_notAfter(x509); 236675801Siedowse row[DB_exp_date] = (char *)OPENSSL_malloc(tm->length + 1); 236775801Siedowse memcpy(row[DB_exp_date], tm->data, tm->length); 236875801Siedowse row[DB_exp_date][tm->length] = '\0'; 236975801Siedowse 237075801Siedowse row[DB_rev_date] = NULL; 237175801Siedowse 237275801Siedowse /* row[DB_serial] done already */ 237375801Siedowse row[DB_file] = (char *)OPENSSL_malloc(8); 23741558Srgrimes 237545927Salex /* row[DB_name] done already */ 23761558Srgrimes 23771558Srgrimes if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || 23781558Srgrimes (row[DB_file] == NULL)) { 23791558Srgrimes BIO_printf(bio_err, "Memory allocation failure\n"); 23801558Srgrimes goto err; 23811558Srgrimes } 23821558Srgrimes BUF_strlcpy(row[DB_file], "unknown", 8); 23831558Srgrimes row[DB_type][0] = 'V'; 23841558Srgrimes row[DB_type][1] = '\0'; 23851558Srgrimes 23861558Srgrimes if ((irow = 23871558Srgrimes (char **)OPENSSL_malloc(sizeof(char *) * (DB_NUMBER + 1))) == 23881558Srgrimes NULL) { 23891558Srgrimes BIO_printf(bio_err, "Memory allocation failure\n"); 23901558Srgrimes goto err; 23911558Srgrimes } 23921558Srgrimes 23931558Srgrimes for (i = 0; i < DB_NUMBER; i++) { 23941558Srgrimes irow[i] = row[i]; 23951558Srgrimes row[i] = NULL; 23969336Sdfr } 23971558Srgrimes irow[DB_NUMBER] = NULL; 23981558Srgrimes 23991558Srgrimes if (!TXT_DB_insert(db->db, irow)) { 24001558Srgrimes BIO_printf(bio_err, "failed to update database\n"); 24011558Srgrimes BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error); 24029336Sdfr goto err; 24031558Srgrimes } 24041558Srgrimes 24051558Srgrimes /* Revoke Certificate */ 24069336Sdfr ok = do_revoke(x509, db, type, value); 240775801Siedowse 240875801Siedowse goto err; 240975801Siedowse 241075801Siedowse } else if (index_name_cmp_noconst(row, rrow)) { 241175801Siedowse BIO_printf(bio_err, "ERROR:name does not match %s\n", row[DB_name]); 241275801Siedowse goto err; 241374462Salfred } else if (rrow[DB_type][0] == 'R') { 241475801Siedowse BIO_printf(bio_err, "ERROR:Already revoked, serial number %s\n", 241575801Siedowse row[DB_serial]); 241674462Salfred goto err; 241775801Siedowse } else { 241875801Siedowse BIO_printf(bio_err, "Revoking Certificate %s.\n", rrow[DB_serial]); 2419103949Smike rev_str = make_revocation_str(type, value); 242075801Siedowse if (!rev_str) { 242174462Salfred BIO_printf(bio_err, "Error in revocation arguments\n"); 242275801Siedowse goto err; 2423103949Smike } 242475801Siedowse rrow[DB_type][0] = 'R'; 242575801Siedowse rrow[DB_type][1] = '\0'; 242674462Salfred rrow[DB_rev_date] = rev_str; 242775801Siedowse } 242874462Salfred ok = 1; 242974462Salfred err: 243075801Siedowse for (i = 0; i < DB_NUMBER; i++) { 243175801Siedowse if (row[i] != NULL) 243275801Siedowse OPENSSL_free(row[i]); 243375801Siedowse } 243475801Siedowse return (ok); 243575801Siedowse} 243674462Salfred 243775801Siedowsestatic int get_certificate_status(const char *serial, CA_DB *db) 243875801Siedowse{ 243974462Salfred char *row[DB_NUMBER], **rrow; 244075801Siedowse int ok = -1, i; 244175801Siedowse 244275801Siedowse /* Free Resources */ 244375801Siedowse for (i = 0; i < DB_NUMBER; i++) 244475801Siedowse row[i] = NULL; 244575801Siedowse 244675801Siedowse /* Malloc needed char spaces */ 244775801Siedowse row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2); 244875801Siedowse if (row[DB_serial] == NULL) { 244975801Siedowse BIO_printf(bio_err, "Malloc failure\n"); 245074462Salfred goto err; 245175801Siedowse } 245275801Siedowse 245375801Siedowse if (strlen(serial) % 2) { 245475801Siedowse /* 245574462Salfred * Set the first char to 0 245674462Salfred */ ; 245775801Siedowse row[DB_serial][0] = '0'; 245875801Siedowse 245975801Siedowse /* Copy String from serial to row[DB_serial] */ 246075801Siedowse memcpy(row[DB_serial] + 1, serial, strlen(serial)); 246175801Siedowse row[DB_serial][strlen(serial) + 1] = '\0'; 246275801Siedowse } else { 246375801Siedowse /* Copy String from serial to row[DB_serial] */ 246474462Salfred memcpy(row[DB_serial], serial, strlen(serial)); 246575801Siedowse row[DB_serial][strlen(serial)] = '\0'; 246675801Siedowse } 246774462Salfred 246875801Siedowse /* Make it Upper Case */ 246975801Siedowse for (i = 0; row[DB_serial][i] != '\0'; i++) 247075801Siedowse row[DB_serial][i] = toupper((unsigned char)row[DB_serial][i]); 247175801Siedowse 247275801Siedowse ok = 1; 247375801Siedowse 247474462Salfred /* Search for the certificate */ 247575801Siedowse rrow = TXT_DB_get_by_index(db->db, DB_serial, row); 247675801Siedowse if (rrow == NULL) { 247775801Siedowse BIO_printf(bio_err, "Serial %s not present in db.\n", row[DB_serial]); 247874462Salfred ok = -1; 247974462Salfred goto err; 248074462Salfred } else if (rrow[DB_type][0] == 'V') { 248175801Siedowse BIO_printf(bio_err, "%s=Valid (%c)\n", 248275801Siedowse row[DB_serial], rrow[DB_type][0]); 248375801Siedowse goto err; 248474462Salfred } else if (rrow[DB_type][0] == 'R') { 248575801Siedowse BIO_printf(bio_err, "%s=Revoked (%c)\n", 248675801Siedowse row[DB_serial], rrow[DB_type][0]); 248775801Siedowse goto err; 248875801Siedowse } else if (rrow[DB_type][0] == 'E') { 248974462Salfred BIO_printf(bio_err, "%s=Expired (%c)\n", 249075801Siedowse row[DB_serial], rrow[DB_type][0]); 249175801Siedowse goto err; 249275801Siedowse } else if (rrow[DB_type][0] == 'S') { 249375801Siedowse BIO_printf(bio_err, "%s=Suspended (%c)\n", 249474462Salfred row[DB_serial], rrow[DB_type][0]); 249574462Salfred goto err; 249675801Siedowse } else { 249775801Siedowse BIO_printf(bio_err, "%s=Unknown (%c).\n", 249875801Siedowse row[DB_serial], rrow[DB_type][0]); 249975801Siedowse ok = -1; 250075801Siedowse } 250175801Siedowse err: 250275801Siedowse for (i = 0; i < DB_NUMBER; i++) { 250375801Siedowse if (row[i] != NULL) 250474462Salfred OPENSSL_free(row[i]); 250574462Salfred } 250675801Siedowse return (ok); 250774462Salfred} 250875801Siedowse 250975801Siedowsestatic int do_updatedb(CA_DB *db) 251074462Salfred{ 251174462Salfred ASN1_UTCTIME *a_tm = NULL; 251275801Siedowse int i, cnt = 0; 251375801Siedowse int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */ 251474462Salfred char **rrow, *a_tm_s; 251574462Salfred 251675801Siedowse a_tm = ASN1_UTCTIME_new(); 251775801Siedowse if (a_tm == NULL) 251874462Salfred return -1; 251974462Salfred 252075801Siedowse /* get actual time and make a string */ 252175801Siedowse a_tm = X509_gmtime_adj(a_tm, 0); 252275801Siedowse a_tm_s = (char *)OPENSSL_malloc(a_tm->length + 1); 252374462Salfred if (a_tm_s == NULL) { 252474462Salfred cnt = -1; 252575754Siedowse goto err; 252675754Siedowse } 252775754Siedowse 252875754Siedowse memcpy(a_tm_s, a_tm->data, a_tm->length); 252975754Siedowse a_tm_s[a_tm->length] = '\0'; 253075754Siedowse 253174462Salfred if (strncmp(a_tm_s, "49", 2) <= 0) 253274462Salfred a_y2k = 1; 253374462Salfred else 253474462Salfred a_y2k = 0; 253574462Salfred 253674792Salfred for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { 253774792Salfred rrow = sk_OPENSSL_PSTRING_value(db->db->data, i); 253874462Salfred 253974462Salfred if (rrow[DB_type][0] == 'V') { 2540 /* ignore entries that are not valid */ 2541 if (strncmp(rrow[DB_exp_date], "49", 2) <= 0) 2542 db_y2k = 1; 2543 else 2544 db_y2k = 0; 2545 2546 if (db_y2k == a_y2k) { 2547 /* all on the same y2k side */ 2548 if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0) { 2549 rrow[DB_type][0] = 'E'; 2550 rrow[DB_type][1] = '\0'; 2551 cnt++; 2552 2553 BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]); 2554 } 2555 } else if (db_y2k < a_y2k) { 2556 rrow[DB_type][0] = 'E'; 2557 rrow[DB_type][1] = '\0'; 2558 cnt++; 2559 2560 BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]); 2561 } 2562 2563 } 2564 } 2565 2566 err: 2567 2568 ASN1_UTCTIME_free(a_tm); 2569 OPENSSL_free(a_tm_s); 2570 2571 return (cnt); 2572} 2573 2574static const char *crl_reasons[] = { 2575 /* CRL reason strings */ 2576 "unspecified", 2577 "keyCompromise", 2578 "CACompromise", 2579 "affiliationChanged", 2580 "superseded", 2581 "cessationOfOperation", 2582 "certificateHold", 2583 "removeFromCRL", 2584 /* Additional pseudo reasons */ 2585 "holdInstruction", 2586 "keyTime", 2587 "CAkeyTime" 2588}; 2589 2590#define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *)) 2591 2592/* 2593 * Given revocation information convert to a DB string. The format of the 2594 * string is: revtime[,reason,extra]. Where 'revtime' is the revocation time 2595 * (the current time). 'reason' is the optional CRL reason and 'extra' is any 2596 * additional argument 2597 */ 2598 2599char *make_revocation_str(int rev_type, char *rev_arg) 2600{ 2601 char *other = NULL, *str; 2602 const char *reason = NULL; 2603 ASN1_OBJECT *otmp; 2604 ASN1_UTCTIME *revtm = NULL; 2605 int i; 2606 switch (rev_type) { 2607 case REV_NONE: 2608 break; 2609 2610 case REV_CRL_REASON: 2611 for (i = 0; i < 8; i++) { 2612 if (!strcasecmp(rev_arg, crl_reasons[i])) { 2613 reason = crl_reasons[i]; 2614 break; 2615 } 2616 } 2617 if (reason == NULL) { 2618 BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg); 2619 return NULL; 2620 } 2621 break; 2622 2623 case REV_HOLD: 2624 /* Argument is an OID */ 2625 2626 otmp = OBJ_txt2obj(rev_arg, 0); 2627 ASN1_OBJECT_free(otmp); 2628 2629 if (otmp == NULL) { 2630 BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg); 2631 return NULL; 2632 } 2633 2634 reason = "holdInstruction"; 2635 other = rev_arg; 2636 break; 2637 2638 case REV_KEY_COMPROMISE: 2639 case REV_CA_COMPROMISE: 2640 2641 /* Argument is the key compromise time */ 2642 if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg)) { 2643 BIO_printf(bio_err, 2644 "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", 2645 rev_arg); 2646 return NULL; 2647 } 2648 other = rev_arg; 2649 if (rev_type == REV_KEY_COMPROMISE) 2650 reason = "keyTime"; 2651 else 2652 reason = "CAkeyTime"; 2653 2654 break; 2655 2656 } 2657 2658 revtm = X509_gmtime_adj(NULL, 0); 2659 2660 if (!revtm) 2661 return NULL; 2662 2663 i = revtm->length + 1; 2664 2665 if (reason) 2666 i += strlen(reason) + 1; 2667 if (other) 2668 i += strlen(other) + 1; 2669 2670 str = OPENSSL_malloc(i); 2671 2672 if (!str) 2673 return NULL; 2674 2675 BUF_strlcpy(str, (char *)revtm->data, i); 2676 if (reason) { 2677 BUF_strlcat(str, ",", i); 2678 BUF_strlcat(str, reason, i); 2679 } 2680 if (other) { 2681 BUF_strlcat(str, ",", i); 2682 BUF_strlcat(str, other, i); 2683 } 2684 ASN1_UTCTIME_free(revtm); 2685 return str; 2686} 2687 2688/*- 2689 * Convert revocation field to X509_REVOKED entry 2690 * return code: 2691 * 0 error 2692 * 1 OK 2693 * 2 OK and some extensions added (i.e. V2 CRL) 2694 */ 2695 2696int make_revoked(X509_REVOKED *rev, const char *str) 2697{ 2698 char *tmp = NULL; 2699 int reason_code = -1; 2700 int i, ret = 0; 2701 ASN1_OBJECT *hold = NULL; 2702 ASN1_GENERALIZEDTIME *comp_time = NULL; 2703 ASN1_ENUMERATED *rtmp = NULL; 2704 2705 ASN1_TIME *revDate = NULL; 2706 2707 i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str); 2708 2709 if (i == 0) 2710 goto err; 2711 2712 if (rev && !X509_REVOKED_set_revocationDate(rev, revDate)) 2713 goto err; 2714 2715 if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)) { 2716 rtmp = ASN1_ENUMERATED_new(); 2717 if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code)) 2718 goto err; 2719 if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0)) 2720 goto err; 2721 } 2722 2723 if (rev && comp_time) { 2724 if (!X509_REVOKED_add1_ext_i2d 2725 (rev, NID_invalidity_date, comp_time, 0, 0)) 2726 goto err; 2727 } 2728 if (rev && hold) { 2729 if (!X509_REVOKED_add1_ext_i2d 2730 (rev, NID_hold_instruction_code, hold, 0, 0)) 2731 goto err; 2732 } 2733 2734 if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS) 2735 ret = 2; 2736 else 2737 ret = 1; 2738 2739 err: 2740 2741 if (tmp) 2742 OPENSSL_free(tmp); 2743 ASN1_OBJECT_free(hold); 2744 ASN1_GENERALIZEDTIME_free(comp_time); 2745 ASN1_ENUMERATED_free(rtmp); 2746 ASN1_TIME_free(revDate); 2747 2748 return ret; 2749} 2750 2751int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str) 2752{ 2753 char buf[25], *pbuf, *p; 2754 int j; 2755 j = i2a_ASN1_OBJECT(bp, obj); 2756 pbuf = buf; 2757 for (j = 22 - j; j > 0; j--) 2758 *(pbuf++) = ' '; 2759 *(pbuf++) = ':'; 2760 *(pbuf++) = '\0'; 2761 BIO_puts(bp, buf); 2762 2763 if (str->type == V_ASN1_PRINTABLESTRING) 2764 BIO_printf(bp, "PRINTABLE:'"); 2765 else if (str->type == V_ASN1_T61STRING) 2766 BIO_printf(bp, "T61STRING:'"); 2767 else if (str->type == V_ASN1_IA5STRING) 2768 BIO_printf(bp, "IA5STRING:'"); 2769 else if (str->type == V_ASN1_UNIVERSALSTRING) 2770 BIO_printf(bp, "UNIVERSALSTRING:'"); 2771 else 2772 BIO_printf(bp, "ASN.1 %2d:'", str->type); 2773 2774 p = (char *)str->data; 2775 for (j = str->length; j > 0; j--) { 2776 if ((*p >= ' ') && (*p <= '~')) 2777 BIO_printf(bp, "%c", *p); 2778 else if (*p & 0x80) 2779 BIO_printf(bp, "\\0x%02X", *p); 2780 else if ((unsigned char)*p == 0xf7) 2781 BIO_printf(bp, "^?"); 2782 else 2783 BIO_printf(bp, "^%c", *p + '@'); 2784 p++; 2785 } 2786 BIO_printf(bp, "'\n"); 2787 return 1; 2788} 2789 2790int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, 2791 ASN1_GENERALIZEDTIME **pinvtm, const char *str) 2792{ 2793 char *tmp = NULL; 2794 char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p; 2795 int reason_code = -1; 2796 int ret = 0; 2797 unsigned int i; 2798 ASN1_OBJECT *hold = NULL; 2799 ASN1_GENERALIZEDTIME *comp_time = NULL; 2800 tmp = BUF_strdup(str); 2801 2802 if (!tmp) { 2803 BIO_printf(bio_err, "memory allocation failure\n"); 2804 goto err; 2805 } 2806 2807 p = strchr(tmp, ','); 2808 2809 rtime_str = tmp; 2810 2811 if (p) { 2812 *p = '\0'; 2813 p++; 2814 reason_str = p; 2815 p = strchr(p, ','); 2816 if (p) { 2817 *p = '\0'; 2818 arg_str = p + 1; 2819 } 2820 } 2821 2822 if (prevtm) { 2823 *prevtm = ASN1_UTCTIME_new(); 2824 if (!*prevtm) { 2825 BIO_printf(bio_err, "memory allocation failure\n"); 2826 goto err; 2827 } 2828 if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str)) { 2829 BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str); 2830 goto err; 2831 } 2832 } 2833 if (reason_str) { 2834 for (i = 0; i < NUM_REASONS; i++) { 2835 if (!strcasecmp(reason_str, crl_reasons[i])) { 2836 reason_code = i; 2837 break; 2838 } 2839 } 2840 if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS) { 2841 BIO_printf(bio_err, "invalid reason code %s\n", reason_str); 2842 goto err; 2843 } 2844 2845 if (reason_code == 7) 2846 reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL; 2847 else if (reason_code == 8) { /* Hold instruction */ 2848 if (!arg_str) { 2849 BIO_printf(bio_err, "missing hold instruction\n"); 2850 goto err; 2851 } 2852 reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD; 2853 hold = OBJ_txt2obj(arg_str, 0); 2854 2855 if (!hold) { 2856 BIO_printf(bio_err, "invalid object identifier %s\n", 2857 arg_str); 2858 goto err; 2859 } 2860 if (phold) 2861 *phold = hold; 2862 } else if ((reason_code == 9) || (reason_code == 10)) { 2863 if (!arg_str) { 2864 BIO_printf(bio_err, "missing compromised time\n"); 2865 goto err; 2866 } 2867 comp_time = ASN1_GENERALIZEDTIME_new(); 2868 if (!comp_time) { 2869 BIO_printf(bio_err, "memory allocation failure\n"); 2870 goto err; 2871 } 2872 if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str)) { 2873 BIO_printf(bio_err, "invalid compromised time %s\n", arg_str); 2874 goto err; 2875 } 2876 if (reason_code == 9) 2877 reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE; 2878 else 2879 reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE; 2880 } 2881 } 2882 2883 if (preason) 2884 *preason = reason_code; 2885 if (pinvtm) 2886 *pinvtm = comp_time; 2887 else 2888 ASN1_GENERALIZEDTIME_free(comp_time); 2889 2890 ret = 1; 2891 2892 err: 2893 2894 if (tmp) 2895 OPENSSL_free(tmp); 2896 if (!phold) 2897 ASN1_OBJECT_free(hold); 2898 if (!pinvtm) 2899 ASN1_GENERALIZEDTIME_free(comp_time); 2900 2901 return ret; 2902} 2903