1*0Sstevel@tonic-gate /* apps/ca.c */ 2*0Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3*0Sstevel@tonic-gate * All rights reserved. 4*0Sstevel@tonic-gate * 5*0Sstevel@tonic-gate * This package is an SSL implementation written 6*0Sstevel@tonic-gate * by Eric Young (eay@cryptsoft.com). 7*0Sstevel@tonic-gate * The implementation was written so as to conform with Netscapes SSL. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * This library is free for commercial and non-commercial use as long as 10*0Sstevel@tonic-gate * the following conditions are aheared to. The following conditions 11*0Sstevel@tonic-gate * apply to all code found in this distribution, be it the RC4, RSA, 12*0Sstevel@tonic-gate * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13*0Sstevel@tonic-gate * included with this distribution is covered by the same copyright terms 14*0Sstevel@tonic-gate * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15*0Sstevel@tonic-gate * 16*0Sstevel@tonic-gate * Copyright remains Eric Young's, and as such any Copyright notices in 17*0Sstevel@tonic-gate * the code are not to be removed. 18*0Sstevel@tonic-gate * If this package is used in a product, Eric Young should be given attribution 19*0Sstevel@tonic-gate * as the author of the parts of the library used. 20*0Sstevel@tonic-gate * This can be in the form of a textual message at program startup or 21*0Sstevel@tonic-gate * in documentation (online or textual) provided with the package. 22*0Sstevel@tonic-gate * 23*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 24*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 25*0Sstevel@tonic-gate * are met: 26*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the copyright 27*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 28*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 29*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 30*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 31*0Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 32*0Sstevel@tonic-gate * must display the following acknowledgement: 33*0Sstevel@tonic-gate * "This product includes cryptographic software written by 34*0Sstevel@tonic-gate * Eric Young (eay@cryptsoft.com)" 35*0Sstevel@tonic-gate * The word 'cryptographic' can be left out if the rouines from the library 36*0Sstevel@tonic-gate * being used are not cryptographic related :-). 37*0Sstevel@tonic-gate * 4. If you include any Windows specific code (or a derivative thereof) from 38*0Sstevel@tonic-gate * the apps directory (application code) you must include an acknowledgement: 39*0Sstevel@tonic-gate * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40*0Sstevel@tonic-gate * 41*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42*0Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43*0Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44*0Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45*0Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46*0Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47*0Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48*0Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49*0Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50*0Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51*0Sstevel@tonic-gate * SUCH DAMAGE. 52*0Sstevel@tonic-gate * 53*0Sstevel@tonic-gate * The licence and distribution terms for any publically available version or 54*0Sstevel@tonic-gate * derivative of this code cannot be changed. i.e. this code cannot simply be 55*0Sstevel@tonic-gate * copied and put under another distribution licence 56*0Sstevel@tonic-gate * [including the GNU Public Licence.] 57*0Sstevel@tonic-gate */ 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate /* The PPKI stuff has been donated by Jeff Barber <jeffb@issl.atl.hp.com> */ 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate #include <stdio.h> 62*0Sstevel@tonic-gate #include <stdlib.h> 63*0Sstevel@tonic-gate #include <string.h> 64*0Sstevel@tonic-gate #include <ctype.h> 65*0Sstevel@tonic-gate #include <sys/types.h> 66*0Sstevel@tonic-gate #include <sys/stat.h> 67*0Sstevel@tonic-gate #include <openssl/conf.h> 68*0Sstevel@tonic-gate #include <openssl/bio.h> 69*0Sstevel@tonic-gate #include <openssl/err.h> 70*0Sstevel@tonic-gate #include <openssl/bn.h> 71*0Sstevel@tonic-gate #include <openssl/txt_db.h> 72*0Sstevel@tonic-gate #include <openssl/evp.h> 73*0Sstevel@tonic-gate #include <openssl/x509.h> 74*0Sstevel@tonic-gate #include <openssl/x509v3.h> 75*0Sstevel@tonic-gate #include <openssl/objects.h> 76*0Sstevel@tonic-gate #include <openssl/ocsp.h> 77*0Sstevel@tonic-gate #include <openssl/pem.h> 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_WINDOWS 80*0Sstevel@tonic-gate #define strcasecmp _stricmp 81*0Sstevel@tonic-gate #else 82*0Sstevel@tonic-gate # ifdef NO_STRINGS_H 83*0Sstevel@tonic-gate int strcasecmp(); 84*0Sstevel@tonic-gate # else 85*0Sstevel@tonic-gate # include <strings.h> 86*0Sstevel@tonic-gate # endif /* NO_STRINGS_H */ 87*0Sstevel@tonic-gate #endif 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate #ifndef W_OK 90*0Sstevel@tonic-gate # ifdef OPENSSL_SYS_VMS 91*0Sstevel@tonic-gate # if defined(__DECC) 92*0Sstevel@tonic-gate # include <unistd.h> 93*0Sstevel@tonic-gate # else 94*0Sstevel@tonic-gate # include <unixlib.h> 95*0Sstevel@tonic-gate # endif 96*0Sstevel@tonic-gate # elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) 97*0Sstevel@tonic-gate # include <sys/file.h> 98*0Sstevel@tonic-gate # endif 99*0Sstevel@tonic-gate #endif 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate #include "apps.h" 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate #ifndef W_OK 104*0Sstevel@tonic-gate # define F_OK 0 105*0Sstevel@tonic-gate # define X_OK 1 106*0Sstevel@tonic-gate # define W_OK 2 107*0Sstevel@tonic-gate # define R_OK 4 108*0Sstevel@tonic-gate #endif 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate #undef PROG 111*0Sstevel@tonic-gate #define PROG ca_main 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate #define BASE_SECTION "ca" 114*0Sstevel@tonic-gate #define CONFIG_FILE "openssl.cnf" 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate #define ENV_DEFAULT_CA "default_ca" 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate #define ENV_DIR "dir" 119*0Sstevel@tonic-gate #define ENV_CERTS "certs" 120*0Sstevel@tonic-gate #define ENV_CRL_DIR "crl_dir" 121*0Sstevel@tonic-gate #define ENV_CA_DB "CA_DB" 122*0Sstevel@tonic-gate #define ENV_NEW_CERTS_DIR "new_certs_dir" 123*0Sstevel@tonic-gate #define ENV_CERTIFICATE "certificate" 124*0Sstevel@tonic-gate #define ENV_SERIAL "serial" 125*0Sstevel@tonic-gate #define ENV_CRLNUMBER "crlnumber" 126*0Sstevel@tonic-gate #define ENV_CRL "crl" 127*0Sstevel@tonic-gate #define ENV_PRIVATE_KEY "private_key" 128*0Sstevel@tonic-gate #define ENV_RANDFILE "RANDFILE" 129*0Sstevel@tonic-gate #define ENV_DEFAULT_DAYS "default_days" 130*0Sstevel@tonic-gate #define ENV_DEFAULT_STARTDATE "default_startdate" 131*0Sstevel@tonic-gate #define ENV_DEFAULT_ENDDATE "default_enddate" 132*0Sstevel@tonic-gate #define ENV_DEFAULT_CRL_DAYS "default_crl_days" 133*0Sstevel@tonic-gate #define ENV_DEFAULT_CRL_HOURS "default_crl_hours" 134*0Sstevel@tonic-gate #define ENV_DEFAULT_MD "default_md" 135*0Sstevel@tonic-gate #define ENV_DEFAULT_EMAIL_DN "email_in_dn" 136*0Sstevel@tonic-gate #define ENV_PRESERVE "preserve" 137*0Sstevel@tonic-gate #define ENV_POLICY "policy" 138*0Sstevel@tonic-gate #define ENV_EXTENSIONS "x509_extensions" 139*0Sstevel@tonic-gate #define ENV_CRLEXT "crl_extensions" 140*0Sstevel@tonic-gate #define ENV_MSIE_HACK "msie_hack" 141*0Sstevel@tonic-gate #define ENV_NAMEOPT "name_opt" 142*0Sstevel@tonic-gate #define ENV_CERTOPT "cert_opt" 143*0Sstevel@tonic-gate #define ENV_EXTCOPY "copy_extensions" 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate #define ENV_DATABASE "database" 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate /* Additional revocation information types */ 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate #define REV_NONE 0 /* No addditional information */ 150*0Sstevel@tonic-gate #define REV_CRL_REASON 1 /* Value is CRL reason code */ 151*0Sstevel@tonic-gate #define REV_HOLD 2 /* Value is hold instruction */ 152*0Sstevel@tonic-gate #define REV_KEY_COMPROMISE 3 /* Value is cert key compromise time */ 153*0Sstevel@tonic-gate #define REV_CA_COMPROMISE 4 /* Value is CA key compromise time */ 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gate static char *ca_usage[]={ 156*0Sstevel@tonic-gate "usage: ca args\n", 157*0Sstevel@tonic-gate "\n", 158*0Sstevel@tonic-gate " -verbose - Talk alot while doing things\n", 159*0Sstevel@tonic-gate " -config file - A config file\n", 160*0Sstevel@tonic-gate " -name arg - The particular CA definition to use\n", 161*0Sstevel@tonic-gate " -gencrl - Generate a new CRL\n", 162*0Sstevel@tonic-gate " -crldays days - Days is when the next CRL is due\n", 163*0Sstevel@tonic-gate " -crlhours hours - Hours is when the next CRL is due\n", 164*0Sstevel@tonic-gate " -startdate YYMMDDHHMMSSZ - certificate validity notBefore\n", 165*0Sstevel@tonic-gate " -enddate YYMMDDHHMMSSZ - certificate validity notAfter (overrides -days)\n", 166*0Sstevel@tonic-gate " -days arg - number of days to certify the certificate for\n", 167*0Sstevel@tonic-gate " -md arg - md to use, one of md2, md5, sha or sha1\n", 168*0Sstevel@tonic-gate " -policy arg - The CA 'policy' to support\n", 169*0Sstevel@tonic-gate " -keyfile arg - private key file\n", 170*0Sstevel@tonic-gate " -keyform arg - private key file format (PEM or ENGINE)\n", 171*0Sstevel@tonic-gate " -key arg - key to decode the private key if it is encrypted\n", 172*0Sstevel@tonic-gate " -cert file - The CA certificate\n", 173*0Sstevel@tonic-gate " -in file - The input PEM encoded certificate request(s)\n", 174*0Sstevel@tonic-gate " -out file - Where to put the output file(s)\n", 175*0Sstevel@tonic-gate " -outdir dir - Where to put output certificates\n", 176*0Sstevel@tonic-gate " -infiles .... - The last argument, requests to process\n", 177*0Sstevel@tonic-gate " -spkac file - File contains DN and signed public key and challenge\n", 178*0Sstevel@tonic-gate " -ss_cert file - File contains a self signed cert to sign\n", 179*0Sstevel@tonic-gate " -preserveDN - Don't re-order the DN\n", 180*0Sstevel@tonic-gate " -noemailDN - Don't add the EMAIL field into certificate' subject\n", 181*0Sstevel@tonic-gate " -batch - Don't ask questions\n", 182*0Sstevel@tonic-gate " -msie_hack - msie modifications to handle all those universal strings\n", 183*0Sstevel@tonic-gate " -revoke file - Revoke a certificate (given in file)\n", 184*0Sstevel@tonic-gate " -subj arg - Use arg instead of request's subject\n", 185*0Sstevel@tonic-gate " -extensions .. - Extension section (override value in config file)\n", 186*0Sstevel@tonic-gate " -extfile file - Configuration file with X509v3 extentions to add\n", 187*0Sstevel@tonic-gate " -crlexts .. - CRL extension section (override value in config file)\n", 188*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE 189*0Sstevel@tonic-gate " -engine e - use engine e, possibly a hardware device.\n", 190*0Sstevel@tonic-gate #endif 191*0Sstevel@tonic-gate " -status serial - Shows certificate status given the serial number\n", 192*0Sstevel@tonic-gate " -updatedb - Updates db for expired certificates\n", 193*0Sstevel@tonic-gate NULL 194*0Sstevel@tonic-gate }; 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate #ifdef EFENCE 197*0Sstevel@tonic-gate extern int EF_PROTECT_FREE; 198*0Sstevel@tonic-gate extern int EF_PROTECT_BELOW; 199*0Sstevel@tonic-gate extern int EF_ALIGNMENT; 200*0Sstevel@tonic-gate #endif 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate static void lookup_fail(char *name,char *tag); 203*0Sstevel@tonic-gate static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509, 204*0Sstevel@tonic-gate const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,CA_DB *db, 205*0Sstevel@tonic-gate BIGNUM *serial, char *subj, int email_dn, char *startdate, 206*0Sstevel@tonic-gate char *enddate, long days, int batch, char *ext_sect, CONF *conf, 207*0Sstevel@tonic-gate int verbose, unsigned long certopt, unsigned long nameopt, 208*0Sstevel@tonic-gate int default_op, int ext_copy); 209*0Sstevel@tonic-gate static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509, 210*0Sstevel@tonic-gate const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy, 211*0Sstevel@tonic-gate CA_DB *db, BIGNUM *serial, char *subj, int email_dn, 212*0Sstevel@tonic-gate char *startdate, char *enddate, long days, int batch, 213*0Sstevel@tonic-gate char *ext_sect, CONF *conf,int verbose, unsigned long certopt, 214*0Sstevel@tonic-gate unsigned long nameopt, int default_op, int ext_copy, 215*0Sstevel@tonic-gate ENGINE *e); 216*0Sstevel@tonic-gate static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509, 217*0Sstevel@tonic-gate const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy, 218*0Sstevel@tonic-gate CA_DB *db, BIGNUM *serial,char *subj, int email_dn, 219*0Sstevel@tonic-gate char *startdate, char *enddate, long days, char *ext_sect, 220*0Sstevel@tonic-gate CONF *conf, int verbose, unsigned long certopt, 221*0Sstevel@tonic-gate unsigned long nameopt, int default_op, int ext_copy); 222*0Sstevel@tonic-gate static int fix_data(int nid, int *type); 223*0Sstevel@tonic-gate static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext); 224*0Sstevel@tonic-gate static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, 225*0Sstevel@tonic-gate STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,char *subj, 226*0Sstevel@tonic-gate int email_dn, char *startdate, char *enddate, long days, int batch, 227*0Sstevel@tonic-gate int verbose, X509_REQ *req, char *ext_sect, CONF *conf, 228*0Sstevel@tonic-gate unsigned long certopt, unsigned long nameopt, int default_op, 229*0Sstevel@tonic-gate int ext_copy); 230*0Sstevel@tonic-gate static int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval); 231*0Sstevel@tonic-gate static int get_certificate_status(const char *ser_status, CA_DB *db); 232*0Sstevel@tonic-gate static int do_updatedb(CA_DB *db); 233*0Sstevel@tonic-gate static int check_time_format(char *str); 234*0Sstevel@tonic-gate char *make_revocation_str(int rev_type, char *rev_arg); 235*0Sstevel@tonic-gate int make_revoked(X509_REVOKED *rev, char *str); 236*0Sstevel@tonic-gate int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str); 237*0Sstevel@tonic-gate static CONF *conf=NULL; 238*0Sstevel@tonic-gate static CONF *extconf=NULL; 239*0Sstevel@tonic-gate static char *section=NULL; 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate static int preserve=0; 242*0Sstevel@tonic-gate static int msie_hack=0; 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate int MAIN(int, char **); 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate int MAIN(int argc, char **argv) 248*0Sstevel@tonic-gate { 249*0Sstevel@tonic-gate ENGINE *e = NULL; 250*0Sstevel@tonic-gate char *key=NULL,*passargin=NULL; 251*0Sstevel@tonic-gate int free_key = 0; 252*0Sstevel@tonic-gate int total=0; 253*0Sstevel@tonic-gate int total_done=0; 254*0Sstevel@tonic-gate int badops=0; 255*0Sstevel@tonic-gate int ret=1; 256*0Sstevel@tonic-gate int email_dn=1; 257*0Sstevel@tonic-gate int req=0; 258*0Sstevel@tonic-gate int verbose=0; 259*0Sstevel@tonic-gate int gencrl=0; 260*0Sstevel@tonic-gate int dorevoke=0; 261*0Sstevel@tonic-gate int doupdatedb=0; 262*0Sstevel@tonic-gate long crldays=0; 263*0Sstevel@tonic-gate long crlhours=0; 264*0Sstevel@tonic-gate long errorline= -1; 265*0Sstevel@tonic-gate char *configfile=NULL; 266*0Sstevel@tonic-gate char *md=NULL; 267*0Sstevel@tonic-gate char *policy=NULL; 268*0Sstevel@tonic-gate char *keyfile=NULL; 269*0Sstevel@tonic-gate char *certfile=NULL; 270*0Sstevel@tonic-gate int keyform=FORMAT_PEM; 271*0Sstevel@tonic-gate char *infile=NULL; 272*0Sstevel@tonic-gate char *spkac_file=NULL; 273*0Sstevel@tonic-gate char *ss_cert_file=NULL; 274*0Sstevel@tonic-gate char *ser_status=NULL; 275*0Sstevel@tonic-gate EVP_PKEY *pkey=NULL; 276*0Sstevel@tonic-gate int output_der = 0; 277*0Sstevel@tonic-gate char *outfile=NULL; 278*0Sstevel@tonic-gate char *outdir=NULL; 279*0Sstevel@tonic-gate char *serialfile=NULL; 280*0Sstevel@tonic-gate char *crlnumberfile=NULL; 281*0Sstevel@tonic-gate char *extensions=NULL; 282*0Sstevel@tonic-gate char *extfile=NULL; 283*0Sstevel@tonic-gate char *subj=NULL; 284*0Sstevel@tonic-gate char *tmp_email_dn=NULL; 285*0Sstevel@tonic-gate char *crl_ext=NULL; 286*0Sstevel@tonic-gate int rev_type = REV_NONE; 287*0Sstevel@tonic-gate char *rev_arg = NULL; 288*0Sstevel@tonic-gate BIGNUM *serial=NULL; 289*0Sstevel@tonic-gate BIGNUM *crlnumber=NULL; 290*0Sstevel@tonic-gate char *startdate=NULL; 291*0Sstevel@tonic-gate char *enddate=NULL; 292*0Sstevel@tonic-gate long days=0; 293*0Sstevel@tonic-gate int batch=0; 294*0Sstevel@tonic-gate int notext=0; 295*0Sstevel@tonic-gate unsigned long nameopt = 0, certopt = 0; 296*0Sstevel@tonic-gate int default_op = 1; 297*0Sstevel@tonic-gate int ext_copy = EXT_COPY_NONE; 298*0Sstevel@tonic-gate X509 *x509=NULL; 299*0Sstevel@tonic-gate X509 *x=NULL; 300*0Sstevel@tonic-gate BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL; 301*0Sstevel@tonic-gate char *dbfile=NULL; 302*0Sstevel@tonic-gate CA_DB *db=NULL; 303*0Sstevel@tonic-gate X509_CRL *crl=NULL; 304*0Sstevel@tonic-gate X509_REVOKED *r=NULL; 305*0Sstevel@tonic-gate ASN1_TIME *tmptm; 306*0Sstevel@tonic-gate ASN1_INTEGER *tmpser; 307*0Sstevel@tonic-gate char **pp,*p,*f; 308*0Sstevel@tonic-gate int i,j; 309*0Sstevel@tonic-gate const EVP_MD *dgst=NULL; 310*0Sstevel@tonic-gate STACK_OF(CONF_VALUE) *attribs=NULL; 311*0Sstevel@tonic-gate STACK_OF(X509) *cert_sk=NULL; 312*0Sstevel@tonic-gate #undef BSIZE 313*0Sstevel@tonic-gate #define BSIZE 256 314*0Sstevel@tonic-gate MS_STATIC char buf[3][BSIZE]; 315*0Sstevel@tonic-gate char *randfile=NULL; 316*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE 317*0Sstevel@tonic-gate char *engine = NULL; 318*0Sstevel@tonic-gate #endif 319*0Sstevel@tonic-gate char *tofree=NULL; 320*0Sstevel@tonic-gate DB_ATTR db_attr; 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gate #ifdef EFENCE 323*0Sstevel@tonic-gate EF_PROTECT_FREE=1; 324*0Sstevel@tonic-gate EF_PROTECT_BELOW=1; 325*0Sstevel@tonic-gate EF_ALIGNMENT=0; 326*0Sstevel@tonic-gate #endif 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate apps_startup(); 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate conf = NULL; 331*0Sstevel@tonic-gate key = NULL; 332*0Sstevel@tonic-gate section = NULL; 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate preserve=0; 335*0Sstevel@tonic-gate msie_hack=0; 336*0Sstevel@tonic-gate if (bio_err == NULL) 337*0Sstevel@tonic-gate if ((bio_err=BIO_new(BIO_s_file())) != NULL) 338*0Sstevel@tonic-gate BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate argc--; 341*0Sstevel@tonic-gate argv++; 342*0Sstevel@tonic-gate while (argc >= 1) 343*0Sstevel@tonic-gate { 344*0Sstevel@tonic-gate if (strcmp(*argv,"-verbose") == 0) 345*0Sstevel@tonic-gate verbose=1; 346*0Sstevel@tonic-gate else if (strcmp(*argv,"-config") == 0) 347*0Sstevel@tonic-gate { 348*0Sstevel@tonic-gate if (--argc < 1) goto bad; 349*0Sstevel@tonic-gate configfile= *(++argv); 350*0Sstevel@tonic-gate } 351*0Sstevel@tonic-gate else if (strcmp(*argv,"-name") == 0) 352*0Sstevel@tonic-gate { 353*0Sstevel@tonic-gate if (--argc < 1) goto bad; 354*0Sstevel@tonic-gate section= *(++argv); 355*0Sstevel@tonic-gate } 356*0Sstevel@tonic-gate else if (strcmp(*argv,"-subj") == 0) 357*0Sstevel@tonic-gate { 358*0Sstevel@tonic-gate if (--argc < 1) goto bad; 359*0Sstevel@tonic-gate subj= *(++argv); 360*0Sstevel@tonic-gate /* preserve=1; */ 361*0Sstevel@tonic-gate } 362*0Sstevel@tonic-gate else if (strcmp(*argv,"-startdate") == 0) 363*0Sstevel@tonic-gate { 364*0Sstevel@tonic-gate if (--argc < 1) goto bad; 365*0Sstevel@tonic-gate startdate= *(++argv); 366*0Sstevel@tonic-gate } 367*0Sstevel@tonic-gate else if (strcmp(*argv,"-enddate") == 0) 368*0Sstevel@tonic-gate { 369*0Sstevel@tonic-gate if (--argc < 1) goto bad; 370*0Sstevel@tonic-gate enddate= *(++argv); 371*0Sstevel@tonic-gate } 372*0Sstevel@tonic-gate else if (strcmp(*argv,"-days") == 0) 373*0Sstevel@tonic-gate { 374*0Sstevel@tonic-gate if (--argc < 1) goto bad; 375*0Sstevel@tonic-gate days=atoi(*(++argv)); 376*0Sstevel@tonic-gate } 377*0Sstevel@tonic-gate else if (strcmp(*argv,"-md") == 0) 378*0Sstevel@tonic-gate { 379*0Sstevel@tonic-gate if (--argc < 1) goto bad; 380*0Sstevel@tonic-gate md= *(++argv); 381*0Sstevel@tonic-gate } 382*0Sstevel@tonic-gate else if (strcmp(*argv,"-policy") == 0) 383*0Sstevel@tonic-gate { 384*0Sstevel@tonic-gate if (--argc < 1) goto bad; 385*0Sstevel@tonic-gate policy= *(++argv); 386*0Sstevel@tonic-gate } 387*0Sstevel@tonic-gate else if (strcmp(*argv,"-keyfile") == 0) 388*0Sstevel@tonic-gate { 389*0Sstevel@tonic-gate if (--argc < 1) goto bad; 390*0Sstevel@tonic-gate keyfile= *(++argv); 391*0Sstevel@tonic-gate } 392*0Sstevel@tonic-gate else if (strcmp(*argv,"-keyform") == 0) 393*0Sstevel@tonic-gate { 394*0Sstevel@tonic-gate if (--argc < 1) goto bad; 395*0Sstevel@tonic-gate keyform=str2fmt(*(++argv)); 396*0Sstevel@tonic-gate } 397*0Sstevel@tonic-gate else if (strcmp(*argv,"-passin") == 0) 398*0Sstevel@tonic-gate { 399*0Sstevel@tonic-gate if (--argc < 1) goto bad; 400*0Sstevel@tonic-gate passargin= *(++argv); 401*0Sstevel@tonic-gate } 402*0Sstevel@tonic-gate else if (strcmp(*argv,"-key") == 0) 403*0Sstevel@tonic-gate { 404*0Sstevel@tonic-gate if (--argc < 1) goto bad; 405*0Sstevel@tonic-gate key= *(++argv); 406*0Sstevel@tonic-gate } 407*0Sstevel@tonic-gate else if (strcmp(*argv,"-cert") == 0) 408*0Sstevel@tonic-gate { 409*0Sstevel@tonic-gate if (--argc < 1) goto bad; 410*0Sstevel@tonic-gate certfile= *(++argv); 411*0Sstevel@tonic-gate } 412*0Sstevel@tonic-gate else if (strcmp(*argv,"-in") == 0) 413*0Sstevel@tonic-gate { 414*0Sstevel@tonic-gate if (--argc < 1) goto bad; 415*0Sstevel@tonic-gate infile= *(++argv); 416*0Sstevel@tonic-gate req=1; 417*0Sstevel@tonic-gate } 418*0Sstevel@tonic-gate else if (strcmp(*argv,"-out") == 0) 419*0Sstevel@tonic-gate { 420*0Sstevel@tonic-gate if (--argc < 1) goto bad; 421*0Sstevel@tonic-gate outfile= *(++argv); 422*0Sstevel@tonic-gate } 423*0Sstevel@tonic-gate else if (strcmp(*argv,"-outdir") == 0) 424*0Sstevel@tonic-gate { 425*0Sstevel@tonic-gate if (--argc < 1) goto bad; 426*0Sstevel@tonic-gate outdir= *(++argv); 427*0Sstevel@tonic-gate } 428*0Sstevel@tonic-gate else if (strcmp(*argv,"-notext") == 0) 429*0Sstevel@tonic-gate notext=1; 430*0Sstevel@tonic-gate else if (strcmp(*argv,"-batch") == 0) 431*0Sstevel@tonic-gate batch=1; 432*0Sstevel@tonic-gate else if (strcmp(*argv,"-preserveDN") == 0) 433*0Sstevel@tonic-gate preserve=1; 434*0Sstevel@tonic-gate else if (strcmp(*argv,"-noemailDN") == 0) 435*0Sstevel@tonic-gate email_dn=0; 436*0Sstevel@tonic-gate else if (strcmp(*argv,"-gencrl") == 0) 437*0Sstevel@tonic-gate gencrl=1; 438*0Sstevel@tonic-gate else if (strcmp(*argv,"-msie_hack") == 0) 439*0Sstevel@tonic-gate msie_hack=1; 440*0Sstevel@tonic-gate else if (strcmp(*argv,"-crldays") == 0) 441*0Sstevel@tonic-gate { 442*0Sstevel@tonic-gate if (--argc < 1) goto bad; 443*0Sstevel@tonic-gate crldays= atol(*(++argv)); 444*0Sstevel@tonic-gate } 445*0Sstevel@tonic-gate else if (strcmp(*argv,"-crlhours") == 0) 446*0Sstevel@tonic-gate { 447*0Sstevel@tonic-gate if (--argc < 1) goto bad; 448*0Sstevel@tonic-gate crlhours= atol(*(++argv)); 449*0Sstevel@tonic-gate } 450*0Sstevel@tonic-gate else if (strcmp(*argv,"-infiles") == 0) 451*0Sstevel@tonic-gate { 452*0Sstevel@tonic-gate argc--; 453*0Sstevel@tonic-gate argv++; 454*0Sstevel@tonic-gate req=1; 455*0Sstevel@tonic-gate break; 456*0Sstevel@tonic-gate } 457*0Sstevel@tonic-gate else if (strcmp(*argv, "-ss_cert") == 0) 458*0Sstevel@tonic-gate { 459*0Sstevel@tonic-gate if (--argc < 1) goto bad; 460*0Sstevel@tonic-gate ss_cert_file = *(++argv); 461*0Sstevel@tonic-gate req=1; 462*0Sstevel@tonic-gate } 463*0Sstevel@tonic-gate else if (strcmp(*argv, "-spkac") == 0) 464*0Sstevel@tonic-gate { 465*0Sstevel@tonic-gate if (--argc < 1) goto bad; 466*0Sstevel@tonic-gate spkac_file = *(++argv); 467*0Sstevel@tonic-gate req=1; 468*0Sstevel@tonic-gate } 469*0Sstevel@tonic-gate else if (strcmp(*argv,"-revoke") == 0) 470*0Sstevel@tonic-gate { 471*0Sstevel@tonic-gate if (--argc < 1) goto bad; 472*0Sstevel@tonic-gate infile= *(++argv); 473*0Sstevel@tonic-gate dorevoke=1; 474*0Sstevel@tonic-gate } 475*0Sstevel@tonic-gate else if (strcmp(*argv,"-extensions") == 0) 476*0Sstevel@tonic-gate { 477*0Sstevel@tonic-gate if (--argc < 1) goto bad; 478*0Sstevel@tonic-gate extensions= *(++argv); 479*0Sstevel@tonic-gate } 480*0Sstevel@tonic-gate else if (strcmp(*argv,"-extfile") == 0) 481*0Sstevel@tonic-gate { 482*0Sstevel@tonic-gate if (--argc < 1) goto bad; 483*0Sstevel@tonic-gate extfile= *(++argv); 484*0Sstevel@tonic-gate } 485*0Sstevel@tonic-gate else if (strcmp(*argv,"-status") == 0) 486*0Sstevel@tonic-gate { 487*0Sstevel@tonic-gate if (--argc < 1) goto bad; 488*0Sstevel@tonic-gate ser_status= *(++argv); 489*0Sstevel@tonic-gate } 490*0Sstevel@tonic-gate else if (strcmp(*argv,"-updatedb") == 0) 491*0Sstevel@tonic-gate { 492*0Sstevel@tonic-gate doupdatedb=1; 493*0Sstevel@tonic-gate } 494*0Sstevel@tonic-gate else if (strcmp(*argv,"-crlexts") == 0) 495*0Sstevel@tonic-gate { 496*0Sstevel@tonic-gate if (--argc < 1) goto bad; 497*0Sstevel@tonic-gate crl_ext= *(++argv); 498*0Sstevel@tonic-gate } 499*0Sstevel@tonic-gate else if (strcmp(*argv,"-crl_reason") == 0) 500*0Sstevel@tonic-gate { 501*0Sstevel@tonic-gate if (--argc < 1) goto bad; 502*0Sstevel@tonic-gate rev_arg = *(++argv); 503*0Sstevel@tonic-gate rev_type = REV_CRL_REASON; 504*0Sstevel@tonic-gate } 505*0Sstevel@tonic-gate else if (strcmp(*argv,"-crl_hold") == 0) 506*0Sstevel@tonic-gate { 507*0Sstevel@tonic-gate if (--argc < 1) goto bad; 508*0Sstevel@tonic-gate rev_arg = *(++argv); 509*0Sstevel@tonic-gate rev_type = REV_HOLD; 510*0Sstevel@tonic-gate } 511*0Sstevel@tonic-gate else if (strcmp(*argv,"-crl_compromise") == 0) 512*0Sstevel@tonic-gate { 513*0Sstevel@tonic-gate if (--argc < 1) goto bad; 514*0Sstevel@tonic-gate rev_arg = *(++argv); 515*0Sstevel@tonic-gate rev_type = REV_KEY_COMPROMISE; 516*0Sstevel@tonic-gate } 517*0Sstevel@tonic-gate else if (strcmp(*argv,"-crl_CA_compromise") == 0) 518*0Sstevel@tonic-gate { 519*0Sstevel@tonic-gate if (--argc < 1) goto bad; 520*0Sstevel@tonic-gate rev_arg = *(++argv); 521*0Sstevel@tonic-gate rev_type = REV_CA_COMPROMISE; 522*0Sstevel@tonic-gate } 523*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE 524*0Sstevel@tonic-gate else if (strcmp(*argv,"-engine") == 0) 525*0Sstevel@tonic-gate { 526*0Sstevel@tonic-gate if (--argc < 1) goto bad; 527*0Sstevel@tonic-gate engine= *(++argv); 528*0Sstevel@tonic-gate } 529*0Sstevel@tonic-gate #endif 530*0Sstevel@tonic-gate else 531*0Sstevel@tonic-gate { 532*0Sstevel@tonic-gate bad: 533*0Sstevel@tonic-gate BIO_printf(bio_err,"unknown option %s\n",*argv); 534*0Sstevel@tonic-gate badops=1; 535*0Sstevel@tonic-gate break; 536*0Sstevel@tonic-gate } 537*0Sstevel@tonic-gate argc--; 538*0Sstevel@tonic-gate argv++; 539*0Sstevel@tonic-gate } 540*0Sstevel@tonic-gate 541*0Sstevel@tonic-gate if (badops) 542*0Sstevel@tonic-gate { 543*0Sstevel@tonic-gate for (pp=ca_usage; (*pp != NULL); pp++) 544*0Sstevel@tonic-gate BIO_printf(bio_err,"%s",*pp); 545*0Sstevel@tonic-gate goto err; 546*0Sstevel@tonic-gate } 547*0Sstevel@tonic-gate 548*0Sstevel@tonic-gate ERR_load_crypto_strings(); 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE 551*0Sstevel@tonic-gate e = setup_engine(bio_err, engine, 0); 552*0Sstevel@tonic-gate #endif 553*0Sstevel@tonic-gate 554*0Sstevel@tonic-gate /*****************************************************************/ 555*0Sstevel@tonic-gate tofree=NULL; 556*0Sstevel@tonic-gate if (configfile == NULL) configfile = getenv("OPENSSL_CONF"); 557*0Sstevel@tonic-gate if (configfile == NULL) configfile = getenv("SSLEAY_CONF"); 558*0Sstevel@tonic-gate if (configfile == NULL) 559*0Sstevel@tonic-gate { 560*0Sstevel@tonic-gate const char *s=X509_get_default_cert_area(); 561*0Sstevel@tonic-gate size_t len; 562*0Sstevel@tonic-gate 563*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS 564*0Sstevel@tonic-gate len = strlen(s)+sizeof(CONFIG_FILE); 565*0Sstevel@tonic-gate tofree=OPENSSL_malloc(len); 566*0Sstevel@tonic-gate strcpy(tofree,s); 567*0Sstevel@tonic-gate #else 568*0Sstevel@tonic-gate len = strlen(s)+sizeof(CONFIG_FILE)+1; 569*0Sstevel@tonic-gate tofree=OPENSSL_malloc(len); 570*0Sstevel@tonic-gate BUF_strlcpy(tofree,s,len); 571*0Sstevel@tonic-gate BUF_strlcat(tofree,"/",len); 572*0Sstevel@tonic-gate #endif 573*0Sstevel@tonic-gate BUF_strlcat(tofree,CONFIG_FILE,len); 574*0Sstevel@tonic-gate configfile=tofree; 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate BIO_printf(bio_err,"Using configuration from %s\n",configfile); 578*0Sstevel@tonic-gate conf = NCONF_new(NULL); 579*0Sstevel@tonic-gate if (NCONF_load(conf,configfile,&errorline) <= 0) 580*0Sstevel@tonic-gate { 581*0Sstevel@tonic-gate if (errorline <= 0) 582*0Sstevel@tonic-gate BIO_printf(bio_err,"error loading the config file '%s'\n", 583*0Sstevel@tonic-gate configfile); 584*0Sstevel@tonic-gate else 585*0Sstevel@tonic-gate BIO_printf(bio_err,"error on line %ld of config file '%s'\n" 586*0Sstevel@tonic-gate ,errorline,configfile); 587*0Sstevel@tonic-gate goto err; 588*0Sstevel@tonic-gate } 589*0Sstevel@tonic-gate if(tofree) 590*0Sstevel@tonic-gate { 591*0Sstevel@tonic-gate OPENSSL_free(tofree); 592*0Sstevel@tonic-gate tofree = NULL; 593*0Sstevel@tonic-gate } 594*0Sstevel@tonic-gate 595*0Sstevel@tonic-gate if (!load_config(bio_err, conf)) 596*0Sstevel@tonic-gate goto err; 597*0Sstevel@tonic-gate 598*0Sstevel@tonic-gate /* Lets get the config section we are using */ 599*0Sstevel@tonic-gate if (section == NULL) 600*0Sstevel@tonic-gate { 601*0Sstevel@tonic-gate section=NCONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA); 602*0Sstevel@tonic-gate if (section == NULL) 603*0Sstevel@tonic-gate { 604*0Sstevel@tonic-gate lookup_fail(BASE_SECTION,ENV_DEFAULT_CA); 605*0Sstevel@tonic-gate goto err; 606*0Sstevel@tonic-gate } 607*0Sstevel@tonic-gate } 608*0Sstevel@tonic-gate 609*0Sstevel@tonic-gate if (conf != NULL) 610*0Sstevel@tonic-gate { 611*0Sstevel@tonic-gate p=NCONF_get_string(conf,NULL,"oid_file"); 612*0Sstevel@tonic-gate if (p == NULL) 613*0Sstevel@tonic-gate ERR_clear_error(); 614*0Sstevel@tonic-gate if (p != NULL) 615*0Sstevel@tonic-gate { 616*0Sstevel@tonic-gate BIO *oid_bio; 617*0Sstevel@tonic-gate 618*0Sstevel@tonic-gate oid_bio=BIO_new_file(p,"r"); 619*0Sstevel@tonic-gate if (oid_bio == NULL) 620*0Sstevel@tonic-gate { 621*0Sstevel@tonic-gate /* 622*0Sstevel@tonic-gate BIO_printf(bio_err,"problems opening %s for extra oid's\n",p); 623*0Sstevel@tonic-gate ERR_print_errors(bio_err); 624*0Sstevel@tonic-gate */ 625*0Sstevel@tonic-gate ERR_clear_error(); 626*0Sstevel@tonic-gate } 627*0Sstevel@tonic-gate else 628*0Sstevel@tonic-gate { 629*0Sstevel@tonic-gate OBJ_create_objects(oid_bio); 630*0Sstevel@tonic-gate BIO_free(oid_bio); 631*0Sstevel@tonic-gate } 632*0Sstevel@tonic-gate } 633*0Sstevel@tonic-gate if (!add_oid_section(bio_err,conf)) 634*0Sstevel@tonic-gate { 635*0Sstevel@tonic-gate ERR_print_errors(bio_err); 636*0Sstevel@tonic-gate goto err; 637*0Sstevel@tonic-gate } 638*0Sstevel@tonic-gate } 639*0Sstevel@tonic-gate 640*0Sstevel@tonic-gate randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE"); 641*0Sstevel@tonic-gate if (randfile == NULL) 642*0Sstevel@tonic-gate ERR_clear_error(); 643*0Sstevel@tonic-gate app_RAND_load_file(randfile, bio_err, 0); 644*0Sstevel@tonic-gate 645*0Sstevel@tonic-gate db_attr.unique_subject = 1; 646*0Sstevel@tonic-gate p = NCONF_get_string(conf, section, "unique_subject"); 647*0Sstevel@tonic-gate if (p) 648*0Sstevel@tonic-gate { 649*0Sstevel@tonic-gate #ifdef RL_DEBUG 650*0Sstevel@tonic-gate BIO_printf(bio_err, "DEBUG: unique_subject = \"%s\"\n", p); 651*0Sstevel@tonic-gate #endif 652*0Sstevel@tonic-gate switch(*p) 653*0Sstevel@tonic-gate { 654*0Sstevel@tonic-gate case 'f': /* false */ 655*0Sstevel@tonic-gate case 'F': /* FALSE */ 656*0Sstevel@tonic-gate case 'n': /* no */ 657*0Sstevel@tonic-gate case 'N': /* NO */ 658*0Sstevel@tonic-gate db_attr.unique_subject = 0; 659*0Sstevel@tonic-gate break; 660*0Sstevel@tonic-gate case 't': /* true */ 661*0Sstevel@tonic-gate case 'T': /* TRUE */ 662*0Sstevel@tonic-gate case 'y': /* yes */ 663*0Sstevel@tonic-gate case 'Y': /* YES */ 664*0Sstevel@tonic-gate default: 665*0Sstevel@tonic-gate db_attr.unique_subject = 1; 666*0Sstevel@tonic-gate break; 667*0Sstevel@tonic-gate } 668*0Sstevel@tonic-gate } 669*0Sstevel@tonic-gate #ifdef RL_DEBUG 670*0Sstevel@tonic-gate else 671*0Sstevel@tonic-gate BIO_printf(bio_err, "DEBUG: unique_subject undefined\n", p); 672*0Sstevel@tonic-gate #endif 673*0Sstevel@tonic-gate #ifdef RL_DEBUG 674*0Sstevel@tonic-gate BIO_printf(bio_err, "DEBUG: configured unique_subject is %d\n", 675*0Sstevel@tonic-gate db_attr.unique_subject); 676*0Sstevel@tonic-gate #endif 677*0Sstevel@tonic-gate 678*0Sstevel@tonic-gate in=BIO_new(BIO_s_file()); 679*0Sstevel@tonic-gate out=BIO_new(BIO_s_file()); 680*0Sstevel@tonic-gate Sout=BIO_new(BIO_s_file()); 681*0Sstevel@tonic-gate Cout=BIO_new(BIO_s_file()); 682*0Sstevel@tonic-gate if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL)) 683*0Sstevel@tonic-gate { 684*0Sstevel@tonic-gate ERR_print_errors(bio_err); 685*0Sstevel@tonic-gate goto err; 686*0Sstevel@tonic-gate } 687*0Sstevel@tonic-gate 688*0Sstevel@tonic-gate /*****************************************************************/ 689*0Sstevel@tonic-gate /* report status of cert with serial number given on command line */ 690*0Sstevel@tonic-gate if (ser_status) 691*0Sstevel@tonic-gate { 692*0Sstevel@tonic-gate if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL) 693*0Sstevel@tonic-gate { 694*0Sstevel@tonic-gate lookup_fail(section,ENV_DATABASE); 695*0Sstevel@tonic-gate goto err; 696*0Sstevel@tonic-gate } 697*0Sstevel@tonic-gate db = load_index(dbfile,&db_attr); 698*0Sstevel@tonic-gate if (db == NULL) goto err; 699*0Sstevel@tonic-gate 700*0Sstevel@tonic-gate if (!index_index(db)) goto err; 701*0Sstevel@tonic-gate 702*0Sstevel@tonic-gate if (get_certificate_status(ser_status,db) != 1) 703*0Sstevel@tonic-gate BIO_printf(bio_err,"Error verifying serial %s!\n", 704*0Sstevel@tonic-gate ser_status); 705*0Sstevel@tonic-gate goto err; 706*0Sstevel@tonic-gate } 707*0Sstevel@tonic-gate 708*0Sstevel@tonic-gate /*****************************************************************/ 709*0Sstevel@tonic-gate /* we definitely need a public key, so let's get it */ 710*0Sstevel@tonic-gate 711*0Sstevel@tonic-gate if ((keyfile == NULL) && ((keyfile=NCONF_get_string(conf, 712*0Sstevel@tonic-gate section,ENV_PRIVATE_KEY)) == NULL)) 713*0Sstevel@tonic-gate { 714*0Sstevel@tonic-gate lookup_fail(section,ENV_PRIVATE_KEY); 715*0Sstevel@tonic-gate goto err; 716*0Sstevel@tonic-gate } 717*0Sstevel@tonic-gate if (!key) 718*0Sstevel@tonic-gate { 719*0Sstevel@tonic-gate free_key = 1; 720*0Sstevel@tonic-gate if (!app_passwd(bio_err, passargin, NULL, &key, NULL)) 721*0Sstevel@tonic-gate { 722*0Sstevel@tonic-gate BIO_printf(bio_err,"Error getting password\n"); 723*0Sstevel@tonic-gate goto err; 724*0Sstevel@tonic-gate } 725*0Sstevel@tonic-gate } 726*0Sstevel@tonic-gate pkey = load_key(bio_err, keyfile, keyform, 0, key, e, 727*0Sstevel@tonic-gate "CA private key"); 728*0Sstevel@tonic-gate if (key) OPENSSL_cleanse(key,strlen(key)); 729*0Sstevel@tonic-gate if (pkey == NULL) 730*0Sstevel@tonic-gate { 731*0Sstevel@tonic-gate /* load_key() has already printed an appropriate message */ 732*0Sstevel@tonic-gate goto err; 733*0Sstevel@tonic-gate } 734*0Sstevel@tonic-gate 735*0Sstevel@tonic-gate /*****************************************************************/ 736*0Sstevel@tonic-gate /* we need a certificate */ 737*0Sstevel@tonic-gate if ((certfile == NULL) && ((certfile=NCONF_get_string(conf, 738*0Sstevel@tonic-gate section,ENV_CERTIFICATE)) == NULL)) 739*0Sstevel@tonic-gate { 740*0Sstevel@tonic-gate lookup_fail(section,ENV_CERTIFICATE); 741*0Sstevel@tonic-gate goto err; 742*0Sstevel@tonic-gate } 743*0Sstevel@tonic-gate x509=load_cert(bio_err, certfile, FORMAT_PEM, NULL, e, 744*0Sstevel@tonic-gate "CA certificate"); 745*0Sstevel@tonic-gate if (x509 == NULL) 746*0Sstevel@tonic-gate goto err; 747*0Sstevel@tonic-gate 748*0Sstevel@tonic-gate if (!X509_check_private_key(x509,pkey)) 749*0Sstevel@tonic-gate { 750*0Sstevel@tonic-gate BIO_printf(bio_err,"CA certificate and CA private key do not match\n"); 751*0Sstevel@tonic-gate goto err; 752*0Sstevel@tonic-gate } 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate f=NCONF_get_string(conf,BASE_SECTION,ENV_PRESERVE); 755*0Sstevel@tonic-gate if (f == NULL) 756*0Sstevel@tonic-gate ERR_clear_error(); 757*0Sstevel@tonic-gate if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) 758*0Sstevel@tonic-gate preserve=1; 759*0Sstevel@tonic-gate f=NCONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK); 760*0Sstevel@tonic-gate if (f == NULL) 761*0Sstevel@tonic-gate ERR_clear_error(); 762*0Sstevel@tonic-gate if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) 763*0Sstevel@tonic-gate msie_hack=1; 764*0Sstevel@tonic-gate 765*0Sstevel@tonic-gate f=NCONF_get_string(conf,section,ENV_NAMEOPT); 766*0Sstevel@tonic-gate 767*0Sstevel@tonic-gate if (f) 768*0Sstevel@tonic-gate { 769*0Sstevel@tonic-gate if (!set_name_ex(&nameopt, f)) 770*0Sstevel@tonic-gate { 771*0Sstevel@tonic-gate BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f); 772*0Sstevel@tonic-gate goto err; 773*0Sstevel@tonic-gate } 774*0Sstevel@tonic-gate default_op = 0; 775*0Sstevel@tonic-gate } 776*0Sstevel@tonic-gate else 777*0Sstevel@tonic-gate ERR_clear_error(); 778*0Sstevel@tonic-gate 779*0Sstevel@tonic-gate f=NCONF_get_string(conf,section,ENV_CERTOPT); 780*0Sstevel@tonic-gate 781*0Sstevel@tonic-gate if (f) 782*0Sstevel@tonic-gate { 783*0Sstevel@tonic-gate if (!set_cert_ex(&certopt, f)) 784*0Sstevel@tonic-gate { 785*0Sstevel@tonic-gate BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f); 786*0Sstevel@tonic-gate goto err; 787*0Sstevel@tonic-gate } 788*0Sstevel@tonic-gate default_op = 0; 789*0Sstevel@tonic-gate } 790*0Sstevel@tonic-gate else 791*0Sstevel@tonic-gate ERR_clear_error(); 792*0Sstevel@tonic-gate 793*0Sstevel@tonic-gate f=NCONF_get_string(conf,section,ENV_EXTCOPY); 794*0Sstevel@tonic-gate 795*0Sstevel@tonic-gate if (f) 796*0Sstevel@tonic-gate { 797*0Sstevel@tonic-gate if (!set_ext_copy(&ext_copy, f)) 798*0Sstevel@tonic-gate { 799*0Sstevel@tonic-gate BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f); 800*0Sstevel@tonic-gate goto err; 801*0Sstevel@tonic-gate } 802*0Sstevel@tonic-gate } 803*0Sstevel@tonic-gate else 804*0Sstevel@tonic-gate ERR_clear_error(); 805*0Sstevel@tonic-gate 806*0Sstevel@tonic-gate /*****************************************************************/ 807*0Sstevel@tonic-gate /* lookup where to write new certificates */ 808*0Sstevel@tonic-gate if ((outdir == NULL) && (req)) 809*0Sstevel@tonic-gate { 810*0Sstevel@tonic-gate struct stat sb; 811*0Sstevel@tonic-gate 812*0Sstevel@tonic-gate if ((outdir=NCONF_get_string(conf,section,ENV_NEW_CERTS_DIR)) 813*0Sstevel@tonic-gate == NULL) 814*0Sstevel@tonic-gate { 815*0Sstevel@tonic-gate BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n"); 816*0Sstevel@tonic-gate goto err; 817*0Sstevel@tonic-gate } 818*0Sstevel@tonic-gate #ifndef OPENSSL_SYS_VMS 819*0Sstevel@tonic-gate /* outdir is a directory spec, but access() for VMS demands a 820*0Sstevel@tonic-gate filename. In any case, stat(), below, will catch the problem 821*0Sstevel@tonic-gate if outdir is not a directory spec, and the fopen() or open() 822*0Sstevel@tonic-gate will catch an error if there is no write access. 823*0Sstevel@tonic-gate 824*0Sstevel@tonic-gate Presumably, this problem could also be solved by using the DEC 825*0Sstevel@tonic-gate C routines to convert the directory syntax to Unixly, and give 826*0Sstevel@tonic-gate that to access(). However, time's too short to do that just 827*0Sstevel@tonic-gate now. 828*0Sstevel@tonic-gate */ 829*0Sstevel@tonic-gate if (access(outdir,R_OK|W_OK|X_OK) != 0) 830*0Sstevel@tonic-gate { 831*0Sstevel@tonic-gate BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir); 832*0Sstevel@tonic-gate perror(outdir); 833*0Sstevel@tonic-gate goto err; 834*0Sstevel@tonic-gate } 835*0Sstevel@tonic-gate 836*0Sstevel@tonic-gate if (stat(outdir,&sb) != 0) 837*0Sstevel@tonic-gate { 838*0Sstevel@tonic-gate BIO_printf(bio_err,"unable to stat(%s)\n",outdir); 839*0Sstevel@tonic-gate perror(outdir); 840*0Sstevel@tonic-gate goto err; 841*0Sstevel@tonic-gate } 842*0Sstevel@tonic-gate #ifdef S_IFDIR 843*0Sstevel@tonic-gate if (!(sb.st_mode & S_IFDIR)) 844*0Sstevel@tonic-gate { 845*0Sstevel@tonic-gate BIO_printf(bio_err,"%s need to be a directory\n",outdir); 846*0Sstevel@tonic-gate perror(outdir); 847*0Sstevel@tonic-gate goto err; 848*0Sstevel@tonic-gate } 849*0Sstevel@tonic-gate #endif 850*0Sstevel@tonic-gate #endif 851*0Sstevel@tonic-gate } 852*0Sstevel@tonic-gate 853*0Sstevel@tonic-gate /*****************************************************************/ 854*0Sstevel@tonic-gate /* we need to load the database file */ 855*0Sstevel@tonic-gate if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL) 856*0Sstevel@tonic-gate { 857*0Sstevel@tonic-gate lookup_fail(section,ENV_DATABASE); 858*0Sstevel@tonic-gate goto err; 859*0Sstevel@tonic-gate } 860*0Sstevel@tonic-gate db = load_index(dbfile, &db_attr); 861*0Sstevel@tonic-gate if (db == NULL) goto err; 862*0Sstevel@tonic-gate 863*0Sstevel@tonic-gate /* Lets check some fields */ 864*0Sstevel@tonic-gate for (i=0; i<sk_num(db->db->data); i++) 865*0Sstevel@tonic-gate { 866*0Sstevel@tonic-gate pp=(char **)sk_value(db->db->data,i); 867*0Sstevel@tonic-gate if ((pp[DB_type][0] != DB_TYPE_REV) && 868*0Sstevel@tonic-gate (pp[DB_rev_date][0] != '\0')) 869*0Sstevel@tonic-gate { 870*0Sstevel@tonic-gate BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1); 871*0Sstevel@tonic-gate goto err; 872*0Sstevel@tonic-gate } 873*0Sstevel@tonic-gate if ((pp[DB_type][0] == DB_TYPE_REV) && 874*0Sstevel@tonic-gate !make_revoked(NULL, pp[DB_rev_date])) 875*0Sstevel@tonic-gate { 876*0Sstevel@tonic-gate BIO_printf(bio_err," in entry %d\n", i+1); 877*0Sstevel@tonic-gate goto err; 878*0Sstevel@tonic-gate } 879*0Sstevel@tonic-gate if (!check_time_format(pp[DB_exp_date])) 880*0Sstevel@tonic-gate { 881*0Sstevel@tonic-gate BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1); 882*0Sstevel@tonic-gate goto err; 883*0Sstevel@tonic-gate } 884*0Sstevel@tonic-gate p=pp[DB_serial]; 885*0Sstevel@tonic-gate j=strlen(p); 886*0Sstevel@tonic-gate if (*p == '-') 887*0Sstevel@tonic-gate { 888*0Sstevel@tonic-gate p++; 889*0Sstevel@tonic-gate j--; 890*0Sstevel@tonic-gate } 891*0Sstevel@tonic-gate if ((j&1) || (j < 2)) 892*0Sstevel@tonic-gate { 893*0Sstevel@tonic-gate BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j); 894*0Sstevel@tonic-gate goto err; 895*0Sstevel@tonic-gate } 896*0Sstevel@tonic-gate while (*p) 897*0Sstevel@tonic-gate { 898*0Sstevel@tonic-gate if (!( ((*p >= '0') && (*p <= '9')) || 899*0Sstevel@tonic-gate ((*p >= 'A') && (*p <= 'F')) || 900*0Sstevel@tonic-gate ((*p >= 'a') && (*p <= 'f'))) ) 901*0Sstevel@tonic-gate { 902*0Sstevel@tonic-gate BIO_printf(bio_err,"entry %d: bad serial number characters, char pos %ld, char is '%c'\n",i+1,(long)(p-pp[DB_serial]),*p); 903*0Sstevel@tonic-gate goto err; 904*0Sstevel@tonic-gate } 905*0Sstevel@tonic-gate p++; 906*0Sstevel@tonic-gate } 907*0Sstevel@tonic-gate } 908*0Sstevel@tonic-gate if (verbose) 909*0Sstevel@tonic-gate { 910*0Sstevel@tonic-gate BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */ 911*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS 912*0Sstevel@tonic-gate { 913*0Sstevel@tonic-gate BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 914*0Sstevel@tonic-gate out = BIO_push(tmpbio, out); 915*0Sstevel@tonic-gate } 916*0Sstevel@tonic-gate #endif 917*0Sstevel@tonic-gate TXT_DB_write(out,db->db); 918*0Sstevel@tonic-gate BIO_printf(bio_err,"%d entries loaded from the database\n", 919*0Sstevel@tonic-gate db->db->data->num); 920*0Sstevel@tonic-gate BIO_printf(bio_err,"generating index\n"); 921*0Sstevel@tonic-gate } 922*0Sstevel@tonic-gate 923*0Sstevel@tonic-gate if (!index_index(db)) goto err; 924*0Sstevel@tonic-gate 925*0Sstevel@tonic-gate /*****************************************************************/ 926*0Sstevel@tonic-gate /* Update the db file for expired certificates */ 927*0Sstevel@tonic-gate if (doupdatedb) 928*0Sstevel@tonic-gate { 929*0Sstevel@tonic-gate if (verbose) 930*0Sstevel@tonic-gate BIO_printf(bio_err, "Updating %s ...\n", 931*0Sstevel@tonic-gate dbfile); 932*0Sstevel@tonic-gate 933*0Sstevel@tonic-gate i = do_updatedb(db); 934*0Sstevel@tonic-gate if (i == -1) 935*0Sstevel@tonic-gate { 936*0Sstevel@tonic-gate BIO_printf(bio_err,"Malloc failure\n"); 937*0Sstevel@tonic-gate goto err; 938*0Sstevel@tonic-gate } 939*0Sstevel@tonic-gate else if (i == 0) 940*0Sstevel@tonic-gate { 941*0Sstevel@tonic-gate if (verbose) BIO_printf(bio_err, 942*0Sstevel@tonic-gate "No entries found to mark expired\n"); 943*0Sstevel@tonic-gate } 944*0Sstevel@tonic-gate else 945*0Sstevel@tonic-gate { 946*0Sstevel@tonic-gate if (!save_index(dbfile,"new",db)) goto err; 947*0Sstevel@tonic-gate 948*0Sstevel@tonic-gate if (!rotate_index(dbfile,"new","old")) goto err; 949*0Sstevel@tonic-gate 950*0Sstevel@tonic-gate if (verbose) BIO_printf(bio_err, 951*0Sstevel@tonic-gate "Done. %d entries marked as expired\n",i); 952*0Sstevel@tonic-gate } 953*0Sstevel@tonic-gate goto err; 954*0Sstevel@tonic-gate } 955*0Sstevel@tonic-gate 956*0Sstevel@tonic-gate /*****************************************************************/ 957*0Sstevel@tonic-gate /* Read extentions config file */ 958*0Sstevel@tonic-gate if (extfile) 959*0Sstevel@tonic-gate { 960*0Sstevel@tonic-gate extconf = NCONF_new(NULL); 961*0Sstevel@tonic-gate if (NCONF_load(extconf,extfile,&errorline) <= 0) 962*0Sstevel@tonic-gate { 963*0Sstevel@tonic-gate if (errorline <= 0) 964*0Sstevel@tonic-gate BIO_printf(bio_err, "ERROR: loading the config file '%s'\n", 965*0Sstevel@tonic-gate extfile); 966*0Sstevel@tonic-gate else 967*0Sstevel@tonic-gate BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n", 968*0Sstevel@tonic-gate errorline,extfile); 969*0Sstevel@tonic-gate ret = 1; 970*0Sstevel@tonic-gate goto err; 971*0Sstevel@tonic-gate } 972*0Sstevel@tonic-gate 973*0Sstevel@tonic-gate if (verbose) 974*0Sstevel@tonic-gate BIO_printf(bio_err, "Successfully loaded extensions file %s\n", extfile); 975*0Sstevel@tonic-gate 976*0Sstevel@tonic-gate /* We can have sections in the ext file */ 977*0Sstevel@tonic-gate if (!extensions && !(extensions = NCONF_get_string(extconf, "default", "extensions"))) 978*0Sstevel@tonic-gate extensions = "default"; 979*0Sstevel@tonic-gate } 980*0Sstevel@tonic-gate 981*0Sstevel@tonic-gate /*****************************************************************/ 982*0Sstevel@tonic-gate if (req || gencrl) 983*0Sstevel@tonic-gate { 984*0Sstevel@tonic-gate if (outfile != NULL) 985*0Sstevel@tonic-gate { 986*0Sstevel@tonic-gate if (BIO_write_filename(Sout,outfile) <= 0) 987*0Sstevel@tonic-gate { 988*0Sstevel@tonic-gate perror(outfile); 989*0Sstevel@tonic-gate goto err; 990*0Sstevel@tonic-gate } 991*0Sstevel@tonic-gate } 992*0Sstevel@tonic-gate else 993*0Sstevel@tonic-gate { 994*0Sstevel@tonic-gate BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT); 995*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS 996*0Sstevel@tonic-gate { 997*0Sstevel@tonic-gate BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 998*0Sstevel@tonic-gate Sout = BIO_push(tmpbio, Sout); 999*0Sstevel@tonic-gate } 1000*0Sstevel@tonic-gate #endif 1001*0Sstevel@tonic-gate } 1002*0Sstevel@tonic-gate } 1003*0Sstevel@tonic-gate 1004*0Sstevel@tonic-gate if (req) 1005*0Sstevel@tonic-gate { 1006*0Sstevel@tonic-gate if ((md == NULL) && ((md=NCONF_get_string(conf, 1007*0Sstevel@tonic-gate section,ENV_DEFAULT_MD)) == NULL)) 1008*0Sstevel@tonic-gate { 1009*0Sstevel@tonic-gate lookup_fail(section,ENV_DEFAULT_MD); 1010*0Sstevel@tonic-gate goto err; 1011*0Sstevel@tonic-gate } 1012*0Sstevel@tonic-gate if ((email_dn == 1) && ((tmp_email_dn=NCONF_get_string(conf, 1013*0Sstevel@tonic-gate section,ENV_DEFAULT_EMAIL_DN)) != NULL )) 1014*0Sstevel@tonic-gate { 1015*0Sstevel@tonic-gate if(strcmp(tmp_email_dn,"no") == 0) 1016*0Sstevel@tonic-gate email_dn=0; 1017*0Sstevel@tonic-gate } 1018*0Sstevel@tonic-gate if ((dgst=EVP_get_digestbyname(md)) == NULL) 1019*0Sstevel@tonic-gate { 1020*0Sstevel@tonic-gate BIO_printf(bio_err,"%s is an unsupported message digest type\n",md); 1021*0Sstevel@tonic-gate goto err; 1022*0Sstevel@tonic-gate } 1023*0Sstevel@tonic-gate if (verbose) 1024*0Sstevel@tonic-gate BIO_printf(bio_err,"message digest is %s\n", 1025*0Sstevel@tonic-gate OBJ_nid2ln(dgst->type)); 1026*0Sstevel@tonic-gate if ((policy == NULL) && ((policy=NCONF_get_string(conf, 1027*0Sstevel@tonic-gate section,ENV_POLICY)) == NULL)) 1028*0Sstevel@tonic-gate { 1029*0Sstevel@tonic-gate lookup_fail(section,ENV_POLICY); 1030*0Sstevel@tonic-gate goto err; 1031*0Sstevel@tonic-gate } 1032*0Sstevel@tonic-gate if (verbose) 1033*0Sstevel@tonic-gate BIO_printf(bio_err,"policy is %s\n",policy); 1034*0Sstevel@tonic-gate 1035*0Sstevel@tonic-gate if ((serialfile=NCONF_get_string(conf,section,ENV_SERIAL)) 1036*0Sstevel@tonic-gate == NULL) 1037*0Sstevel@tonic-gate { 1038*0Sstevel@tonic-gate lookup_fail(section,ENV_SERIAL); 1039*0Sstevel@tonic-gate goto err; 1040*0Sstevel@tonic-gate } 1041*0Sstevel@tonic-gate 1042*0Sstevel@tonic-gate if (!extconf) 1043*0Sstevel@tonic-gate { 1044*0Sstevel@tonic-gate /* no '-extfile' option, so we look for extensions 1045*0Sstevel@tonic-gate * in the main configuration file */ 1046*0Sstevel@tonic-gate if (!extensions) 1047*0Sstevel@tonic-gate { 1048*0Sstevel@tonic-gate extensions=NCONF_get_string(conf,section, 1049*0Sstevel@tonic-gate ENV_EXTENSIONS); 1050*0Sstevel@tonic-gate if (!extensions) 1051*0Sstevel@tonic-gate ERR_clear_error(); 1052*0Sstevel@tonic-gate } 1053*0Sstevel@tonic-gate if (extensions) 1054*0Sstevel@tonic-gate { 1055*0Sstevel@tonic-gate /* Check syntax of file */ 1056*0Sstevel@tonic-gate X509V3_CTX ctx; 1057*0Sstevel@tonic-gate X509V3_set_ctx_test(&ctx); 1058*0Sstevel@tonic-gate X509V3_set_nconf(&ctx, conf); 1059*0Sstevel@tonic-gate if (!X509V3_EXT_add_nconf(conf, &ctx, extensions, 1060*0Sstevel@tonic-gate NULL)) 1061*0Sstevel@tonic-gate { 1062*0Sstevel@tonic-gate BIO_printf(bio_err, 1063*0Sstevel@tonic-gate "Error Loading extension section %s\n", 1064*0Sstevel@tonic-gate extensions); 1065*0Sstevel@tonic-gate ret = 1; 1066*0Sstevel@tonic-gate goto err; 1067*0Sstevel@tonic-gate } 1068*0Sstevel@tonic-gate } 1069*0Sstevel@tonic-gate } 1070*0Sstevel@tonic-gate 1071*0Sstevel@tonic-gate if (startdate == NULL) 1072*0Sstevel@tonic-gate { 1073*0Sstevel@tonic-gate startdate=NCONF_get_string(conf,section, 1074*0Sstevel@tonic-gate ENV_DEFAULT_STARTDATE); 1075*0Sstevel@tonic-gate if (startdate == NULL) 1076*0Sstevel@tonic-gate ERR_clear_error(); 1077*0Sstevel@tonic-gate } 1078*0Sstevel@tonic-gate if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate)) 1079*0Sstevel@tonic-gate { 1080*0Sstevel@tonic-gate BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n"); 1081*0Sstevel@tonic-gate goto err; 1082*0Sstevel@tonic-gate } 1083*0Sstevel@tonic-gate if (startdate == NULL) startdate="today"; 1084*0Sstevel@tonic-gate 1085*0Sstevel@tonic-gate if (enddate == NULL) 1086*0Sstevel@tonic-gate { 1087*0Sstevel@tonic-gate enddate=NCONF_get_string(conf,section, 1088*0Sstevel@tonic-gate ENV_DEFAULT_ENDDATE); 1089*0Sstevel@tonic-gate if (enddate == NULL) 1090*0Sstevel@tonic-gate ERR_clear_error(); 1091*0Sstevel@tonic-gate } 1092*0Sstevel@tonic-gate if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate)) 1093*0Sstevel@tonic-gate { 1094*0Sstevel@tonic-gate BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n"); 1095*0Sstevel@tonic-gate goto err; 1096*0Sstevel@tonic-gate } 1097*0Sstevel@tonic-gate 1098*0Sstevel@tonic-gate if (days == 0) 1099*0Sstevel@tonic-gate { 1100*0Sstevel@tonic-gate if(!NCONF_get_number(conf,section, ENV_DEFAULT_DAYS, &days)) 1101*0Sstevel@tonic-gate days = 0; 1102*0Sstevel@tonic-gate } 1103*0Sstevel@tonic-gate if (!enddate && (days == 0)) 1104*0Sstevel@tonic-gate { 1105*0Sstevel@tonic-gate BIO_printf(bio_err,"cannot lookup how many days to certify for\n"); 1106*0Sstevel@tonic-gate goto err; 1107*0Sstevel@tonic-gate } 1108*0Sstevel@tonic-gate 1109*0Sstevel@tonic-gate if ((serial=load_serial(serialfile, 0, NULL)) == NULL) 1110*0Sstevel@tonic-gate { 1111*0Sstevel@tonic-gate BIO_printf(bio_err,"error while loading serial number\n"); 1112*0Sstevel@tonic-gate goto err; 1113*0Sstevel@tonic-gate } 1114*0Sstevel@tonic-gate if (verbose) 1115*0Sstevel@tonic-gate { 1116*0Sstevel@tonic-gate if (BN_is_zero(serial)) 1117*0Sstevel@tonic-gate BIO_printf(bio_err,"next serial number is 00\n"); 1118*0Sstevel@tonic-gate else 1119*0Sstevel@tonic-gate { 1120*0Sstevel@tonic-gate if ((f=BN_bn2hex(serial)) == NULL) goto err; 1121*0Sstevel@tonic-gate BIO_printf(bio_err,"next serial number is %s\n",f); 1122*0Sstevel@tonic-gate OPENSSL_free(f); 1123*0Sstevel@tonic-gate } 1124*0Sstevel@tonic-gate } 1125*0Sstevel@tonic-gate 1126*0Sstevel@tonic-gate if ((attribs=NCONF_get_section(conf,policy)) == NULL) 1127*0Sstevel@tonic-gate { 1128*0Sstevel@tonic-gate BIO_printf(bio_err,"unable to find 'section' for %s\n",policy); 1129*0Sstevel@tonic-gate goto err; 1130*0Sstevel@tonic-gate } 1131*0Sstevel@tonic-gate 1132*0Sstevel@tonic-gate if ((cert_sk=sk_X509_new_null()) == NULL) 1133*0Sstevel@tonic-gate { 1134*0Sstevel@tonic-gate BIO_printf(bio_err,"Memory allocation failure\n"); 1135*0Sstevel@tonic-gate goto err; 1136*0Sstevel@tonic-gate } 1137*0Sstevel@tonic-gate if (spkac_file != NULL) 1138*0Sstevel@tonic-gate { 1139*0Sstevel@tonic-gate total++; 1140*0Sstevel@tonic-gate j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db, 1141*0Sstevel@tonic-gate serial,subj,email_dn,startdate,enddate,days,extensions, 1142*0Sstevel@tonic-gate conf,verbose,certopt,nameopt,default_op,ext_copy); 1143*0Sstevel@tonic-gate if (j < 0) goto err; 1144*0Sstevel@tonic-gate if (j > 0) 1145*0Sstevel@tonic-gate { 1146*0Sstevel@tonic-gate total_done++; 1147*0Sstevel@tonic-gate BIO_printf(bio_err,"\n"); 1148*0Sstevel@tonic-gate if (!BN_add_word(serial,1)) goto err; 1149*0Sstevel@tonic-gate if (!sk_X509_push(cert_sk,x)) 1150*0Sstevel@tonic-gate { 1151*0Sstevel@tonic-gate BIO_printf(bio_err,"Memory allocation failure\n"); 1152*0Sstevel@tonic-gate goto err; 1153*0Sstevel@tonic-gate } 1154*0Sstevel@tonic-gate if (outfile) 1155*0Sstevel@tonic-gate { 1156*0Sstevel@tonic-gate output_der = 1; 1157*0Sstevel@tonic-gate batch = 1; 1158*0Sstevel@tonic-gate } 1159*0Sstevel@tonic-gate } 1160*0Sstevel@tonic-gate } 1161*0Sstevel@tonic-gate if (ss_cert_file != NULL) 1162*0Sstevel@tonic-gate { 1163*0Sstevel@tonic-gate total++; 1164*0Sstevel@tonic-gate j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs, 1165*0Sstevel@tonic-gate db,serial,subj,email_dn,startdate,enddate,days,batch, 1166*0Sstevel@tonic-gate extensions,conf,verbose, certopt, nameopt, 1167*0Sstevel@tonic-gate default_op, ext_copy, e); 1168*0Sstevel@tonic-gate if (j < 0) goto err; 1169*0Sstevel@tonic-gate if (j > 0) 1170*0Sstevel@tonic-gate { 1171*0Sstevel@tonic-gate total_done++; 1172*0Sstevel@tonic-gate BIO_printf(bio_err,"\n"); 1173*0Sstevel@tonic-gate if (!BN_add_word(serial,1)) goto err; 1174*0Sstevel@tonic-gate if (!sk_X509_push(cert_sk,x)) 1175*0Sstevel@tonic-gate { 1176*0Sstevel@tonic-gate BIO_printf(bio_err,"Memory allocation failure\n"); 1177*0Sstevel@tonic-gate goto err; 1178*0Sstevel@tonic-gate } 1179*0Sstevel@tonic-gate } 1180*0Sstevel@tonic-gate } 1181*0Sstevel@tonic-gate if (infile != NULL) 1182*0Sstevel@tonic-gate { 1183*0Sstevel@tonic-gate total++; 1184*0Sstevel@tonic-gate j=certify(&x,infile,pkey,x509,dgst,attribs,db, 1185*0Sstevel@tonic-gate serial,subj,email_dn,startdate,enddate,days,batch, 1186*0Sstevel@tonic-gate extensions,conf,verbose, certopt, nameopt, 1187*0Sstevel@tonic-gate default_op, ext_copy); 1188*0Sstevel@tonic-gate if (j < 0) goto err; 1189*0Sstevel@tonic-gate if (j > 0) 1190*0Sstevel@tonic-gate { 1191*0Sstevel@tonic-gate total_done++; 1192*0Sstevel@tonic-gate BIO_printf(bio_err,"\n"); 1193*0Sstevel@tonic-gate if (!BN_add_word(serial,1)) goto err; 1194*0Sstevel@tonic-gate if (!sk_X509_push(cert_sk,x)) 1195*0Sstevel@tonic-gate { 1196*0Sstevel@tonic-gate BIO_printf(bio_err,"Memory allocation failure\n"); 1197*0Sstevel@tonic-gate goto err; 1198*0Sstevel@tonic-gate } 1199*0Sstevel@tonic-gate } 1200*0Sstevel@tonic-gate } 1201*0Sstevel@tonic-gate for (i=0; i<argc; i++) 1202*0Sstevel@tonic-gate { 1203*0Sstevel@tonic-gate total++; 1204*0Sstevel@tonic-gate j=certify(&x,argv[i],pkey,x509,dgst,attribs,db, 1205*0Sstevel@tonic-gate serial,subj,email_dn,startdate,enddate,days,batch, 1206*0Sstevel@tonic-gate extensions,conf,verbose, certopt, nameopt, 1207*0Sstevel@tonic-gate default_op, ext_copy); 1208*0Sstevel@tonic-gate if (j < 0) goto err; 1209*0Sstevel@tonic-gate if (j > 0) 1210*0Sstevel@tonic-gate { 1211*0Sstevel@tonic-gate total_done++; 1212*0Sstevel@tonic-gate BIO_printf(bio_err,"\n"); 1213*0Sstevel@tonic-gate if (!BN_add_word(serial,1)) goto err; 1214*0Sstevel@tonic-gate if (!sk_X509_push(cert_sk,x)) 1215*0Sstevel@tonic-gate { 1216*0Sstevel@tonic-gate BIO_printf(bio_err,"Memory allocation failure\n"); 1217*0Sstevel@tonic-gate goto err; 1218*0Sstevel@tonic-gate } 1219*0Sstevel@tonic-gate } 1220*0Sstevel@tonic-gate } 1221*0Sstevel@tonic-gate /* we have a stack of newly certified certificates 1222*0Sstevel@tonic-gate * and a data base and serial number that need 1223*0Sstevel@tonic-gate * updating */ 1224*0Sstevel@tonic-gate 1225*0Sstevel@tonic-gate if (sk_X509_num(cert_sk) > 0) 1226*0Sstevel@tonic-gate { 1227*0Sstevel@tonic-gate if (!batch) 1228*0Sstevel@tonic-gate { 1229*0Sstevel@tonic-gate BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total); 1230*0Sstevel@tonic-gate (void)BIO_flush(bio_err); 1231*0Sstevel@tonic-gate buf[0][0]='\0'; 1232*0Sstevel@tonic-gate fgets(buf[0],10,stdin); 1233*0Sstevel@tonic-gate if ((buf[0][0] != 'y') && (buf[0][0] != 'Y')) 1234*0Sstevel@tonic-gate { 1235*0Sstevel@tonic-gate BIO_printf(bio_err,"CERTIFICATION CANCELED\n"); 1236*0Sstevel@tonic-gate ret=0; 1237*0Sstevel@tonic-gate goto err; 1238*0Sstevel@tonic-gate } 1239*0Sstevel@tonic-gate } 1240*0Sstevel@tonic-gate 1241*0Sstevel@tonic-gate BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk)); 1242*0Sstevel@tonic-gate 1243*0Sstevel@tonic-gate if (!save_serial(serialfile,"new",serial,NULL)) goto err; 1244*0Sstevel@tonic-gate 1245*0Sstevel@tonic-gate if (!save_index(dbfile, "new", db)) goto err; 1246*0Sstevel@tonic-gate } 1247*0Sstevel@tonic-gate 1248*0Sstevel@tonic-gate if (verbose) 1249*0Sstevel@tonic-gate BIO_printf(bio_err,"writing new certificates\n"); 1250*0Sstevel@tonic-gate for (i=0; i<sk_X509_num(cert_sk); i++) 1251*0Sstevel@tonic-gate { 1252*0Sstevel@tonic-gate int k; 1253*0Sstevel@tonic-gate char *n; 1254*0Sstevel@tonic-gate 1255*0Sstevel@tonic-gate x=sk_X509_value(cert_sk,i); 1256*0Sstevel@tonic-gate 1257*0Sstevel@tonic-gate j=x->cert_info->serialNumber->length; 1258*0Sstevel@tonic-gate p=(char *)x->cert_info->serialNumber->data; 1259*0Sstevel@tonic-gate 1260*0Sstevel@tonic-gate if(strlen(outdir) >= (size_t)(j ? BSIZE-j*2-6 : BSIZE-8)) 1261*0Sstevel@tonic-gate { 1262*0Sstevel@tonic-gate BIO_printf(bio_err,"certificate file name too long\n"); 1263*0Sstevel@tonic-gate goto err; 1264*0Sstevel@tonic-gate } 1265*0Sstevel@tonic-gate 1266*0Sstevel@tonic-gate strcpy(buf[2],outdir); 1267*0Sstevel@tonic-gate 1268*0Sstevel@tonic-gate #ifndef OPENSSL_SYS_VMS 1269*0Sstevel@tonic-gate BUF_strlcat(buf[2],"/",sizeof(buf[2])); 1270*0Sstevel@tonic-gate #endif 1271*0Sstevel@tonic-gate 1272*0Sstevel@tonic-gate n=(char *)&(buf[2][strlen(buf[2])]); 1273*0Sstevel@tonic-gate if (j > 0) 1274*0Sstevel@tonic-gate { 1275*0Sstevel@tonic-gate for (k=0; k<j; k++) 1276*0Sstevel@tonic-gate { 1277*0Sstevel@tonic-gate if (n >= &(buf[2][sizeof(buf[2])])) 1278*0Sstevel@tonic-gate break; 1279*0Sstevel@tonic-gate BIO_snprintf(n, 1280*0Sstevel@tonic-gate &buf[2][0] + sizeof(buf[2]) - n, 1281*0Sstevel@tonic-gate "%02X",(unsigned char)*(p++)); 1282*0Sstevel@tonic-gate n+=2; 1283*0Sstevel@tonic-gate } 1284*0Sstevel@tonic-gate } 1285*0Sstevel@tonic-gate else 1286*0Sstevel@tonic-gate { 1287*0Sstevel@tonic-gate *(n++)='0'; 1288*0Sstevel@tonic-gate *(n++)='0'; 1289*0Sstevel@tonic-gate } 1290*0Sstevel@tonic-gate *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m'; 1291*0Sstevel@tonic-gate *n='\0'; 1292*0Sstevel@tonic-gate if (verbose) 1293*0Sstevel@tonic-gate BIO_printf(bio_err,"writing %s\n",buf[2]); 1294*0Sstevel@tonic-gate 1295*0Sstevel@tonic-gate if (BIO_write_filename(Cout,buf[2]) <= 0) 1296*0Sstevel@tonic-gate { 1297*0Sstevel@tonic-gate perror(buf[2]); 1298*0Sstevel@tonic-gate goto err; 1299*0Sstevel@tonic-gate } 1300*0Sstevel@tonic-gate write_new_certificate(Cout,x, 0, notext); 1301*0Sstevel@tonic-gate write_new_certificate(Sout,x, output_der, notext); 1302*0Sstevel@tonic-gate } 1303*0Sstevel@tonic-gate 1304*0Sstevel@tonic-gate if (sk_X509_num(cert_sk)) 1305*0Sstevel@tonic-gate { 1306*0Sstevel@tonic-gate /* Rename the database and the serial file */ 1307*0Sstevel@tonic-gate if (!rotate_serial(serialfile,"new","old")) goto err; 1308*0Sstevel@tonic-gate 1309*0Sstevel@tonic-gate if (!rotate_index(dbfile,"new","old")) goto err; 1310*0Sstevel@tonic-gate 1311*0Sstevel@tonic-gate BIO_printf(bio_err,"Data Base Updated\n"); 1312*0Sstevel@tonic-gate } 1313*0Sstevel@tonic-gate } 1314*0Sstevel@tonic-gate 1315*0Sstevel@tonic-gate /*****************************************************************/ 1316*0Sstevel@tonic-gate if (gencrl) 1317*0Sstevel@tonic-gate { 1318*0Sstevel@tonic-gate int crl_v2 = 0; 1319*0Sstevel@tonic-gate if (!crl_ext) 1320*0Sstevel@tonic-gate { 1321*0Sstevel@tonic-gate crl_ext=NCONF_get_string(conf,section,ENV_CRLEXT); 1322*0Sstevel@tonic-gate if (!crl_ext) 1323*0Sstevel@tonic-gate ERR_clear_error(); 1324*0Sstevel@tonic-gate } 1325*0Sstevel@tonic-gate if (crl_ext) 1326*0Sstevel@tonic-gate { 1327*0Sstevel@tonic-gate /* Check syntax of file */ 1328*0Sstevel@tonic-gate X509V3_CTX ctx; 1329*0Sstevel@tonic-gate X509V3_set_ctx_test(&ctx); 1330*0Sstevel@tonic-gate X509V3_set_nconf(&ctx, conf); 1331*0Sstevel@tonic-gate if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL)) 1332*0Sstevel@tonic-gate { 1333*0Sstevel@tonic-gate BIO_printf(bio_err, 1334*0Sstevel@tonic-gate "Error Loading CRL extension section %s\n", 1335*0Sstevel@tonic-gate crl_ext); 1336*0Sstevel@tonic-gate ret = 1; 1337*0Sstevel@tonic-gate goto err; 1338*0Sstevel@tonic-gate } 1339*0Sstevel@tonic-gate } 1340*0Sstevel@tonic-gate 1341*0Sstevel@tonic-gate if ((crlnumberfile=NCONF_get_string(conf,section,ENV_CRLNUMBER)) 1342*0Sstevel@tonic-gate != NULL) 1343*0Sstevel@tonic-gate if ((crlnumber=load_serial(crlnumberfile,0,NULL)) == NULL) 1344*0Sstevel@tonic-gate { 1345*0Sstevel@tonic-gate BIO_printf(bio_err,"error while loading CRL number\n"); 1346*0Sstevel@tonic-gate goto err; 1347*0Sstevel@tonic-gate } 1348*0Sstevel@tonic-gate 1349*0Sstevel@tonic-gate if (!crldays && !crlhours) 1350*0Sstevel@tonic-gate { 1351*0Sstevel@tonic-gate if (!NCONF_get_number(conf,section, 1352*0Sstevel@tonic-gate ENV_DEFAULT_CRL_DAYS, &crldays)) 1353*0Sstevel@tonic-gate crldays = 0; 1354*0Sstevel@tonic-gate if (!NCONF_get_number(conf,section, 1355*0Sstevel@tonic-gate ENV_DEFAULT_CRL_HOURS, &crlhours)) 1356*0Sstevel@tonic-gate crlhours = 0; 1357*0Sstevel@tonic-gate } 1358*0Sstevel@tonic-gate if ((crldays == 0) && (crlhours == 0)) 1359*0Sstevel@tonic-gate { 1360*0Sstevel@tonic-gate BIO_printf(bio_err,"cannot lookup how long until the next CRL is issued\n"); 1361*0Sstevel@tonic-gate goto err; 1362*0Sstevel@tonic-gate } 1363*0Sstevel@tonic-gate 1364*0Sstevel@tonic-gate if (verbose) BIO_printf(bio_err,"making CRL\n"); 1365*0Sstevel@tonic-gate if ((crl=X509_CRL_new()) == NULL) goto err; 1366*0Sstevel@tonic-gate if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) goto err; 1367*0Sstevel@tonic-gate 1368*0Sstevel@tonic-gate tmptm = ASN1_TIME_new(); 1369*0Sstevel@tonic-gate if (!tmptm) goto err; 1370*0Sstevel@tonic-gate X509_gmtime_adj(tmptm,0); 1371*0Sstevel@tonic-gate X509_CRL_set_lastUpdate(crl, tmptm); 1372*0Sstevel@tonic-gate X509_gmtime_adj(tmptm,(crldays*24+crlhours)*60*60); 1373*0Sstevel@tonic-gate X509_CRL_set_nextUpdate(crl, tmptm); 1374*0Sstevel@tonic-gate 1375*0Sstevel@tonic-gate ASN1_TIME_free(tmptm); 1376*0Sstevel@tonic-gate 1377*0Sstevel@tonic-gate for (i=0; i<sk_num(db->db->data); i++) 1378*0Sstevel@tonic-gate { 1379*0Sstevel@tonic-gate pp=(char **)sk_value(db->db->data,i); 1380*0Sstevel@tonic-gate if (pp[DB_type][0] == DB_TYPE_REV) 1381*0Sstevel@tonic-gate { 1382*0Sstevel@tonic-gate if ((r=X509_REVOKED_new()) == NULL) goto err; 1383*0Sstevel@tonic-gate j = make_revoked(r, pp[DB_rev_date]); 1384*0Sstevel@tonic-gate if (!j) goto err; 1385*0Sstevel@tonic-gate if (j == 2) crl_v2 = 1; 1386*0Sstevel@tonic-gate if (!BN_hex2bn(&serial, pp[DB_serial])) 1387*0Sstevel@tonic-gate goto err; 1388*0Sstevel@tonic-gate tmpser = BN_to_ASN1_INTEGER(serial, NULL); 1389*0Sstevel@tonic-gate BN_free(serial); 1390*0Sstevel@tonic-gate serial = NULL; 1391*0Sstevel@tonic-gate if (!tmpser) 1392*0Sstevel@tonic-gate goto err; 1393*0Sstevel@tonic-gate X509_REVOKED_set_serialNumber(r, tmpser); 1394*0Sstevel@tonic-gate ASN1_INTEGER_free(tmpser); 1395*0Sstevel@tonic-gate X509_CRL_add0_revoked(crl,r); 1396*0Sstevel@tonic-gate } 1397*0Sstevel@tonic-gate } 1398*0Sstevel@tonic-gate 1399*0Sstevel@tonic-gate /* sort the data so it will be written in serial 1400*0Sstevel@tonic-gate * number order */ 1401*0Sstevel@tonic-gate X509_CRL_sort(crl); 1402*0Sstevel@tonic-gate 1403*0Sstevel@tonic-gate /* we now have a CRL */ 1404*0Sstevel@tonic-gate if (verbose) BIO_printf(bio_err,"signing CRL\n"); 1405*0Sstevel@tonic-gate if (md != NULL) 1406*0Sstevel@tonic-gate { 1407*0Sstevel@tonic-gate if ((dgst=EVP_get_digestbyname(md)) == NULL) 1408*0Sstevel@tonic-gate { 1409*0Sstevel@tonic-gate BIO_printf(bio_err,"%s is an unsupported message digest type\n",md); 1410*0Sstevel@tonic-gate goto err; 1411*0Sstevel@tonic-gate } 1412*0Sstevel@tonic-gate } 1413*0Sstevel@tonic-gate else 1414*0Sstevel@tonic-gate { 1415*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA 1416*0Sstevel@tonic-gate if (pkey->type == EVP_PKEY_DSA) 1417*0Sstevel@tonic-gate dgst=EVP_dss1(); 1418*0Sstevel@tonic-gate else 1419*0Sstevel@tonic-gate #endif 1420*0Sstevel@tonic-gate dgst=EVP_md5(); 1421*0Sstevel@tonic-gate } 1422*0Sstevel@tonic-gate 1423*0Sstevel@tonic-gate /* Add any extensions asked for */ 1424*0Sstevel@tonic-gate 1425*0Sstevel@tonic-gate if (crl_ext || crlnumberfile != NULL) 1426*0Sstevel@tonic-gate { 1427*0Sstevel@tonic-gate X509V3_CTX crlctx; 1428*0Sstevel@tonic-gate X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0); 1429*0Sstevel@tonic-gate X509V3_set_nconf(&crlctx, conf); 1430*0Sstevel@tonic-gate 1431*0Sstevel@tonic-gate if (crl_ext) 1432*0Sstevel@tonic-gate if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, 1433*0Sstevel@tonic-gate crl_ext, crl)) goto err; 1434*0Sstevel@tonic-gate if (crlnumberfile != NULL) 1435*0Sstevel@tonic-gate { 1436*0Sstevel@tonic-gate tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL); 1437*0Sstevel@tonic-gate if (!tmpser) goto err; 1438*0Sstevel@tonic-gate X509_CRL_add1_ext_i2d(crl,NID_crl_number,tmpser,0,0); 1439*0Sstevel@tonic-gate ASN1_INTEGER_free(tmpser); 1440*0Sstevel@tonic-gate crl_v2 = 1; 1441*0Sstevel@tonic-gate if (!BN_add_word(crlnumber,1)) goto err; 1442*0Sstevel@tonic-gate } 1443*0Sstevel@tonic-gate } 1444*0Sstevel@tonic-gate if (crl_ext || crl_v2) 1445*0Sstevel@tonic-gate { 1446*0Sstevel@tonic-gate if (!X509_CRL_set_version(crl, 1)) 1447*0Sstevel@tonic-gate goto err; /* version 2 CRL */ 1448*0Sstevel@tonic-gate } 1449*0Sstevel@tonic-gate 1450*0Sstevel@tonic-gate 1451*0Sstevel@tonic-gate if (crlnumberfile != NULL) /* we have a CRL number that need updating */ 1452*0Sstevel@tonic-gate if (!save_serial(crlnumberfile,"new",crlnumber,NULL)) goto err; 1453*0Sstevel@tonic-gate 1454*0Sstevel@tonic-gate if (!X509_CRL_sign(crl,pkey,dgst)) goto err; 1455*0Sstevel@tonic-gate 1456*0Sstevel@tonic-gate PEM_write_bio_X509_CRL(Sout,crl); 1457*0Sstevel@tonic-gate 1458*0Sstevel@tonic-gate if (crlnumberfile != NULL) /* Rename the crlnumber file */ 1459*0Sstevel@tonic-gate if (!rotate_serial(crlnumberfile,"new","old")) goto err; 1460*0Sstevel@tonic-gate 1461*0Sstevel@tonic-gate } 1462*0Sstevel@tonic-gate /*****************************************************************/ 1463*0Sstevel@tonic-gate if (dorevoke) 1464*0Sstevel@tonic-gate { 1465*0Sstevel@tonic-gate if (infile == NULL) 1466*0Sstevel@tonic-gate { 1467*0Sstevel@tonic-gate BIO_printf(bio_err,"no input files\n"); 1468*0Sstevel@tonic-gate goto err; 1469*0Sstevel@tonic-gate } 1470*0Sstevel@tonic-gate else 1471*0Sstevel@tonic-gate { 1472*0Sstevel@tonic-gate X509 *revcert; 1473*0Sstevel@tonic-gate revcert=load_cert(bio_err, infile, FORMAT_PEM, 1474*0Sstevel@tonic-gate NULL, e, infile); 1475*0Sstevel@tonic-gate if (revcert == NULL) 1476*0Sstevel@tonic-gate goto err; 1477*0Sstevel@tonic-gate j=do_revoke(revcert,db, rev_type, rev_arg); 1478*0Sstevel@tonic-gate if (j <= 0) goto err; 1479*0Sstevel@tonic-gate X509_free(revcert); 1480*0Sstevel@tonic-gate 1481*0Sstevel@tonic-gate if (!save_index(dbfile, "new", db)) goto err; 1482*0Sstevel@tonic-gate 1483*0Sstevel@tonic-gate if (!rotate_index(dbfile, "new", "old")) goto err; 1484*0Sstevel@tonic-gate 1485*0Sstevel@tonic-gate BIO_printf(bio_err,"Data Base Updated\n"); 1486*0Sstevel@tonic-gate } 1487*0Sstevel@tonic-gate } 1488*0Sstevel@tonic-gate /*****************************************************************/ 1489*0Sstevel@tonic-gate ret=0; 1490*0Sstevel@tonic-gate err: 1491*0Sstevel@tonic-gate if(tofree) 1492*0Sstevel@tonic-gate OPENSSL_free(tofree); 1493*0Sstevel@tonic-gate BIO_free_all(Cout); 1494*0Sstevel@tonic-gate BIO_free_all(Sout); 1495*0Sstevel@tonic-gate BIO_free_all(out); 1496*0Sstevel@tonic-gate BIO_free_all(in); 1497*0Sstevel@tonic-gate 1498*0Sstevel@tonic-gate if (cert_sk) 1499*0Sstevel@tonic-gate sk_X509_pop_free(cert_sk,X509_free); 1500*0Sstevel@tonic-gate 1501*0Sstevel@tonic-gate if (ret) ERR_print_errors(bio_err); 1502*0Sstevel@tonic-gate app_RAND_write_file(randfile, bio_err); 1503*0Sstevel@tonic-gate if (free_key && key) 1504*0Sstevel@tonic-gate OPENSSL_free(key); 1505*0Sstevel@tonic-gate BN_free(serial); 1506*0Sstevel@tonic-gate if (db) 1507*0Sstevel@tonic-gate free_index(db); 1508*0Sstevel@tonic-gate EVP_PKEY_free(pkey); 1509*0Sstevel@tonic-gate X509_free(x509); 1510*0Sstevel@tonic-gate X509_CRL_free(crl); 1511*0Sstevel@tonic-gate NCONF_free(conf); 1512*0Sstevel@tonic-gate OBJ_cleanup(); 1513*0Sstevel@tonic-gate apps_shutdown(); 1514*0Sstevel@tonic-gate OPENSSL_EXIT(ret); 1515*0Sstevel@tonic-gate } 1516*0Sstevel@tonic-gate 1517*0Sstevel@tonic-gate static void lookup_fail(char *name, char *tag) 1518*0Sstevel@tonic-gate { 1519*0Sstevel@tonic-gate BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag); 1520*0Sstevel@tonic-gate } 1521*0Sstevel@tonic-gate 1522*0Sstevel@tonic-gate static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 1523*0Sstevel@tonic-gate const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db, 1524*0Sstevel@tonic-gate BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate, 1525*0Sstevel@tonic-gate long days, int batch, char *ext_sect, CONF *lconf, int verbose, 1526*0Sstevel@tonic-gate unsigned long certopt, unsigned long nameopt, int default_op, 1527*0Sstevel@tonic-gate int ext_copy) 1528*0Sstevel@tonic-gate { 1529*0Sstevel@tonic-gate X509_REQ *req=NULL; 1530*0Sstevel@tonic-gate BIO *in=NULL; 1531*0Sstevel@tonic-gate EVP_PKEY *pktmp=NULL; 1532*0Sstevel@tonic-gate int ok= -1,i; 1533*0Sstevel@tonic-gate 1534*0Sstevel@tonic-gate in=BIO_new(BIO_s_file()); 1535*0Sstevel@tonic-gate 1536*0Sstevel@tonic-gate if (BIO_read_filename(in,infile) <= 0) 1537*0Sstevel@tonic-gate { 1538*0Sstevel@tonic-gate perror(infile); 1539*0Sstevel@tonic-gate goto err; 1540*0Sstevel@tonic-gate } 1541*0Sstevel@tonic-gate if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL) 1542*0Sstevel@tonic-gate { 1543*0Sstevel@tonic-gate BIO_printf(bio_err,"Error reading certificate request in %s\n", 1544*0Sstevel@tonic-gate infile); 1545*0Sstevel@tonic-gate goto err; 1546*0Sstevel@tonic-gate } 1547*0Sstevel@tonic-gate if (verbose) 1548*0Sstevel@tonic-gate X509_REQ_print(bio_err,req); 1549*0Sstevel@tonic-gate 1550*0Sstevel@tonic-gate BIO_printf(bio_err,"Check that the request matches the signature\n"); 1551*0Sstevel@tonic-gate 1552*0Sstevel@tonic-gate if ((pktmp=X509_REQ_get_pubkey(req)) == NULL) 1553*0Sstevel@tonic-gate { 1554*0Sstevel@tonic-gate BIO_printf(bio_err,"error unpacking public key\n"); 1555*0Sstevel@tonic-gate goto err; 1556*0Sstevel@tonic-gate } 1557*0Sstevel@tonic-gate i=X509_REQ_verify(req,pktmp); 1558*0Sstevel@tonic-gate EVP_PKEY_free(pktmp); 1559*0Sstevel@tonic-gate if (i < 0) 1560*0Sstevel@tonic-gate { 1561*0Sstevel@tonic-gate ok=0; 1562*0Sstevel@tonic-gate BIO_printf(bio_err,"Signature verification problems....\n"); 1563*0Sstevel@tonic-gate goto err; 1564*0Sstevel@tonic-gate } 1565*0Sstevel@tonic-gate if (i == 0) 1566*0Sstevel@tonic-gate { 1567*0Sstevel@tonic-gate ok=0; 1568*0Sstevel@tonic-gate BIO_printf(bio_err,"Signature did not match the certificate request\n"); 1569*0Sstevel@tonic-gate goto err; 1570*0Sstevel@tonic-gate } 1571*0Sstevel@tonic-gate else 1572*0Sstevel@tonic-gate BIO_printf(bio_err,"Signature ok\n"); 1573*0Sstevel@tonic-gate 1574*0Sstevel@tonic-gate ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj, email_dn, 1575*0Sstevel@tonic-gate startdate,enddate,days,batch,verbose,req,ext_sect,lconf, 1576*0Sstevel@tonic-gate certopt, nameopt, default_op, ext_copy); 1577*0Sstevel@tonic-gate 1578*0Sstevel@tonic-gate err: 1579*0Sstevel@tonic-gate if (req != NULL) X509_REQ_free(req); 1580*0Sstevel@tonic-gate if (in != NULL) BIO_free(in); 1581*0Sstevel@tonic-gate return(ok); 1582*0Sstevel@tonic-gate } 1583*0Sstevel@tonic-gate 1584*0Sstevel@tonic-gate static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 1585*0Sstevel@tonic-gate const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db, 1586*0Sstevel@tonic-gate BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate, 1587*0Sstevel@tonic-gate long days, int batch, char *ext_sect, CONF *lconf, int verbose, 1588*0Sstevel@tonic-gate unsigned long certopt, unsigned long nameopt, int default_op, 1589*0Sstevel@tonic-gate int ext_copy, ENGINE *e) 1590*0Sstevel@tonic-gate { 1591*0Sstevel@tonic-gate X509 *req=NULL; 1592*0Sstevel@tonic-gate X509_REQ *rreq=NULL; 1593*0Sstevel@tonic-gate EVP_PKEY *pktmp=NULL; 1594*0Sstevel@tonic-gate int ok= -1,i; 1595*0Sstevel@tonic-gate 1596*0Sstevel@tonic-gate if ((req=load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL) 1597*0Sstevel@tonic-gate goto err; 1598*0Sstevel@tonic-gate if (verbose) 1599*0Sstevel@tonic-gate X509_print(bio_err,req); 1600*0Sstevel@tonic-gate 1601*0Sstevel@tonic-gate BIO_printf(bio_err,"Check that the request matches the signature\n"); 1602*0Sstevel@tonic-gate 1603*0Sstevel@tonic-gate if ((pktmp=X509_get_pubkey(req)) == NULL) 1604*0Sstevel@tonic-gate { 1605*0Sstevel@tonic-gate BIO_printf(bio_err,"error unpacking public key\n"); 1606*0Sstevel@tonic-gate goto err; 1607*0Sstevel@tonic-gate } 1608*0Sstevel@tonic-gate i=X509_verify(req,pktmp); 1609*0Sstevel@tonic-gate EVP_PKEY_free(pktmp); 1610*0Sstevel@tonic-gate if (i < 0) 1611*0Sstevel@tonic-gate { 1612*0Sstevel@tonic-gate ok=0; 1613*0Sstevel@tonic-gate BIO_printf(bio_err,"Signature verification problems....\n"); 1614*0Sstevel@tonic-gate goto err; 1615*0Sstevel@tonic-gate } 1616*0Sstevel@tonic-gate if (i == 0) 1617*0Sstevel@tonic-gate { 1618*0Sstevel@tonic-gate ok=0; 1619*0Sstevel@tonic-gate BIO_printf(bio_err,"Signature did not match the certificate\n"); 1620*0Sstevel@tonic-gate goto err; 1621*0Sstevel@tonic-gate } 1622*0Sstevel@tonic-gate else 1623*0Sstevel@tonic-gate BIO_printf(bio_err,"Signature ok\n"); 1624*0Sstevel@tonic-gate 1625*0Sstevel@tonic-gate if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL) 1626*0Sstevel@tonic-gate goto err; 1627*0Sstevel@tonic-gate 1628*0Sstevel@tonic-gate ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,email_dn,startdate,enddate, 1629*0Sstevel@tonic-gate days,batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op, 1630*0Sstevel@tonic-gate ext_copy); 1631*0Sstevel@tonic-gate 1632*0Sstevel@tonic-gate err: 1633*0Sstevel@tonic-gate if (rreq != NULL) X509_REQ_free(rreq); 1634*0Sstevel@tonic-gate if (req != NULL) X509_free(req); 1635*0Sstevel@tonic-gate return(ok); 1636*0Sstevel@tonic-gate } 1637*0Sstevel@tonic-gate 1638*0Sstevel@tonic-gate static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, 1639*0Sstevel@tonic-gate STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj, 1640*0Sstevel@tonic-gate int email_dn, char *startdate, char *enddate, long days, int batch, 1641*0Sstevel@tonic-gate int verbose, X509_REQ *req, char *ext_sect, CONF *lconf, 1642*0Sstevel@tonic-gate unsigned long certopt, unsigned long nameopt, int default_op, 1643*0Sstevel@tonic-gate int ext_copy) 1644*0Sstevel@tonic-gate { 1645*0Sstevel@tonic-gate X509_NAME *name=NULL,*CAname=NULL,*subject=NULL, *dn_subject=NULL; 1646*0Sstevel@tonic-gate ASN1_UTCTIME *tm,*tmptm; 1647*0Sstevel@tonic-gate ASN1_STRING *str,*str2; 1648*0Sstevel@tonic-gate ASN1_OBJECT *obj; 1649*0Sstevel@tonic-gate X509 *ret=NULL; 1650*0Sstevel@tonic-gate X509_CINF *ci; 1651*0Sstevel@tonic-gate X509_NAME_ENTRY *ne; 1652*0Sstevel@tonic-gate X509_NAME_ENTRY *tne,*push; 1653*0Sstevel@tonic-gate EVP_PKEY *pktmp; 1654*0Sstevel@tonic-gate int ok= -1,i,j,last,nid; 1655*0Sstevel@tonic-gate char *p; 1656*0Sstevel@tonic-gate CONF_VALUE *cv; 1657*0Sstevel@tonic-gate char *row[DB_NUMBER],**rrow=NULL,**irow=NULL; 1658*0Sstevel@tonic-gate char buf[25]; 1659*0Sstevel@tonic-gate 1660*0Sstevel@tonic-gate tmptm=ASN1_UTCTIME_new(); 1661*0Sstevel@tonic-gate if (tmptm == NULL) 1662*0Sstevel@tonic-gate { 1663*0Sstevel@tonic-gate BIO_printf(bio_err,"malloc error\n"); 1664*0Sstevel@tonic-gate return(0); 1665*0Sstevel@tonic-gate } 1666*0Sstevel@tonic-gate 1667*0Sstevel@tonic-gate for (i=0; i<DB_NUMBER; i++) 1668*0Sstevel@tonic-gate row[i]=NULL; 1669*0Sstevel@tonic-gate 1670*0Sstevel@tonic-gate if (subj) 1671*0Sstevel@tonic-gate { 1672*0Sstevel@tonic-gate X509_NAME *n = do_subject(subj, MBSTRING_ASC); 1673*0Sstevel@tonic-gate 1674*0Sstevel@tonic-gate if (!n) 1675*0Sstevel@tonic-gate { 1676*0Sstevel@tonic-gate ERR_print_errors(bio_err); 1677*0Sstevel@tonic-gate goto err; 1678*0Sstevel@tonic-gate } 1679*0Sstevel@tonic-gate X509_REQ_set_subject_name(req,n); 1680*0Sstevel@tonic-gate req->req_info->enc.modified = 1; 1681*0Sstevel@tonic-gate X509_NAME_free(n); 1682*0Sstevel@tonic-gate } 1683*0Sstevel@tonic-gate 1684*0Sstevel@tonic-gate if (default_op) 1685*0Sstevel@tonic-gate BIO_printf(bio_err,"The Subject's Distinguished Name is as follows\n"); 1686*0Sstevel@tonic-gate 1687*0Sstevel@tonic-gate name=X509_REQ_get_subject_name(req); 1688*0Sstevel@tonic-gate for (i=0; i<X509_NAME_entry_count(name); i++) 1689*0Sstevel@tonic-gate { 1690*0Sstevel@tonic-gate ne= X509_NAME_get_entry(name,i); 1691*0Sstevel@tonic-gate str=X509_NAME_ENTRY_get_data(ne); 1692*0Sstevel@tonic-gate obj=X509_NAME_ENTRY_get_object(ne); 1693*0Sstevel@tonic-gate 1694*0Sstevel@tonic-gate if (msie_hack) 1695*0Sstevel@tonic-gate { 1696*0Sstevel@tonic-gate /* assume all type should be strings */ 1697*0Sstevel@tonic-gate nid=OBJ_obj2nid(ne->object); 1698*0Sstevel@tonic-gate 1699*0Sstevel@tonic-gate if (str->type == V_ASN1_UNIVERSALSTRING) 1700*0Sstevel@tonic-gate ASN1_UNIVERSALSTRING_to_string(str); 1701*0Sstevel@tonic-gate 1702*0Sstevel@tonic-gate if ((str->type == V_ASN1_IA5STRING) && 1703*0Sstevel@tonic-gate (nid != NID_pkcs9_emailAddress)) 1704*0Sstevel@tonic-gate str->type=V_ASN1_T61STRING; 1705*0Sstevel@tonic-gate 1706*0Sstevel@tonic-gate if ((nid == NID_pkcs9_emailAddress) && 1707*0Sstevel@tonic-gate (str->type == V_ASN1_PRINTABLESTRING)) 1708*0Sstevel@tonic-gate str->type=V_ASN1_IA5STRING; 1709*0Sstevel@tonic-gate } 1710*0Sstevel@tonic-gate 1711*0Sstevel@tonic-gate /* If no EMAIL is wanted in the subject */ 1712*0Sstevel@tonic-gate if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn)) 1713*0Sstevel@tonic-gate continue; 1714*0Sstevel@tonic-gate 1715*0Sstevel@tonic-gate /* check some things */ 1716*0Sstevel@tonic-gate if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && 1717*0Sstevel@tonic-gate (str->type != V_ASN1_IA5STRING)) 1718*0Sstevel@tonic-gate { 1719*0Sstevel@tonic-gate BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n"); 1720*0Sstevel@tonic-gate goto err; 1721*0Sstevel@tonic-gate } 1722*0Sstevel@tonic-gate if ((str->type != V_ASN1_BMPSTRING) && (str->type != V_ASN1_UTF8STRING)) 1723*0Sstevel@tonic-gate { 1724*0Sstevel@tonic-gate j=ASN1_PRINTABLE_type(str->data,str->length); 1725*0Sstevel@tonic-gate if ( ((j == V_ASN1_T61STRING) && 1726*0Sstevel@tonic-gate (str->type != V_ASN1_T61STRING)) || 1727*0Sstevel@tonic-gate ((j == V_ASN1_IA5STRING) && 1728*0Sstevel@tonic-gate (str->type == V_ASN1_PRINTABLESTRING))) 1729*0Sstevel@tonic-gate { 1730*0Sstevel@tonic-gate BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n"); 1731*0Sstevel@tonic-gate goto err; 1732*0Sstevel@tonic-gate } 1733*0Sstevel@tonic-gate } 1734*0Sstevel@tonic-gate 1735*0Sstevel@tonic-gate if (default_op) 1736*0Sstevel@tonic-gate old_entry_print(bio_err, obj, str); 1737*0Sstevel@tonic-gate } 1738*0Sstevel@tonic-gate 1739*0Sstevel@tonic-gate /* Ok, now we check the 'policy' stuff. */ 1740*0Sstevel@tonic-gate if ((subject=X509_NAME_new()) == NULL) 1741*0Sstevel@tonic-gate { 1742*0Sstevel@tonic-gate BIO_printf(bio_err,"Memory allocation failure\n"); 1743*0Sstevel@tonic-gate goto err; 1744*0Sstevel@tonic-gate } 1745*0Sstevel@tonic-gate 1746*0Sstevel@tonic-gate /* take a copy of the issuer name before we mess with it. */ 1747*0Sstevel@tonic-gate CAname=X509_NAME_dup(x509->cert_info->subject); 1748*0Sstevel@tonic-gate if (CAname == NULL) goto err; 1749*0Sstevel@tonic-gate str=str2=NULL; 1750*0Sstevel@tonic-gate 1751*0Sstevel@tonic-gate for (i=0; i<sk_CONF_VALUE_num(policy); i++) 1752*0Sstevel@tonic-gate { 1753*0Sstevel@tonic-gate cv=sk_CONF_VALUE_value(policy,i); /* get the object id */ 1754*0Sstevel@tonic-gate if ((j=OBJ_txt2nid(cv->name)) == NID_undef) 1755*0Sstevel@tonic-gate { 1756*0Sstevel@tonic-gate BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name); 1757*0Sstevel@tonic-gate goto err; 1758*0Sstevel@tonic-gate } 1759*0Sstevel@tonic-gate obj=OBJ_nid2obj(j); 1760*0Sstevel@tonic-gate 1761*0Sstevel@tonic-gate last= -1; 1762*0Sstevel@tonic-gate for (;;) 1763*0Sstevel@tonic-gate { 1764*0Sstevel@tonic-gate /* lookup the object in the supplied name list */ 1765*0Sstevel@tonic-gate j=X509_NAME_get_index_by_OBJ(name,obj,last); 1766*0Sstevel@tonic-gate if (j < 0) 1767*0Sstevel@tonic-gate { 1768*0Sstevel@tonic-gate if (last != -1) break; 1769*0Sstevel@tonic-gate tne=NULL; 1770*0Sstevel@tonic-gate } 1771*0Sstevel@tonic-gate else 1772*0Sstevel@tonic-gate { 1773*0Sstevel@tonic-gate tne=X509_NAME_get_entry(name,j); 1774*0Sstevel@tonic-gate } 1775*0Sstevel@tonic-gate last=j; 1776*0Sstevel@tonic-gate 1777*0Sstevel@tonic-gate /* depending on the 'policy', decide what to do. */ 1778*0Sstevel@tonic-gate push=NULL; 1779*0Sstevel@tonic-gate if (strcmp(cv->value,"optional") == 0) 1780*0Sstevel@tonic-gate { 1781*0Sstevel@tonic-gate if (tne != NULL) 1782*0Sstevel@tonic-gate push=tne; 1783*0Sstevel@tonic-gate } 1784*0Sstevel@tonic-gate else if (strcmp(cv->value,"supplied") == 0) 1785*0Sstevel@tonic-gate { 1786*0Sstevel@tonic-gate if (tne == NULL) 1787*0Sstevel@tonic-gate { 1788*0Sstevel@tonic-gate BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name); 1789*0Sstevel@tonic-gate goto err; 1790*0Sstevel@tonic-gate } 1791*0Sstevel@tonic-gate else 1792*0Sstevel@tonic-gate push=tne; 1793*0Sstevel@tonic-gate } 1794*0Sstevel@tonic-gate else if (strcmp(cv->value,"match") == 0) 1795*0Sstevel@tonic-gate { 1796*0Sstevel@tonic-gate int last2; 1797*0Sstevel@tonic-gate 1798*0Sstevel@tonic-gate if (tne == NULL) 1799*0Sstevel@tonic-gate { 1800*0Sstevel@tonic-gate BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name); 1801*0Sstevel@tonic-gate goto err; 1802*0Sstevel@tonic-gate } 1803*0Sstevel@tonic-gate 1804*0Sstevel@tonic-gate last2= -1; 1805*0Sstevel@tonic-gate 1806*0Sstevel@tonic-gate again2: 1807*0Sstevel@tonic-gate j=X509_NAME_get_index_by_OBJ(CAname,obj,last2); 1808*0Sstevel@tonic-gate if ((j < 0) && (last2 == -1)) 1809*0Sstevel@tonic-gate { 1810*0Sstevel@tonic-gate BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name); 1811*0Sstevel@tonic-gate goto err; 1812*0Sstevel@tonic-gate } 1813*0Sstevel@tonic-gate if (j >= 0) 1814*0Sstevel@tonic-gate { 1815*0Sstevel@tonic-gate push=X509_NAME_get_entry(CAname,j); 1816*0Sstevel@tonic-gate str=X509_NAME_ENTRY_get_data(tne); 1817*0Sstevel@tonic-gate str2=X509_NAME_ENTRY_get_data(push); 1818*0Sstevel@tonic-gate last2=j; 1819*0Sstevel@tonic-gate if (ASN1_STRING_cmp(str,str2) != 0) 1820*0Sstevel@tonic-gate goto again2; 1821*0Sstevel@tonic-gate } 1822*0Sstevel@tonic-gate if (j < 0) 1823*0Sstevel@tonic-gate { 1824*0Sstevel@tonic-gate BIO_printf(bio_err,"The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n",cv->name,((str2 == NULL)?"NULL":(char *)str2->data),((str == NULL)?"NULL":(char *)str->data)); 1825*0Sstevel@tonic-gate goto err; 1826*0Sstevel@tonic-gate } 1827*0Sstevel@tonic-gate } 1828*0Sstevel@tonic-gate else 1829*0Sstevel@tonic-gate { 1830*0Sstevel@tonic-gate BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value); 1831*0Sstevel@tonic-gate goto err; 1832*0Sstevel@tonic-gate } 1833*0Sstevel@tonic-gate 1834*0Sstevel@tonic-gate if (push != NULL) 1835*0Sstevel@tonic-gate { 1836*0Sstevel@tonic-gate if (!X509_NAME_add_entry(subject,push, -1, 0)) 1837*0Sstevel@tonic-gate { 1838*0Sstevel@tonic-gate if (push != NULL) 1839*0Sstevel@tonic-gate X509_NAME_ENTRY_free(push); 1840*0Sstevel@tonic-gate BIO_printf(bio_err,"Memory allocation failure\n"); 1841*0Sstevel@tonic-gate goto err; 1842*0Sstevel@tonic-gate } 1843*0Sstevel@tonic-gate } 1844*0Sstevel@tonic-gate if (j < 0) break; 1845*0Sstevel@tonic-gate } 1846*0Sstevel@tonic-gate } 1847*0Sstevel@tonic-gate 1848*0Sstevel@tonic-gate if (preserve) 1849*0Sstevel@tonic-gate { 1850*0Sstevel@tonic-gate X509_NAME_free(subject); 1851*0Sstevel@tonic-gate /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */ 1852*0Sstevel@tonic-gate subject=X509_NAME_dup(name); 1853*0Sstevel@tonic-gate if (subject == NULL) goto err; 1854*0Sstevel@tonic-gate } 1855*0Sstevel@tonic-gate 1856*0Sstevel@tonic-gate if (verbose) 1857*0Sstevel@tonic-gate BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n"); 1858*0Sstevel@tonic-gate 1859*0Sstevel@tonic-gate /* Build the correct Subject if no e-mail is wanted in the subject */ 1860*0Sstevel@tonic-gate /* and add it later on because of the method extensions are added (altName) */ 1861*0Sstevel@tonic-gate 1862*0Sstevel@tonic-gate if (email_dn) 1863*0Sstevel@tonic-gate dn_subject = subject; 1864*0Sstevel@tonic-gate else 1865*0Sstevel@tonic-gate { 1866*0Sstevel@tonic-gate X509_NAME_ENTRY *tmpne; 1867*0Sstevel@tonic-gate /* Its best to dup the subject DN and then delete any email 1868*0Sstevel@tonic-gate * addresses because this retains its structure. 1869*0Sstevel@tonic-gate */ 1870*0Sstevel@tonic-gate if (!(dn_subject = X509_NAME_dup(subject))) 1871*0Sstevel@tonic-gate { 1872*0Sstevel@tonic-gate BIO_printf(bio_err,"Memory allocation failure\n"); 1873*0Sstevel@tonic-gate goto err; 1874*0Sstevel@tonic-gate } 1875*0Sstevel@tonic-gate while((i = X509_NAME_get_index_by_NID(dn_subject, 1876*0Sstevel@tonic-gate NID_pkcs9_emailAddress, -1)) >= 0) 1877*0Sstevel@tonic-gate { 1878*0Sstevel@tonic-gate tmpne = X509_NAME_get_entry(dn_subject, i); 1879*0Sstevel@tonic-gate X509_NAME_delete_entry(dn_subject, i); 1880*0Sstevel@tonic-gate X509_NAME_ENTRY_free(tmpne); 1881*0Sstevel@tonic-gate } 1882*0Sstevel@tonic-gate } 1883*0Sstevel@tonic-gate 1884*0Sstevel@tonic-gate if (BN_is_zero(serial)) 1885*0Sstevel@tonic-gate row[DB_serial]=BUF_strdup("00"); 1886*0Sstevel@tonic-gate else 1887*0Sstevel@tonic-gate row[DB_serial]=BN_bn2hex(serial); 1888*0Sstevel@tonic-gate if (row[DB_serial] == NULL) 1889*0Sstevel@tonic-gate { 1890*0Sstevel@tonic-gate BIO_printf(bio_err,"Memory allocation failure\n"); 1891*0Sstevel@tonic-gate goto err; 1892*0Sstevel@tonic-gate } 1893*0Sstevel@tonic-gate 1894*0Sstevel@tonic-gate if (db->attributes.unique_subject) 1895*0Sstevel@tonic-gate { 1896*0Sstevel@tonic-gate rrow=TXT_DB_get_by_index(db->db,DB_name,row); 1897*0Sstevel@tonic-gate if (rrow != NULL) 1898*0Sstevel@tonic-gate { 1899*0Sstevel@tonic-gate BIO_printf(bio_err, 1900*0Sstevel@tonic-gate "ERROR:There is already a certificate for %s\n", 1901*0Sstevel@tonic-gate row[DB_name]); 1902*0Sstevel@tonic-gate } 1903*0Sstevel@tonic-gate } 1904*0Sstevel@tonic-gate if (rrow == NULL) 1905*0Sstevel@tonic-gate { 1906*0Sstevel@tonic-gate rrow=TXT_DB_get_by_index(db->db,DB_serial,row); 1907*0Sstevel@tonic-gate if (rrow != NULL) 1908*0Sstevel@tonic-gate { 1909*0Sstevel@tonic-gate BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n", 1910*0Sstevel@tonic-gate row[DB_serial]); 1911*0Sstevel@tonic-gate BIO_printf(bio_err," check the database/serial_file for corruption\n"); 1912*0Sstevel@tonic-gate } 1913*0Sstevel@tonic-gate } 1914*0Sstevel@tonic-gate 1915*0Sstevel@tonic-gate if (rrow != NULL) 1916*0Sstevel@tonic-gate { 1917*0Sstevel@tonic-gate BIO_printf(bio_err, 1918*0Sstevel@tonic-gate "The matching entry has the following details\n"); 1919*0Sstevel@tonic-gate if (rrow[DB_type][0] == 'E') 1920*0Sstevel@tonic-gate p="Expired"; 1921*0Sstevel@tonic-gate else if (rrow[DB_type][0] == 'R') 1922*0Sstevel@tonic-gate p="Revoked"; 1923*0Sstevel@tonic-gate else if (rrow[DB_type][0] == 'V') 1924*0Sstevel@tonic-gate p="Valid"; 1925*0Sstevel@tonic-gate else 1926*0Sstevel@tonic-gate p="\ninvalid type, Data base error\n"; 1927*0Sstevel@tonic-gate BIO_printf(bio_err,"Type :%s\n",p);; 1928*0Sstevel@tonic-gate if (rrow[DB_type][0] == 'R') 1929*0Sstevel@tonic-gate { 1930*0Sstevel@tonic-gate p=rrow[DB_exp_date]; if (p == NULL) p="undef"; 1931*0Sstevel@tonic-gate BIO_printf(bio_err,"Was revoked on:%s\n",p); 1932*0Sstevel@tonic-gate } 1933*0Sstevel@tonic-gate p=rrow[DB_exp_date]; if (p == NULL) p="undef"; 1934*0Sstevel@tonic-gate BIO_printf(bio_err,"Expires on :%s\n",p); 1935*0Sstevel@tonic-gate p=rrow[DB_serial]; if (p == NULL) p="undef"; 1936*0Sstevel@tonic-gate BIO_printf(bio_err,"Serial Number :%s\n",p); 1937*0Sstevel@tonic-gate p=rrow[DB_file]; if (p == NULL) p="undef"; 1938*0Sstevel@tonic-gate BIO_printf(bio_err,"File name :%s\n",p); 1939*0Sstevel@tonic-gate p=rrow[DB_name]; if (p == NULL) p="undef"; 1940*0Sstevel@tonic-gate BIO_printf(bio_err,"Subject Name :%s\n",p); 1941*0Sstevel@tonic-gate ok= -1; /* This is now a 'bad' error. */ 1942*0Sstevel@tonic-gate goto err; 1943*0Sstevel@tonic-gate } 1944*0Sstevel@tonic-gate 1945*0Sstevel@tonic-gate /* We are now totally happy, lets make and sign the certificate */ 1946*0Sstevel@tonic-gate if (verbose) 1947*0Sstevel@tonic-gate BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n"); 1948*0Sstevel@tonic-gate 1949*0Sstevel@tonic-gate if ((ret=X509_new()) == NULL) goto err; 1950*0Sstevel@tonic-gate ci=ret->cert_info; 1951*0Sstevel@tonic-gate 1952*0Sstevel@tonic-gate #ifdef X509_V3 1953*0Sstevel@tonic-gate /* Make it an X509 v3 certificate. */ 1954*0Sstevel@tonic-gate if (!X509_set_version(ret,2)) goto err; 1955*0Sstevel@tonic-gate #endif 1956*0Sstevel@tonic-gate 1957*0Sstevel@tonic-gate if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL) 1958*0Sstevel@tonic-gate goto err; 1959*0Sstevel@tonic-gate if (!X509_set_issuer_name(ret,X509_get_subject_name(x509))) 1960*0Sstevel@tonic-gate goto err; 1961*0Sstevel@tonic-gate 1962*0Sstevel@tonic-gate if (strcmp(startdate,"today") == 0) 1963*0Sstevel@tonic-gate X509_gmtime_adj(X509_get_notBefore(ret),0); 1964*0Sstevel@tonic-gate else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate); 1965*0Sstevel@tonic-gate 1966*0Sstevel@tonic-gate if (enddate == NULL) 1967*0Sstevel@tonic-gate X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days); 1968*0Sstevel@tonic-gate else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate); 1969*0Sstevel@tonic-gate 1970*0Sstevel@tonic-gate if (!X509_set_subject_name(ret,subject)) goto err; 1971*0Sstevel@tonic-gate 1972*0Sstevel@tonic-gate pktmp=X509_REQ_get_pubkey(req); 1973*0Sstevel@tonic-gate i = X509_set_pubkey(ret,pktmp); 1974*0Sstevel@tonic-gate EVP_PKEY_free(pktmp); 1975*0Sstevel@tonic-gate if (!i) goto err; 1976*0Sstevel@tonic-gate 1977*0Sstevel@tonic-gate /* Lets add the extensions, if there are any */ 1978*0Sstevel@tonic-gate if (ext_sect) 1979*0Sstevel@tonic-gate { 1980*0Sstevel@tonic-gate X509V3_CTX ctx; 1981*0Sstevel@tonic-gate if (ci->version == NULL) 1982*0Sstevel@tonic-gate if ((ci->version=ASN1_INTEGER_new()) == NULL) 1983*0Sstevel@tonic-gate goto err; 1984*0Sstevel@tonic-gate ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */ 1985*0Sstevel@tonic-gate 1986*0Sstevel@tonic-gate /* Free the current entries if any, there should not 1987*0Sstevel@tonic-gate * be any I believe */ 1988*0Sstevel@tonic-gate if (ci->extensions != NULL) 1989*0Sstevel@tonic-gate sk_X509_EXTENSION_pop_free(ci->extensions, 1990*0Sstevel@tonic-gate X509_EXTENSION_free); 1991*0Sstevel@tonic-gate 1992*0Sstevel@tonic-gate ci->extensions = NULL; 1993*0Sstevel@tonic-gate 1994*0Sstevel@tonic-gate /* Initialize the context structure */ 1995*0Sstevel@tonic-gate X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0); 1996*0Sstevel@tonic-gate 1997*0Sstevel@tonic-gate if (extconf) 1998*0Sstevel@tonic-gate { 1999*0Sstevel@tonic-gate if (verbose) 2000*0Sstevel@tonic-gate BIO_printf(bio_err, "Extra configuration file found\n"); 2001*0Sstevel@tonic-gate 2002*0Sstevel@tonic-gate /* Use the extconf configuration db LHASH */ 2003*0Sstevel@tonic-gate X509V3_set_nconf(&ctx, extconf); 2004*0Sstevel@tonic-gate 2005*0Sstevel@tonic-gate /* Test the structure (needed?) */ 2006*0Sstevel@tonic-gate /* X509V3_set_ctx_test(&ctx); */ 2007*0Sstevel@tonic-gate 2008*0Sstevel@tonic-gate /* Adds exts contained in the configuration file */ 2009*0Sstevel@tonic-gate if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect,ret)) 2010*0Sstevel@tonic-gate { 2011*0Sstevel@tonic-gate BIO_printf(bio_err, 2012*0Sstevel@tonic-gate "ERROR: adding extensions in section %s\n", 2013*0Sstevel@tonic-gate ext_sect); 2014*0Sstevel@tonic-gate ERR_print_errors(bio_err); 2015*0Sstevel@tonic-gate goto err; 2016*0Sstevel@tonic-gate } 2017*0Sstevel@tonic-gate if (verbose) 2018*0Sstevel@tonic-gate BIO_printf(bio_err, "Successfully added extensions from file.\n"); 2019*0Sstevel@tonic-gate } 2020*0Sstevel@tonic-gate else if (ext_sect) 2021*0Sstevel@tonic-gate { 2022*0Sstevel@tonic-gate /* We found extensions to be set from config file */ 2023*0Sstevel@tonic-gate X509V3_set_nconf(&ctx, lconf); 2024*0Sstevel@tonic-gate 2025*0Sstevel@tonic-gate if(!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret)) 2026*0Sstevel@tonic-gate { 2027*0Sstevel@tonic-gate BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect); 2028*0Sstevel@tonic-gate ERR_print_errors(bio_err); 2029*0Sstevel@tonic-gate goto err; 2030*0Sstevel@tonic-gate } 2031*0Sstevel@tonic-gate 2032*0Sstevel@tonic-gate if (verbose) 2033*0Sstevel@tonic-gate BIO_printf(bio_err, "Successfully added extensions from config\n"); 2034*0Sstevel@tonic-gate } 2035*0Sstevel@tonic-gate } 2036*0Sstevel@tonic-gate 2037*0Sstevel@tonic-gate /* Copy extensions from request (if any) */ 2038*0Sstevel@tonic-gate 2039*0Sstevel@tonic-gate if (!copy_extensions(ret, req, ext_copy)) 2040*0Sstevel@tonic-gate { 2041*0Sstevel@tonic-gate BIO_printf(bio_err, "ERROR: adding extensions from request\n"); 2042*0Sstevel@tonic-gate ERR_print_errors(bio_err); 2043*0Sstevel@tonic-gate goto err; 2044*0Sstevel@tonic-gate } 2045*0Sstevel@tonic-gate 2046*0Sstevel@tonic-gate /* Set the right value for the noemailDN option */ 2047*0Sstevel@tonic-gate if( email_dn == 0 ) 2048*0Sstevel@tonic-gate { 2049*0Sstevel@tonic-gate if (!X509_set_subject_name(ret,dn_subject)) goto err; 2050*0Sstevel@tonic-gate } 2051*0Sstevel@tonic-gate 2052*0Sstevel@tonic-gate if (!default_op) 2053*0Sstevel@tonic-gate { 2054*0Sstevel@tonic-gate BIO_printf(bio_err, "Certificate Details:\n"); 2055*0Sstevel@tonic-gate /* Never print signature details because signature not present */ 2056*0Sstevel@tonic-gate certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME; 2057*0Sstevel@tonic-gate X509_print_ex(bio_err, ret, nameopt, certopt); 2058*0Sstevel@tonic-gate } 2059*0Sstevel@tonic-gate 2060*0Sstevel@tonic-gate BIO_printf(bio_err,"Certificate is to be certified until "); 2061*0Sstevel@tonic-gate ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret)); 2062*0Sstevel@tonic-gate if (days) BIO_printf(bio_err," (%d days)",days); 2063*0Sstevel@tonic-gate BIO_printf(bio_err, "\n"); 2064*0Sstevel@tonic-gate 2065*0Sstevel@tonic-gate if (!batch) 2066*0Sstevel@tonic-gate { 2067*0Sstevel@tonic-gate 2068*0Sstevel@tonic-gate BIO_printf(bio_err,"Sign the certificate? [y/n]:"); 2069*0Sstevel@tonic-gate (void)BIO_flush(bio_err); 2070*0Sstevel@tonic-gate buf[0]='\0'; 2071*0Sstevel@tonic-gate fgets(buf,sizeof(buf)-1,stdin); 2072*0Sstevel@tonic-gate if (!((buf[0] == 'y') || (buf[0] == 'Y'))) 2073*0Sstevel@tonic-gate { 2074*0Sstevel@tonic-gate BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n"); 2075*0Sstevel@tonic-gate ok=0; 2076*0Sstevel@tonic-gate goto err; 2077*0Sstevel@tonic-gate } 2078*0Sstevel@tonic-gate } 2079*0Sstevel@tonic-gate 2080*0Sstevel@tonic-gate 2081*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA 2082*0Sstevel@tonic-gate if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1(); 2083*0Sstevel@tonic-gate pktmp=X509_get_pubkey(ret); 2084*0Sstevel@tonic-gate if (EVP_PKEY_missing_parameters(pktmp) && 2085*0Sstevel@tonic-gate !EVP_PKEY_missing_parameters(pkey)) 2086*0Sstevel@tonic-gate EVP_PKEY_copy_parameters(pktmp,pkey); 2087*0Sstevel@tonic-gate EVP_PKEY_free(pktmp); 2088*0Sstevel@tonic-gate #endif 2089*0Sstevel@tonic-gate 2090*0Sstevel@tonic-gate if (!X509_sign(ret,pkey,dgst)) 2091*0Sstevel@tonic-gate goto err; 2092*0Sstevel@tonic-gate 2093*0Sstevel@tonic-gate /* We now just add it to the database */ 2094*0Sstevel@tonic-gate row[DB_type]=(char *)OPENSSL_malloc(2); 2095*0Sstevel@tonic-gate 2096*0Sstevel@tonic-gate tm=X509_get_notAfter(ret); 2097*0Sstevel@tonic-gate row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1); 2098*0Sstevel@tonic-gate memcpy(row[DB_exp_date],tm->data,tm->length); 2099*0Sstevel@tonic-gate row[DB_exp_date][tm->length]='\0'; 2100*0Sstevel@tonic-gate 2101*0Sstevel@tonic-gate row[DB_rev_date]=NULL; 2102*0Sstevel@tonic-gate 2103*0Sstevel@tonic-gate /* row[DB_serial] done already */ 2104*0Sstevel@tonic-gate row[DB_file]=(char *)OPENSSL_malloc(8); 2105*0Sstevel@tonic-gate row[DB_name]=X509_NAME_oneline(X509_get_subject_name(ret),NULL,0); 2106*0Sstevel@tonic-gate 2107*0Sstevel@tonic-gate if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || 2108*0Sstevel@tonic-gate (row[DB_file] == NULL) || (row[DB_name] == NULL)) 2109*0Sstevel@tonic-gate { 2110*0Sstevel@tonic-gate BIO_printf(bio_err,"Memory allocation failure\n"); 2111*0Sstevel@tonic-gate goto err; 2112*0Sstevel@tonic-gate } 2113*0Sstevel@tonic-gate BUF_strlcpy(row[DB_file],"unknown",8); 2114*0Sstevel@tonic-gate row[DB_type][0]='V'; 2115*0Sstevel@tonic-gate row[DB_type][1]='\0'; 2116*0Sstevel@tonic-gate 2117*0Sstevel@tonic-gate if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL) 2118*0Sstevel@tonic-gate { 2119*0Sstevel@tonic-gate BIO_printf(bio_err,"Memory allocation failure\n"); 2120*0Sstevel@tonic-gate goto err; 2121*0Sstevel@tonic-gate } 2122*0Sstevel@tonic-gate 2123*0Sstevel@tonic-gate for (i=0; i<DB_NUMBER; i++) 2124*0Sstevel@tonic-gate { 2125*0Sstevel@tonic-gate irow[i]=row[i]; 2126*0Sstevel@tonic-gate row[i]=NULL; 2127*0Sstevel@tonic-gate } 2128*0Sstevel@tonic-gate irow[DB_NUMBER]=NULL; 2129*0Sstevel@tonic-gate 2130*0Sstevel@tonic-gate if (!TXT_DB_insert(db->db,irow)) 2131*0Sstevel@tonic-gate { 2132*0Sstevel@tonic-gate BIO_printf(bio_err,"failed to update database\n"); 2133*0Sstevel@tonic-gate BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error); 2134*0Sstevel@tonic-gate goto err; 2135*0Sstevel@tonic-gate } 2136*0Sstevel@tonic-gate ok=1; 2137*0Sstevel@tonic-gate err: 2138*0Sstevel@tonic-gate for (i=0; i<DB_NUMBER; i++) 2139*0Sstevel@tonic-gate if (row[i] != NULL) OPENSSL_free(row[i]); 2140*0Sstevel@tonic-gate 2141*0Sstevel@tonic-gate if (CAname != NULL) 2142*0Sstevel@tonic-gate X509_NAME_free(CAname); 2143*0Sstevel@tonic-gate if (subject != NULL) 2144*0Sstevel@tonic-gate X509_NAME_free(subject); 2145*0Sstevel@tonic-gate if ((dn_subject != NULL) && !email_dn) 2146*0Sstevel@tonic-gate X509_NAME_free(dn_subject); 2147*0Sstevel@tonic-gate if (tmptm != NULL) 2148*0Sstevel@tonic-gate ASN1_UTCTIME_free(tmptm); 2149*0Sstevel@tonic-gate if (ok <= 0) 2150*0Sstevel@tonic-gate { 2151*0Sstevel@tonic-gate if (ret != NULL) X509_free(ret); 2152*0Sstevel@tonic-gate ret=NULL; 2153*0Sstevel@tonic-gate } 2154*0Sstevel@tonic-gate else 2155*0Sstevel@tonic-gate *xret=ret; 2156*0Sstevel@tonic-gate return(ok); 2157*0Sstevel@tonic-gate } 2158*0Sstevel@tonic-gate 2159*0Sstevel@tonic-gate static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext) 2160*0Sstevel@tonic-gate { 2161*0Sstevel@tonic-gate 2162*0Sstevel@tonic-gate if (output_der) 2163*0Sstevel@tonic-gate { 2164*0Sstevel@tonic-gate (void)i2d_X509_bio(bp,x); 2165*0Sstevel@tonic-gate return; 2166*0Sstevel@tonic-gate } 2167*0Sstevel@tonic-gate #if 0 2168*0Sstevel@tonic-gate /* ??? Not needed since X509_print prints all this stuff anyway */ 2169*0Sstevel@tonic-gate f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256); 2170*0Sstevel@tonic-gate BIO_printf(bp,"issuer :%s\n",f); 2171*0Sstevel@tonic-gate 2172*0Sstevel@tonic-gate f=X509_NAME_oneline(X509_get_subject_name(x),buf,256); 2173*0Sstevel@tonic-gate BIO_printf(bp,"subject:%s\n",f); 2174*0Sstevel@tonic-gate 2175*0Sstevel@tonic-gate BIO_puts(bp,"serial :"); 2176*0Sstevel@tonic-gate i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber); 2177*0Sstevel@tonic-gate BIO_puts(bp,"\n\n"); 2178*0Sstevel@tonic-gate #endif 2179*0Sstevel@tonic-gate if (!notext)X509_print(bp,x); 2180*0Sstevel@tonic-gate PEM_write_bio_X509(bp,x); 2181*0Sstevel@tonic-gate } 2182*0Sstevel@tonic-gate 2183*0Sstevel@tonic-gate static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 2184*0Sstevel@tonic-gate const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db, 2185*0Sstevel@tonic-gate BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate, 2186*0Sstevel@tonic-gate long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, 2187*0Sstevel@tonic-gate unsigned long nameopt, int default_op, int ext_copy) 2188*0Sstevel@tonic-gate { 2189*0Sstevel@tonic-gate STACK_OF(CONF_VALUE) *sk=NULL; 2190*0Sstevel@tonic-gate LHASH *parms=NULL; 2191*0Sstevel@tonic-gate X509_REQ *req=NULL; 2192*0Sstevel@tonic-gate CONF_VALUE *cv=NULL; 2193*0Sstevel@tonic-gate NETSCAPE_SPKI *spki = NULL; 2194*0Sstevel@tonic-gate X509_REQ_INFO *ri; 2195*0Sstevel@tonic-gate char *type,*buf; 2196*0Sstevel@tonic-gate EVP_PKEY *pktmp=NULL; 2197*0Sstevel@tonic-gate X509_NAME *n=NULL; 2198*0Sstevel@tonic-gate X509_NAME_ENTRY *ne=NULL; 2199*0Sstevel@tonic-gate int ok= -1,i,j; 2200*0Sstevel@tonic-gate long errline; 2201*0Sstevel@tonic-gate int nid; 2202*0Sstevel@tonic-gate 2203*0Sstevel@tonic-gate /* 2204*0Sstevel@tonic-gate * Load input file into a hash table. (This is just an easy 2205*0Sstevel@tonic-gate * way to read and parse the file, then put it into a convenient 2206*0Sstevel@tonic-gate * STACK format). 2207*0Sstevel@tonic-gate */ 2208*0Sstevel@tonic-gate parms=CONF_load(NULL,infile,&errline); 2209*0Sstevel@tonic-gate if (parms == NULL) 2210*0Sstevel@tonic-gate { 2211*0Sstevel@tonic-gate BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile); 2212*0Sstevel@tonic-gate ERR_print_errors(bio_err); 2213*0Sstevel@tonic-gate goto err; 2214*0Sstevel@tonic-gate } 2215*0Sstevel@tonic-gate 2216*0Sstevel@tonic-gate sk=CONF_get_section(parms, "default"); 2217*0Sstevel@tonic-gate if (sk_CONF_VALUE_num(sk) == 0) 2218*0Sstevel@tonic-gate { 2219*0Sstevel@tonic-gate BIO_printf(bio_err, "no name/value pairs found in %s\n", infile); 2220*0Sstevel@tonic-gate CONF_free(parms); 2221*0Sstevel@tonic-gate goto err; 2222*0Sstevel@tonic-gate } 2223*0Sstevel@tonic-gate 2224*0Sstevel@tonic-gate /* 2225*0Sstevel@tonic-gate * Now create a dummy X509 request structure. We don't actually 2226*0Sstevel@tonic-gate * have an X509 request, but we have many of the components 2227*0Sstevel@tonic-gate * (a public key, various DN components). The idea is that we 2228*0Sstevel@tonic-gate * put these components into the right X509 request structure 2229*0Sstevel@tonic-gate * and we can use the same code as if you had a real X509 request. 2230*0Sstevel@tonic-gate */ 2231*0Sstevel@tonic-gate req=X509_REQ_new(); 2232*0Sstevel@tonic-gate if (req == NULL) 2233*0Sstevel@tonic-gate { 2234*0Sstevel@tonic-gate ERR_print_errors(bio_err); 2235*0Sstevel@tonic-gate goto err; 2236*0Sstevel@tonic-gate } 2237*0Sstevel@tonic-gate 2238*0Sstevel@tonic-gate /* 2239*0Sstevel@tonic-gate * Build up the subject name set. 2240*0Sstevel@tonic-gate */ 2241*0Sstevel@tonic-gate ri=req->req_info; 2242*0Sstevel@tonic-gate n = ri->subject; 2243*0Sstevel@tonic-gate 2244*0Sstevel@tonic-gate for (i = 0; ; i++) 2245*0Sstevel@tonic-gate { 2246*0Sstevel@tonic-gate if (sk_CONF_VALUE_num(sk) <= i) break; 2247*0Sstevel@tonic-gate 2248*0Sstevel@tonic-gate cv=sk_CONF_VALUE_value(sk,i); 2249*0Sstevel@tonic-gate type=cv->name; 2250*0Sstevel@tonic-gate /* Skip past any leading X. X: X, etc to allow for 2251*0Sstevel@tonic-gate * multiple instances 2252*0Sstevel@tonic-gate */ 2253*0Sstevel@tonic-gate for (buf = cv->name; *buf ; buf++) 2254*0Sstevel@tonic-gate if ((*buf == ':') || (*buf == ',') || (*buf == '.')) 2255*0Sstevel@tonic-gate { 2256*0Sstevel@tonic-gate buf++; 2257*0Sstevel@tonic-gate if (*buf) type = buf; 2258*0Sstevel@tonic-gate break; 2259*0Sstevel@tonic-gate } 2260*0Sstevel@tonic-gate 2261*0Sstevel@tonic-gate buf=cv->value; 2262*0Sstevel@tonic-gate if ((nid=OBJ_txt2nid(type)) == NID_undef) 2263*0Sstevel@tonic-gate { 2264*0Sstevel@tonic-gate if (strcmp(type, "SPKAC") == 0) 2265*0Sstevel@tonic-gate { 2266*0Sstevel@tonic-gate spki = NETSCAPE_SPKI_b64_decode(cv->value, -1); 2267*0Sstevel@tonic-gate if (spki == NULL) 2268*0Sstevel@tonic-gate { 2269*0Sstevel@tonic-gate BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n"); 2270*0Sstevel@tonic-gate ERR_print_errors(bio_err); 2271*0Sstevel@tonic-gate goto err; 2272*0Sstevel@tonic-gate } 2273*0Sstevel@tonic-gate } 2274*0Sstevel@tonic-gate continue; 2275*0Sstevel@tonic-gate } 2276*0Sstevel@tonic-gate 2277*0Sstevel@tonic-gate /* 2278*0Sstevel@tonic-gate if ((nid == NID_pkcs9_emailAddress) && (email_dn == 0)) 2279*0Sstevel@tonic-gate continue; 2280*0Sstevel@tonic-gate */ 2281*0Sstevel@tonic-gate 2282*0Sstevel@tonic-gate j=ASN1_PRINTABLE_type((unsigned char *)buf,-1); 2283*0Sstevel@tonic-gate if (fix_data(nid, &j) == 0) 2284*0Sstevel@tonic-gate { 2285*0Sstevel@tonic-gate BIO_printf(bio_err, 2286*0Sstevel@tonic-gate "invalid characters in string %s\n",buf); 2287*0Sstevel@tonic-gate goto err; 2288*0Sstevel@tonic-gate } 2289*0Sstevel@tonic-gate 2290*0Sstevel@tonic-gate if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j, 2291*0Sstevel@tonic-gate (unsigned char *)buf, 2292*0Sstevel@tonic-gate strlen(buf))) == NULL) 2293*0Sstevel@tonic-gate goto err; 2294*0Sstevel@tonic-gate 2295*0Sstevel@tonic-gate if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err; 2296*0Sstevel@tonic-gate } 2297*0Sstevel@tonic-gate if (spki == NULL) 2298*0Sstevel@tonic-gate { 2299*0Sstevel@tonic-gate BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n", 2300*0Sstevel@tonic-gate infile); 2301*0Sstevel@tonic-gate goto err; 2302*0Sstevel@tonic-gate } 2303*0Sstevel@tonic-gate 2304*0Sstevel@tonic-gate /* 2305*0Sstevel@tonic-gate * Now extract the key from the SPKI structure. 2306*0Sstevel@tonic-gate */ 2307*0Sstevel@tonic-gate 2308*0Sstevel@tonic-gate BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n"); 2309*0Sstevel@tonic-gate 2310*0Sstevel@tonic-gate if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL) 2311*0Sstevel@tonic-gate { 2312*0Sstevel@tonic-gate BIO_printf(bio_err,"error unpacking SPKAC public key\n"); 2313*0Sstevel@tonic-gate goto err; 2314*0Sstevel@tonic-gate } 2315*0Sstevel@tonic-gate 2316*0Sstevel@tonic-gate j = NETSCAPE_SPKI_verify(spki, pktmp); 2317*0Sstevel@tonic-gate if (j <= 0) 2318*0Sstevel@tonic-gate { 2319*0Sstevel@tonic-gate BIO_printf(bio_err,"signature verification failed on SPKAC public key\n"); 2320*0Sstevel@tonic-gate goto err; 2321*0Sstevel@tonic-gate } 2322*0Sstevel@tonic-gate BIO_printf(bio_err,"Signature ok\n"); 2323*0Sstevel@tonic-gate 2324*0Sstevel@tonic-gate X509_REQ_set_pubkey(req,pktmp); 2325*0Sstevel@tonic-gate EVP_PKEY_free(pktmp); 2326*0Sstevel@tonic-gate ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,email_dn,startdate,enddate, 2327*0Sstevel@tonic-gate days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op, 2328*0Sstevel@tonic-gate ext_copy); 2329*0Sstevel@tonic-gate err: 2330*0Sstevel@tonic-gate if (req != NULL) X509_REQ_free(req); 2331*0Sstevel@tonic-gate if (parms != NULL) CONF_free(parms); 2332*0Sstevel@tonic-gate if (spki != NULL) NETSCAPE_SPKI_free(spki); 2333*0Sstevel@tonic-gate if (ne != NULL) X509_NAME_ENTRY_free(ne); 2334*0Sstevel@tonic-gate 2335*0Sstevel@tonic-gate return(ok); 2336*0Sstevel@tonic-gate } 2337*0Sstevel@tonic-gate 2338*0Sstevel@tonic-gate static int fix_data(int nid, int *type) 2339*0Sstevel@tonic-gate { 2340*0Sstevel@tonic-gate if (nid == NID_pkcs9_emailAddress) 2341*0Sstevel@tonic-gate *type=V_ASN1_IA5STRING; 2342*0Sstevel@tonic-gate if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING)) 2343*0Sstevel@tonic-gate *type=V_ASN1_T61STRING; 2344*0Sstevel@tonic-gate if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING)) 2345*0Sstevel@tonic-gate *type=V_ASN1_T61STRING; 2346*0Sstevel@tonic-gate if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING)) 2347*0Sstevel@tonic-gate return(0); 2348*0Sstevel@tonic-gate if (nid == NID_pkcs9_unstructuredName) 2349*0Sstevel@tonic-gate *type=V_ASN1_IA5STRING; 2350*0Sstevel@tonic-gate return(1); 2351*0Sstevel@tonic-gate } 2352*0Sstevel@tonic-gate 2353*0Sstevel@tonic-gate static int check_time_format(char *str) 2354*0Sstevel@tonic-gate { 2355*0Sstevel@tonic-gate ASN1_UTCTIME tm; 2356*0Sstevel@tonic-gate 2357*0Sstevel@tonic-gate tm.data=(unsigned char *)str; 2358*0Sstevel@tonic-gate tm.length=strlen(str); 2359*0Sstevel@tonic-gate tm.type=V_ASN1_UTCTIME; 2360*0Sstevel@tonic-gate return(ASN1_UTCTIME_check(&tm)); 2361*0Sstevel@tonic-gate } 2362*0Sstevel@tonic-gate 2363*0Sstevel@tonic-gate static int do_revoke(X509 *x509, CA_DB *db, int type, char *value) 2364*0Sstevel@tonic-gate { 2365*0Sstevel@tonic-gate ASN1_UTCTIME *tm=NULL; 2366*0Sstevel@tonic-gate char *row[DB_NUMBER],**rrow,**irow; 2367*0Sstevel@tonic-gate char *rev_str = NULL; 2368*0Sstevel@tonic-gate BIGNUM *bn = NULL; 2369*0Sstevel@tonic-gate int ok=-1,i; 2370*0Sstevel@tonic-gate 2371*0Sstevel@tonic-gate for (i=0; i<DB_NUMBER; i++) 2372*0Sstevel@tonic-gate row[i]=NULL; 2373*0Sstevel@tonic-gate row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0); 2374*0Sstevel@tonic-gate bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL); 2375*0Sstevel@tonic-gate if (BN_is_zero(bn)) 2376*0Sstevel@tonic-gate row[DB_serial]=BUF_strdup("00"); 2377*0Sstevel@tonic-gate else 2378*0Sstevel@tonic-gate row[DB_serial]=BN_bn2hex(bn); 2379*0Sstevel@tonic-gate BN_free(bn); 2380*0Sstevel@tonic-gate if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) 2381*0Sstevel@tonic-gate { 2382*0Sstevel@tonic-gate BIO_printf(bio_err,"Memory allocation failure\n"); 2383*0Sstevel@tonic-gate goto err; 2384*0Sstevel@tonic-gate } 2385*0Sstevel@tonic-gate /* We have to lookup by serial number because name lookup 2386*0Sstevel@tonic-gate * skips revoked certs 2387*0Sstevel@tonic-gate */ 2388*0Sstevel@tonic-gate rrow=TXT_DB_get_by_index(db->db,DB_serial,row); 2389*0Sstevel@tonic-gate if (rrow == NULL) 2390*0Sstevel@tonic-gate { 2391*0Sstevel@tonic-gate BIO_printf(bio_err,"Adding Entry with serial number %s to DB for %s\n", row[DB_serial], row[DB_name]); 2392*0Sstevel@tonic-gate 2393*0Sstevel@tonic-gate /* We now just add it to the database */ 2394*0Sstevel@tonic-gate row[DB_type]=(char *)OPENSSL_malloc(2); 2395*0Sstevel@tonic-gate 2396*0Sstevel@tonic-gate tm=X509_get_notAfter(x509); 2397*0Sstevel@tonic-gate row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1); 2398*0Sstevel@tonic-gate memcpy(row[DB_exp_date],tm->data,tm->length); 2399*0Sstevel@tonic-gate row[DB_exp_date][tm->length]='\0'; 2400*0Sstevel@tonic-gate 2401*0Sstevel@tonic-gate row[DB_rev_date]=NULL; 2402*0Sstevel@tonic-gate 2403*0Sstevel@tonic-gate /* row[DB_serial] done already */ 2404*0Sstevel@tonic-gate row[DB_file]=(char *)OPENSSL_malloc(8); 2405*0Sstevel@tonic-gate 2406*0Sstevel@tonic-gate /* row[DB_name] done already */ 2407*0Sstevel@tonic-gate 2408*0Sstevel@tonic-gate if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || 2409*0Sstevel@tonic-gate (row[DB_file] == NULL)) 2410*0Sstevel@tonic-gate { 2411*0Sstevel@tonic-gate BIO_printf(bio_err,"Memory allocation failure\n"); 2412*0Sstevel@tonic-gate goto err; 2413*0Sstevel@tonic-gate } 2414*0Sstevel@tonic-gate BUF_strlcpy(row[DB_file],"unknown",8); 2415*0Sstevel@tonic-gate row[DB_type][0]='V'; 2416*0Sstevel@tonic-gate row[DB_type][1]='\0'; 2417*0Sstevel@tonic-gate 2418*0Sstevel@tonic-gate if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL) 2419*0Sstevel@tonic-gate { 2420*0Sstevel@tonic-gate BIO_printf(bio_err,"Memory allocation failure\n"); 2421*0Sstevel@tonic-gate goto err; 2422*0Sstevel@tonic-gate } 2423*0Sstevel@tonic-gate 2424*0Sstevel@tonic-gate for (i=0; i<DB_NUMBER; i++) 2425*0Sstevel@tonic-gate { 2426*0Sstevel@tonic-gate irow[i]=row[i]; 2427*0Sstevel@tonic-gate row[i]=NULL; 2428*0Sstevel@tonic-gate } 2429*0Sstevel@tonic-gate irow[DB_NUMBER]=NULL; 2430*0Sstevel@tonic-gate 2431*0Sstevel@tonic-gate if (!TXT_DB_insert(db->db,irow)) 2432*0Sstevel@tonic-gate { 2433*0Sstevel@tonic-gate BIO_printf(bio_err,"failed to update database\n"); 2434*0Sstevel@tonic-gate BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error); 2435*0Sstevel@tonic-gate goto err; 2436*0Sstevel@tonic-gate } 2437*0Sstevel@tonic-gate 2438*0Sstevel@tonic-gate /* Revoke Certificate */ 2439*0Sstevel@tonic-gate ok = do_revoke(x509,db, type, value); 2440*0Sstevel@tonic-gate 2441*0Sstevel@tonic-gate goto err; 2442*0Sstevel@tonic-gate 2443*0Sstevel@tonic-gate } 2444*0Sstevel@tonic-gate else if (index_name_cmp((const char **)row,(const char **)rrow)) 2445*0Sstevel@tonic-gate { 2446*0Sstevel@tonic-gate BIO_printf(bio_err,"ERROR:name does not match %s\n", 2447*0Sstevel@tonic-gate row[DB_name]); 2448*0Sstevel@tonic-gate goto err; 2449*0Sstevel@tonic-gate } 2450*0Sstevel@tonic-gate else if (rrow[DB_type][0]=='R') 2451*0Sstevel@tonic-gate { 2452*0Sstevel@tonic-gate BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n", 2453*0Sstevel@tonic-gate row[DB_serial]); 2454*0Sstevel@tonic-gate goto err; 2455*0Sstevel@tonic-gate } 2456*0Sstevel@tonic-gate else 2457*0Sstevel@tonic-gate { 2458*0Sstevel@tonic-gate BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]); 2459*0Sstevel@tonic-gate rev_str = make_revocation_str(type, value); 2460*0Sstevel@tonic-gate if (!rev_str) 2461*0Sstevel@tonic-gate { 2462*0Sstevel@tonic-gate BIO_printf(bio_err, "Error in revocation arguments\n"); 2463*0Sstevel@tonic-gate goto err; 2464*0Sstevel@tonic-gate } 2465*0Sstevel@tonic-gate rrow[DB_type][0]='R'; 2466*0Sstevel@tonic-gate rrow[DB_type][1]='\0'; 2467*0Sstevel@tonic-gate rrow[DB_rev_date] = rev_str; 2468*0Sstevel@tonic-gate } 2469*0Sstevel@tonic-gate ok=1; 2470*0Sstevel@tonic-gate err: 2471*0Sstevel@tonic-gate for (i=0; i<DB_NUMBER; i++) 2472*0Sstevel@tonic-gate { 2473*0Sstevel@tonic-gate if (row[i] != NULL) 2474*0Sstevel@tonic-gate OPENSSL_free(row[i]); 2475*0Sstevel@tonic-gate } 2476*0Sstevel@tonic-gate return(ok); 2477*0Sstevel@tonic-gate } 2478*0Sstevel@tonic-gate 2479*0Sstevel@tonic-gate static int get_certificate_status(const char *serial, CA_DB *db) 2480*0Sstevel@tonic-gate { 2481*0Sstevel@tonic-gate char *row[DB_NUMBER],**rrow; 2482*0Sstevel@tonic-gate int ok=-1,i; 2483*0Sstevel@tonic-gate 2484*0Sstevel@tonic-gate /* Free Resources */ 2485*0Sstevel@tonic-gate for (i=0; i<DB_NUMBER; i++) 2486*0Sstevel@tonic-gate row[i]=NULL; 2487*0Sstevel@tonic-gate 2488*0Sstevel@tonic-gate /* Malloc needed char spaces */ 2489*0Sstevel@tonic-gate row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2); 2490*0Sstevel@tonic-gate if (row[DB_serial] == NULL) 2491*0Sstevel@tonic-gate { 2492*0Sstevel@tonic-gate BIO_printf(bio_err,"Malloc failure\n"); 2493*0Sstevel@tonic-gate goto err; 2494*0Sstevel@tonic-gate } 2495*0Sstevel@tonic-gate 2496*0Sstevel@tonic-gate if (strlen(serial) % 2) 2497*0Sstevel@tonic-gate { 2498*0Sstevel@tonic-gate /* Set the first char to 0 */; 2499*0Sstevel@tonic-gate row[DB_serial][0]='0'; 2500*0Sstevel@tonic-gate 2501*0Sstevel@tonic-gate /* Copy String from serial to row[DB_serial] */ 2502*0Sstevel@tonic-gate memcpy(row[DB_serial]+1, serial, strlen(serial)); 2503*0Sstevel@tonic-gate row[DB_serial][strlen(serial)+1]='\0'; 2504*0Sstevel@tonic-gate } 2505*0Sstevel@tonic-gate else 2506*0Sstevel@tonic-gate { 2507*0Sstevel@tonic-gate /* Copy String from serial to row[DB_serial] */ 2508*0Sstevel@tonic-gate memcpy(row[DB_serial], serial, strlen(serial)); 2509*0Sstevel@tonic-gate row[DB_serial][strlen(serial)]='\0'; 2510*0Sstevel@tonic-gate } 2511*0Sstevel@tonic-gate 2512*0Sstevel@tonic-gate /* Make it Upper Case */ 2513*0Sstevel@tonic-gate for (i=0; row[DB_serial][i] != '\0'; i++) 2514*0Sstevel@tonic-gate row[DB_serial][i] = toupper(row[DB_serial][i]); 2515*0Sstevel@tonic-gate 2516*0Sstevel@tonic-gate 2517*0Sstevel@tonic-gate ok=1; 2518*0Sstevel@tonic-gate 2519*0Sstevel@tonic-gate /* Search for the certificate */ 2520*0Sstevel@tonic-gate rrow=TXT_DB_get_by_index(db->db,DB_serial,row); 2521*0Sstevel@tonic-gate if (rrow == NULL) 2522*0Sstevel@tonic-gate { 2523*0Sstevel@tonic-gate BIO_printf(bio_err,"Serial %s not present in db.\n", 2524*0Sstevel@tonic-gate row[DB_serial]); 2525*0Sstevel@tonic-gate ok=-1; 2526*0Sstevel@tonic-gate goto err; 2527*0Sstevel@tonic-gate } 2528*0Sstevel@tonic-gate else if (rrow[DB_type][0]=='V') 2529*0Sstevel@tonic-gate { 2530*0Sstevel@tonic-gate BIO_printf(bio_err,"%s=Valid (%c)\n", 2531*0Sstevel@tonic-gate row[DB_serial], rrow[DB_type][0]); 2532*0Sstevel@tonic-gate goto err; 2533*0Sstevel@tonic-gate } 2534*0Sstevel@tonic-gate else if (rrow[DB_type][0]=='R') 2535*0Sstevel@tonic-gate { 2536*0Sstevel@tonic-gate BIO_printf(bio_err,"%s=Revoked (%c)\n", 2537*0Sstevel@tonic-gate row[DB_serial], rrow[DB_type][0]); 2538*0Sstevel@tonic-gate goto err; 2539*0Sstevel@tonic-gate } 2540*0Sstevel@tonic-gate else if (rrow[DB_type][0]=='E') 2541*0Sstevel@tonic-gate { 2542*0Sstevel@tonic-gate BIO_printf(bio_err,"%s=Expired (%c)\n", 2543*0Sstevel@tonic-gate row[DB_serial], rrow[DB_type][0]); 2544*0Sstevel@tonic-gate goto err; 2545*0Sstevel@tonic-gate } 2546*0Sstevel@tonic-gate else if (rrow[DB_type][0]=='S') 2547*0Sstevel@tonic-gate { 2548*0Sstevel@tonic-gate BIO_printf(bio_err,"%s=Suspended (%c)\n", 2549*0Sstevel@tonic-gate row[DB_serial], rrow[DB_type][0]); 2550*0Sstevel@tonic-gate goto err; 2551*0Sstevel@tonic-gate } 2552*0Sstevel@tonic-gate else 2553*0Sstevel@tonic-gate { 2554*0Sstevel@tonic-gate BIO_printf(bio_err,"%s=Unknown (%c).\n", 2555*0Sstevel@tonic-gate row[DB_serial], rrow[DB_type][0]); 2556*0Sstevel@tonic-gate ok=-1; 2557*0Sstevel@tonic-gate } 2558*0Sstevel@tonic-gate err: 2559*0Sstevel@tonic-gate for (i=0; i<DB_NUMBER; i++) 2560*0Sstevel@tonic-gate { 2561*0Sstevel@tonic-gate if (row[i] != NULL) 2562*0Sstevel@tonic-gate OPENSSL_free(row[i]); 2563*0Sstevel@tonic-gate } 2564*0Sstevel@tonic-gate return(ok); 2565*0Sstevel@tonic-gate } 2566*0Sstevel@tonic-gate 2567*0Sstevel@tonic-gate static int do_updatedb (CA_DB *db) 2568*0Sstevel@tonic-gate { 2569*0Sstevel@tonic-gate ASN1_UTCTIME *a_tm = NULL; 2570*0Sstevel@tonic-gate int i, cnt = 0; 2571*0Sstevel@tonic-gate int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */ 2572*0Sstevel@tonic-gate char **rrow, *a_tm_s; 2573*0Sstevel@tonic-gate 2574*0Sstevel@tonic-gate a_tm = ASN1_UTCTIME_new(); 2575*0Sstevel@tonic-gate 2576*0Sstevel@tonic-gate /* get actual time and make a string */ 2577*0Sstevel@tonic-gate a_tm = X509_gmtime_adj(a_tm, 0); 2578*0Sstevel@tonic-gate a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1); 2579*0Sstevel@tonic-gate if (a_tm_s == NULL) 2580*0Sstevel@tonic-gate { 2581*0Sstevel@tonic-gate cnt = -1; 2582*0Sstevel@tonic-gate goto err; 2583*0Sstevel@tonic-gate } 2584*0Sstevel@tonic-gate 2585*0Sstevel@tonic-gate memcpy(a_tm_s, a_tm->data, a_tm->length); 2586*0Sstevel@tonic-gate a_tm_s[a_tm->length] = '\0'; 2587*0Sstevel@tonic-gate 2588*0Sstevel@tonic-gate if (strncmp(a_tm_s, "49", 2) <= 0) 2589*0Sstevel@tonic-gate a_y2k = 1; 2590*0Sstevel@tonic-gate else 2591*0Sstevel@tonic-gate a_y2k = 0; 2592*0Sstevel@tonic-gate 2593*0Sstevel@tonic-gate for (i = 0; i < sk_num(db->db->data); i++) 2594*0Sstevel@tonic-gate { 2595*0Sstevel@tonic-gate rrow = (char **) sk_value(db->db->data, i); 2596*0Sstevel@tonic-gate 2597*0Sstevel@tonic-gate if (rrow[DB_type][0] == 'V') 2598*0Sstevel@tonic-gate { 2599*0Sstevel@tonic-gate /* ignore entries that are not valid */ 2600*0Sstevel@tonic-gate if (strncmp(rrow[DB_exp_date], "49", 2) <= 0) 2601*0Sstevel@tonic-gate db_y2k = 1; 2602*0Sstevel@tonic-gate else 2603*0Sstevel@tonic-gate db_y2k = 0; 2604*0Sstevel@tonic-gate 2605*0Sstevel@tonic-gate if (db_y2k == a_y2k) 2606*0Sstevel@tonic-gate { 2607*0Sstevel@tonic-gate /* all on the same y2k side */ 2608*0Sstevel@tonic-gate if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0) 2609*0Sstevel@tonic-gate { 2610*0Sstevel@tonic-gate rrow[DB_type][0] = 'E'; 2611*0Sstevel@tonic-gate rrow[DB_type][1] = '\0'; 2612*0Sstevel@tonic-gate cnt++; 2613*0Sstevel@tonic-gate 2614*0Sstevel@tonic-gate BIO_printf(bio_err, "%s=Expired\n", 2615*0Sstevel@tonic-gate rrow[DB_serial]); 2616*0Sstevel@tonic-gate } 2617*0Sstevel@tonic-gate } 2618*0Sstevel@tonic-gate else if (db_y2k < a_y2k) 2619*0Sstevel@tonic-gate { 2620*0Sstevel@tonic-gate rrow[DB_type][0] = 'E'; 2621*0Sstevel@tonic-gate rrow[DB_type][1] = '\0'; 2622*0Sstevel@tonic-gate cnt++; 2623*0Sstevel@tonic-gate 2624*0Sstevel@tonic-gate BIO_printf(bio_err, "%s=Expired\n", 2625*0Sstevel@tonic-gate rrow[DB_serial]); 2626*0Sstevel@tonic-gate } 2627*0Sstevel@tonic-gate 2628*0Sstevel@tonic-gate } 2629*0Sstevel@tonic-gate } 2630*0Sstevel@tonic-gate 2631*0Sstevel@tonic-gate err: 2632*0Sstevel@tonic-gate 2633*0Sstevel@tonic-gate ASN1_UTCTIME_free(a_tm); 2634*0Sstevel@tonic-gate OPENSSL_free(a_tm_s); 2635*0Sstevel@tonic-gate 2636*0Sstevel@tonic-gate return (cnt); 2637*0Sstevel@tonic-gate } 2638*0Sstevel@tonic-gate 2639*0Sstevel@tonic-gate static char *crl_reasons[] = { 2640*0Sstevel@tonic-gate /* CRL reason strings */ 2641*0Sstevel@tonic-gate "unspecified", 2642*0Sstevel@tonic-gate "keyCompromise", 2643*0Sstevel@tonic-gate "CACompromise", 2644*0Sstevel@tonic-gate "affiliationChanged", 2645*0Sstevel@tonic-gate "superseded", 2646*0Sstevel@tonic-gate "cessationOfOperation", 2647*0Sstevel@tonic-gate "certificateHold", 2648*0Sstevel@tonic-gate "removeFromCRL", 2649*0Sstevel@tonic-gate /* Additional pseudo reasons */ 2650*0Sstevel@tonic-gate "holdInstruction", 2651*0Sstevel@tonic-gate "keyTime", 2652*0Sstevel@tonic-gate "CAkeyTime" 2653*0Sstevel@tonic-gate }; 2654*0Sstevel@tonic-gate 2655*0Sstevel@tonic-gate #define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *)) 2656*0Sstevel@tonic-gate 2657*0Sstevel@tonic-gate /* Given revocation information convert to a DB string. 2658*0Sstevel@tonic-gate * The format of the string is: 2659*0Sstevel@tonic-gate * revtime[,reason,extra]. Where 'revtime' is the 2660*0Sstevel@tonic-gate * revocation time (the current time). 'reason' is the 2661*0Sstevel@tonic-gate * optional CRL reason and 'extra' is any additional 2662*0Sstevel@tonic-gate * argument 2663*0Sstevel@tonic-gate */ 2664*0Sstevel@tonic-gate 2665*0Sstevel@tonic-gate char *make_revocation_str(int rev_type, char *rev_arg) 2666*0Sstevel@tonic-gate { 2667*0Sstevel@tonic-gate char *reason = NULL, *other = NULL, *str; 2668*0Sstevel@tonic-gate ASN1_OBJECT *otmp; 2669*0Sstevel@tonic-gate ASN1_UTCTIME *revtm = NULL; 2670*0Sstevel@tonic-gate int i; 2671*0Sstevel@tonic-gate switch (rev_type) 2672*0Sstevel@tonic-gate { 2673*0Sstevel@tonic-gate case REV_NONE: 2674*0Sstevel@tonic-gate break; 2675*0Sstevel@tonic-gate 2676*0Sstevel@tonic-gate case REV_CRL_REASON: 2677*0Sstevel@tonic-gate for (i = 0; i < 8; i++) 2678*0Sstevel@tonic-gate { 2679*0Sstevel@tonic-gate if (!strcasecmp(rev_arg, crl_reasons[i])) 2680*0Sstevel@tonic-gate { 2681*0Sstevel@tonic-gate reason = crl_reasons[i]; 2682*0Sstevel@tonic-gate break; 2683*0Sstevel@tonic-gate } 2684*0Sstevel@tonic-gate } 2685*0Sstevel@tonic-gate if (reason == NULL) 2686*0Sstevel@tonic-gate { 2687*0Sstevel@tonic-gate BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg); 2688*0Sstevel@tonic-gate return NULL; 2689*0Sstevel@tonic-gate } 2690*0Sstevel@tonic-gate break; 2691*0Sstevel@tonic-gate 2692*0Sstevel@tonic-gate case REV_HOLD: 2693*0Sstevel@tonic-gate /* Argument is an OID */ 2694*0Sstevel@tonic-gate 2695*0Sstevel@tonic-gate otmp = OBJ_txt2obj(rev_arg, 0); 2696*0Sstevel@tonic-gate ASN1_OBJECT_free(otmp); 2697*0Sstevel@tonic-gate 2698*0Sstevel@tonic-gate if (otmp == NULL) 2699*0Sstevel@tonic-gate { 2700*0Sstevel@tonic-gate BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg); 2701*0Sstevel@tonic-gate return NULL; 2702*0Sstevel@tonic-gate } 2703*0Sstevel@tonic-gate 2704*0Sstevel@tonic-gate reason = "holdInstruction"; 2705*0Sstevel@tonic-gate other = rev_arg; 2706*0Sstevel@tonic-gate break; 2707*0Sstevel@tonic-gate 2708*0Sstevel@tonic-gate case REV_KEY_COMPROMISE: 2709*0Sstevel@tonic-gate case REV_CA_COMPROMISE: 2710*0Sstevel@tonic-gate 2711*0Sstevel@tonic-gate /* Argument is the key compromise time */ 2712*0Sstevel@tonic-gate if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg)) 2713*0Sstevel@tonic-gate { 2714*0Sstevel@tonic-gate BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg); 2715*0Sstevel@tonic-gate return NULL; 2716*0Sstevel@tonic-gate } 2717*0Sstevel@tonic-gate other = rev_arg; 2718*0Sstevel@tonic-gate if (rev_type == REV_KEY_COMPROMISE) 2719*0Sstevel@tonic-gate reason = "keyTime"; 2720*0Sstevel@tonic-gate else 2721*0Sstevel@tonic-gate reason = "CAkeyTime"; 2722*0Sstevel@tonic-gate 2723*0Sstevel@tonic-gate break; 2724*0Sstevel@tonic-gate 2725*0Sstevel@tonic-gate } 2726*0Sstevel@tonic-gate 2727*0Sstevel@tonic-gate revtm = X509_gmtime_adj(NULL, 0); 2728*0Sstevel@tonic-gate 2729*0Sstevel@tonic-gate i = revtm->length + 1; 2730*0Sstevel@tonic-gate 2731*0Sstevel@tonic-gate if (reason) i += strlen(reason) + 1; 2732*0Sstevel@tonic-gate if (other) i += strlen(other) + 1; 2733*0Sstevel@tonic-gate 2734*0Sstevel@tonic-gate str = OPENSSL_malloc(i); 2735*0Sstevel@tonic-gate 2736*0Sstevel@tonic-gate if (!str) return NULL; 2737*0Sstevel@tonic-gate 2738*0Sstevel@tonic-gate BUF_strlcpy(str, (char *)revtm->data, i); 2739*0Sstevel@tonic-gate if (reason) 2740*0Sstevel@tonic-gate { 2741*0Sstevel@tonic-gate BUF_strlcat(str, ",", i); 2742*0Sstevel@tonic-gate BUF_strlcat(str, reason, i); 2743*0Sstevel@tonic-gate } 2744*0Sstevel@tonic-gate if (other) 2745*0Sstevel@tonic-gate { 2746*0Sstevel@tonic-gate BUF_strlcat(str, ",", i); 2747*0Sstevel@tonic-gate BUF_strlcat(str, other, i); 2748*0Sstevel@tonic-gate } 2749*0Sstevel@tonic-gate ASN1_UTCTIME_free(revtm); 2750*0Sstevel@tonic-gate return str; 2751*0Sstevel@tonic-gate } 2752*0Sstevel@tonic-gate 2753*0Sstevel@tonic-gate /* Convert revocation field to X509_REVOKED entry 2754*0Sstevel@tonic-gate * return code: 2755*0Sstevel@tonic-gate * 0 error 2756*0Sstevel@tonic-gate * 1 OK 2757*0Sstevel@tonic-gate * 2 OK and some extensions added (i.e. V2 CRL) 2758*0Sstevel@tonic-gate */ 2759*0Sstevel@tonic-gate 2760*0Sstevel@tonic-gate 2761*0Sstevel@tonic-gate int make_revoked(X509_REVOKED *rev, char *str) 2762*0Sstevel@tonic-gate { 2763*0Sstevel@tonic-gate char *tmp = NULL; 2764*0Sstevel@tonic-gate int reason_code = -1; 2765*0Sstevel@tonic-gate int i, ret = 0; 2766*0Sstevel@tonic-gate ASN1_OBJECT *hold = NULL; 2767*0Sstevel@tonic-gate ASN1_GENERALIZEDTIME *comp_time = NULL; 2768*0Sstevel@tonic-gate ASN1_ENUMERATED *rtmp = NULL; 2769*0Sstevel@tonic-gate 2770*0Sstevel@tonic-gate ASN1_TIME *revDate = NULL; 2771*0Sstevel@tonic-gate 2772*0Sstevel@tonic-gate i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str); 2773*0Sstevel@tonic-gate 2774*0Sstevel@tonic-gate if (i == 0) 2775*0Sstevel@tonic-gate goto err; 2776*0Sstevel@tonic-gate 2777*0Sstevel@tonic-gate if (rev && !X509_REVOKED_set_revocationDate(rev, revDate)) 2778*0Sstevel@tonic-gate goto err; 2779*0Sstevel@tonic-gate 2780*0Sstevel@tonic-gate if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)) 2781*0Sstevel@tonic-gate { 2782*0Sstevel@tonic-gate rtmp = ASN1_ENUMERATED_new(); 2783*0Sstevel@tonic-gate if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code)) 2784*0Sstevel@tonic-gate goto err; 2785*0Sstevel@tonic-gate if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0)) 2786*0Sstevel@tonic-gate goto err; 2787*0Sstevel@tonic-gate } 2788*0Sstevel@tonic-gate 2789*0Sstevel@tonic-gate if (rev && comp_time) 2790*0Sstevel@tonic-gate { 2791*0Sstevel@tonic-gate if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0)) 2792*0Sstevel@tonic-gate goto err; 2793*0Sstevel@tonic-gate } 2794*0Sstevel@tonic-gate if (rev && hold) 2795*0Sstevel@tonic-gate { 2796*0Sstevel@tonic-gate if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0)) 2797*0Sstevel@tonic-gate goto err; 2798*0Sstevel@tonic-gate } 2799*0Sstevel@tonic-gate 2800*0Sstevel@tonic-gate if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS) 2801*0Sstevel@tonic-gate ret = 2; 2802*0Sstevel@tonic-gate else ret = 1; 2803*0Sstevel@tonic-gate 2804*0Sstevel@tonic-gate err: 2805*0Sstevel@tonic-gate 2806*0Sstevel@tonic-gate if (tmp) OPENSSL_free(tmp); 2807*0Sstevel@tonic-gate ASN1_OBJECT_free(hold); 2808*0Sstevel@tonic-gate ASN1_GENERALIZEDTIME_free(comp_time); 2809*0Sstevel@tonic-gate ASN1_ENUMERATED_free(rtmp); 2810*0Sstevel@tonic-gate ASN1_TIME_free(revDate); 2811*0Sstevel@tonic-gate 2812*0Sstevel@tonic-gate return ret; 2813*0Sstevel@tonic-gate } 2814*0Sstevel@tonic-gate 2815*0Sstevel@tonic-gate /* 2816*0Sstevel@tonic-gate * subject is expected to be in the format /type0=value0/type1=value1/type2=... 2817*0Sstevel@tonic-gate * where characters may be escaped by \ 2818*0Sstevel@tonic-gate */ 2819*0Sstevel@tonic-gate X509_NAME *do_subject(char *subject, long chtype) 2820*0Sstevel@tonic-gate { 2821*0Sstevel@tonic-gate size_t buflen = strlen(subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */ 2822*0Sstevel@tonic-gate char *buf = OPENSSL_malloc(buflen); 2823*0Sstevel@tonic-gate size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */ 2824*0Sstevel@tonic-gate char **ne_types = OPENSSL_malloc(max_ne * sizeof (char *)); 2825*0Sstevel@tonic-gate char **ne_values = OPENSSL_malloc(max_ne * sizeof (char *)); 2826*0Sstevel@tonic-gate 2827*0Sstevel@tonic-gate char *sp = subject, *bp = buf; 2828*0Sstevel@tonic-gate int i, ne_num = 0; 2829*0Sstevel@tonic-gate 2830*0Sstevel@tonic-gate X509_NAME *n = NULL; 2831*0Sstevel@tonic-gate int nid; 2832*0Sstevel@tonic-gate 2833*0Sstevel@tonic-gate if (!buf || !ne_types || !ne_values) 2834*0Sstevel@tonic-gate { 2835*0Sstevel@tonic-gate BIO_printf(bio_err, "malloc error\n"); 2836*0Sstevel@tonic-gate goto error; 2837*0Sstevel@tonic-gate } 2838*0Sstevel@tonic-gate 2839*0Sstevel@tonic-gate if (*subject != '/') 2840*0Sstevel@tonic-gate { 2841*0Sstevel@tonic-gate BIO_printf(bio_err, "Subject does not start with '/'.\n"); 2842*0Sstevel@tonic-gate goto error; 2843*0Sstevel@tonic-gate } 2844*0Sstevel@tonic-gate sp++; /* skip leading / */ 2845*0Sstevel@tonic-gate 2846*0Sstevel@tonic-gate while (*sp) 2847*0Sstevel@tonic-gate { 2848*0Sstevel@tonic-gate /* collect type */ 2849*0Sstevel@tonic-gate ne_types[ne_num] = bp; 2850*0Sstevel@tonic-gate while (*sp) 2851*0Sstevel@tonic-gate { 2852*0Sstevel@tonic-gate if (*sp == '\\') /* is there anything to escape in the type...? */ 2853*0Sstevel@tonic-gate { 2854*0Sstevel@tonic-gate if (*++sp) 2855*0Sstevel@tonic-gate *bp++ = *sp++; 2856*0Sstevel@tonic-gate else 2857*0Sstevel@tonic-gate { 2858*0Sstevel@tonic-gate BIO_printf(bio_err, "escape character at end of string\n"); 2859*0Sstevel@tonic-gate goto error; 2860*0Sstevel@tonic-gate } 2861*0Sstevel@tonic-gate } 2862*0Sstevel@tonic-gate else if (*sp == '=') 2863*0Sstevel@tonic-gate { 2864*0Sstevel@tonic-gate sp++; 2865*0Sstevel@tonic-gate *bp++ = '\0'; 2866*0Sstevel@tonic-gate break; 2867*0Sstevel@tonic-gate } 2868*0Sstevel@tonic-gate else 2869*0Sstevel@tonic-gate *bp++ = *sp++; 2870*0Sstevel@tonic-gate } 2871*0Sstevel@tonic-gate if (!*sp) 2872*0Sstevel@tonic-gate { 2873*0Sstevel@tonic-gate BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num); 2874*0Sstevel@tonic-gate goto error; 2875*0Sstevel@tonic-gate } 2876*0Sstevel@tonic-gate ne_values[ne_num] = bp; 2877*0Sstevel@tonic-gate while (*sp) 2878*0Sstevel@tonic-gate { 2879*0Sstevel@tonic-gate if (*sp == '\\') 2880*0Sstevel@tonic-gate { 2881*0Sstevel@tonic-gate if (*++sp) 2882*0Sstevel@tonic-gate *bp++ = *sp++; 2883*0Sstevel@tonic-gate else 2884*0Sstevel@tonic-gate { 2885*0Sstevel@tonic-gate BIO_printf(bio_err, "escape character at end of string\n"); 2886*0Sstevel@tonic-gate goto error; 2887*0Sstevel@tonic-gate } 2888*0Sstevel@tonic-gate } 2889*0Sstevel@tonic-gate else if (*sp == '/') 2890*0Sstevel@tonic-gate { 2891*0Sstevel@tonic-gate sp++; 2892*0Sstevel@tonic-gate break; 2893*0Sstevel@tonic-gate } 2894*0Sstevel@tonic-gate else 2895*0Sstevel@tonic-gate *bp++ = *sp++; 2896*0Sstevel@tonic-gate } 2897*0Sstevel@tonic-gate *bp++ = '\0'; 2898*0Sstevel@tonic-gate ne_num++; 2899*0Sstevel@tonic-gate } 2900*0Sstevel@tonic-gate 2901*0Sstevel@tonic-gate if (!(n = X509_NAME_new())) 2902*0Sstevel@tonic-gate goto error; 2903*0Sstevel@tonic-gate 2904*0Sstevel@tonic-gate for (i = 0; i < ne_num; i++) 2905*0Sstevel@tonic-gate { 2906*0Sstevel@tonic-gate if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef) 2907*0Sstevel@tonic-gate { 2908*0Sstevel@tonic-gate BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]); 2909*0Sstevel@tonic-gate continue; 2910*0Sstevel@tonic-gate } 2911*0Sstevel@tonic-gate 2912*0Sstevel@tonic-gate if (!*ne_values[i]) 2913*0Sstevel@tonic-gate { 2914*0Sstevel@tonic-gate BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]); 2915*0Sstevel@tonic-gate continue; 2916*0Sstevel@tonic-gate } 2917*0Sstevel@tonic-gate 2918*0Sstevel@tonic-gate if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,0)) 2919*0Sstevel@tonic-gate goto error; 2920*0Sstevel@tonic-gate } 2921*0Sstevel@tonic-gate 2922*0Sstevel@tonic-gate OPENSSL_free(ne_values); 2923*0Sstevel@tonic-gate OPENSSL_free(ne_types); 2924*0Sstevel@tonic-gate OPENSSL_free(buf); 2925*0Sstevel@tonic-gate return n; 2926*0Sstevel@tonic-gate 2927*0Sstevel@tonic-gate error: 2928*0Sstevel@tonic-gate X509_NAME_free(n); 2929*0Sstevel@tonic-gate if (ne_values) 2930*0Sstevel@tonic-gate OPENSSL_free(ne_values); 2931*0Sstevel@tonic-gate if (ne_types) 2932*0Sstevel@tonic-gate OPENSSL_free(ne_types); 2933*0Sstevel@tonic-gate if (buf) 2934*0Sstevel@tonic-gate OPENSSL_free(buf); 2935*0Sstevel@tonic-gate return NULL; 2936*0Sstevel@tonic-gate } 2937*0Sstevel@tonic-gate 2938*0Sstevel@tonic-gate int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str) 2939*0Sstevel@tonic-gate { 2940*0Sstevel@tonic-gate char buf[25],*pbuf, *p; 2941*0Sstevel@tonic-gate int j; 2942*0Sstevel@tonic-gate j=i2a_ASN1_OBJECT(bp,obj); 2943*0Sstevel@tonic-gate pbuf=buf; 2944*0Sstevel@tonic-gate for (j=22-j; j>0; j--) 2945*0Sstevel@tonic-gate *(pbuf++)=' '; 2946*0Sstevel@tonic-gate *(pbuf++)=':'; 2947*0Sstevel@tonic-gate *(pbuf++)='\0'; 2948*0Sstevel@tonic-gate BIO_puts(bp,buf); 2949*0Sstevel@tonic-gate 2950*0Sstevel@tonic-gate if (str->type == V_ASN1_PRINTABLESTRING) 2951*0Sstevel@tonic-gate BIO_printf(bp,"PRINTABLE:'"); 2952*0Sstevel@tonic-gate else if (str->type == V_ASN1_T61STRING) 2953*0Sstevel@tonic-gate BIO_printf(bp,"T61STRING:'"); 2954*0Sstevel@tonic-gate else if (str->type == V_ASN1_IA5STRING) 2955*0Sstevel@tonic-gate BIO_printf(bp,"IA5STRING:'"); 2956*0Sstevel@tonic-gate else if (str->type == V_ASN1_UNIVERSALSTRING) 2957*0Sstevel@tonic-gate BIO_printf(bp,"UNIVERSALSTRING:'"); 2958*0Sstevel@tonic-gate else 2959*0Sstevel@tonic-gate BIO_printf(bp,"ASN.1 %2d:'",str->type); 2960*0Sstevel@tonic-gate 2961*0Sstevel@tonic-gate p=(char *)str->data; 2962*0Sstevel@tonic-gate for (j=str->length; j>0; j--) 2963*0Sstevel@tonic-gate { 2964*0Sstevel@tonic-gate if ((*p >= ' ') && (*p <= '~')) 2965*0Sstevel@tonic-gate BIO_printf(bp,"%c",*p); 2966*0Sstevel@tonic-gate else if (*p & 0x80) 2967*0Sstevel@tonic-gate BIO_printf(bp,"\\0x%02X",*p); 2968*0Sstevel@tonic-gate else if ((unsigned char)*p == 0xf7) 2969*0Sstevel@tonic-gate BIO_printf(bp,"^?"); 2970*0Sstevel@tonic-gate else BIO_printf(bp,"^%c",*p+'@'); 2971*0Sstevel@tonic-gate p++; 2972*0Sstevel@tonic-gate } 2973*0Sstevel@tonic-gate BIO_printf(bp,"'\n"); 2974*0Sstevel@tonic-gate return 1; 2975*0Sstevel@tonic-gate } 2976*0Sstevel@tonic-gate 2977*0Sstevel@tonic-gate int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, char *str) 2978*0Sstevel@tonic-gate { 2979*0Sstevel@tonic-gate char *tmp = NULL; 2980*0Sstevel@tonic-gate char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p; 2981*0Sstevel@tonic-gate int reason_code = -1; 2982*0Sstevel@tonic-gate int i, ret = 0; 2983*0Sstevel@tonic-gate ASN1_OBJECT *hold = NULL; 2984*0Sstevel@tonic-gate ASN1_GENERALIZEDTIME *comp_time = NULL; 2985*0Sstevel@tonic-gate tmp = BUF_strdup(str); 2986*0Sstevel@tonic-gate 2987*0Sstevel@tonic-gate p = strchr(tmp, ','); 2988*0Sstevel@tonic-gate 2989*0Sstevel@tonic-gate rtime_str = tmp; 2990*0Sstevel@tonic-gate 2991*0Sstevel@tonic-gate if (p) 2992*0Sstevel@tonic-gate { 2993*0Sstevel@tonic-gate *p = '\0'; 2994*0Sstevel@tonic-gate p++; 2995*0Sstevel@tonic-gate reason_str = p; 2996*0Sstevel@tonic-gate p = strchr(p, ','); 2997*0Sstevel@tonic-gate if (p) 2998*0Sstevel@tonic-gate { 2999*0Sstevel@tonic-gate *p = '\0'; 3000*0Sstevel@tonic-gate arg_str = p + 1; 3001*0Sstevel@tonic-gate } 3002*0Sstevel@tonic-gate } 3003*0Sstevel@tonic-gate 3004*0Sstevel@tonic-gate if (prevtm) 3005*0Sstevel@tonic-gate { 3006*0Sstevel@tonic-gate *prevtm = ASN1_UTCTIME_new(); 3007*0Sstevel@tonic-gate if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str)) 3008*0Sstevel@tonic-gate { 3009*0Sstevel@tonic-gate BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str); 3010*0Sstevel@tonic-gate goto err; 3011*0Sstevel@tonic-gate } 3012*0Sstevel@tonic-gate } 3013*0Sstevel@tonic-gate if (reason_str) 3014*0Sstevel@tonic-gate { 3015*0Sstevel@tonic-gate for (i = 0; i < NUM_REASONS; i++) 3016*0Sstevel@tonic-gate { 3017*0Sstevel@tonic-gate if(!strcasecmp(reason_str, crl_reasons[i])) 3018*0Sstevel@tonic-gate { 3019*0Sstevel@tonic-gate reason_code = i; 3020*0Sstevel@tonic-gate break; 3021*0Sstevel@tonic-gate } 3022*0Sstevel@tonic-gate } 3023*0Sstevel@tonic-gate if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS) 3024*0Sstevel@tonic-gate { 3025*0Sstevel@tonic-gate BIO_printf(bio_err, "invalid reason code %s\n", reason_str); 3026*0Sstevel@tonic-gate goto err; 3027*0Sstevel@tonic-gate } 3028*0Sstevel@tonic-gate 3029*0Sstevel@tonic-gate if (reason_code == 7) 3030*0Sstevel@tonic-gate reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL; 3031*0Sstevel@tonic-gate else if (reason_code == 8) /* Hold instruction */ 3032*0Sstevel@tonic-gate { 3033*0Sstevel@tonic-gate if (!arg_str) 3034*0Sstevel@tonic-gate { 3035*0Sstevel@tonic-gate BIO_printf(bio_err, "missing hold instruction\n"); 3036*0Sstevel@tonic-gate goto err; 3037*0Sstevel@tonic-gate } 3038*0Sstevel@tonic-gate reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD; 3039*0Sstevel@tonic-gate hold = OBJ_txt2obj(arg_str, 0); 3040*0Sstevel@tonic-gate 3041*0Sstevel@tonic-gate if (!hold) 3042*0Sstevel@tonic-gate { 3043*0Sstevel@tonic-gate BIO_printf(bio_err, "invalid object identifier %s\n", arg_str); 3044*0Sstevel@tonic-gate goto err; 3045*0Sstevel@tonic-gate } 3046*0Sstevel@tonic-gate if (phold) *phold = hold; 3047*0Sstevel@tonic-gate } 3048*0Sstevel@tonic-gate else if ((reason_code == 9) || (reason_code == 10)) 3049*0Sstevel@tonic-gate { 3050*0Sstevel@tonic-gate if (!arg_str) 3051*0Sstevel@tonic-gate { 3052*0Sstevel@tonic-gate BIO_printf(bio_err, "missing compromised time\n"); 3053*0Sstevel@tonic-gate goto err; 3054*0Sstevel@tonic-gate } 3055*0Sstevel@tonic-gate comp_time = ASN1_GENERALIZEDTIME_new(); 3056*0Sstevel@tonic-gate if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str)) 3057*0Sstevel@tonic-gate { 3058*0Sstevel@tonic-gate BIO_printf(bio_err, "invalid compromised time %s\n", arg_str); 3059*0Sstevel@tonic-gate goto err; 3060*0Sstevel@tonic-gate } 3061*0Sstevel@tonic-gate if (reason_code == 9) 3062*0Sstevel@tonic-gate reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE; 3063*0Sstevel@tonic-gate else 3064*0Sstevel@tonic-gate reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE; 3065*0Sstevel@tonic-gate } 3066*0Sstevel@tonic-gate } 3067*0Sstevel@tonic-gate 3068*0Sstevel@tonic-gate if (preason) *preason = reason_code; 3069*0Sstevel@tonic-gate if (pinvtm) *pinvtm = comp_time; 3070*0Sstevel@tonic-gate else ASN1_GENERALIZEDTIME_free(comp_time); 3071*0Sstevel@tonic-gate 3072*0Sstevel@tonic-gate ret = 1; 3073*0Sstevel@tonic-gate 3074*0Sstevel@tonic-gate err: 3075*0Sstevel@tonic-gate 3076*0Sstevel@tonic-gate if (tmp) OPENSSL_free(tmp); 3077*0Sstevel@tonic-gate if (!phold) ASN1_OBJECT_free(hold); 3078*0Sstevel@tonic-gate if (!pinvtm) ASN1_GENERALIZEDTIME_free(comp_time); 3079*0Sstevel@tonic-gate 3080*0Sstevel@tonic-gate return ret; 3081*0Sstevel@tonic-gate } 3082