1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/ssl/tsrc/topenssl/src/ca.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,3004 @@
1.4 +/* apps/ca.c */
1.5 +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
1.6 + * All rights reserved.
1.7 + *
1.8 + * This package is an SSL implementation written
1.9 + * by Eric Young (eay@cryptsoft.com).
1.10 + * The implementation was written so as to conform with Netscapes SSL.
1.11 + *
1.12 + * This library is free for commercial and non-commercial use as long as
1.13 + * the following conditions are aheared to. The following conditions
1.14 + * apply to all code found in this distribution, be it the RC4, RSA,
1.15 + * lhash, DES, etc., code; not just the SSL code. The SSL documentation
1.16 + * included with this distribution is covered by the same copyright terms
1.17 + * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1.18 + *
1.19 + * Copyright remains Eric Young's, and as such any Copyright notices in
1.20 + * the code are not to be removed.
1.21 + * If this package is used in a product, Eric Young should be given attribution
1.22 + * as the author of the parts of the library used.
1.23 + * This can be in the form of a textual message at program startup or
1.24 + * in documentation (online or textual) provided with the package.
1.25 + *
1.26 + * Redistribution and use in source and binary forms, with or without
1.27 + * modification, are permitted provided that the following conditions
1.28 + * are met:
1.29 + * 1. Redistributions of source code must retain the copyright
1.30 + * notice, this list of conditions and the following disclaimer.
1.31 + * 2. Redistributions in binary form must reproduce the above copyright
1.32 + * notice, this list of conditions and the following disclaimer in the
1.33 + * documentation and/or other materials provided with the distribution.
1.34 + * 3. All advertising materials mentioning features or use of this software
1.35 + * must display the following acknowledgement:
1.36 + * "This product includes cryptographic software written by
1.37 + * Eric Young (eay@cryptsoft.com)"
1.38 + * The word 'cryptographic' can be left out if the rouines from the library
1.39 + * being used are not cryptographic related :-).
1.40 + * 4. If you include any Windows specific code (or a derivative thereof) from
1.41 + * the apps directory (application code) you must include an acknowledgement:
1.42 + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
1.43 + *
1.44 + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
1.45 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1.46 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1.47 + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1.48 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1.49 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1.50 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1.51 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1.52 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1.53 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1.54 + * SUCH DAMAGE.
1.55 + *
1.56 + * The licence and distribution terms for any publically available version or
1.57 + * derivative of this code cannot be changed. i.e. this code cannot simply be
1.58 + * copied and put under another distribution licence
1.59 + * [including the GNU Public Licence.]
1.60 + */
1.61 +
1.62 +/* The PPKI stuff has been donated by Jeff Barber <jeffb@issl.atl.hp.com> */
1.63 +
1.64 +#include <stdio.h>
1.65 +#include <stdlib.h>
1.66 +#include <string.h>
1.67 +#include <ctype.h>
1.68 +#include <sys/types.h>
1.69 +#include <sys/stat.h>
1.70 +#include <openssl/conf.h>
1.71 +#include <openssl/bio.h>
1.72 +#include <openssl/err.h>
1.73 +#include <openssl/bn.h>
1.74 +#include <openssl/txt_db.h>
1.75 +#include <openssl/evp.h>
1.76 +#include <openssl/x509.h>
1.77 +#include <openssl/x509v3.h>
1.78 +#include <openssl/objects.h>
1.79 +#include <openssl/ocsp.h>
1.80 +#include <openssl/pem.h>
1.81 +
1.82 +#ifndef W_OK
1.83 +# ifdef OPENSSL_SYS_VMS
1.84 +# if defined(__DECC)
1.85 +# include <unistd.h>
1.86 +# else
1.87 +# include <unixlib.h>
1.88 +# endif
1.89 +# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_NETWARE)
1.90 +# include <sys/file.h>
1.91 +# endif
1.92 +#endif
1.93 +
1.94 +#include "apps.h"
1.95 +
1.96 +#ifndef W_OK
1.97 +# define F_OK 0
1.98 +# define X_OK 1
1.99 +# define W_OK 2
1.100 +# define R_OK 4
1.101 +#endif
1.102 +
1.103 +#undef PROG
1.104 +#define PROG ca_main
1.105 +
1.106 +#define BASE_SECTION "ca"
1.107 +#define CONFIG_FILE "openssl.cnf"
1.108 +
1.109 +#define ENV_DEFAULT_CA "default_ca"
1.110 +
1.111 +#define STRING_MASK "string_mask"
1.112 +#define UTF8_IN "utf8"
1.113 +
1.114 +#define ENV_DIR "dir"
1.115 +#define ENV_CERTS "certs"
1.116 +#define ENV_CRL_DIR "crl_dir"
1.117 +#define ENV_CA_DB "CA_DB"
1.118 +#define ENV_NEW_CERTS_DIR "new_certs_dir"
1.119 +#define ENV_CERTIFICATE "certificate"
1.120 +#define ENV_SERIAL "serial"
1.121 +#define ENV_CRLNUMBER "crlnumber"
1.122 +#define ENV_CRL "crl"
1.123 +#define ENV_PRIVATE_KEY "private_key"
1.124 +#define ENV_RANDFILE "RANDFILE"
1.125 +#define ENV_DEFAULT_DAYS "default_days"
1.126 +#define ENV_DEFAULT_STARTDATE "default_startdate"
1.127 +#define ENV_DEFAULT_ENDDATE "default_enddate"
1.128 +#define ENV_DEFAULT_CRL_DAYS "default_crl_days"
1.129 +#define ENV_DEFAULT_CRL_HOURS "default_crl_hours"
1.130 +#define ENV_DEFAULT_MD "default_md"
1.131 +#define ENV_DEFAULT_EMAIL_DN "email_in_dn"
1.132 +#define ENV_PRESERVE "preserve"
1.133 +#define ENV_POLICY "policy"
1.134 +#define ENV_EXTENSIONS "x509_extensions"
1.135 +#define ENV_CRLEXT "crl_extensions"
1.136 +#define ENV_MSIE_HACK "msie_hack"
1.137 +#define ENV_NAMEOPT "name_opt"
1.138 +#define ENV_CERTOPT "cert_opt"
1.139 +#define ENV_EXTCOPY "copy_extensions"
1.140 +#define ENV_UNIQUE_SUBJECT "unique_subject"
1.141 +
1.142 +#define ENV_DATABASE "database"
1.143 +
1.144 +/* Additional revocation information types */
1.145 +
1.146 +#define REV_NONE 0 /* No addditional information */
1.147 +#define REV_CRL_REASON 1 /* Value is CRL reason code */
1.148 +#define REV_HOLD 2 /* Value is hold instruction */
1.149 +#define REV_KEY_COMPROMISE 3 /* Value is cert key compromise time */
1.150 +#define REV_CA_COMPROMISE 4 /* Value is CA key compromise time */
1.151 +
1.152 +static const char *ca_usage[]={
1.153 +"usage: ca args\n",
1.154 +"\n",
1.155 +" -verbose - Talk alot while doing things\n",
1.156 +" -config file - A config file\n",
1.157 +" -name arg - The particular CA definition to use\n",
1.158 +" -gencrl - Generate a new CRL\n",
1.159 +" -crldays days - Days is when the next CRL is due\n",
1.160 +" -crlhours hours - Hours is when the next CRL is due\n",
1.161 +" -startdate YYMMDDHHMMSSZ - certificate validity notBefore\n",
1.162 +" -enddate YYMMDDHHMMSSZ - certificate validity notAfter (overrides -days)\n",
1.163 +" -days arg - number of days to certify the certificate for\n",
1.164 +" -md arg - md to use, one of md2, md5, sha or sha1\n",
1.165 +" -policy arg - The CA 'policy' to support\n",
1.166 +" -keyfile arg - private key file\n",
1.167 +" -keyform arg - private key file format (PEM or ENGINE)\n",
1.168 +" -key arg - key to decode the private key if it is encrypted\n",
1.169 +" -cert file - The CA certificate\n",
1.170 +" -selfsign - sign a certificate with the key associated with it\n",
1.171 +" -in file - The input PEM encoded certificate request(s)\n",
1.172 +" -out file - Where to put the output file(s)\n",
1.173 +" -outdir dir - Where to put output certificates\n",
1.174 +" -infiles .... - The last argument, requests to process\n",
1.175 +" -spkac file - File contains DN and signed public key and challenge\n",
1.176 +" -ss_cert file - File contains a self signed cert to sign\n",
1.177 +" -preserveDN - Don't re-order the DN\n",
1.178 +" -noemailDN - Don't add the EMAIL field into certificate' subject\n",
1.179 +" -batch - Don't ask questions\n",
1.180 +" -msie_hack - msie modifications to handle all those universal strings\n",
1.181 +" -revoke file - Revoke a certificate (given in file)\n",
1.182 +" -subj arg - Use arg instead of request's subject\n",
1.183 +" -utf8 - input characters are UTF8 (default ASCII)\n",
1.184 +" -multivalue-rdn - enable support for multivalued RDNs\n",
1.185 +" -extensions .. - Extension section (override value in config file)\n",
1.186 +" -extfile file - Configuration file with X509v3 extentions to add\n",
1.187 +" -crlexts .. - CRL extension section (override value in config file)\n",
1.188 +#ifndef OPENSSL_NO_ENGINE
1.189 +" -engine e - use engine e, possibly a hardware device.\n",
1.190 +#endif
1.191 +" -status serial - Shows certificate status given the serial number\n",
1.192 +" -updatedb - Updates db for expired certificates\n",
1.193 +NULL
1.194 +};
1.195 +
1.196 +#ifdef EFENCE
1.197 +extern int EF_PROTECT_FREE;
1.198 +extern int EF_PROTECT_BELOW;
1.199 +extern int EF_ALIGNMENT;
1.200 +#endif
1.201 +
1.202 +static void lookup_fail(const char *name, const char *tag);
1.203 +static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
1.204 + const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,CA_DB *db,
1.205 + BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate,
1.206 + char *enddate, long days, int batch, char *ext_sect, CONF *conf,
1.207 + int verbose, unsigned long certopt, unsigned long nameopt,
1.208 + int default_op, int ext_copy, int selfsign);
1.209 +static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
1.210 + const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
1.211 + CA_DB *db, BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn,
1.212 + char *startdate, char *enddate, long days, int batch,
1.213 + char *ext_sect, CONF *conf,int verbose, unsigned long certopt,
1.214 + unsigned long nameopt, int default_op, int ext_copy,
1.215 + ENGINE *e);
1.216 +static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
1.217 + const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
1.218 + CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn, int email_dn,
1.219 + char *startdate, char *enddate, long days, char *ext_sect,
1.220 + CONF *conf, int verbose, unsigned long certopt,
1.221 + unsigned long nameopt, int default_op, int ext_copy);
1.222 +static int fix_data(int nid, int *type);
1.223 +static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
1.224 +static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1.225 + STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn,
1.226 + int email_dn, char *startdate, char *enddate, long days, int batch,
1.227 + int verbose, X509_REQ *req, char *ext_sect, CONF *conf,
1.228 + unsigned long certopt, unsigned long nameopt, int default_op,
1.229 + int ext_copy, int selfsign);
1.230 +static int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval);
1.231 +static int get_certificate_status(const char *ser_status, CA_DB *db);
1.232 +static int do_updatedb(CA_DB *db);
1.233 +static int check_time_format(char *str);
1.234 +char *make_revocation_str(int rev_type, char *rev_arg);
1.235 +int make_revoked(X509_REVOKED *rev, const char *str);
1.236 +int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str);
1.237 +static CONF *conf=NULL;
1.238 +static CONF *extconf=NULL;
1.239 +static char *section=NULL;
1.240 +
1.241 +static int preserve=0;
1.242 +static int msie_hack=0;
1.243 +
1.244 +
1.245 +
1.246 +int MAIN(int, char **);
1.247 +
1.248 +int MAIN(int argc, char **argv)
1.249 + {
1.250 + ENGINE *e = NULL;
1.251 + char *key=NULL,*passargin=NULL;
1.252 + int create_ser = 0;
1.253 + int free_key = 0;
1.254 + int total=0;
1.255 + int total_done=0;
1.256 + int badops=0;
1.257 + int ret=1;
1.258 + int email_dn=1;
1.259 + int req=0;
1.260 + int verbose=0;
1.261 + int gencrl=0;
1.262 + int dorevoke=0;
1.263 + int doupdatedb=0;
1.264 + long crldays=0;
1.265 + long crlhours=0;
1.266 + long errorline= -1;
1.267 + char *configfile=NULL;
1.268 + char *md=NULL;
1.269 + char *policy=NULL;
1.270 + char *keyfile=NULL;
1.271 + char *certfile=NULL;
1.272 + int keyform=FORMAT_PEM;
1.273 + char *infile=NULL;
1.274 + char *spkac_file=NULL;
1.275 + char *ss_cert_file=NULL;
1.276 + char *ser_status=NULL;
1.277 + EVP_PKEY *pkey=NULL;
1.278 + int output_der = 0;
1.279 + char *outfile=NULL;
1.280 + char *outdir=NULL;
1.281 + char *serialfile=NULL;
1.282 + char *crlnumberfile=NULL;
1.283 + char *extensions=NULL;
1.284 + char *extfile=NULL;
1.285 + char *subj=NULL;
1.286 + unsigned long chtype = MBSTRING_ASC;
1.287 + int multirdn = 0;
1.288 + char *tmp_email_dn=NULL;
1.289 + char *crl_ext=NULL;
1.290 + int rev_type = REV_NONE;
1.291 + char *rev_arg = NULL;
1.292 + BIGNUM *serial=NULL;
1.293 + BIGNUM *crlnumber=NULL;
1.294 + char *startdate=NULL;
1.295 + char *enddate=NULL;
1.296 + long days=0;
1.297 + int batch=0;
1.298 + int notext=0;
1.299 + unsigned long nameopt = 0, certopt = 0;
1.300 + int default_op = 1;
1.301 + int ext_copy = EXT_COPY_NONE;
1.302 + int selfsign = 0;
1.303 + X509 *x509=NULL, *x509p = NULL;
1.304 + X509 *x=NULL;
1.305 + BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
1.306 + char *dbfile=NULL;
1.307 + CA_DB *db=NULL;
1.308 + X509_CRL *crl=NULL;
1.309 + X509_REVOKED *r=NULL;
1.310 + ASN1_TIME *tmptm;
1.311 + ASN1_INTEGER *tmpser;
1.312 + char *f;
1.313 + const char *p, **pp;
1.314 + int i,j;
1.315 + const EVP_MD *dgst=NULL;
1.316 + STACK_OF(CONF_VALUE) *attribs=NULL;
1.317 + STACK_OF(X509) *cert_sk=NULL;
1.318 +#undef BSIZE
1.319 +#define BSIZE 256
1.320 + MS_STATIC char buf[3][BSIZE];
1.321 + char *randfile=NULL;
1.322 +#ifndef OPENSSL_NO_ENGINE
1.323 + char *engine = NULL;
1.324 +#endif
1.325 + char *tofree=NULL;
1.326 + DB_ATTR db_attr;
1.327 +
1.328 +#ifdef EFENCE
1.329 +EF_PROTECT_FREE=1;
1.330 +EF_PROTECT_BELOW=1;
1.331 +EF_ALIGNMENT=0;
1.332 +#endif
1.333 +
1.334 + apps_startup();
1.335 +
1.336 + conf = NULL;
1.337 + key = NULL;
1.338 + section = NULL;
1.339 +
1.340 + preserve=0;
1.341 + msie_hack=0;
1.342 + if (bio_err == NULL)
1.343 + if ((bio_err=BIO_new(BIO_s_file())) != NULL)
1.344 + BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
1.345 +
1.346 + argc--;
1.347 + argv++;
1.348 + while (argc >= 1)
1.349 + {
1.350 + if (strcmp(*argv,"-verbose") == 0)
1.351 + verbose=1;
1.352 + else if (strcmp(*argv,"-config") == 0)
1.353 + {
1.354 + if (--argc < 1) goto bad;
1.355 + configfile= *(++argv);
1.356 + }
1.357 + else if (strcmp(*argv,"-name") == 0)
1.358 + {
1.359 + if (--argc < 1) goto bad;
1.360 + section= *(++argv);
1.361 + }
1.362 + else if (strcmp(*argv,"-subj") == 0)
1.363 + {
1.364 + if (--argc < 1) goto bad;
1.365 + subj= *(++argv);
1.366 + /* preserve=1; */
1.367 + }
1.368 + else if (strcmp(*argv,"-utf8") == 0)
1.369 + chtype = MBSTRING_UTF8;
1.370 + else if (strcmp(*argv,"-create_serial") == 0)
1.371 + create_ser = 1;
1.372 + else if (strcmp(*argv,"-multivalue-rdn") == 0)
1.373 + multirdn=1;
1.374 + else if (strcmp(*argv,"-startdate") == 0)
1.375 + {
1.376 + if (--argc < 1) goto bad;
1.377 + startdate= *(++argv);
1.378 + }
1.379 + else if (strcmp(*argv,"-enddate") == 0)
1.380 + {
1.381 + if (--argc < 1) goto bad;
1.382 + enddate= *(++argv);
1.383 + }
1.384 + else if (strcmp(*argv,"-days") == 0)
1.385 + {
1.386 + if (--argc < 1) goto bad;
1.387 + days=atoi(*(++argv));
1.388 + }
1.389 + else if (strcmp(*argv,"-md") == 0)
1.390 + {
1.391 + if (--argc < 1) goto bad;
1.392 + md= *(++argv);
1.393 + }
1.394 + else if (strcmp(*argv,"-policy") == 0)
1.395 + {
1.396 + if (--argc < 1) goto bad;
1.397 + policy= *(++argv);
1.398 + }
1.399 + else if (strcmp(*argv,"-keyfile") == 0)
1.400 + {
1.401 + if (--argc < 1) goto bad;
1.402 + keyfile= *(++argv);
1.403 + }
1.404 + else if (strcmp(*argv,"-keyform") == 0)
1.405 + {
1.406 + if (--argc < 1) goto bad;
1.407 + keyform=str2fmt(*(++argv));
1.408 + }
1.409 + else if (strcmp(*argv,"-passin") == 0)
1.410 + {
1.411 + if (--argc < 1) goto bad;
1.412 + passargin= *(++argv);
1.413 + }
1.414 + else if (strcmp(*argv,"-key") == 0)
1.415 + {
1.416 + if (--argc < 1) goto bad;
1.417 + key= *(++argv);
1.418 + }
1.419 + else if (strcmp(*argv,"-cert") == 0)
1.420 + {
1.421 + if (--argc < 1) goto bad;
1.422 + certfile= *(++argv);
1.423 + }
1.424 + else if (strcmp(*argv,"-selfsign") == 0)
1.425 + selfsign=1;
1.426 + else if (strcmp(*argv,"-in") == 0)
1.427 + {
1.428 + if (--argc < 1) goto bad;
1.429 + infile= *(++argv);
1.430 + req=1;
1.431 + }
1.432 + else if (strcmp(*argv,"-out") == 0)
1.433 + {
1.434 + if (--argc < 1) goto bad;
1.435 + outfile= *(++argv);
1.436 + }
1.437 + else if (strcmp(*argv,"-outdir") == 0)
1.438 + {
1.439 + if (--argc < 1) goto bad;
1.440 + outdir= *(++argv);
1.441 + }
1.442 + else if (strcmp(*argv,"-notext") == 0)
1.443 + notext=1;
1.444 + else if (strcmp(*argv,"-batch") == 0)
1.445 + batch=1;
1.446 + else if (strcmp(*argv,"-preserveDN") == 0)
1.447 + preserve=1;
1.448 + else if (strcmp(*argv,"-noemailDN") == 0)
1.449 + email_dn=0;
1.450 + else if (strcmp(*argv,"-gencrl") == 0)
1.451 + gencrl=1;
1.452 + else if (strcmp(*argv,"-msie_hack") == 0)
1.453 + msie_hack=1;
1.454 + else if (strcmp(*argv,"-crldays") == 0)
1.455 + {
1.456 + if (--argc < 1) goto bad;
1.457 + crldays= atol(*(++argv));
1.458 + }
1.459 + else if (strcmp(*argv,"-crlhours") == 0)
1.460 + {
1.461 + if (--argc < 1) goto bad;
1.462 + crlhours= atol(*(++argv));
1.463 + }
1.464 + else if (strcmp(*argv,"-infiles") == 0)
1.465 + {
1.466 + argc--;
1.467 + argv++;
1.468 + req=1;
1.469 + break;
1.470 + }
1.471 + else if (strcmp(*argv, "-ss_cert") == 0)
1.472 + {
1.473 + if (--argc < 1) goto bad;
1.474 + ss_cert_file = *(++argv);
1.475 + req=1;
1.476 + }
1.477 + else if (strcmp(*argv, "-spkac") == 0)
1.478 + {
1.479 + if (--argc < 1) goto bad;
1.480 + spkac_file = *(++argv);
1.481 + req=1;
1.482 + }
1.483 + else if (strcmp(*argv,"-revoke") == 0)
1.484 + {
1.485 + if (--argc < 1) goto bad;
1.486 + infile= *(++argv);
1.487 + dorevoke=1;
1.488 + }
1.489 + else if (strcmp(*argv,"-extensions") == 0)
1.490 + {
1.491 + if (--argc < 1) goto bad;
1.492 + extensions= *(++argv);
1.493 + }
1.494 + else if (strcmp(*argv,"-extfile") == 0)
1.495 + {
1.496 + if (--argc < 1) goto bad;
1.497 + extfile= *(++argv);
1.498 + }
1.499 + else if (strcmp(*argv,"-status") == 0)
1.500 + {
1.501 + if (--argc < 1) goto bad;
1.502 + ser_status= *(++argv);
1.503 + }
1.504 + else if (strcmp(*argv,"-updatedb") == 0)
1.505 + {
1.506 + doupdatedb=1;
1.507 + }
1.508 + else if (strcmp(*argv,"-crlexts") == 0)
1.509 + {
1.510 + if (--argc < 1) goto bad;
1.511 + crl_ext= *(++argv);
1.512 + }
1.513 + else if (strcmp(*argv,"-crl_reason") == 0)
1.514 + {
1.515 + if (--argc < 1) goto bad;
1.516 + rev_arg = *(++argv);
1.517 + rev_type = REV_CRL_REASON;
1.518 + }
1.519 + else if (strcmp(*argv,"-crl_hold") == 0)
1.520 + {
1.521 + if (--argc < 1) goto bad;
1.522 + rev_arg = *(++argv);
1.523 + rev_type = REV_HOLD;
1.524 + }
1.525 + else if (strcmp(*argv,"-crl_compromise") == 0)
1.526 + {
1.527 + if (--argc < 1) goto bad;
1.528 + rev_arg = *(++argv);
1.529 + rev_type = REV_KEY_COMPROMISE;
1.530 + }
1.531 + else if (strcmp(*argv,"-crl_CA_compromise") == 0)
1.532 + {
1.533 + if (--argc < 1) goto bad;
1.534 + rev_arg = *(++argv);
1.535 + rev_type = REV_CA_COMPROMISE;
1.536 + }
1.537 +#ifndef OPENSSL_NO_ENGINE
1.538 + else if (strcmp(*argv,"-engine") == 0)
1.539 + {
1.540 + if (--argc < 1) goto bad;
1.541 + engine= *(++argv);
1.542 + }
1.543 +#endif
1.544 + else
1.545 + {
1.546 +bad:
1.547 + BIO_printf(bio_err,"unknown option %s\n",*argv);
1.548 + badops=1;
1.549 + break;
1.550 + }
1.551 + argc--;
1.552 + argv++;
1.553 + }
1.554 +
1.555 + if (badops)
1.556 + {
1.557 + for (pp=ca_usage; (*pp != NULL); pp++)
1.558 + BIO_printf(bio_err,"%s",*pp);
1.559 + goto err;
1.560 + }
1.561 +
1.562 + ERR_load_crypto_strings();
1.563 +
1.564 + /*****************************************************************/
1.565 + tofree=NULL;
1.566 + if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
1.567 + if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
1.568 + if (configfile == NULL)
1.569 + {
1.570 + const char *s=X509_get_default_cert_area();
1.571 + size_t len;
1.572 +
1.573 +#ifdef OPENSSL_SYS_VMS
1.574 + len = strlen(s)+sizeof(CONFIG_FILE);
1.575 + tofree=OPENSSL_malloc(len);
1.576 + strcpy(tofree,s);
1.577 +#else
1.578 + len = strlen(s)+sizeof(CONFIG_FILE)+1;
1.579 + tofree=OPENSSL_malloc(len);
1.580 + BUF_strlcpy(tofree,s,len);
1.581 + BUF_strlcat(tofree,"/",len);
1.582 +#endif
1.583 + BUF_strlcat(tofree,CONFIG_FILE,len);
1.584 + configfile=tofree;
1.585 + }
1.586 +
1.587 + BIO_printf(bio_err,"Using configuration from %s\n",configfile);
1.588 + conf = NCONF_new(NULL);
1.589 + if (NCONF_load(conf,configfile,&errorline) <= 0)
1.590 + {
1.591 + if (errorline <= 0)
1.592 + BIO_printf(bio_err,"error loading the config file '%s'\n",
1.593 + configfile);
1.594 + else
1.595 + BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
1.596 + ,errorline,configfile);
1.597 + goto err;
1.598 + }
1.599 + if(tofree)
1.600 + {
1.601 + OPENSSL_free(tofree);
1.602 + tofree = NULL;
1.603 + }
1.604 +
1.605 + if (!load_config(bio_err, conf))
1.606 + goto err;
1.607 +
1.608 +#ifndef OPENSSL_NO_ENGINE
1.609 + e = setup_engine(bio_err, engine, 0);
1.610 +#endif
1.611 +
1.612 + /* Lets get the config section we are using */
1.613 + if (section == NULL)
1.614 + {
1.615 + section=NCONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
1.616 + if (section == NULL)
1.617 + {
1.618 + lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
1.619 + goto err;
1.620 + }
1.621 + }
1.622 +
1.623 + if (conf != NULL)
1.624 + {
1.625 + p=NCONF_get_string(conf,NULL,"oid_file");
1.626 + if (p == NULL)
1.627 + ERR_clear_error();
1.628 + if (p != NULL)
1.629 + {
1.630 + BIO *oid_bio;
1.631 +
1.632 + oid_bio=BIO_new_file(p,"r");
1.633 + if (oid_bio == NULL)
1.634 + {
1.635 + /*
1.636 + BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
1.637 + ERR_print_errors(bio_err);
1.638 + */
1.639 + ERR_clear_error();
1.640 + }
1.641 + else
1.642 + {
1.643 + OBJ_create_objects(oid_bio);
1.644 + BIO_free(oid_bio);
1.645 + }
1.646 + }
1.647 + if (!add_oid_section(bio_err,conf))
1.648 + {
1.649 + ERR_print_errors(bio_err);
1.650 + goto err;
1.651 + }
1.652 + }
1.653 +
1.654 + randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
1.655 + if (randfile == NULL)
1.656 + ERR_clear_error();
1.657 + app_RAND_load_file(randfile, bio_err, 0);
1.658 +
1.659 + f = NCONF_get_string(conf, section, STRING_MASK);
1.660 + if (!f)
1.661 + ERR_clear_error();
1.662 +
1.663 + if(f && !ASN1_STRING_set_default_mask_asc(f)) {
1.664 + BIO_printf(bio_err, "Invalid global string mask setting %s\n", f);
1.665 + goto err;
1.666 + }
1.667 +
1.668 + if (chtype != MBSTRING_UTF8){
1.669 + f = NCONF_get_string(conf, section, UTF8_IN);
1.670 + if (!f)
1.671 + ERR_clear_error();
1.672 + else if (!strcmp(f, "yes"))
1.673 + chtype = MBSTRING_UTF8;
1.674 + }
1.675 +
1.676 + db_attr.unique_subject = 1;
1.677 + p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT);
1.678 + if (p)
1.679 + {
1.680 +#ifdef RL_DEBUG
1.681 + BIO_printf(bio_err, "DEBUG: unique_subject = \"%s\"\n", p);
1.682 +#endif
1.683 + db_attr.unique_subject = parse_yesno(p,1);
1.684 + }
1.685 + else
1.686 + ERR_clear_error();
1.687 +#ifdef RL_DEBUG
1.688 + if (!p)
1.689 + BIO_printf(bio_err, "DEBUG: unique_subject undefined\n", p);
1.690 +#endif
1.691 +#ifdef RL_DEBUG
1.692 + BIO_printf(bio_err, "DEBUG: configured unique_subject is %d\n",
1.693 + db_attr.unique_subject);
1.694 +#endif
1.695 +
1.696 + in=BIO_new(BIO_s_file());
1.697 + out=BIO_new(BIO_s_file());
1.698 + Sout=BIO_new(BIO_s_file());
1.699 + Cout=BIO_new(BIO_s_file());
1.700 + if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL))
1.701 + {
1.702 + ERR_print_errors(bio_err);
1.703 + goto err;
1.704 + }
1.705 +
1.706 + /*****************************************************************/
1.707 + /* report status of cert with serial number given on command line */
1.708 + if (ser_status)
1.709 + {
1.710 + if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
1.711 + {
1.712 + lookup_fail(section,ENV_DATABASE);
1.713 + goto err;
1.714 + }
1.715 + db = load_index(dbfile,&db_attr);
1.716 + if (db == NULL) goto err;
1.717 +
1.718 + if (!index_index(db)) goto err;
1.719 +
1.720 + if (get_certificate_status(ser_status,db) != 1)
1.721 + BIO_printf(bio_err,"Error verifying serial %s!\n",
1.722 + ser_status);
1.723 + goto err;
1.724 + }
1.725 +
1.726 + /*****************************************************************/
1.727 + /* we definitely need a private key, so let's get it */
1.728 +
1.729 + if ((keyfile == NULL) && ((keyfile=NCONF_get_string(conf,
1.730 + section,ENV_PRIVATE_KEY)) == NULL))
1.731 + {
1.732 + lookup_fail(section,ENV_PRIVATE_KEY);
1.733 + goto err;
1.734 + }
1.735 + if (!key)
1.736 + {
1.737 + free_key = 1;
1.738 + if (!app_passwd(bio_err, passargin, NULL, &key, NULL))
1.739 + {
1.740 + BIO_printf(bio_err,"Error getting password\n");
1.741 + goto err;
1.742 + }
1.743 + }
1.744 + pkey = load_key(bio_err, keyfile, keyform, 0, key, e,
1.745 + "CA private key");
1.746 + if (key) OPENSSL_cleanse(key,strlen(key));
1.747 + if (pkey == NULL)
1.748 + {
1.749 + /* load_key() has already printed an appropriate message */
1.750 + goto err;
1.751 + }
1.752 +
1.753 + /*****************************************************************/
1.754 + /* we need a certificate */
1.755 + if (!selfsign || spkac_file || ss_cert_file || gencrl)
1.756 + {
1.757 + if ((certfile == NULL)
1.758 + && ((certfile=NCONF_get_string(conf,
1.759 + section,ENV_CERTIFICATE)) == NULL))
1.760 + {
1.761 + lookup_fail(section,ENV_CERTIFICATE);
1.762 + goto err;
1.763 + }
1.764 + x509=load_cert(bio_err, certfile, FORMAT_PEM, NULL, e,
1.765 + "CA certificate");
1.766 + if (x509 == NULL)
1.767 + goto err;
1.768 +
1.769 + if (!X509_check_private_key(x509,pkey))
1.770 + {
1.771 + BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
1.772 + goto err;
1.773 + }
1.774 + }
1.775 + if (!selfsign) x509p = x509;
1.776 +
1.777 + f=NCONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
1.778 + if (f == NULL)
1.779 + ERR_clear_error();
1.780 + if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
1.781 + preserve=1;
1.782 + f=NCONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
1.783 + if (f == NULL)
1.784 + ERR_clear_error();
1.785 + if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
1.786 + msie_hack=1;
1.787 +
1.788 + f=NCONF_get_string(conf,section,ENV_NAMEOPT);
1.789 +
1.790 + if (f)
1.791 + {
1.792 + if (!set_name_ex(&nameopt, f))
1.793 + {
1.794 + BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f);
1.795 + goto err;
1.796 + }
1.797 + default_op = 0;
1.798 + }
1.799 + else
1.800 + ERR_clear_error();
1.801 +
1.802 + f=NCONF_get_string(conf,section,ENV_CERTOPT);
1.803 +
1.804 + if (f)
1.805 + {
1.806 + if (!set_cert_ex(&certopt, f))
1.807 + {
1.808 + BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f);
1.809 + goto err;
1.810 + }
1.811 + default_op = 0;
1.812 + }
1.813 + else
1.814 + ERR_clear_error();
1.815 +
1.816 + f=NCONF_get_string(conf,section,ENV_EXTCOPY);
1.817 +
1.818 + if (f)
1.819 + {
1.820 + if (!set_ext_copy(&ext_copy, f))
1.821 + {
1.822 + BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f);
1.823 + goto err;
1.824 + }
1.825 + }
1.826 + else
1.827 + ERR_clear_error();
1.828 +
1.829 + /*****************************************************************/
1.830 + /* lookup where to write new certificates */
1.831 + if ((outdir == NULL) && (req))
1.832 + {
1.833 + struct stat sb;
1.834 +
1.835 + if ((outdir=NCONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
1.836 + == NULL)
1.837 + {
1.838 + BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
1.839 + goto err;
1.840 + }
1.841 +#ifndef OPENSSL_SYS_VMS
1.842 + /* outdir is a directory spec, but access() for VMS demands a
1.843 + filename. In any case, stat(), below, will catch the problem
1.844 + if outdir is not a directory spec, and the fopen() or open()
1.845 + will catch an error if there is no write access.
1.846 +
1.847 + Presumably, this problem could also be solved by using the DEC
1.848 + C routines to convert the directory syntax to Unixly, and give
1.849 + that to access(). However, time's too short to do that just
1.850 + now.
1.851 + */
1.852 + if (access(outdir,R_OK|W_OK|X_OK) != 0)
1.853 + {
1.854 + BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
1.855 + perror(outdir);
1.856 + goto err;
1.857 + }
1.858 +
1.859 + if (stat(outdir,&sb) != 0)
1.860 + {
1.861 + BIO_printf(bio_err,"unable to stat(%s)\n",outdir);
1.862 + perror(outdir);
1.863 + goto err;
1.864 + }
1.865 +#ifdef S_IFDIR
1.866 + if (!(sb.st_mode & S_IFDIR))
1.867 + {
1.868 + BIO_printf(bio_err,"%s need to be a directory\n",outdir);
1.869 + perror(outdir);
1.870 + goto err;
1.871 + }
1.872 +#endif
1.873 +#endif
1.874 + }
1.875 +
1.876 + /*****************************************************************/
1.877 + /* we need to load the database file */
1.878 + if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
1.879 + {
1.880 + lookup_fail(section,ENV_DATABASE);
1.881 + goto err;
1.882 + }
1.883 + db = load_index(dbfile, &db_attr);
1.884 + if (db == NULL) goto err;
1.885 +
1.886 + /* Lets check some fields */
1.887 + for (i=0; i<sk_num(db->db->data); i++)
1.888 + {
1.889 + pp=(const char **)sk_value(db->db->data,i);
1.890 + if ((pp[DB_type][0] != DB_TYPE_REV) &&
1.891 + (pp[DB_rev_date][0] != '\0'))
1.892 + {
1.893 + BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
1.894 + goto err;
1.895 + }
1.896 + if ((pp[DB_type][0] == DB_TYPE_REV) &&
1.897 + !make_revoked(NULL, pp[DB_rev_date]))
1.898 + {
1.899 + BIO_printf(bio_err," in entry %d\n", i+1);
1.900 + goto err;
1.901 + }
1.902 + if (!check_time_format((char *)pp[DB_exp_date]))
1.903 + {
1.904 + BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
1.905 + goto err;
1.906 + }
1.907 + p=pp[DB_serial];
1.908 + j=strlen(p);
1.909 + if (*p == '-')
1.910 + {
1.911 + p++;
1.912 + j--;
1.913 + }
1.914 + if ((j&1) || (j < 2))
1.915 + {
1.916 + BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
1.917 + goto err;
1.918 + }
1.919 + while (*p)
1.920 + {
1.921 + if (!( ((*p >= '0') && (*p <= '9')) ||
1.922 + ((*p >= 'A') && (*p <= 'F')) ||
1.923 + ((*p >= 'a') && (*p <= 'f'))) )
1.924 + {
1.925 + 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);
1.926 + goto err;
1.927 + }
1.928 + p++;
1.929 + }
1.930 + }
1.931 + if (verbose)
1.932 + {
1.933 + BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
1.934 +#ifdef OPENSSL_SYS_VMS
1.935 + {
1.936 + BIO *tmpbio = BIO_new(BIO_f_linebuffer());
1.937 + out = BIO_push(tmpbio, out);
1.938 + }
1.939 +#endif
1.940 + TXT_DB_write(out,db->db);
1.941 + BIO_printf(bio_err,"%d entries loaded from the database\n",
1.942 + db->db->data->num);
1.943 + BIO_printf(bio_err,"generating index\n");
1.944 + }
1.945 +
1.946 + if (!index_index(db)) goto err;
1.947 +
1.948 + /*****************************************************************/
1.949 + /* Update the db file for expired certificates */
1.950 + if (doupdatedb)
1.951 + {
1.952 + if (verbose)
1.953 + BIO_printf(bio_err, "Updating %s ...\n",
1.954 + dbfile);
1.955 +
1.956 + i = do_updatedb(db);
1.957 + if (i == -1)
1.958 + {
1.959 + BIO_printf(bio_err,"Malloc failure\n");
1.960 + goto err;
1.961 + }
1.962 + else if (i == 0)
1.963 + {
1.964 + if (verbose) BIO_printf(bio_err,
1.965 + "No entries found to mark expired\n");
1.966 + }
1.967 + else
1.968 + {
1.969 + if (!save_index(dbfile,"new",db)) goto err;
1.970 +
1.971 + if (!rotate_index(dbfile,"new","old")) goto err;
1.972 +
1.973 + if (verbose) BIO_printf(bio_err,
1.974 + "Done. %d entries marked as expired\n",i);
1.975 + }
1.976 + }
1.977 +
1.978 + /*****************************************************************/
1.979 + /* Read extentions config file */
1.980 + if (extfile)
1.981 + {
1.982 + extconf = NCONF_new(NULL);
1.983 + if (NCONF_load(extconf,extfile,&errorline) <= 0)
1.984 + {
1.985 + if (errorline <= 0)
1.986 + BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
1.987 + extfile);
1.988 + else
1.989 + BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n",
1.990 + errorline,extfile);
1.991 + ret = 1;
1.992 + goto err;
1.993 + }
1.994 +
1.995 + if (verbose)
1.996 + BIO_printf(bio_err, "Successfully loaded extensions file %s\n", extfile);
1.997 +
1.998 + /* We can have sections in the ext file */
1.999 + if (!extensions && !(extensions = NCONF_get_string(extconf, "default", "extensions")))
1.1000 + extensions = "default";
1.1001 + }
1.1002 +
1.1003 + /*****************************************************************/
1.1004 + if (req || gencrl)
1.1005 + {
1.1006 + if (outfile != NULL)
1.1007 + {
1.1008 + if (BIO_write_filename(Sout,outfile) <= 0)
1.1009 + {
1.1010 + perror(outfile);
1.1011 + goto err;
1.1012 + }
1.1013 + }
1.1014 + else
1.1015 + {
1.1016 + BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
1.1017 +#ifdef OPENSSL_SYS_VMS
1.1018 + {
1.1019 + BIO *tmpbio = BIO_new(BIO_f_linebuffer());
1.1020 + Sout = BIO_push(tmpbio, Sout);
1.1021 + }
1.1022 +#endif
1.1023 + }
1.1024 + }
1.1025 +
1.1026 + if ((md == NULL) && ((md=NCONF_get_string(conf,
1.1027 + section,ENV_DEFAULT_MD)) == NULL))
1.1028 + {
1.1029 + lookup_fail(section,ENV_DEFAULT_MD);
1.1030 + goto err;
1.1031 + }
1.1032 +
1.1033 + if ((dgst=EVP_get_digestbyname(md)) == NULL)
1.1034 + {
1.1035 + BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1.1036 + goto err;
1.1037 + }
1.1038 +
1.1039 + if (req)
1.1040 + {
1.1041 + if ((email_dn == 1) && ((tmp_email_dn=NCONF_get_string(conf,
1.1042 + section,ENV_DEFAULT_EMAIL_DN)) != NULL ))
1.1043 + {
1.1044 + if(strcmp(tmp_email_dn,"no") == 0)
1.1045 + email_dn=0;
1.1046 + }
1.1047 + if (verbose)
1.1048 + BIO_printf(bio_err,"message digest is %s\n",
1.1049 + OBJ_nid2ln(dgst->type));
1.1050 + if ((policy == NULL) && ((policy=NCONF_get_string(conf,
1.1051 + section,ENV_POLICY)) == NULL))
1.1052 + {
1.1053 + lookup_fail(section,ENV_POLICY);
1.1054 + goto err;
1.1055 + }
1.1056 + if (verbose)
1.1057 + BIO_printf(bio_err,"policy is %s\n",policy);
1.1058 +
1.1059 + if ((serialfile=NCONF_get_string(conf,section,ENV_SERIAL))
1.1060 + == NULL)
1.1061 + {
1.1062 + lookup_fail(section,ENV_SERIAL);
1.1063 + goto err;
1.1064 + }
1.1065 +
1.1066 + if (!extconf)
1.1067 + {
1.1068 + /* no '-extfile' option, so we look for extensions
1.1069 + * in the main configuration file */
1.1070 + if (!extensions)
1.1071 + {
1.1072 + extensions=NCONF_get_string(conf,section,
1.1073 + ENV_EXTENSIONS);
1.1074 + if (!extensions)
1.1075 + ERR_clear_error();
1.1076 + }
1.1077 + if (extensions)
1.1078 + {
1.1079 + /* Check syntax of file */
1.1080 + X509V3_CTX ctx;
1.1081 + X509V3_set_ctx_test(&ctx);
1.1082 + X509V3_set_nconf(&ctx, conf);
1.1083 + if (!X509V3_EXT_add_nconf(conf, &ctx, extensions,
1.1084 + NULL))
1.1085 + {
1.1086 + BIO_printf(bio_err,
1.1087 + "Error Loading extension section %s\n",
1.1088 + extensions);
1.1089 + ret = 1;
1.1090 + goto err;
1.1091 + }
1.1092 + }
1.1093 + }
1.1094 +
1.1095 + if (startdate == NULL)
1.1096 + {
1.1097 + startdate=NCONF_get_string(conf,section,
1.1098 + ENV_DEFAULT_STARTDATE);
1.1099 + if (startdate == NULL)
1.1100 + ERR_clear_error();
1.1101 + }
1.1102 + if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
1.1103 + {
1.1104 + BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
1.1105 + goto err;
1.1106 + }
1.1107 + if (startdate == NULL) startdate="today";
1.1108 +
1.1109 + if (enddate == NULL)
1.1110 + {
1.1111 + enddate=NCONF_get_string(conf,section,
1.1112 + ENV_DEFAULT_ENDDATE);
1.1113 + if (enddate == NULL)
1.1114 + ERR_clear_error();
1.1115 + }
1.1116 + if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
1.1117 + {
1.1118 + BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
1.1119 + goto err;
1.1120 + }
1.1121 +
1.1122 + if (days == 0)
1.1123 + {
1.1124 + if(!NCONF_get_number(conf,section, ENV_DEFAULT_DAYS, &days))
1.1125 + days = 0;
1.1126 + }
1.1127 + if (!enddate && (days == 0))
1.1128 + {
1.1129 + BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
1.1130 + goto err;
1.1131 + }
1.1132 +
1.1133 + if ((serial=load_serial(serialfile, create_ser, NULL)) == NULL)
1.1134 + {
1.1135 + BIO_printf(bio_err,"error while loading serial number\n");
1.1136 + goto err;
1.1137 + }
1.1138 + if (verbose)
1.1139 + {
1.1140 + if (BN_is_zero(serial))
1.1141 + BIO_printf(bio_err,"next serial number is 00\n");
1.1142 + else
1.1143 + {
1.1144 + if ((f=BN_bn2hex(serial)) == NULL) goto err;
1.1145 + BIO_printf(bio_err,"next serial number is %s\n",f);
1.1146 + OPENSSL_free(f);
1.1147 + }
1.1148 + }
1.1149 +
1.1150 + if ((attribs=NCONF_get_section(conf,policy)) == NULL)
1.1151 + {
1.1152 + BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
1.1153 + goto err;
1.1154 + }
1.1155 +
1.1156 + if ((cert_sk=sk_X509_new_null()) == NULL)
1.1157 + {
1.1158 + BIO_printf(bio_err,"Memory allocation failure\n");
1.1159 + goto err;
1.1160 + }
1.1161 + if (spkac_file != NULL)
1.1162 + {
1.1163 + total++;
1.1164 + j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
1.1165 + serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,extensions,
1.1166 + conf,verbose,certopt,nameopt,default_op,ext_copy);
1.1167 + if (j < 0) goto err;
1.1168 + if (j > 0)
1.1169 + {
1.1170 + total_done++;
1.1171 + BIO_printf(bio_err,"\n");
1.1172 + if (!BN_add_word(serial,1)) goto err;
1.1173 + if (!sk_X509_push(cert_sk,x))
1.1174 + {
1.1175 + BIO_printf(bio_err,"Memory allocation failure\n");
1.1176 + goto err;
1.1177 + }
1.1178 + if (outfile)
1.1179 + {
1.1180 + output_der = 1;
1.1181 + batch = 1;
1.1182 + }
1.1183 + }
1.1184 + }
1.1185 + if (ss_cert_file != NULL)
1.1186 + {
1.1187 + total++;
1.1188 + j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
1.1189 + db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
1.1190 + extensions,conf,verbose, certopt, nameopt,
1.1191 + default_op, ext_copy, e);
1.1192 + if (j < 0) goto err;
1.1193 + if (j > 0)
1.1194 + {
1.1195 + total_done++;
1.1196 + BIO_printf(bio_err,"\n");
1.1197 + if (!BN_add_word(serial,1)) goto err;
1.1198 + if (!sk_X509_push(cert_sk,x))
1.1199 + {
1.1200 + BIO_printf(bio_err,"Memory allocation failure\n");
1.1201 + goto err;
1.1202 + }
1.1203 + }
1.1204 + }
1.1205 + if (infile != NULL)
1.1206 + {
1.1207 + total++;
1.1208 + j=certify(&x,infile,pkey,x509p,dgst,attribs,db,
1.1209 + serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
1.1210 + extensions,conf,verbose, certopt, nameopt,
1.1211 + default_op, ext_copy, selfsign);
1.1212 + if (j < 0) goto err;
1.1213 + if (j > 0)
1.1214 + {
1.1215 + total_done++;
1.1216 + BIO_printf(bio_err,"\n");
1.1217 + if (!BN_add_word(serial,1)) goto err;
1.1218 + if (!sk_X509_push(cert_sk,x))
1.1219 + {
1.1220 + BIO_printf(bio_err,"Memory allocation failure\n");
1.1221 + goto err;
1.1222 + }
1.1223 + }
1.1224 + }
1.1225 + for (i=0; i<argc; i++)
1.1226 + {
1.1227 + total++;
1.1228 + j=certify(&x,argv[i],pkey,x509p,dgst,attribs,db,
1.1229 + serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
1.1230 + extensions,conf,verbose, certopt, nameopt,
1.1231 + default_op, ext_copy, selfsign);
1.1232 + if (j < 0) goto err;
1.1233 + if (j > 0)
1.1234 + {
1.1235 + total_done++;
1.1236 + BIO_printf(bio_err,"\n");
1.1237 + if (!BN_add_word(serial,1)) goto err;
1.1238 + if (!sk_X509_push(cert_sk,x))
1.1239 + {
1.1240 + BIO_printf(bio_err,"Memory allocation failure\n");
1.1241 + goto err;
1.1242 + }
1.1243 + }
1.1244 + }
1.1245 + /* we have a stack of newly certified certificates
1.1246 + * and a data base and serial number that need
1.1247 + * updating */
1.1248 +
1.1249 + if (sk_X509_num(cert_sk) > 0)
1.1250 + {
1.1251 + if (!batch)
1.1252 + {
1.1253 + BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
1.1254 + (void)BIO_flush(bio_err);
1.1255 + buf[0][0]='\0';
1.1256 + fgets(buf[0],10,stdin);
1.1257 + if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
1.1258 + {
1.1259 + BIO_printf(bio_err,"CERTIFICATION CANCELED\n");
1.1260 + ret=0;
1.1261 + goto err;
1.1262 + }
1.1263 + }
1.1264 +
1.1265 + BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
1.1266 +
1.1267 + if (!save_serial(serialfile,"new",serial,NULL)) goto err;
1.1268 +
1.1269 + if (!save_index(dbfile, "new", db)) goto err;
1.1270 + }
1.1271 +
1.1272 + if (verbose)
1.1273 + BIO_printf(bio_err,"writing new certificates\n");
1.1274 + for (i=0; i<sk_X509_num(cert_sk); i++)
1.1275 + {
1.1276 + int k;
1.1277 + char *n;
1.1278 +
1.1279 + x=sk_X509_value(cert_sk,i);
1.1280 +
1.1281 + j=x->cert_info->serialNumber->length;
1.1282 + p=(const char *)x->cert_info->serialNumber->data;
1.1283 +
1.1284 + if(strlen(outdir) >= (size_t)(j ? BSIZE-j*2-6 : BSIZE-8))
1.1285 + {
1.1286 + BIO_printf(bio_err,"certificate file name too long\n");
1.1287 + goto err;
1.1288 + }
1.1289 +
1.1290 + strcpy(buf[2],outdir);
1.1291 +
1.1292 +#ifndef OPENSSL_SYS_VMS
1.1293 + BUF_strlcat(buf[2],"/",sizeof(buf[2]));
1.1294 +#endif
1.1295 +
1.1296 + n=(char *)&(buf[2][strlen(buf[2])]);
1.1297 + if (j > 0)
1.1298 + {
1.1299 + for (k=0; k<j; k++)
1.1300 + {
1.1301 + if (n >= &(buf[2][sizeof(buf[2])]))
1.1302 + break;
1.1303 + BIO_snprintf(n,
1.1304 + &buf[2][0] + sizeof(buf[2]) - n,
1.1305 + "%02X",(unsigned char)*(p++));
1.1306 + n+=2;
1.1307 + }
1.1308 + }
1.1309 + else
1.1310 + {
1.1311 + *(n++)='0';
1.1312 + *(n++)='0';
1.1313 + }
1.1314 + *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
1.1315 + *n='\0';
1.1316 + if (verbose)
1.1317 + BIO_printf(bio_err,"writing %s\n",buf[2]);
1.1318 +
1.1319 + if (BIO_write_filename(Cout,buf[2]) <= 0)
1.1320 + {
1.1321 + perror(buf[2]);
1.1322 + goto err;
1.1323 + }
1.1324 + write_new_certificate(Cout,x, 0, notext);
1.1325 + write_new_certificate(Sout,x, output_der, notext);
1.1326 + }
1.1327 +
1.1328 + if (sk_X509_num(cert_sk))
1.1329 + {
1.1330 + /* Rename the database and the serial file */
1.1331 + if (!rotate_serial(serialfile,"new","old")) goto err;
1.1332 +
1.1333 + if (!rotate_index(dbfile,"new","old")) goto err;
1.1334 +
1.1335 + BIO_printf(bio_err,"Data Base Updated\n");
1.1336 + }
1.1337 + }
1.1338 +
1.1339 + /*****************************************************************/
1.1340 + if (gencrl)
1.1341 + {
1.1342 + int crl_v2 = 0;
1.1343 + if (!crl_ext)
1.1344 + {
1.1345 + crl_ext=NCONF_get_string(conf,section,ENV_CRLEXT);
1.1346 + if (!crl_ext)
1.1347 + ERR_clear_error();
1.1348 + }
1.1349 + if (crl_ext)
1.1350 + {
1.1351 + /* Check syntax of file */
1.1352 + X509V3_CTX ctx;
1.1353 + X509V3_set_ctx_test(&ctx);
1.1354 + X509V3_set_nconf(&ctx, conf);
1.1355 + if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL))
1.1356 + {
1.1357 + BIO_printf(bio_err,
1.1358 + "Error Loading CRL extension section %s\n",
1.1359 + crl_ext);
1.1360 + ret = 1;
1.1361 + goto err;
1.1362 + }
1.1363 + }
1.1364 +
1.1365 + if ((crlnumberfile=NCONF_get_string(conf,section,ENV_CRLNUMBER))
1.1366 + != NULL)
1.1367 + if ((crlnumber=load_serial(crlnumberfile,0,NULL)) == NULL)
1.1368 + {
1.1369 + BIO_printf(bio_err,"error while loading CRL number\n");
1.1370 + goto err;
1.1371 + }
1.1372 +
1.1373 + if (!crldays && !crlhours)
1.1374 + {
1.1375 + if (!NCONF_get_number(conf,section,
1.1376 + ENV_DEFAULT_CRL_DAYS, &crldays))
1.1377 + crldays = 0;
1.1378 + if (!NCONF_get_number(conf,section,
1.1379 + ENV_DEFAULT_CRL_HOURS, &crlhours))
1.1380 + crlhours = 0;
1.1381 + }
1.1382 + if ((crldays == 0) && (crlhours == 0))
1.1383 + {
1.1384 + BIO_printf(bio_err,"cannot lookup how long until the next CRL is issued\n");
1.1385 + goto err;
1.1386 + }
1.1387 +
1.1388 + if (verbose) BIO_printf(bio_err,"making CRL\n");
1.1389 + if ((crl=X509_CRL_new()) == NULL) goto err;
1.1390 + if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) goto err;
1.1391 +
1.1392 + tmptm = ASN1_TIME_new();
1.1393 + if (!tmptm) goto err;
1.1394 + X509_gmtime_adj(tmptm,0);
1.1395 + X509_CRL_set_lastUpdate(crl, tmptm);
1.1396 + X509_gmtime_adj(tmptm,(crldays*24+crlhours)*60*60);
1.1397 + X509_CRL_set_nextUpdate(crl, tmptm);
1.1398 +
1.1399 + ASN1_TIME_free(tmptm);
1.1400 +
1.1401 + for (i=0; i<sk_num(db->db->data); i++)
1.1402 + {
1.1403 + pp=(const char **)sk_value(db->db->data,i);
1.1404 + if (pp[DB_type][0] == DB_TYPE_REV)
1.1405 + {
1.1406 + if ((r=X509_REVOKED_new()) == NULL) goto err;
1.1407 + j = make_revoked(r, pp[DB_rev_date]);
1.1408 + if (!j) goto err;
1.1409 + if (j == 2) crl_v2 = 1;
1.1410 + if (!BN_hex2bn(&serial, pp[DB_serial]))
1.1411 + goto err;
1.1412 + tmpser = BN_to_ASN1_INTEGER(serial, NULL);
1.1413 + BN_free(serial);
1.1414 + serial = NULL;
1.1415 + if (!tmpser)
1.1416 + goto err;
1.1417 + X509_REVOKED_set_serialNumber(r, tmpser);
1.1418 + ASN1_INTEGER_free(tmpser);
1.1419 + X509_CRL_add0_revoked(crl,r);
1.1420 + }
1.1421 + }
1.1422 +
1.1423 + /* sort the data so it will be written in serial
1.1424 + * number order */
1.1425 + X509_CRL_sort(crl);
1.1426 +
1.1427 + /* we now have a CRL */
1.1428 + if (verbose) BIO_printf(bio_err,"signing CRL\n");
1.1429 +#ifndef OPENSSL_NO_DSA
1.1430 + if (pkey->type == EVP_PKEY_DSA)
1.1431 + dgst=EVP_dss1();
1.1432 + else
1.1433 +#endif
1.1434 +#ifndef OPENSSL_NO_ECDSA
1.1435 + if (pkey->type == EVP_PKEY_EC)
1.1436 + dgst=EVP_ecdsa();
1.1437 +#endif
1.1438 +
1.1439 + /* Add any extensions asked for */
1.1440 +
1.1441 + if (crl_ext || crlnumberfile != NULL)
1.1442 + {
1.1443 + X509V3_CTX crlctx;
1.1444 + X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1.1445 + X509V3_set_nconf(&crlctx, conf);
1.1446 +
1.1447 + if (crl_ext)
1.1448 + if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx,
1.1449 + crl_ext, crl)) goto err;
1.1450 + if (crlnumberfile != NULL)
1.1451 + {
1.1452 + tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL);
1.1453 + if (!tmpser) goto err;
1.1454 + X509_CRL_add1_ext_i2d(crl,NID_crl_number,tmpser,0,0);
1.1455 + ASN1_INTEGER_free(tmpser);
1.1456 + crl_v2 = 1;
1.1457 + if (!BN_add_word(crlnumber,1)) goto err;
1.1458 + }
1.1459 + }
1.1460 + if (crl_ext || crl_v2)
1.1461 + {
1.1462 + if (!X509_CRL_set_version(crl, 1))
1.1463 + goto err; /* version 2 CRL */
1.1464 + }
1.1465 +
1.1466 +
1.1467 + if (crlnumberfile != NULL) /* we have a CRL number that need updating */
1.1468 + if (!save_serial(crlnumberfile,"new",crlnumber,NULL)) goto err;
1.1469 +
1.1470 + if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1.1471 +
1.1472 + PEM_write_bio_X509_CRL(Sout,crl);
1.1473 +
1.1474 + if (crlnumberfile != NULL) /* Rename the crlnumber file */
1.1475 + if (!rotate_serial(crlnumberfile,"new","old")) goto err;
1.1476 +
1.1477 + }
1.1478 + /*****************************************************************/
1.1479 + if (dorevoke)
1.1480 + {
1.1481 + if (infile == NULL)
1.1482 + {
1.1483 + BIO_printf(bio_err,"no input files\n");
1.1484 + goto err;
1.1485 + }
1.1486 + else
1.1487 + {
1.1488 + X509 *revcert;
1.1489 + revcert=load_cert(bio_err, infile, FORMAT_PEM,
1.1490 + NULL, e, infile);
1.1491 + if (revcert == NULL)
1.1492 + goto err;
1.1493 + j=do_revoke(revcert,db, rev_type, rev_arg);
1.1494 + if (j <= 0) goto err;
1.1495 + X509_free(revcert);
1.1496 +
1.1497 + if (!save_index(dbfile, "new", db)) goto err;
1.1498 +
1.1499 + if (!rotate_index(dbfile, "new", "old")) goto err;
1.1500 +
1.1501 + BIO_printf(bio_err,"Data Base Updated\n");
1.1502 + }
1.1503 + }
1.1504 + /*****************************************************************/
1.1505 + ret=0;
1.1506 +err:
1.1507 + if(tofree)
1.1508 + OPENSSL_free(tofree);
1.1509 + BIO_free_all(Cout);
1.1510 + BIO_free_all(Sout);
1.1511 + BIO_free_all(out);
1.1512 + BIO_free_all(in);
1.1513 +
1.1514 + if (cert_sk)
1.1515 + sk_X509_pop_free(cert_sk,X509_free);
1.1516 +
1.1517 + if (ret) ERR_print_errors(bio_err);
1.1518 + app_RAND_write_file(randfile, bio_err);
1.1519 + if (free_key && key)
1.1520 + OPENSSL_free(key);
1.1521 + BN_free(serial);
1.1522 + free_index(db);
1.1523 + EVP_PKEY_free(pkey);
1.1524 + if (x509) X509_free(x509);
1.1525 + X509_CRL_free(crl);
1.1526 + NCONF_free(conf);
1.1527 + NCONF_free(extconf);
1.1528 + OBJ_cleanup();
1.1529 + apps_shutdown();
1.1530 + OPENSSL_EXIT(ret);
1.1531 + }
1.1532 +
1.1533 +static void lookup_fail(const char *name, const char *tag)
1.1534 + {
1.1535 + BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1.1536 + }
1.1537 +
1.1538 +static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1.1539 + const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
1.1540 + BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate,
1.1541 + long days, int batch, char *ext_sect, CONF *lconf, int verbose,
1.1542 + unsigned long certopt, unsigned long nameopt, int default_op,
1.1543 + int ext_copy, int selfsign)
1.1544 + {
1.1545 + X509_REQ *req=NULL;
1.1546 + BIO *in=NULL;
1.1547 + EVP_PKEY *pktmp=NULL;
1.1548 + int ok= -1,i;
1.1549 +
1.1550 + in=BIO_new(BIO_s_file());
1.1551 +
1.1552 + if (BIO_read_filename(in,infile) <= 0)
1.1553 + {
1.1554 + perror(infile);
1.1555 + goto err;
1.1556 + }
1.1557 + if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
1.1558 + {
1.1559 + BIO_printf(bio_err,"Error reading certificate request in %s\n",
1.1560 + infile);
1.1561 + goto err;
1.1562 + }
1.1563 + if (verbose)
1.1564 + X509_REQ_print(bio_err,req);
1.1565 +
1.1566 + BIO_printf(bio_err,"Check that the request matches the signature\n");
1.1567 +
1.1568 + if (selfsign && !X509_REQ_check_private_key(req,pkey))
1.1569 + {
1.1570 + BIO_printf(bio_err,"Certificate request and CA private key do not match\n");
1.1571 + ok=0;
1.1572 + goto err;
1.1573 + }
1.1574 + if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
1.1575 + {
1.1576 + BIO_printf(bio_err,"error unpacking public key\n");
1.1577 + goto err;
1.1578 + }
1.1579 + i=X509_REQ_verify(req,pktmp);
1.1580 + EVP_PKEY_free(pktmp);
1.1581 + if (i < 0)
1.1582 + {
1.1583 + ok=0;
1.1584 + BIO_printf(bio_err,"Signature verification problems....\n");
1.1585 + goto err;
1.1586 + }
1.1587 + if (i == 0)
1.1588 + {
1.1589 + ok=0;
1.1590 + BIO_printf(bio_err,"Signature did not match the certificate request\n");
1.1591 + goto err;
1.1592 + }
1.1593 + else
1.1594 + BIO_printf(bio_err,"Signature ok\n");
1.1595 +
1.1596 + ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn, email_dn,
1.1597 + startdate,enddate,days,batch,verbose,req,ext_sect,lconf,
1.1598 + certopt, nameopt, default_op, ext_copy, selfsign);
1.1599 +
1.1600 +err:
1.1601 + if (req != NULL) X509_REQ_free(req);
1.1602 + if (in != NULL) BIO_free(in);
1.1603 + return(ok);
1.1604 + }
1.1605 +
1.1606 +static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1.1607 + const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
1.1608 + BIGNUM *serial, char *subj, unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate,
1.1609 + long days, int batch, char *ext_sect, CONF *lconf, int verbose,
1.1610 + unsigned long certopt, unsigned long nameopt, int default_op,
1.1611 + int ext_copy, ENGINE *e)
1.1612 + {
1.1613 + X509 *req=NULL;
1.1614 + X509_REQ *rreq=NULL;
1.1615 + EVP_PKEY *pktmp=NULL;
1.1616 + int ok= -1,i;
1.1617 +
1.1618 + if ((req=load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL)
1.1619 + goto err;
1.1620 + if (verbose)
1.1621 + X509_print(bio_err,req);
1.1622 +
1.1623 + BIO_printf(bio_err,"Check that the request matches the signature\n");
1.1624 +
1.1625 + if ((pktmp=X509_get_pubkey(req)) == NULL)
1.1626 + {
1.1627 + BIO_printf(bio_err,"error unpacking public key\n");
1.1628 + goto err;
1.1629 + }
1.1630 + i=X509_verify(req,pktmp);
1.1631 + EVP_PKEY_free(pktmp);
1.1632 + if (i < 0)
1.1633 + {
1.1634 + ok=0;
1.1635 + BIO_printf(bio_err,"Signature verification problems....\n");
1.1636 + goto err;
1.1637 + }
1.1638 + if (i == 0)
1.1639 + {
1.1640 + ok=0;
1.1641 + BIO_printf(bio_err,"Signature did not match the certificate\n");
1.1642 + goto err;
1.1643 + }
1.1644 + else
1.1645 + BIO_printf(bio_err,"Signature ok\n");
1.1646 +
1.1647 + if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
1.1648 + goto err;
1.1649 +
1.1650 + ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,
1.1651 + days,batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op,
1.1652 + ext_copy, 0);
1.1653 +
1.1654 +err:
1.1655 + if (rreq != NULL) X509_REQ_free(rreq);
1.1656 + if (req != NULL) X509_free(req);
1.1657 + return(ok);
1.1658 + }
1.1659 +
1.1660 +static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1.1661 + STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj,
1.1662 + unsigned long chtype, int multirdn,
1.1663 + int email_dn, char *startdate, char *enddate, long days, int batch,
1.1664 + int verbose, X509_REQ *req, char *ext_sect, CONF *lconf,
1.1665 + unsigned long certopt, unsigned long nameopt, int default_op,
1.1666 + int ext_copy, int selfsign)
1.1667 + {
1.1668 + X509_NAME *name=NULL,*CAname=NULL,*subject=NULL, *dn_subject=NULL;
1.1669 + ASN1_UTCTIME *tm,*tmptm;
1.1670 + ASN1_STRING *str,*str2;
1.1671 + ASN1_OBJECT *obj;
1.1672 + X509 *ret=NULL;
1.1673 + X509_CINF *ci;
1.1674 + X509_NAME_ENTRY *ne;
1.1675 + X509_NAME_ENTRY *tne,*push;
1.1676 + EVP_PKEY *pktmp;
1.1677 + int ok= -1,i,j,last,nid;
1.1678 + const char *p;
1.1679 + CONF_VALUE *cv;
1.1680 + char *row[DB_NUMBER],**rrow=NULL,**irow=NULL;
1.1681 + char buf[25];
1.1682 +
1.1683 + tmptm=ASN1_UTCTIME_new();
1.1684 + if (tmptm == NULL)
1.1685 + {
1.1686 + BIO_printf(bio_err,"malloc error\n");
1.1687 + return(0);
1.1688 + }
1.1689 +
1.1690 + for (i=0; i<DB_NUMBER; i++)
1.1691 + row[i]=NULL;
1.1692 +
1.1693 + if (subj)
1.1694 + {
1.1695 + X509_NAME *n = parse_name(subj, chtype, multirdn);
1.1696 +
1.1697 + if (!n)
1.1698 + {
1.1699 + ERR_print_errors(bio_err);
1.1700 + goto err;
1.1701 + }
1.1702 + X509_REQ_set_subject_name(req,n);
1.1703 + req->req_info->enc.modified = 1;
1.1704 + X509_NAME_free(n);
1.1705 + }
1.1706 +
1.1707 + if (default_op)
1.1708 + BIO_printf(bio_err,"The Subject's Distinguished Name is as follows\n");
1.1709 +
1.1710 + name=X509_REQ_get_subject_name(req);
1.1711 + for (i=0; i<X509_NAME_entry_count(name); i++)
1.1712 + {
1.1713 + ne= X509_NAME_get_entry(name,i);
1.1714 + str=X509_NAME_ENTRY_get_data(ne);
1.1715 + obj=X509_NAME_ENTRY_get_object(ne);
1.1716 +
1.1717 + if (msie_hack)
1.1718 + {
1.1719 + /* assume all type should be strings */
1.1720 + nid=OBJ_obj2nid(ne->object);
1.1721 +
1.1722 + if (str->type == V_ASN1_UNIVERSALSTRING)
1.1723 + ASN1_UNIVERSALSTRING_to_string(str);
1.1724 +
1.1725 + if ((str->type == V_ASN1_IA5STRING) &&
1.1726 + (nid != NID_pkcs9_emailAddress))
1.1727 + str->type=V_ASN1_T61STRING;
1.1728 +
1.1729 + if ((nid == NID_pkcs9_emailAddress) &&
1.1730 + (str->type == V_ASN1_PRINTABLESTRING))
1.1731 + str->type=V_ASN1_IA5STRING;
1.1732 + }
1.1733 +
1.1734 + /* If no EMAIL is wanted in the subject */
1.1735 + if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn))
1.1736 + continue;
1.1737 +
1.1738 + /* check some things */
1.1739 + if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1.1740 + (str->type != V_ASN1_IA5STRING))
1.1741 + {
1.1742 + BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
1.1743 + goto err;
1.1744 + }
1.1745 + if ((str->type != V_ASN1_BMPSTRING) && (str->type != V_ASN1_UTF8STRING))
1.1746 + {
1.1747 + j=ASN1_PRINTABLE_type(str->data,str->length);
1.1748 + if ( ((j == V_ASN1_T61STRING) &&
1.1749 + (str->type != V_ASN1_T61STRING)) ||
1.1750 + ((j == V_ASN1_IA5STRING) &&
1.1751 + (str->type == V_ASN1_PRINTABLESTRING)))
1.1752 + {
1.1753 + BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1.1754 + goto err;
1.1755 + }
1.1756 + }
1.1757 +
1.1758 + if (default_op)
1.1759 + old_entry_print(bio_err, obj, str);
1.1760 + }
1.1761 +
1.1762 + /* Ok, now we check the 'policy' stuff. */
1.1763 + if ((subject=X509_NAME_new()) == NULL)
1.1764 + {
1.1765 + BIO_printf(bio_err,"Memory allocation failure\n");
1.1766 + goto err;
1.1767 + }
1.1768 +
1.1769 + /* take a copy of the issuer name before we mess with it. */
1.1770 + if (selfsign)
1.1771 + CAname=X509_NAME_dup(name);
1.1772 + else
1.1773 + CAname=X509_NAME_dup(x509->cert_info->subject);
1.1774 + if (CAname == NULL) goto err;
1.1775 + str=str2=NULL;
1.1776 +
1.1777 + for (i=0; i<sk_CONF_VALUE_num(policy); i++)
1.1778 + {
1.1779 + cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
1.1780 + if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
1.1781 + {
1.1782 + BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
1.1783 + goto err;
1.1784 + }
1.1785 + obj=OBJ_nid2obj(j);
1.1786 +
1.1787 + last= -1;
1.1788 + for (;;)
1.1789 + {
1.1790 + /* lookup the object in the supplied name list */
1.1791 + j=X509_NAME_get_index_by_OBJ(name,obj,last);
1.1792 + if (j < 0)
1.1793 + {
1.1794 + if (last != -1) break;
1.1795 + tne=NULL;
1.1796 + }
1.1797 + else
1.1798 + {
1.1799 + tne=X509_NAME_get_entry(name,j);
1.1800 + }
1.1801 + last=j;
1.1802 +
1.1803 + /* depending on the 'policy', decide what to do. */
1.1804 + push=NULL;
1.1805 + if (strcmp(cv->value,"optional") == 0)
1.1806 + {
1.1807 + if (tne != NULL)
1.1808 + push=tne;
1.1809 + }
1.1810 + else if (strcmp(cv->value,"supplied") == 0)
1.1811 + {
1.1812 + if (tne == NULL)
1.1813 + {
1.1814 + BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
1.1815 + goto err;
1.1816 + }
1.1817 + else
1.1818 + push=tne;
1.1819 + }
1.1820 + else if (strcmp(cv->value,"match") == 0)
1.1821 + {
1.1822 + int last2;
1.1823 +
1.1824 + if (tne == NULL)
1.1825 + {
1.1826 + BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
1.1827 + goto err;
1.1828 + }
1.1829 +
1.1830 + last2= -1;
1.1831 +
1.1832 +again2:
1.1833 + j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
1.1834 + if ((j < 0) && (last2 == -1))
1.1835 + {
1.1836 + BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
1.1837 + goto err;
1.1838 + }
1.1839 + if (j >= 0)
1.1840 + {
1.1841 + push=X509_NAME_get_entry(CAname,j);
1.1842 + str=X509_NAME_ENTRY_get_data(tne);
1.1843 + str2=X509_NAME_ENTRY_get_data(push);
1.1844 + last2=j;
1.1845 + if (ASN1_STRING_cmp(str,str2) != 0)
1.1846 + goto again2;
1.1847 + }
1.1848 + if (j < 0)
1.1849 + {
1.1850 + 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));
1.1851 + goto err;
1.1852 + }
1.1853 + }
1.1854 + else
1.1855 + {
1.1856 + BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
1.1857 + goto err;
1.1858 + }
1.1859 +
1.1860 + if (push != NULL)
1.1861 + {
1.1862 + if (!X509_NAME_add_entry(subject,push, -1, 0))
1.1863 + {
1.1864 + if (push != NULL)
1.1865 + X509_NAME_ENTRY_free(push);
1.1866 + BIO_printf(bio_err,"Memory allocation failure\n");
1.1867 + goto err;
1.1868 + }
1.1869 + }
1.1870 + if (j < 0) break;
1.1871 + }
1.1872 + }
1.1873 +
1.1874 + if (preserve)
1.1875 + {
1.1876 + X509_NAME_free(subject);
1.1877 + /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */
1.1878 + subject=X509_NAME_dup(name);
1.1879 + if (subject == NULL) goto err;
1.1880 + }
1.1881 +
1.1882 + if (verbose)
1.1883 + BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
1.1884 +
1.1885 + /* Build the correct Subject if no e-mail is wanted in the subject */
1.1886 + /* and add it later on because of the method extensions are added (altName) */
1.1887 +
1.1888 + if (email_dn)
1.1889 + dn_subject = subject;
1.1890 + else
1.1891 + {
1.1892 + X509_NAME_ENTRY *tmpne;
1.1893 + /* Its best to dup the subject DN and then delete any email
1.1894 + * addresses because this retains its structure.
1.1895 + */
1.1896 + if (!(dn_subject = X509_NAME_dup(subject)))
1.1897 + {
1.1898 + BIO_printf(bio_err,"Memory allocation failure\n");
1.1899 + goto err;
1.1900 + }
1.1901 + while((i = X509_NAME_get_index_by_NID(dn_subject,
1.1902 + NID_pkcs9_emailAddress, -1)) >= 0)
1.1903 + {
1.1904 + tmpne = X509_NAME_get_entry(dn_subject, i);
1.1905 + X509_NAME_delete_entry(dn_subject, i);
1.1906 + X509_NAME_ENTRY_free(tmpne);
1.1907 + }
1.1908 + }
1.1909 +
1.1910 + if (BN_is_zero(serial))
1.1911 + row[DB_serial]=BUF_strdup("00");
1.1912 + else
1.1913 + row[DB_serial]=BN_bn2hex(serial);
1.1914 + if (row[DB_serial] == NULL)
1.1915 + {
1.1916 + BIO_printf(bio_err,"Memory allocation failure\n");
1.1917 + goto err;
1.1918 + }
1.1919 +
1.1920 + if (db->attributes.unique_subject)
1.1921 + {
1.1922 + rrow=TXT_DB_get_by_index(db->db,DB_name,row);
1.1923 + if (rrow != NULL)
1.1924 + {
1.1925 + BIO_printf(bio_err,
1.1926 + "ERROR:There is already a certificate for %s\n",
1.1927 + row[DB_name]);
1.1928 + }
1.1929 + }
1.1930 + if (rrow == NULL)
1.1931 + {
1.1932 + rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
1.1933 + if (rrow != NULL)
1.1934 + {
1.1935 + BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
1.1936 + row[DB_serial]);
1.1937 + BIO_printf(bio_err," check the database/serial_file for corruption\n");
1.1938 + }
1.1939 + }
1.1940 +
1.1941 + if (rrow != NULL)
1.1942 + {
1.1943 + BIO_printf(bio_err,
1.1944 + "The matching entry has the following details\n");
1.1945 + if (rrow[DB_type][0] == 'E')
1.1946 + p="Expired";
1.1947 + else if (rrow[DB_type][0] == 'R')
1.1948 + p="Revoked";
1.1949 + else if (rrow[DB_type][0] == 'V')
1.1950 + p="Valid";
1.1951 + else
1.1952 + p="\ninvalid type, Data base error\n";
1.1953 + BIO_printf(bio_err,"Type :%s\n",p);;
1.1954 + if (rrow[DB_type][0] == 'R')
1.1955 + {
1.1956 + p=rrow[DB_exp_date]; if (p == NULL) p="undef";
1.1957 + BIO_printf(bio_err,"Was revoked on:%s\n",p);
1.1958 + }
1.1959 + p=rrow[DB_exp_date]; if (p == NULL) p="undef";
1.1960 + BIO_printf(bio_err,"Expires on :%s\n",p);
1.1961 + p=rrow[DB_serial]; if (p == NULL) p="undef";
1.1962 + BIO_printf(bio_err,"Serial Number :%s\n",p);
1.1963 + p=rrow[DB_file]; if (p == NULL) p="undef";
1.1964 + BIO_printf(bio_err,"File name :%s\n",p);
1.1965 + p=rrow[DB_name]; if (p == NULL) p="undef";
1.1966 + BIO_printf(bio_err,"Subject Name :%s\n",p);
1.1967 + ok= -1; /* This is now a 'bad' error. */
1.1968 + goto err;
1.1969 + }
1.1970 +
1.1971 + /* We are now totally happy, lets make and sign the certificate */
1.1972 + if (verbose)
1.1973 + BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
1.1974 +
1.1975 + if ((ret=X509_new()) == NULL) goto err;
1.1976 + ci=ret->cert_info;
1.1977 +
1.1978 +#ifdef X509_V3
1.1979 + /* Make it an X509 v3 certificate. */
1.1980 + if (!X509_set_version(ret,2)) goto err;
1.1981 +#endif
1.1982 +
1.1983 + if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
1.1984 + goto err;
1.1985 + if (selfsign)
1.1986 + {
1.1987 + if (!X509_set_issuer_name(ret,subject))
1.1988 + goto err;
1.1989 + }
1.1990 + else
1.1991 + {
1.1992 + if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
1.1993 + goto err;
1.1994 + }
1.1995 +
1.1996 + if (strcmp(startdate,"today") == 0)
1.1997 + X509_gmtime_adj(X509_get_notBefore(ret),0);
1.1998 + else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
1.1999 +
1.2000 + if (enddate == NULL)
1.2001 + X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
1.2002 + else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
1.2003 +
1.2004 + if (!X509_set_subject_name(ret,subject)) goto err;
1.2005 +
1.2006 + pktmp=X509_REQ_get_pubkey(req);
1.2007 + i = X509_set_pubkey(ret,pktmp);
1.2008 + EVP_PKEY_free(pktmp);
1.2009 + if (!i) goto err;
1.2010 +
1.2011 + /* Lets add the extensions, if there are any */
1.2012 + if (ext_sect)
1.2013 + {
1.2014 + X509V3_CTX ctx;
1.2015 + if (ci->version == NULL)
1.2016 + if ((ci->version=ASN1_INTEGER_new()) == NULL)
1.2017 + goto err;
1.2018 + ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
1.2019 +
1.2020 + /* Free the current entries if any, there should not
1.2021 + * be any I believe */
1.2022 + if (ci->extensions != NULL)
1.2023 + sk_X509_EXTENSION_pop_free(ci->extensions,
1.2024 + X509_EXTENSION_free);
1.2025 +
1.2026 + ci->extensions = NULL;
1.2027 +
1.2028 + /* Initialize the context structure */
1.2029 + if (selfsign)
1.2030 + X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0);
1.2031 + else
1.2032 + X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
1.2033 +
1.2034 + if (extconf)
1.2035 + {
1.2036 + if (verbose)
1.2037 + BIO_printf(bio_err, "Extra configuration file found\n");
1.2038 +
1.2039 + /* Use the extconf configuration db LHASH */
1.2040 + X509V3_set_nconf(&ctx, extconf);
1.2041 +
1.2042 + /* Test the structure (needed?) */
1.2043 + /* X509V3_set_ctx_test(&ctx); */
1.2044 +
1.2045 + /* Adds exts contained in the configuration file */
1.2046 + if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect,ret))
1.2047 + {
1.2048 + BIO_printf(bio_err,
1.2049 + "ERROR: adding extensions in section %s\n",
1.2050 + ext_sect);
1.2051 + ERR_print_errors(bio_err);
1.2052 + goto err;
1.2053 + }
1.2054 + if (verbose)
1.2055 + BIO_printf(bio_err, "Successfully added extensions from file.\n");
1.2056 + }
1.2057 + else if (ext_sect)
1.2058 + {
1.2059 + /* We found extensions to be set from config file */
1.2060 + X509V3_set_nconf(&ctx, lconf);
1.2061 +
1.2062 + if(!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret))
1.2063 + {
1.2064 + BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
1.2065 + ERR_print_errors(bio_err);
1.2066 + goto err;
1.2067 + }
1.2068 +
1.2069 + if (verbose)
1.2070 + BIO_printf(bio_err, "Successfully added extensions from config\n");
1.2071 + }
1.2072 + }
1.2073 +
1.2074 + /* Copy extensions from request (if any) */
1.2075 +
1.2076 + if (!copy_extensions(ret, req, ext_copy))
1.2077 + {
1.2078 + BIO_printf(bio_err, "ERROR: adding extensions from request\n");
1.2079 + ERR_print_errors(bio_err);
1.2080 + goto err;
1.2081 + }
1.2082 +
1.2083 + /* Set the right value for the noemailDN option */
1.2084 + if( email_dn == 0 )
1.2085 + {
1.2086 + if (!X509_set_subject_name(ret,dn_subject)) goto err;
1.2087 + }
1.2088 +
1.2089 + if (!default_op)
1.2090 + {
1.2091 + BIO_printf(bio_err, "Certificate Details:\n");
1.2092 + /* Never print signature details because signature not present */
1.2093 + certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
1.2094 + X509_print_ex(bio_err, ret, nameopt, certopt);
1.2095 + }
1.2096 +
1.2097 + BIO_printf(bio_err,"Certificate is to be certified until ");
1.2098 + ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
1.2099 + if (days) BIO_printf(bio_err," (%ld days)",days);
1.2100 + BIO_printf(bio_err, "\n");
1.2101 +
1.2102 + if (!batch)
1.2103 + {
1.2104 +
1.2105 + BIO_printf(bio_err,"Sign the certificate? [y/n]:");
1.2106 + (void)BIO_flush(bio_err);
1.2107 + buf[0]='\0';
1.2108 + fgets(buf,sizeof(buf)-1,stdin);
1.2109 + if (!((buf[0] == 'y') || (buf[0] == 'Y')))
1.2110 + {
1.2111 + BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
1.2112 + ok=0;
1.2113 + goto err;
1.2114 + }
1.2115 + }
1.2116 +
1.2117 +
1.2118 +#ifndef OPENSSL_NO_DSA
1.2119 + if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
1.2120 + pktmp=X509_get_pubkey(ret);
1.2121 + if (EVP_PKEY_missing_parameters(pktmp) &&
1.2122 + !EVP_PKEY_missing_parameters(pkey))
1.2123 + EVP_PKEY_copy_parameters(pktmp,pkey);
1.2124 + EVP_PKEY_free(pktmp);
1.2125 +#endif
1.2126 +#ifndef OPENSSL_NO_ECDSA
1.2127 + if (pkey->type == EVP_PKEY_EC)
1.2128 + dgst = EVP_ecdsa();
1.2129 + pktmp = X509_get_pubkey(ret);
1.2130 + if (EVP_PKEY_missing_parameters(pktmp) &&
1.2131 + !EVP_PKEY_missing_parameters(pkey))
1.2132 + EVP_PKEY_copy_parameters(pktmp, pkey);
1.2133 + EVP_PKEY_free(pktmp);
1.2134 +#endif
1.2135 +
1.2136 +
1.2137 + if (!X509_sign(ret,pkey,dgst))
1.2138 + goto err;
1.2139 +
1.2140 + /* We now just add it to the database */
1.2141 + row[DB_type]=(char *)OPENSSL_malloc(2);
1.2142 +
1.2143 + tm=X509_get_notAfter(ret);
1.2144 + row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
1.2145 + memcpy(row[DB_exp_date],tm->data,tm->length);
1.2146 + row[DB_exp_date][tm->length]='\0';
1.2147 +
1.2148 + row[DB_rev_date]=NULL;
1.2149 +
1.2150 + /* row[DB_serial] done already */
1.2151 + row[DB_file]=(char *)OPENSSL_malloc(8);
1.2152 + row[DB_name]=X509_NAME_oneline(X509_get_subject_name(ret),NULL,0);
1.2153 +
1.2154 + if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
1.2155 + (row[DB_file] == NULL) || (row[DB_name] == NULL))
1.2156 + {
1.2157 + BIO_printf(bio_err,"Memory allocation failure\n");
1.2158 + goto err;
1.2159 + }
1.2160 + BUF_strlcpy(row[DB_file],"unknown",8);
1.2161 + row[DB_type][0]='V';
1.2162 + row[DB_type][1]='\0';
1.2163 +
1.2164 + if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
1.2165 + {
1.2166 + BIO_printf(bio_err,"Memory allocation failure\n");
1.2167 + goto err;
1.2168 + }
1.2169 +
1.2170 + for (i=0; i<DB_NUMBER; i++)
1.2171 + {
1.2172 + irow[i]=row[i];
1.2173 + row[i]=NULL;
1.2174 + }
1.2175 + irow[DB_NUMBER]=NULL;
1.2176 +
1.2177 + if (!TXT_DB_insert(db->db,irow))
1.2178 + {
1.2179 + BIO_printf(bio_err,"failed to update database\n");
1.2180 + BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error);
1.2181 + goto err;
1.2182 + }
1.2183 + ok=1;
1.2184 +err:
1.2185 + for (i=0; i<DB_NUMBER; i++)
1.2186 + if (row[i] != NULL) OPENSSL_free(row[i]);
1.2187 +
1.2188 + if (CAname != NULL)
1.2189 + X509_NAME_free(CAname);
1.2190 + if (subject != NULL)
1.2191 + X509_NAME_free(subject);
1.2192 + if ((dn_subject != NULL) && !email_dn)
1.2193 + X509_NAME_free(dn_subject);
1.2194 + if (tmptm != NULL)
1.2195 + ASN1_UTCTIME_free(tmptm);
1.2196 + if (ok <= 0)
1.2197 + {
1.2198 + if (ret != NULL) X509_free(ret);
1.2199 + ret=NULL;
1.2200 + }
1.2201 + else
1.2202 + *xret=ret;
1.2203 + return(ok);
1.2204 + }
1.2205 +
1.2206 +static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
1.2207 + {
1.2208 +
1.2209 + if (output_der)
1.2210 + {
1.2211 + (void)i2d_X509_bio(bp,x);
1.2212 + return;
1.2213 + }
1.2214 +#if 0
1.2215 + /* ??? Not needed since X509_print prints all this stuff anyway */
1.2216 + f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
1.2217 + BIO_printf(bp,"issuer :%s\n",f);
1.2218 +
1.2219 + f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
1.2220 + BIO_printf(bp,"subject:%s\n",f);
1.2221 +
1.2222 + BIO_puts(bp,"serial :");
1.2223 + i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
1.2224 + BIO_puts(bp,"\n\n");
1.2225 +#endif
1.2226 + if (!notext)X509_print(bp,x);
1.2227 + PEM_write_bio_X509(bp,x);
1.2228 + }
1.2229 +
1.2230 +static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1.2231 + const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
1.2232 + BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate,
1.2233 + long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt,
1.2234 + unsigned long nameopt, int default_op, int ext_copy)
1.2235 + {
1.2236 + STACK_OF(CONF_VALUE) *sk=NULL;
1.2237 + LHASH *parms=NULL;
1.2238 + X509_REQ *req=NULL;
1.2239 + CONF_VALUE *cv=NULL;
1.2240 + NETSCAPE_SPKI *spki = NULL;
1.2241 + X509_REQ_INFO *ri;
1.2242 + char *type,*buf;
1.2243 + EVP_PKEY *pktmp=NULL;
1.2244 + X509_NAME *n=NULL;
1.2245 + X509_NAME_ENTRY *ne=NULL;
1.2246 + int ok= -1,i,j;
1.2247 + long errline;
1.2248 + int nid;
1.2249 +
1.2250 + /*
1.2251 + * Load input file into a hash table. (This is just an easy
1.2252 + * way to read and parse the file, then put it into a convenient
1.2253 + * STACK format).
1.2254 + */
1.2255 + parms=CONF_load(NULL,infile,&errline);
1.2256 + if (parms == NULL)
1.2257 + {
1.2258 + BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
1.2259 + ERR_print_errors(bio_err);
1.2260 + goto err;
1.2261 + }
1.2262 +
1.2263 + sk=CONF_get_section(parms, "default");
1.2264 + if (sk_CONF_VALUE_num(sk) == 0)
1.2265 + {
1.2266 + BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
1.2267 + CONF_free(parms);
1.2268 + goto err;
1.2269 + }
1.2270 +
1.2271 + /*
1.2272 + * Now create a dummy X509 request structure. We don't actually
1.2273 + * have an X509 request, but we have many of the components
1.2274 + * (a public key, various DN components). The idea is that we
1.2275 + * put these components into the right X509 request structure
1.2276 + * and we can use the same code as if you had a real X509 request.
1.2277 + */
1.2278 + req=X509_REQ_new();
1.2279 + if (req == NULL)
1.2280 + {
1.2281 + ERR_print_errors(bio_err);
1.2282 + goto err;
1.2283 + }
1.2284 +
1.2285 + /*
1.2286 + * Build up the subject name set.
1.2287 + */
1.2288 + ri=req->req_info;
1.2289 + n = ri->subject;
1.2290 +
1.2291 + for (i = 0; ; i++)
1.2292 + {
1.2293 + if (sk_CONF_VALUE_num(sk) <= i) break;
1.2294 +
1.2295 + cv=sk_CONF_VALUE_value(sk,i);
1.2296 + type=cv->name;
1.2297 + /* Skip past any leading X. X: X, etc to allow for
1.2298 + * multiple instances
1.2299 + */
1.2300 + for (buf = cv->name; *buf ; buf++)
1.2301 + if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
1.2302 + {
1.2303 + buf++;
1.2304 + if (*buf) type = buf;
1.2305 + break;
1.2306 + }
1.2307 +
1.2308 + buf=cv->value;
1.2309 + if ((nid=OBJ_txt2nid(type)) == NID_undef)
1.2310 + {
1.2311 + if (strcmp(type, "SPKAC") == 0)
1.2312 + {
1.2313 + spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
1.2314 + if (spki == NULL)
1.2315 + {
1.2316 + BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
1.2317 + ERR_print_errors(bio_err);
1.2318 + goto err;
1.2319 + }
1.2320 + }
1.2321 + continue;
1.2322 + }
1.2323 +
1.2324 + /*
1.2325 + if ((nid == NID_pkcs9_emailAddress) && (email_dn == 0))
1.2326 + continue;
1.2327 + */
1.2328 +
1.2329 + j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
1.2330 + if (fix_data(nid, &j) == 0)
1.2331 + {
1.2332 + BIO_printf(bio_err,
1.2333 + "invalid characters in string %s\n",buf);
1.2334 + goto err;
1.2335 + }
1.2336 +
1.2337 + if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
1.2338 + (unsigned char *)buf,
1.2339 + strlen(buf))) == NULL)
1.2340 + goto err;
1.2341 +
1.2342 + if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
1.2343 + }
1.2344 + if (spki == NULL)
1.2345 + {
1.2346 + BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
1.2347 + infile);
1.2348 + goto err;
1.2349 + }
1.2350 +
1.2351 + /*
1.2352 + * Now extract the key from the SPKI structure.
1.2353 + */
1.2354 +
1.2355 + BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
1.2356 +
1.2357 + if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
1.2358 + {
1.2359 + BIO_printf(bio_err,"error unpacking SPKAC public key\n");
1.2360 + goto err;
1.2361 + }
1.2362 +
1.2363 + j = NETSCAPE_SPKI_verify(spki, pktmp);
1.2364 + if (j <= 0)
1.2365 + {
1.2366 + BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
1.2367 + goto err;
1.2368 + }
1.2369 + BIO_printf(bio_err,"Signature ok\n");
1.2370 +
1.2371 + X509_REQ_set_pubkey(req,pktmp);
1.2372 + EVP_PKEY_free(pktmp);
1.2373 + ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,
1.2374 + days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op,
1.2375 + ext_copy, 0);
1.2376 +err:
1.2377 + if (req != NULL) X509_REQ_free(req);
1.2378 + if (parms != NULL) CONF_free(parms);
1.2379 + if (spki != NULL) NETSCAPE_SPKI_free(spki);
1.2380 + if (ne != NULL) X509_NAME_ENTRY_free(ne);
1.2381 +
1.2382 + return(ok);
1.2383 + }
1.2384 +
1.2385 +static int fix_data(int nid, int *type)
1.2386 + {
1.2387 + if (nid == NID_pkcs9_emailAddress)
1.2388 + *type=V_ASN1_IA5STRING;
1.2389 + if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
1.2390 + *type=V_ASN1_T61STRING;
1.2391 + if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
1.2392 + *type=V_ASN1_T61STRING;
1.2393 + if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
1.2394 + return(0);
1.2395 + if (nid == NID_pkcs9_unstructuredName)
1.2396 + *type=V_ASN1_IA5STRING;
1.2397 + return(1);
1.2398 + }
1.2399 +
1.2400 +static int check_time_format(char *str)
1.2401 + {
1.2402 + ASN1_UTCTIME tm;
1.2403 +
1.2404 + tm.data=(unsigned char *)str;
1.2405 + tm.length=strlen(str);
1.2406 + tm.type=V_ASN1_UTCTIME;
1.2407 + return(ASN1_UTCTIME_check(&tm));
1.2408 + }
1.2409 +
1.2410 +static int do_revoke(X509 *x509, CA_DB *db, int type, char *value)
1.2411 + {
1.2412 + ASN1_UTCTIME *tm=NULL;
1.2413 + char *row[DB_NUMBER],**rrow,**irow;
1.2414 + char *rev_str = NULL;
1.2415 + BIGNUM *bn = NULL;
1.2416 + int ok=-1,i;
1.2417 +
1.2418 + for (i=0; i<DB_NUMBER; i++)
1.2419 + row[i]=NULL;
1.2420 + row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
1.2421 + bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
1.2422 + if (BN_is_zero(bn))
1.2423 + row[DB_serial]=BUF_strdup("00");
1.2424 + else
1.2425 + row[DB_serial]=BN_bn2hex(bn);
1.2426 + BN_free(bn);
1.2427 + if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
1.2428 + {
1.2429 + BIO_printf(bio_err,"Memory allocation failure\n");
1.2430 + goto err;
1.2431 + }
1.2432 + /* We have to lookup by serial number because name lookup
1.2433 + * skips revoked certs
1.2434 + */
1.2435 + rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
1.2436 + if (rrow == NULL)
1.2437 + {
1.2438 + BIO_printf(bio_err,"Adding Entry with serial number %s to DB for %s\n", row[DB_serial], row[DB_name]);
1.2439 +
1.2440 + /* We now just add it to the database */
1.2441 + row[DB_type]=(char *)OPENSSL_malloc(2);
1.2442 +
1.2443 + tm=X509_get_notAfter(x509);
1.2444 + row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
1.2445 + memcpy(row[DB_exp_date],tm->data,tm->length);
1.2446 + row[DB_exp_date][tm->length]='\0';
1.2447 +
1.2448 + row[DB_rev_date]=NULL;
1.2449 +
1.2450 + /* row[DB_serial] done already */
1.2451 + row[DB_file]=(char *)OPENSSL_malloc(8);
1.2452 +
1.2453 + /* row[DB_name] done already */
1.2454 +
1.2455 + if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
1.2456 + (row[DB_file] == NULL))
1.2457 + {
1.2458 + BIO_printf(bio_err,"Memory allocation failure\n");
1.2459 + goto err;
1.2460 + }
1.2461 + BUF_strlcpy(row[DB_file],"unknown",8);
1.2462 + row[DB_type][0]='V';
1.2463 + row[DB_type][1]='\0';
1.2464 +
1.2465 + if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
1.2466 + {
1.2467 + BIO_printf(bio_err,"Memory allocation failure\n");
1.2468 + goto err;
1.2469 + }
1.2470 +
1.2471 + for (i=0; i<DB_NUMBER; i++)
1.2472 + {
1.2473 + irow[i]=row[i];
1.2474 + row[i]=NULL;
1.2475 + }
1.2476 + irow[DB_NUMBER]=NULL;
1.2477 +
1.2478 + if (!TXT_DB_insert(db->db,irow))
1.2479 + {
1.2480 + BIO_printf(bio_err,"failed to update database\n");
1.2481 + BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error);
1.2482 + goto err;
1.2483 + }
1.2484 +
1.2485 + /* Revoke Certificate */
1.2486 + ok = do_revoke(x509,db, type, value);
1.2487 +
1.2488 + goto err;
1.2489 +
1.2490 + }
1.2491 + else if (index_name_cmp((const char **)row,(const char **)rrow))
1.2492 + {
1.2493 + BIO_printf(bio_err,"ERROR:name does not match %s\n",
1.2494 + row[DB_name]);
1.2495 + goto err;
1.2496 + }
1.2497 + else if (rrow[DB_type][0]=='R')
1.2498 + {
1.2499 + BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
1.2500 + row[DB_serial]);
1.2501 + goto err;
1.2502 + }
1.2503 + else
1.2504 + {
1.2505 + BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
1.2506 + rev_str = make_revocation_str(type, value);
1.2507 + if (!rev_str)
1.2508 + {
1.2509 + BIO_printf(bio_err, "Error in revocation arguments\n");
1.2510 + goto err;
1.2511 + }
1.2512 + rrow[DB_type][0]='R';
1.2513 + rrow[DB_type][1]='\0';
1.2514 + rrow[DB_rev_date] = rev_str;
1.2515 + }
1.2516 + ok=1;
1.2517 +err:
1.2518 + for (i=0; i<DB_NUMBER; i++)
1.2519 + {
1.2520 + if (row[i] != NULL)
1.2521 + OPENSSL_free(row[i]);
1.2522 + }
1.2523 + return(ok);
1.2524 + }
1.2525 +
1.2526 +static int get_certificate_status(const char *serial, CA_DB *db)
1.2527 + {
1.2528 + char *row[DB_NUMBER],**rrow;
1.2529 + int ok=-1,i;
1.2530 +
1.2531 + /* Free Resources */
1.2532 + for (i=0; i<DB_NUMBER; i++)
1.2533 + row[i]=NULL;
1.2534 +
1.2535 + /* Malloc needed char spaces */
1.2536 + row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
1.2537 + if (row[DB_serial] == NULL)
1.2538 + {
1.2539 + BIO_printf(bio_err,"Malloc failure\n");
1.2540 + goto err;
1.2541 + }
1.2542 +
1.2543 + if (strlen(serial) % 2)
1.2544 + {
1.2545 + /* Set the first char to 0 */;
1.2546 + row[DB_serial][0]='0';
1.2547 +
1.2548 + /* Copy String from serial to row[DB_serial] */
1.2549 + memcpy(row[DB_serial]+1, serial, strlen(serial));
1.2550 + row[DB_serial][strlen(serial)+1]='\0';
1.2551 + }
1.2552 + else
1.2553 + {
1.2554 + /* Copy String from serial to row[DB_serial] */
1.2555 + memcpy(row[DB_serial], serial, strlen(serial));
1.2556 + row[DB_serial][strlen(serial)]='\0';
1.2557 + }
1.2558 +
1.2559 + /* Make it Upper Case */
1.2560 + for (i=0; row[DB_serial][i] != '\0'; i++)
1.2561 + row[DB_serial][i] = toupper(row[DB_serial][i]);
1.2562 +
1.2563 +
1.2564 + ok=1;
1.2565 +
1.2566 + /* Search for the certificate */
1.2567 + rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
1.2568 + if (rrow == NULL)
1.2569 + {
1.2570 + BIO_printf(bio_err,"Serial %s not present in db.\n",
1.2571 + row[DB_serial]);
1.2572 + ok=-1;
1.2573 + goto err;
1.2574 + }
1.2575 + else if (rrow[DB_type][0]=='V')
1.2576 + {
1.2577 + BIO_printf(bio_err,"%s=Valid (%c)\n",
1.2578 + row[DB_serial], rrow[DB_type][0]);
1.2579 + goto err;
1.2580 + }
1.2581 + else if (rrow[DB_type][0]=='R')
1.2582 + {
1.2583 + BIO_printf(bio_err,"%s=Revoked (%c)\n",
1.2584 + row[DB_serial], rrow[DB_type][0]);
1.2585 + goto err;
1.2586 + }
1.2587 + else if (rrow[DB_type][0]=='E')
1.2588 + {
1.2589 + BIO_printf(bio_err,"%s=Expired (%c)\n",
1.2590 + row[DB_serial], rrow[DB_type][0]);
1.2591 + goto err;
1.2592 + }
1.2593 + else if (rrow[DB_type][0]=='S')
1.2594 + {
1.2595 + BIO_printf(bio_err,"%s=Suspended (%c)\n",
1.2596 + row[DB_serial], rrow[DB_type][0]);
1.2597 + goto err;
1.2598 + }
1.2599 + else
1.2600 + {
1.2601 + BIO_printf(bio_err,"%s=Unknown (%c).\n",
1.2602 + row[DB_serial], rrow[DB_type][0]);
1.2603 + ok=-1;
1.2604 + }
1.2605 +err:
1.2606 + for (i=0; i<DB_NUMBER; i++)
1.2607 + {
1.2608 + if (row[i] != NULL)
1.2609 + OPENSSL_free(row[i]);
1.2610 + }
1.2611 + return(ok);
1.2612 + }
1.2613 +
1.2614 +static int do_updatedb (CA_DB *db)
1.2615 + {
1.2616 + ASN1_UTCTIME *a_tm = NULL;
1.2617 + int i, cnt = 0;
1.2618 + int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */
1.2619 + char **rrow, *a_tm_s;
1.2620 +
1.2621 + a_tm = ASN1_UTCTIME_new();
1.2622 +
1.2623 + /* get actual time and make a string */
1.2624 + a_tm = X509_gmtime_adj(a_tm, 0);
1.2625 + a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
1.2626 + if (a_tm_s == NULL)
1.2627 + {
1.2628 + cnt = -1;
1.2629 + goto err;
1.2630 + }
1.2631 +
1.2632 + memcpy(a_tm_s, a_tm->data, a_tm->length);
1.2633 + a_tm_s[a_tm->length] = '\0';
1.2634 +
1.2635 + if (strncmp(a_tm_s, "49", 2) <= 0)
1.2636 + a_y2k = 1;
1.2637 + else
1.2638 + a_y2k = 0;
1.2639 +
1.2640 + for (i = 0; i < sk_num(db->db->data); i++)
1.2641 + {
1.2642 + rrow = (char **) sk_value(db->db->data, i);
1.2643 +
1.2644 + if (rrow[DB_type][0] == 'V')
1.2645 + {
1.2646 + /* ignore entries that are not valid */
1.2647 + if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
1.2648 + db_y2k = 1;
1.2649 + else
1.2650 + db_y2k = 0;
1.2651 +
1.2652 + if (db_y2k == a_y2k)
1.2653 + {
1.2654 + /* all on the same y2k side */
1.2655 + if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
1.2656 + {
1.2657 + rrow[DB_type][0] = 'E';
1.2658 + rrow[DB_type][1] = '\0';
1.2659 + cnt++;
1.2660 +
1.2661 + BIO_printf(bio_err, "%s=Expired\n",
1.2662 + rrow[DB_serial]);
1.2663 + }
1.2664 + }
1.2665 + else if (db_y2k < a_y2k)
1.2666 + {
1.2667 + rrow[DB_type][0] = 'E';
1.2668 + rrow[DB_type][1] = '\0';
1.2669 + cnt++;
1.2670 +
1.2671 + BIO_printf(bio_err, "%s=Expired\n",
1.2672 + rrow[DB_serial]);
1.2673 + }
1.2674 +
1.2675 + }
1.2676 + }
1.2677 +
1.2678 +err:
1.2679 +
1.2680 + ASN1_UTCTIME_free(a_tm);
1.2681 + OPENSSL_free(a_tm_s);
1.2682 +
1.2683 + return (cnt);
1.2684 + }
1.2685 +
1.2686 +static const char *crl_reasons[] = {
1.2687 + /* CRL reason strings */
1.2688 + "unspecified",
1.2689 + "keyCompromise",
1.2690 + "CACompromise",
1.2691 + "affiliationChanged",
1.2692 + "superseded",
1.2693 + "cessationOfOperation",
1.2694 + "certificateHold",
1.2695 + "removeFromCRL",
1.2696 + /* Additional pseudo reasons */
1.2697 + "holdInstruction",
1.2698 + "keyTime",
1.2699 + "CAkeyTime"
1.2700 +};
1.2701 +
1.2702 +#define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
1.2703 +
1.2704 +/* Given revocation information convert to a DB string.
1.2705 + * The format of the string is:
1.2706 + * revtime[,reason,extra]. Where 'revtime' is the
1.2707 + * revocation time (the current time). 'reason' is the
1.2708 + * optional CRL reason and 'extra' is any additional
1.2709 + * argument
1.2710 + */
1.2711 +
1.2712 +char *make_revocation_str(int rev_type, char *rev_arg)
1.2713 + {
1.2714 + char *other = NULL, *str;
1.2715 + const char *reason = NULL;
1.2716 + ASN1_OBJECT *otmp;
1.2717 + ASN1_UTCTIME *revtm = NULL;
1.2718 + int i;
1.2719 + switch (rev_type)
1.2720 + {
1.2721 + case REV_NONE:
1.2722 + break;
1.2723 +
1.2724 + case REV_CRL_REASON:
1.2725 + for (i = 0; i < 8; i++)
1.2726 + {
1.2727 + if (!strcasecmp(rev_arg, crl_reasons[i]))
1.2728 + {
1.2729 + reason = crl_reasons[i];
1.2730 + break;
1.2731 + }
1.2732 + }
1.2733 + if (reason == NULL)
1.2734 + {
1.2735 + BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
1.2736 + return NULL;
1.2737 + }
1.2738 + break;
1.2739 +
1.2740 + case REV_HOLD:
1.2741 + /* Argument is an OID */
1.2742 +
1.2743 + otmp = OBJ_txt2obj(rev_arg, 0);
1.2744 + ASN1_OBJECT_free(otmp);
1.2745 +
1.2746 + if (otmp == NULL)
1.2747 + {
1.2748 + BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
1.2749 + return NULL;
1.2750 + }
1.2751 +
1.2752 + reason = "holdInstruction";
1.2753 + other = rev_arg;
1.2754 + break;
1.2755 +
1.2756 + case REV_KEY_COMPROMISE:
1.2757 + case REV_CA_COMPROMISE:
1.2758 +
1.2759 + /* Argument is the key compromise time */
1.2760 + if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg))
1.2761 + {
1.2762 + BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg);
1.2763 + return NULL;
1.2764 + }
1.2765 + other = rev_arg;
1.2766 + if (rev_type == REV_KEY_COMPROMISE)
1.2767 + reason = "keyTime";
1.2768 + else
1.2769 + reason = "CAkeyTime";
1.2770 +
1.2771 + break;
1.2772 +
1.2773 + }
1.2774 +
1.2775 + revtm = X509_gmtime_adj(NULL, 0);
1.2776 +
1.2777 + i = revtm->length + 1;
1.2778 +
1.2779 + if (reason) i += strlen(reason) + 1;
1.2780 + if (other) i += strlen(other) + 1;
1.2781 +
1.2782 + str = OPENSSL_malloc(i);
1.2783 +
1.2784 + if (!str) return NULL;
1.2785 +
1.2786 + BUF_strlcpy(str, (char *)revtm->data, i);
1.2787 + if (reason)
1.2788 + {
1.2789 + BUF_strlcat(str, ",", i);
1.2790 + BUF_strlcat(str, reason, i);
1.2791 + }
1.2792 + if (other)
1.2793 + {
1.2794 + BUF_strlcat(str, ",", i);
1.2795 + BUF_strlcat(str, other, i);
1.2796 + }
1.2797 + ASN1_UTCTIME_free(revtm);
1.2798 + return str;
1.2799 + }
1.2800 +
1.2801 +/* Convert revocation field to X509_REVOKED entry
1.2802 + * return code:
1.2803 + * 0 error
1.2804 + * 1 OK
1.2805 + * 2 OK and some extensions added (i.e. V2 CRL)
1.2806 + */
1.2807 +
1.2808 +
1.2809 +int make_revoked(X509_REVOKED *rev, const char *str)
1.2810 + {
1.2811 + char *tmp = NULL;
1.2812 + int reason_code = -1;
1.2813 + int i, ret = 0;
1.2814 + ASN1_OBJECT *hold = NULL;
1.2815 + ASN1_GENERALIZEDTIME *comp_time = NULL;
1.2816 + ASN1_ENUMERATED *rtmp = NULL;
1.2817 +
1.2818 + ASN1_TIME *revDate = NULL;
1.2819 +
1.2820 + i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str);
1.2821 +
1.2822 + if (i == 0)
1.2823 + goto err;
1.2824 +
1.2825 + if (rev && !X509_REVOKED_set_revocationDate(rev, revDate))
1.2826 + goto err;
1.2827 +
1.2828 + if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
1.2829 + {
1.2830 + rtmp = ASN1_ENUMERATED_new();
1.2831 + if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
1.2832 + goto err;
1.2833 + if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
1.2834 + goto err;
1.2835 + }
1.2836 +
1.2837 + if (rev && comp_time)
1.2838 + {
1.2839 + if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
1.2840 + goto err;
1.2841 + }
1.2842 + if (rev && hold)
1.2843 + {
1.2844 + if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
1.2845 + goto err;
1.2846 + }
1.2847 +
1.2848 + if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
1.2849 + ret = 2;
1.2850 + else ret = 1;
1.2851 +
1.2852 + err:
1.2853 +
1.2854 + if (tmp) OPENSSL_free(tmp);
1.2855 + ASN1_OBJECT_free(hold);
1.2856 + ASN1_GENERALIZEDTIME_free(comp_time);
1.2857 + ASN1_ENUMERATED_free(rtmp);
1.2858 + ASN1_TIME_free(revDate);
1.2859 +
1.2860 + return ret;
1.2861 + }
1.2862 +
1.2863 +int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
1.2864 + {
1.2865 + char buf[25],*pbuf, *p;
1.2866 + int j;
1.2867 + j=i2a_ASN1_OBJECT(bp,obj);
1.2868 + pbuf=buf;
1.2869 + for (j=22-j; j>0; j--)
1.2870 + *(pbuf++)=' ';
1.2871 + *(pbuf++)=':';
1.2872 + *(pbuf++)='\0';
1.2873 + BIO_puts(bp,buf);
1.2874 +
1.2875 + if (str->type == V_ASN1_PRINTABLESTRING)
1.2876 + BIO_printf(bp,"PRINTABLE:'");
1.2877 + else if (str->type == V_ASN1_T61STRING)
1.2878 + BIO_printf(bp,"T61STRING:'");
1.2879 + else if (str->type == V_ASN1_IA5STRING)
1.2880 + BIO_printf(bp,"IA5STRING:'");
1.2881 + else if (str->type == V_ASN1_UNIVERSALSTRING)
1.2882 + BIO_printf(bp,"UNIVERSALSTRING:'");
1.2883 + else
1.2884 + BIO_printf(bp,"ASN.1 %2d:'",str->type);
1.2885 +
1.2886 + p=(char *)str->data;
1.2887 + for (j=str->length; j>0; j--)
1.2888 + {
1.2889 + if ((*p >= ' ') && (*p <= '~'))
1.2890 + BIO_printf(bp,"%c",*p);
1.2891 + else if (*p & 0x80)
1.2892 + BIO_printf(bp,"\\0x%02X",*p);
1.2893 + else if ((unsigned char)*p == 0xf7)
1.2894 + BIO_printf(bp,"^?");
1.2895 + else BIO_printf(bp,"^%c",*p+'@');
1.2896 + p++;
1.2897 + }
1.2898 + BIO_printf(bp,"'\n");
1.2899 + return 1;
1.2900 + }
1.2901 +
1.2902 +int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, const char *str)
1.2903 + {
1.2904 + char *tmp = NULL;
1.2905 + char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
1.2906 + int reason_code = -1;
1.2907 + int ret = 0;
1.2908 + unsigned int i;
1.2909 + ASN1_OBJECT *hold = NULL;
1.2910 + ASN1_GENERALIZEDTIME *comp_time = NULL;
1.2911 + tmp = BUF_strdup(str);
1.2912 +
1.2913 + p = strchr(tmp, ',');
1.2914 +
1.2915 + rtime_str = tmp;
1.2916 +
1.2917 + if (p)
1.2918 + {
1.2919 + *p = '\0';
1.2920 + p++;
1.2921 + reason_str = p;
1.2922 + p = strchr(p, ',');
1.2923 + if (p)
1.2924 + {
1.2925 + *p = '\0';
1.2926 + arg_str = p + 1;
1.2927 + }
1.2928 + }
1.2929 +
1.2930 + if (prevtm)
1.2931 + {
1.2932 + *prevtm = ASN1_UTCTIME_new();
1.2933 + if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str))
1.2934 + {
1.2935 + BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
1.2936 + goto err;
1.2937 + }
1.2938 + }
1.2939 + if (reason_str)
1.2940 + {
1.2941 + for (i = 0; i < NUM_REASONS; i++)
1.2942 + {
1.2943 + if(!strcasecmp(reason_str, crl_reasons[i]))
1.2944 + {
1.2945 + reason_code = i;
1.2946 + break;
1.2947 + }
1.2948 + }
1.2949 + if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS)
1.2950 + {
1.2951 + BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
1.2952 + goto err;
1.2953 + }
1.2954 +
1.2955 + if (reason_code == 7)
1.2956 + reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
1.2957 + else if (reason_code == 8) /* Hold instruction */
1.2958 + {
1.2959 + if (!arg_str)
1.2960 + {
1.2961 + BIO_printf(bio_err, "missing hold instruction\n");
1.2962 + goto err;
1.2963 + }
1.2964 + reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
1.2965 + hold = OBJ_txt2obj(arg_str, 0);
1.2966 +
1.2967 + if (!hold)
1.2968 + {
1.2969 + BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
1.2970 + goto err;
1.2971 + }
1.2972 + if (phold) *phold = hold;
1.2973 + }
1.2974 + else if ((reason_code == 9) || (reason_code == 10))
1.2975 + {
1.2976 + if (!arg_str)
1.2977 + {
1.2978 + BIO_printf(bio_err, "missing compromised time\n");
1.2979 + goto err;
1.2980 + }
1.2981 + comp_time = ASN1_GENERALIZEDTIME_new();
1.2982 + if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str))
1.2983 + {
1.2984 + BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
1.2985 + goto err;
1.2986 + }
1.2987 + if (reason_code == 9)
1.2988 + reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
1.2989 + else
1.2990 + reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
1.2991 + }
1.2992 + }
1.2993 +
1.2994 + if (preason) *preason = reason_code;
1.2995 + if (pinvtm) *pinvtm = comp_time;
1.2996 + else ASN1_GENERALIZEDTIME_free(comp_time);
1.2997 +
1.2998 + ret = 1;
1.2999 +
1.3000 + err:
1.3001 +
1.3002 + if (tmp) OPENSSL_free(tmp);
1.3003 + if (!phold) ASN1_OBJECT_free(hold);
1.3004 + if (!pinvtm) ASN1_GENERALIZEDTIME_free(comp_time);
1.3005 +
1.3006 + return ret;
1.3007 + }