ca.c revision 279265
155714Skris/* apps/ca.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
855714Skris *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1555714Skris *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
2255714Skris *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4055714Skris *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
5255714Skris *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris/* The PPKI stuff has been donated by Jeff Barber <jeffb@issl.atl.hp.com> */
6055714Skris
6155714Skris#include <stdio.h>
6255714Skris#include <stdlib.h>
6355714Skris#include <string.h>
64109998Smarkm#include <ctype.h>
6555714Skris#include <sys/types.h>
6655714Skris#include <sys/stat.h>
6755714Skris#include <openssl/conf.h>
6855714Skris#include <openssl/bio.h>
6955714Skris#include <openssl/err.h>
7055714Skris#include <openssl/bn.h>
7155714Skris#include <openssl/txt_db.h>
7255714Skris#include <openssl/evp.h>
7355714Skris#include <openssl/x509.h>
7455714Skris#include <openssl/x509v3.h>
7555714Skris#include <openssl/objects.h>
76109998Smarkm#include <openssl/ocsp.h>
7755714Skris#include <openssl/pem.h>
7855714Skris
7955714Skris#ifndef W_OK
80109998Smarkm#  ifdef OPENSSL_SYS_VMS
8155714Skris#    if defined(__DECC)
8255714Skris#      include <unistd.h>
8355714Skris#    else
8455714Skris#      include <unixlib.h>
8555714Skris#    endif
86194206Ssimon#  elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_NETWARE) && !defined(__TANDEM)
8755714Skris#    include <sys/file.h>
8855714Skris#  endif
8955714Skris#endif
9055714Skris
91109998Smarkm#include "apps.h"
92109998Smarkm
9355714Skris#ifndef W_OK
9455714Skris#  define F_OK 0
9555714Skris#  define X_OK 1
9655714Skris#  define W_OK 2
9755714Skris#  define R_OK 4
9855714Skris#endif
9955714Skris
10055714Skris#undef PROG
10155714Skris#define PROG ca_main
10255714Skris
10355714Skris#define BASE_SECTION	"ca"
10455714Skris#define CONFIG_FILE "openssl.cnf"
10555714Skris
10655714Skris#define ENV_DEFAULT_CA		"default_ca"
10755714Skris
108160814Ssimon#define STRING_MASK	"string_mask"
109160814Ssimon#define UTF8_IN			"utf8"
110160814Ssimon
11155714Skris#define ENV_DIR			"dir"
11255714Skris#define ENV_CERTS		"certs"
11355714Skris#define ENV_CRL_DIR		"crl_dir"
11455714Skris#define ENV_CA_DB		"CA_DB"
11555714Skris#define ENV_NEW_CERTS_DIR	"new_certs_dir"
11655714Skris#define ENV_CERTIFICATE 	"certificate"
11755714Skris#define ENV_SERIAL		"serial"
118127128Snectar#define ENV_CRLNUMBER		"crlnumber"
11955714Skris#define ENV_CRL			"crl"
12055714Skris#define ENV_PRIVATE_KEY		"private_key"
12155714Skris#define ENV_RANDFILE		"RANDFILE"
12255714Skris#define ENV_DEFAULT_DAYS 	"default_days"
12355714Skris#define ENV_DEFAULT_STARTDATE 	"default_startdate"
12455714Skris#define ENV_DEFAULT_ENDDATE 	"default_enddate"
12555714Skris#define ENV_DEFAULT_CRL_DAYS 	"default_crl_days"
12655714Skris#define ENV_DEFAULT_CRL_HOURS 	"default_crl_hours"
12755714Skris#define ENV_DEFAULT_MD		"default_md"
128109998Smarkm#define ENV_DEFAULT_EMAIL_DN	"email_in_dn"
12955714Skris#define ENV_PRESERVE		"preserve"
13055714Skris#define ENV_POLICY      	"policy"
13155714Skris#define ENV_EXTENSIONS      	"x509_extensions"
13255714Skris#define ENV_CRLEXT      	"crl_extensions"
13355714Skris#define ENV_MSIE_HACK		"msie_hack"
134109998Smarkm#define ENV_NAMEOPT		"name_opt"
135109998Smarkm#define ENV_CERTOPT		"cert_opt"
136109998Smarkm#define ENV_EXTCOPY		"copy_extensions"
137160814Ssimon#define ENV_UNIQUE_SUBJECT	"unique_subject"
13855714Skris
13955714Skris#define ENV_DATABASE		"database"
14055714Skris
141109998Smarkm/* Additional revocation information types */
142109998Smarkm
143109998Smarkm#define REV_NONE		0	/* No addditional information */
144109998Smarkm#define REV_CRL_REASON		1	/* Value is CRL reason code */
145109998Smarkm#define REV_HOLD		2	/* Value is hold instruction */
146109998Smarkm#define REV_KEY_COMPROMISE	3	/* Value is cert key compromise time */
147109998Smarkm#define REV_CA_COMPROMISE	4	/* Value is CA key compromise time */
148109998Smarkm
149160814Ssimonstatic const char *ca_usage[]={
15055714Skris"usage: ca args\n",
15155714Skris"\n",
15255714Skris" -verbose        - Talk alot while doing things\n",
15355714Skris" -config file    - A config file\n",
15455714Skris" -name arg       - The particular CA definition to use\n",
15555714Skris" -gencrl         - Generate a new CRL\n",
15655714Skris" -crldays days   - Days is when the next CRL is due\n",
15755714Skris" -crlhours hours - Hours is when the next CRL is due\n",
15859191Skris" -startdate YYMMDDHHMMSSZ  - certificate validity notBefore\n",
15959191Skris" -enddate YYMMDDHHMMSSZ    - certificate validity notAfter (overrides -days)\n",
16055714Skris" -days arg       - number of days to certify the certificate for\n",
16155714Skris" -md arg         - md to use, one of md2, md5, sha or sha1\n",
16255714Skris" -policy arg     - The CA 'policy' to support\n",
163109998Smarkm" -keyfile arg    - private key file\n",
164109998Smarkm" -keyform arg    - private key file format (PEM or ENGINE)\n",
16555714Skris" -key arg        - key to decode the private key if it is encrypted\n",
16655714Skris" -cert file      - The CA certificate\n",
167160814Ssimon" -selfsign       - sign a certificate with the key associated with it\n",
16855714Skris" -in file        - The input PEM encoded certificate request(s)\n",
16955714Skris" -out file       - Where to put the output file(s)\n",
17055714Skris" -outdir dir     - Where to put output certificates\n",
17155714Skris" -infiles ....   - The last argument, requests to process\n",
17255714Skris" -spkac file     - File contains DN and signed public key and challenge\n",
17355714Skris" -ss_cert file   - File contains a self signed cert to sign\n",
17455714Skris" -preserveDN     - Don't re-order the DN\n",
175109998Smarkm" -noemailDN      - Don't add the EMAIL field into certificate' subject\n",
17655714Skris" -batch          - Don't ask questions\n",
17755714Skris" -msie_hack      - msie modifications to handle all those universal strings\n",
17855714Skris" -revoke file    - Revoke a certificate (given in file)\n",
179109998Smarkm" -subj arg       - Use arg instead of request's subject\n",
180160814Ssimon" -utf8           - input characters are UTF8 (default ASCII)\n",
181160814Ssimon" -multivalue-rdn - enable support for multivalued RDNs\n",
18259191Skris" -extensions ..  - Extension section (override value in config file)\n",
183109998Smarkm" -extfile file   - Configuration file with X509v3 extentions to add\n",
18459191Skris" -crlexts ..     - CRL extension section (override value in config file)\n",
185111147Snectar#ifndef OPENSSL_NO_ENGINE
186109998Smarkm" -engine e       - use engine e, possibly a hardware device.\n",
187111147Snectar#endif
188109998Smarkm" -status serial  - Shows certificate status given the serial number\n",
189109998Smarkm" -updatedb       - Updates db for expired certificates\n",
19055714SkrisNULL
19155714Skris};
19255714Skris
19355714Skris#ifdef EFENCE
19455714Skrisextern int EF_PROTECT_FREE;
19555714Skrisextern int EF_PROTECT_BELOW;
19655714Skrisextern int EF_ALIGNMENT;
19755714Skris#endif
19855714Skris
199160814Ssimonstatic void lookup_fail(const char *name, const char *tag);
20055714Skrisstatic int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
201127128Snectar		   const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,CA_DB *db,
202160814Ssimon		   BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate,
203109998Smarkm		   char *enddate, long days, int batch, char *ext_sect, CONF *conf,
204109998Smarkm		   int verbose, unsigned long certopt, unsigned long nameopt,
205160814Ssimon		   int default_op, int ext_copy, int selfsign);
20655714Skrisstatic int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
20755714Skris			const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
208160814Ssimon			CA_DB *db, BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn,
209109998Smarkm			char *startdate, char *enddate, long days, int batch,
210109998Smarkm			char *ext_sect, CONF *conf,int verbose, unsigned long certopt,
211109998Smarkm			unsigned long nameopt, int default_op, int ext_copy,
212109998Smarkm			ENGINE *e);
21355714Skrisstatic int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
21455714Skris			 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
215160814Ssimon			 CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn, int email_dn,
216109998Smarkm			 char *startdate, char *enddate, long days, char *ext_sect,
217109998Smarkm			 CONF *conf, int verbose, unsigned long certopt,
218109998Smarkm			 unsigned long nameopt, int default_op, int ext_copy);
21959191Skrisstatic void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
22055714Skrisstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
221160814Ssimon	STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn,
222109998Smarkm	int email_dn, char *startdate, char *enddate, long days, int batch,
223109998Smarkm       	int verbose, X509_REQ *req, char *ext_sect, CONF *conf,
224109998Smarkm	unsigned long certopt, unsigned long nameopt, int default_op,
225160814Ssimon	int ext_copy, int selfsign);
226127128Snectarstatic int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval);
227127128Snectarstatic int get_certificate_status(const char *ser_status, CA_DB *db);
228127128Snectarstatic int do_updatedb(CA_DB *db);
229205128Ssimonstatic int check_time_format(const char *str);
230109998Smarkmchar *make_revocation_str(int rev_type, char *rev_arg);
231160814Ssimonint make_revoked(X509_REVOKED *rev, const char *str);
232109998Smarkmint old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str);
233109998Smarkmstatic CONF *conf=NULL;
234109998Smarkmstatic CONF *extconf=NULL;
23555714Skrisstatic char *section=NULL;
23655714Skris
23755714Skrisstatic int preserve=0;
23855714Skrisstatic int msie_hack=0;
23955714Skris
240109998Smarkm
24159191Skrisint MAIN(int, char **);
24259191Skris
24355714Skrisint MAIN(int argc, char **argv)
24455714Skris	{
245109998Smarkm	ENGINE *e = NULL;
24668651Skris	char *key=NULL,*passargin=NULL;
247142425Snectar	int create_ser = 0;
248109998Smarkm	int free_key = 0;
24955714Skris	int total=0;
25055714Skris	int total_done=0;
25155714Skris	int badops=0;
25255714Skris	int ret=1;
253109998Smarkm	int email_dn=1;
25455714Skris	int req=0;
25555714Skris	int verbose=0;
25655714Skris	int gencrl=0;
25755714Skris	int dorevoke=0;
258109998Smarkm	int doupdatedb=0;
25955714Skris	long crldays=0;
26055714Skris	long crlhours=0;
26155714Skris	long errorline= -1;
26255714Skris	char *configfile=NULL;
26355714Skris	char *md=NULL;
26455714Skris	char *policy=NULL;
26555714Skris	char *keyfile=NULL;
26655714Skris	char *certfile=NULL;
267109998Smarkm	int keyform=FORMAT_PEM;
26855714Skris	char *infile=NULL;
26955714Skris	char *spkac_file=NULL;
27055714Skris	char *ss_cert_file=NULL;
271109998Smarkm	char *ser_status=NULL;
27255714Skris	EVP_PKEY *pkey=NULL;
27355714Skris	int output_der = 0;
27455714Skris	char *outfile=NULL;
27555714Skris	char *outdir=NULL;
27655714Skris	char *serialfile=NULL;
277127128Snectar	char *crlnumberfile=NULL;
27855714Skris	char *extensions=NULL;
279109998Smarkm	char *extfile=NULL;
280109998Smarkm	char *subj=NULL;
281160814Ssimon	unsigned long chtype = MBSTRING_ASC;
282160814Ssimon	int multirdn = 0;
283109998Smarkm	char *tmp_email_dn=NULL;
28455714Skris	char *crl_ext=NULL;
285109998Smarkm	int rev_type = REV_NONE;
286109998Smarkm	char *rev_arg = NULL;
28755714Skris	BIGNUM *serial=NULL;
288127128Snectar	BIGNUM *crlnumber=NULL;
28955714Skris	char *startdate=NULL;
29055714Skris	char *enddate=NULL;
291109998Smarkm	long days=0;
29255714Skris	int batch=0;
29359191Skris	int notext=0;
294109998Smarkm	unsigned long nameopt = 0, certopt = 0;
295109998Smarkm	int default_op = 1;
296109998Smarkm	int ext_copy = EXT_COPY_NONE;
297160814Ssimon	int selfsign = 0;
298160814Ssimon	X509 *x509=NULL, *x509p = NULL;
29955714Skris	X509 *x=NULL;
30055714Skris	BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
30155714Skris	char *dbfile=NULL;
302127128Snectar	CA_DB *db=NULL;
30355714Skris	X509_CRL *crl=NULL;
30455714Skris	X509_REVOKED *r=NULL;
305109998Smarkm	ASN1_TIME *tmptm;
306109998Smarkm	ASN1_INTEGER *tmpser;
307160814Ssimon	char *f;
308160814Ssimon	const char *p, **pp;
30955714Skris	int i,j;
31055714Skris	const EVP_MD *dgst=NULL;
31155714Skris	STACK_OF(CONF_VALUE) *attribs=NULL;
31268651Skris	STACK_OF(X509) *cert_sk=NULL;
31355714Skris#undef BSIZE
31455714Skris#define BSIZE 256
31555714Skris	MS_STATIC char buf[3][BSIZE];
31659191Skris	char *randfile=NULL;
317111147Snectar#ifndef OPENSSL_NO_ENGINE
318109998Smarkm	char *engine = NULL;
319111147Snectar#endif
320109998Smarkm	char *tofree=NULL;
321127128Snectar	DB_ATTR db_attr;
32255714Skris
32355714Skris#ifdef EFENCE
32455714SkrisEF_PROTECT_FREE=1;
32555714SkrisEF_PROTECT_BELOW=1;
32655714SkrisEF_ALIGNMENT=0;
32755714Skris#endif
32855714Skris
32955714Skris	apps_startup();
33055714Skris
33159191Skris	conf = NULL;
33259191Skris	key = NULL;
33359191Skris	section = NULL;
33455714Skris
33555714Skris	preserve=0;
33659191Skris	msie_hack=0;
33755714Skris	if (bio_err == NULL)
33855714Skris		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
33955714Skris			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
34055714Skris
34155714Skris	argc--;
34255714Skris	argv++;
34355714Skris	while (argc >= 1)
34455714Skris		{
34555714Skris		if	(strcmp(*argv,"-verbose") == 0)
34655714Skris			verbose=1;
34755714Skris		else if	(strcmp(*argv,"-config") == 0)
34855714Skris			{
34955714Skris			if (--argc < 1) goto bad;
35055714Skris			configfile= *(++argv);
35155714Skris			}
35255714Skris		else if (strcmp(*argv,"-name") == 0)
35355714Skris			{
35455714Skris			if (--argc < 1) goto bad;
35555714Skris			section= *(++argv);
35655714Skris			}
357109998Smarkm		else if (strcmp(*argv,"-subj") == 0)
358109998Smarkm			{
359109998Smarkm			if (--argc < 1) goto bad;
360109998Smarkm			subj= *(++argv);
361109998Smarkm			/* preserve=1; */
362109998Smarkm			}
363160814Ssimon		else if (strcmp(*argv,"-utf8") == 0)
364160814Ssimon			chtype = MBSTRING_UTF8;
365160814Ssimon		else if (strcmp(*argv,"-create_serial") == 0)
366160814Ssimon			create_ser = 1;
367160814Ssimon		else if (strcmp(*argv,"-multivalue-rdn") == 0)
368160814Ssimon			multirdn=1;
36955714Skris		else if (strcmp(*argv,"-startdate") == 0)
37055714Skris			{
37155714Skris			if (--argc < 1) goto bad;
37255714Skris			startdate= *(++argv);
37355714Skris			}
37455714Skris		else if (strcmp(*argv,"-enddate") == 0)
37555714Skris			{
37655714Skris			if (--argc < 1) goto bad;
37755714Skris			enddate= *(++argv);
37855714Skris			}
37955714Skris		else if (strcmp(*argv,"-days") == 0)
38055714Skris			{
38155714Skris			if (--argc < 1) goto bad;
38255714Skris			days=atoi(*(++argv));
38355714Skris			}
38455714Skris		else if (strcmp(*argv,"-md") == 0)
38555714Skris			{
38655714Skris			if (--argc < 1) goto bad;
38755714Skris			md= *(++argv);
38855714Skris			}
38955714Skris		else if (strcmp(*argv,"-policy") == 0)
39055714Skris			{
39155714Skris			if (--argc < 1) goto bad;
39255714Skris			policy= *(++argv);
39355714Skris			}
39455714Skris		else if (strcmp(*argv,"-keyfile") == 0)
39555714Skris			{
39655714Skris			if (--argc < 1) goto bad;
39755714Skris			keyfile= *(++argv);
39855714Skris			}
399109998Smarkm		else if (strcmp(*argv,"-keyform") == 0)
400109998Smarkm			{
401109998Smarkm			if (--argc < 1) goto bad;
402109998Smarkm			keyform=str2fmt(*(++argv));
403109998Smarkm			}
40468651Skris		else if (strcmp(*argv,"-passin") == 0)
40568651Skris			{
40668651Skris			if (--argc < 1) goto bad;
40768651Skris			passargin= *(++argv);
40868651Skris			}
40955714Skris		else if (strcmp(*argv,"-key") == 0)
41055714Skris			{
41155714Skris			if (--argc < 1) goto bad;
41255714Skris			key= *(++argv);
41355714Skris			}
41455714Skris		else if (strcmp(*argv,"-cert") == 0)
41555714Skris			{
41655714Skris			if (--argc < 1) goto bad;
41755714Skris			certfile= *(++argv);
41855714Skris			}
419160814Ssimon		else if (strcmp(*argv,"-selfsign") == 0)
420160814Ssimon			selfsign=1;
42155714Skris		else if (strcmp(*argv,"-in") == 0)
42255714Skris			{
42355714Skris			if (--argc < 1) goto bad;
42455714Skris			infile= *(++argv);
42555714Skris			req=1;
42655714Skris			}
42755714Skris		else if (strcmp(*argv,"-out") == 0)
42855714Skris			{
42955714Skris			if (--argc < 1) goto bad;
43055714Skris			outfile= *(++argv);
43155714Skris			}
43255714Skris		else if (strcmp(*argv,"-outdir") == 0)
43355714Skris			{
43455714Skris			if (--argc < 1) goto bad;
43555714Skris			outdir= *(++argv);
43655714Skris			}
43759191Skris		else if (strcmp(*argv,"-notext") == 0)
43859191Skris			notext=1;
43955714Skris		else if (strcmp(*argv,"-batch") == 0)
44055714Skris			batch=1;
44155714Skris		else if (strcmp(*argv,"-preserveDN") == 0)
44255714Skris			preserve=1;
443109998Smarkm		else if (strcmp(*argv,"-noemailDN") == 0)
444109998Smarkm			email_dn=0;
44555714Skris		else if (strcmp(*argv,"-gencrl") == 0)
44655714Skris			gencrl=1;
44755714Skris		else if (strcmp(*argv,"-msie_hack") == 0)
44855714Skris			msie_hack=1;
44955714Skris		else if (strcmp(*argv,"-crldays") == 0)
45055714Skris			{
45155714Skris			if (--argc < 1) goto bad;
45255714Skris			crldays= atol(*(++argv));
45355714Skris			}
45455714Skris		else if (strcmp(*argv,"-crlhours") == 0)
45555714Skris			{
45655714Skris			if (--argc < 1) goto bad;
45755714Skris			crlhours= atol(*(++argv));
45855714Skris			}
45955714Skris		else if (strcmp(*argv,"-infiles") == 0)
46055714Skris			{
46155714Skris			argc--;
46255714Skris			argv++;
46355714Skris			req=1;
46455714Skris			break;
46555714Skris			}
46655714Skris		else if (strcmp(*argv, "-ss_cert") == 0)
46755714Skris			{
46855714Skris			if (--argc < 1) goto bad;
46955714Skris			ss_cert_file = *(++argv);
47055714Skris			req=1;
47155714Skris			}
47255714Skris		else if (strcmp(*argv, "-spkac") == 0)
47355714Skris			{
47455714Skris			if (--argc < 1) goto bad;
47555714Skris			spkac_file = *(++argv);
47655714Skris			req=1;
47755714Skris			}
47855714Skris		else if (strcmp(*argv,"-revoke") == 0)
47955714Skris			{
48055714Skris			if (--argc < 1) goto bad;
48155714Skris			infile= *(++argv);
48255714Skris			dorevoke=1;
48355714Skris			}
48459191Skris		else if (strcmp(*argv,"-extensions") == 0)
48559191Skris			{
48659191Skris			if (--argc < 1) goto bad;
48759191Skris			extensions= *(++argv);
48859191Skris			}
489109998Smarkm		else if (strcmp(*argv,"-extfile") == 0)
490109998Smarkm			{
491109998Smarkm			if (--argc < 1) goto bad;
492109998Smarkm			extfile= *(++argv);
493109998Smarkm			}
494109998Smarkm		else if (strcmp(*argv,"-status") == 0)
495109998Smarkm			{
496109998Smarkm			if (--argc < 1) goto bad;
497109998Smarkm			ser_status= *(++argv);
498109998Smarkm			}
499109998Smarkm		else if (strcmp(*argv,"-updatedb") == 0)
500109998Smarkm			{
501109998Smarkm			doupdatedb=1;
502109998Smarkm			}
50359191Skris		else if (strcmp(*argv,"-crlexts") == 0)
50459191Skris			{
50559191Skris			if (--argc < 1) goto bad;
50659191Skris			crl_ext= *(++argv);
50759191Skris			}
508109998Smarkm		else if (strcmp(*argv,"-crl_reason") == 0)
509109998Smarkm			{
510109998Smarkm			if (--argc < 1) goto bad;
511109998Smarkm			rev_arg = *(++argv);
512109998Smarkm			rev_type = REV_CRL_REASON;
513109998Smarkm			}
514109998Smarkm		else if (strcmp(*argv,"-crl_hold") == 0)
515109998Smarkm			{
516109998Smarkm			if (--argc < 1) goto bad;
517109998Smarkm			rev_arg = *(++argv);
518109998Smarkm			rev_type = REV_HOLD;
519109998Smarkm			}
520109998Smarkm		else if (strcmp(*argv,"-crl_compromise") == 0)
521109998Smarkm			{
522109998Smarkm			if (--argc < 1) goto bad;
523109998Smarkm			rev_arg = *(++argv);
524109998Smarkm			rev_type = REV_KEY_COMPROMISE;
525109998Smarkm			}
526109998Smarkm		else if (strcmp(*argv,"-crl_CA_compromise") == 0)
527109998Smarkm			{
528109998Smarkm			if (--argc < 1) goto bad;
529109998Smarkm			rev_arg = *(++argv);
530109998Smarkm			rev_type = REV_CA_COMPROMISE;
531109998Smarkm			}
532111147Snectar#ifndef OPENSSL_NO_ENGINE
533109998Smarkm		else if (strcmp(*argv,"-engine") == 0)
534109998Smarkm			{
535109998Smarkm			if (--argc < 1) goto bad;
536109998Smarkm			engine= *(++argv);
537109998Smarkm			}
538111147Snectar#endif
53955714Skris		else
54055714Skris			{
54155714Skrisbad:
54255714Skris			BIO_printf(bio_err,"unknown option %s\n",*argv);
54355714Skris			badops=1;
54455714Skris			break;
54555714Skris			}
54655714Skris		argc--;
54755714Skris		argv++;
54855714Skris		}
54955714Skris
55055714Skris	if (badops)
55155714Skris		{
55255714Skris		for (pp=ca_usage; (*pp != NULL); pp++)
553109998Smarkm			BIO_printf(bio_err,"%s",*pp);
55455714Skris		goto err;
55555714Skris		}
55655714Skris
55755714Skris	ERR_load_crypto_strings();
55855714Skris
55955714Skris	/*****************************************************************/
560109998Smarkm	tofree=NULL;
56155714Skris	if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
56255714Skris	if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
56355714Skris	if (configfile == NULL)
56455714Skris		{
565109998Smarkm		const char *s=X509_get_default_cert_area();
566127128Snectar		size_t len;
567109998Smarkm
568109998Smarkm#ifdef OPENSSL_SYS_VMS
569127128Snectar		len = strlen(s)+sizeof(CONFIG_FILE);
570127128Snectar		tofree=OPENSSL_malloc(len);
571109998Smarkm		strcpy(tofree,s);
57255714Skris#else
573127128Snectar		len = strlen(s)+sizeof(CONFIG_FILE)+1;
574127128Snectar		tofree=OPENSSL_malloc(len);
575127128Snectar		BUF_strlcpy(tofree,s,len);
576127128Snectar		BUF_strlcat(tofree,"/",len);
57755714Skris#endif
578127128Snectar		BUF_strlcat(tofree,CONFIG_FILE,len);
579109998Smarkm		configfile=tofree;
58055714Skris		}
58155714Skris
58255714Skris	BIO_printf(bio_err,"Using configuration from %s\n",configfile);
583109998Smarkm	conf = NCONF_new(NULL);
584109998Smarkm	if (NCONF_load(conf,configfile,&errorline) <= 0)
58555714Skris		{
58655714Skris		if (errorline <= 0)
58755714Skris			BIO_printf(bio_err,"error loading the config file '%s'\n",
58855714Skris				configfile);
58955714Skris		else
59055714Skris			BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
59155714Skris				,errorline,configfile);
59255714Skris		goto err;
59355714Skris		}
594109998Smarkm	if(tofree)
595111147Snectar		{
596109998Smarkm		OPENSSL_free(tofree);
597111147Snectar		tofree = NULL;
598111147Snectar		}
59955714Skris
600109998Smarkm	if (!load_config(bio_err, conf))
601109998Smarkm		goto err;
602109998Smarkm
603142425Snectar#ifndef OPENSSL_NO_ENGINE
604142425Snectar	e = setup_engine(bio_err, engine, 0);
605142425Snectar#endif
606142425Snectar
60755714Skris	/* Lets get the config section we are using */
60855714Skris	if (section == NULL)
60955714Skris		{
610109998Smarkm		section=NCONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
61155714Skris		if (section == NULL)
61255714Skris			{
61355714Skris			lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
61455714Skris			goto err;
61555714Skris			}
61655714Skris		}
61755714Skris
61855714Skris	if (conf != NULL)
61955714Skris		{
620109998Smarkm		p=NCONF_get_string(conf,NULL,"oid_file");
621109998Smarkm		if (p == NULL)
622109998Smarkm			ERR_clear_error();
62355714Skris		if (p != NULL)
62455714Skris			{
62555714Skris			BIO *oid_bio;
62655714Skris
62755714Skris			oid_bio=BIO_new_file(p,"r");
62855714Skris			if (oid_bio == NULL)
62955714Skris				{
63055714Skris				/*
63155714Skris				BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
63255714Skris				ERR_print_errors(bio_err);
63355714Skris				*/
63455714Skris				ERR_clear_error();
63555714Skris				}
63655714Skris			else
63755714Skris				{
63855714Skris				OBJ_create_objects(oid_bio);
63955714Skris				BIO_free(oid_bio);
64055714Skris				}
64155714Skris			}
642109998Smarkm		if (!add_oid_section(bio_err,conf))
64359191Skris			{
64455714Skris			ERR_print_errors(bio_err);
64555714Skris			goto err;
64659191Skris			}
64755714Skris		}
64855714Skris
649109998Smarkm	randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
650109998Smarkm	if (randfile == NULL)
651109998Smarkm		ERR_clear_error();
65259191Skris	app_RAND_load_file(randfile, bio_err, 0);
653127128Snectar
654160814Ssimon	f = NCONF_get_string(conf, section, STRING_MASK);
655160814Ssimon	if (!f)
656160814Ssimon		ERR_clear_error();
657160814Ssimon
658160814Ssimon	if(f && !ASN1_STRING_set_default_mask_asc(f)) {
659160814Ssimon		BIO_printf(bio_err, "Invalid global string mask setting %s\n", f);
660160814Ssimon		goto err;
661160814Ssimon	}
662160814Ssimon
663160814Ssimon	if (chtype != MBSTRING_UTF8){
664160814Ssimon		f = NCONF_get_string(conf, section, UTF8_IN);
665160814Ssimon		if (!f)
666160814Ssimon			ERR_clear_error();
667160814Ssimon		else if (!strcmp(f, "yes"))
668160814Ssimon			chtype = MBSTRING_UTF8;
669160814Ssimon	}
670160814Ssimon
671127128Snectar	db_attr.unique_subject = 1;
672160814Ssimon	p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT);
673127128Snectar	if (p)
674127128Snectar		{
675127128Snectar#ifdef RL_DEBUG
676127128Snectar		BIO_printf(bio_err, "DEBUG: unique_subject = \"%s\"\n", p);
677127128Snectar#endif
678160814Ssimon		db_attr.unique_subject = parse_yesno(p,1);
679127128Snectar		}
680142425Snectar	else
681142425Snectar		ERR_clear_error();
682127128Snectar#ifdef RL_DEBUG
683142425Snectar	if (!p)
684127128Snectar		BIO_printf(bio_err, "DEBUG: unique_subject undefined\n", p);
685127128Snectar#endif
686127128Snectar#ifdef RL_DEBUG
687127128Snectar	BIO_printf(bio_err, "DEBUG: configured unique_subject is %d\n",
688127128Snectar		db_attr.unique_subject);
689127128Snectar#endif
69059191Skris
69155714Skris	in=BIO_new(BIO_s_file());
69255714Skris	out=BIO_new(BIO_s_file());
69355714Skris	Sout=BIO_new(BIO_s_file());
69455714Skris	Cout=BIO_new(BIO_s_file());
69555714Skris	if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL))
69655714Skris		{
69755714Skris		ERR_print_errors(bio_err);
69855714Skris		goto err;
69955714Skris		}
70055714Skris
70155714Skris	/*****************************************************************/
702109998Smarkm	/* report status of cert with serial number given on command line */
703109998Smarkm	if (ser_status)
704109998Smarkm	{
705109998Smarkm		if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
706109998Smarkm			{
707109998Smarkm			lookup_fail(section,ENV_DATABASE);
708109998Smarkm			goto err;
709109998Smarkm			}
710127128Snectar		db = load_index(dbfile,&db_attr);
711109998Smarkm		if (db == NULL) goto err;
71255714Skris
713127128Snectar		if (!index_index(db)) goto err;
714109998Smarkm
715109998Smarkm		if (get_certificate_status(ser_status,db) != 1)
716109998Smarkm			BIO_printf(bio_err,"Error verifying serial %s!\n",
717109998Smarkm				 ser_status);
718109998Smarkm		goto err;
719109998Smarkm	}
720109998Smarkm
721109998Smarkm	/*****************************************************************/
722160814Ssimon	/* we definitely need a private key, so let's get it */
723109998Smarkm
724109998Smarkm	if ((keyfile == NULL) && ((keyfile=NCONF_get_string(conf,
72555714Skris		section,ENV_PRIVATE_KEY)) == NULL))
72655714Skris		{
72755714Skris		lookup_fail(section,ENV_PRIVATE_KEY);
72855714Skris		goto err;
72955714Skris		}
730109998Smarkm	if (!key)
73168651Skris		{
732109998Smarkm		free_key = 1;
733109998Smarkm		if (!app_passwd(bio_err, passargin, NULL, &key, NULL))
734109998Smarkm			{
735109998Smarkm			BIO_printf(bio_err,"Error getting password\n");
736109998Smarkm			goto err;
737109998Smarkm			}
73868651Skris		}
739109998Smarkm	pkey = load_key(bio_err, keyfile, keyform, 0, key, e,
740109998Smarkm		"CA private key");
741109998Smarkm	if (key) OPENSSL_cleanse(key,strlen(key));
74255714Skris	if (pkey == NULL)
74355714Skris		{
744109998Smarkm		/* load_key() has already printed an appropriate message */
74555714Skris		goto err;
74655714Skris		}
74755714Skris
74855714Skris	/*****************************************************************/
74955714Skris	/* we need a certificate */
750160814Ssimon	if (!selfsign || spkac_file || ss_cert_file || gencrl)
75155714Skris		{
752160814Ssimon		if ((certfile == NULL)
753160814Ssimon			&& ((certfile=NCONF_get_string(conf,
754160814Ssimon				     section,ENV_CERTIFICATE)) == NULL))
755160814Ssimon			{
756160814Ssimon			lookup_fail(section,ENV_CERTIFICATE);
757160814Ssimon			goto err;
758160814Ssimon			}
759160814Ssimon		x509=load_cert(bio_err, certfile, FORMAT_PEM, NULL, e,
760160814Ssimon			"CA certificate");
761160814Ssimon		if (x509 == NULL)
762160814Ssimon			goto err;
76355714Skris
764160814Ssimon		if (!X509_check_private_key(x509,pkey))
765160814Ssimon			{
766160814Ssimon			BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
767160814Ssimon			goto err;
768160814Ssimon			}
76955714Skris		}
770160814Ssimon	if (!selfsign) x509p = x509;
77155714Skris
772109998Smarkm	f=NCONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
773109998Smarkm	if (f == NULL)
774109998Smarkm		ERR_clear_error();
77555714Skris	if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
77655714Skris		preserve=1;
777109998Smarkm	f=NCONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
778109998Smarkm	if (f == NULL)
779109998Smarkm		ERR_clear_error();
78055714Skris	if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
78155714Skris		msie_hack=1;
78255714Skris
783109998Smarkm	f=NCONF_get_string(conf,section,ENV_NAMEOPT);
784109998Smarkm
785109998Smarkm	if (f)
786109998Smarkm		{
787109998Smarkm		if (!set_name_ex(&nameopt, f))
788109998Smarkm			{
789109998Smarkm			BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f);
790109998Smarkm			goto err;
791109998Smarkm			}
792109998Smarkm		default_op = 0;
793109998Smarkm		}
794109998Smarkm	else
795109998Smarkm		ERR_clear_error();
796109998Smarkm
797109998Smarkm	f=NCONF_get_string(conf,section,ENV_CERTOPT);
798109998Smarkm
799109998Smarkm	if (f)
800109998Smarkm		{
801109998Smarkm		if (!set_cert_ex(&certopt, f))
802109998Smarkm			{
803109998Smarkm			BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f);
804109998Smarkm			goto err;
805109998Smarkm			}
806109998Smarkm		default_op = 0;
807109998Smarkm		}
808109998Smarkm	else
809109998Smarkm		ERR_clear_error();
810109998Smarkm
811109998Smarkm	f=NCONF_get_string(conf,section,ENV_EXTCOPY);
812109998Smarkm
813109998Smarkm	if (f)
814109998Smarkm		{
815109998Smarkm		if (!set_ext_copy(&ext_copy, f))
816109998Smarkm			{
817109998Smarkm			BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f);
818109998Smarkm			goto err;
819109998Smarkm			}
820109998Smarkm		}
821109998Smarkm	else
822109998Smarkm		ERR_clear_error();
823109998Smarkm
82455714Skris	/*****************************************************************/
82555714Skris	/* lookup where to write new certificates */
82655714Skris	if ((outdir == NULL) && (req))
82755714Skris		{
82855714Skris		struct stat sb;
82955714Skris
830109998Smarkm		if ((outdir=NCONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
83155714Skris			== NULL)
83255714Skris			{
83355714Skris			BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
83455714Skris			goto err;
83555714Skris			}
836109998Smarkm#ifndef OPENSSL_SYS_VMS
837109998Smarkm	    /* outdir is a directory spec, but access() for VMS demands a
83859191Skris	       filename.  In any case, stat(), below, will catch the problem
83959191Skris	       if outdir is not a directory spec, and the fopen() or open()
84059191Skris	       will catch an error if there is no write access.
84159191Skris
84259191Skris	       Presumably, this problem could also be solved by using the DEC
84359191Skris	       C routines to convert the directory syntax to Unixly, and give
84459191Skris	       that to access().  However, time's too short to do that just
84559191Skris	       now.
846109998Smarkm	    */
84755714Skris		if (access(outdir,R_OK|W_OK|X_OK) != 0)
84855714Skris			{
84959191Skris			BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
85055714Skris			perror(outdir);
85155714Skris			goto err;
85255714Skris			}
85355714Skris
85455714Skris		if (stat(outdir,&sb) != 0)
85555714Skris			{
85655714Skris			BIO_printf(bio_err,"unable to stat(%s)\n",outdir);
85755714Skris			perror(outdir);
85855714Skris			goto err;
85955714Skris			}
860205128Ssimon#ifdef S_ISDIR
861205128Ssimon		if (!S_ISDIR(sb.st_mode))
86255714Skris			{
86355714Skris			BIO_printf(bio_err,"%s need to be a directory\n",outdir);
86455714Skris			perror(outdir);
86555714Skris			goto err;
86655714Skris			}
86759191Skris#endif
86859191Skris#endif
86955714Skris		}
87055714Skris
87155714Skris	/*****************************************************************/
87255714Skris	/* we need to load the database file */
873109998Smarkm	if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
87455714Skris		{
87555714Skris		lookup_fail(section,ENV_DATABASE);
87655714Skris		goto err;
87755714Skris		}
878127128Snectar	db = load_index(dbfile, &db_attr);
87955714Skris	if (db == NULL) goto err;
88055714Skris
88155714Skris	/* Lets check some fields */
882127128Snectar	for (i=0; i<sk_num(db->db->data); i++)
88355714Skris		{
884160814Ssimon		pp=(const char **)sk_value(db->db->data,i);
88555714Skris		if ((pp[DB_type][0] != DB_TYPE_REV) &&
88655714Skris			(pp[DB_rev_date][0] != '\0'))
88755714Skris			{
88855714Skris			BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
88955714Skris			goto err;
89055714Skris			}
89155714Skris		if ((pp[DB_type][0] == DB_TYPE_REV) &&
892109998Smarkm			!make_revoked(NULL, pp[DB_rev_date]))
89355714Skris			{
894109998Smarkm			BIO_printf(bio_err," in entry %d\n", i+1);
89555714Skris			goto err;
89655714Skris			}
897205128Ssimon		if (!check_time_format(pp[DB_exp_date]))
89855714Skris			{
89955714Skris			BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
90055714Skris			goto err;
90155714Skris			}
90255714Skris		p=pp[DB_serial];
90355714Skris		j=strlen(p);
904109998Smarkm		if (*p == '-')
905109998Smarkm			{
906109998Smarkm			p++;
907109998Smarkm			j--;
908109998Smarkm			}
90955714Skris		if ((j&1) || (j < 2))
91055714Skris			{
91155714Skris			BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
91255714Skris			goto err;
91355714Skris			}
91455714Skris		while (*p)
91555714Skris			{
91655714Skris			if (!(	((*p >= '0') && (*p <= '9')) ||
91755714Skris				((*p >= 'A') && (*p <= 'F')) ||
91855714Skris				((*p >= 'a') && (*p <= 'f')))  )
91955714Skris				{
92055714Skris				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);
92155714Skris				goto err;
92255714Skris				}
92355714Skris			p++;
92455714Skris			}
92555714Skris		}
92655714Skris	if (verbose)
92755714Skris		{
92855714Skris		BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
929109998Smarkm#ifdef OPENSSL_SYS_VMS
93068651Skris		{
93168651Skris		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
93268651Skris		out = BIO_push(tmpbio, out);
93368651Skris		}
93468651Skris#endif
935127128Snectar		TXT_DB_write(out,db->db);
93655714Skris		BIO_printf(bio_err,"%d entries loaded from the database\n",
937127128Snectar			db->db->data->num);
93859191Skris		BIO_printf(bio_err,"generating index\n");
93955714Skris		}
94055714Skris
941127128Snectar	if (!index_index(db)) goto err;
94255714Skris
94355714Skris	/*****************************************************************/
944109998Smarkm	/* Update the db file for expired certificates */
945109998Smarkm	if (doupdatedb)
946109998Smarkm		{
947109998Smarkm		if (verbose)
948109998Smarkm			BIO_printf(bio_err, "Updating %s ...\n",
949109998Smarkm							dbfile);
950109998Smarkm
951109998Smarkm		i = do_updatedb(db);
952109998Smarkm		if (i == -1)
953109998Smarkm			{
954109998Smarkm			BIO_printf(bio_err,"Malloc failure\n");
955109998Smarkm			goto err;
956109998Smarkm			}
957109998Smarkm		else if (i == 0)
958109998Smarkm			{
959109998Smarkm			if (verbose) BIO_printf(bio_err,
960109998Smarkm					"No entries found to mark expired\n");
961109998Smarkm			}
962109998Smarkm	    	else
963109998Smarkm			{
964127128Snectar			if (!save_index(dbfile,"new",db)) goto err;
965109998Smarkm
966127128Snectar			if (!rotate_index(dbfile,"new","old")) goto err;
967127128Snectar
968109998Smarkm			if (verbose) BIO_printf(bio_err,
969109998Smarkm				"Done. %d entries marked as expired\n",i);
970109998Smarkm	      		}
971109998Smarkm	  	}
972109998Smarkm
973109998Smarkm 	/*****************************************************************/
974109998Smarkm	/* Read extentions config file                                   */
975109998Smarkm	if (extfile)
976109998Smarkm		{
977109998Smarkm		extconf = NCONF_new(NULL);
978109998Smarkm		if (NCONF_load(extconf,extfile,&errorline) <= 0)
979109998Smarkm			{
980109998Smarkm			if (errorline <= 0)
981109998Smarkm				BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
982109998Smarkm					extfile);
983109998Smarkm			else
984109998Smarkm				BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n",
985109998Smarkm					errorline,extfile);
986109998Smarkm			ret = 1;
987109998Smarkm			goto err;
988109998Smarkm			}
989109998Smarkm
990109998Smarkm		if (verbose)
991109998Smarkm			BIO_printf(bio_err, "Successfully loaded extensions file %s\n", extfile);
992109998Smarkm
993109998Smarkm		/* We can have sections in the ext file */
994109998Smarkm		if (!extensions && !(extensions = NCONF_get_string(extconf, "default", "extensions")))
995109998Smarkm			extensions = "default";
996109998Smarkm		}
997109998Smarkm
998109998Smarkm	/*****************************************************************/
99955714Skris	if (req || gencrl)
100055714Skris		{
100155714Skris		if (outfile != NULL)
100255714Skris			{
100355714Skris			if (BIO_write_filename(Sout,outfile) <= 0)
100455714Skris				{
100555714Skris				perror(outfile);
100655714Skris				goto err;
100755714Skris				}
100855714Skris			}
100955714Skris		else
101068651Skris			{
101155714Skris			BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
1012109998Smarkm#ifdef OPENSSL_SYS_VMS
101368651Skris			{
101468651Skris			BIO *tmpbio = BIO_new(BIO_f_linebuffer());
101568651Skris			Sout = BIO_push(tmpbio, Sout);
101668651Skris			}
101768651Skris#endif
101868651Skris			}
101955714Skris		}
102055714Skris
1021160814Ssimon	if ((md == NULL) && ((md=NCONF_get_string(conf,
1022160814Ssimon		section,ENV_DEFAULT_MD)) == NULL))
1023160814Ssimon		{
1024160814Ssimon		lookup_fail(section,ENV_DEFAULT_MD);
1025160814Ssimon		goto err;
1026160814Ssimon		}
1027160814Ssimon
1028160814Ssimon	if ((dgst=EVP_get_digestbyname(md)) == NULL)
1029160814Ssimon		{
1030160814Ssimon		BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1031160814Ssimon		goto err;
1032160814Ssimon		}
1033160814Ssimon
103455714Skris	if (req)
103555714Skris		{
1036109998Smarkm		if ((email_dn == 1) && ((tmp_email_dn=NCONF_get_string(conf,
1037109998Smarkm			section,ENV_DEFAULT_EMAIL_DN)) != NULL ))
1038109998Smarkm			{
1039109998Smarkm			if(strcmp(tmp_email_dn,"no") == 0)
1040109998Smarkm				email_dn=0;
1041109998Smarkm			}
104255714Skris		if (verbose)
104355714Skris			BIO_printf(bio_err,"message digest is %s\n",
104455714Skris				OBJ_nid2ln(dgst->type));
1045109998Smarkm		if ((policy == NULL) && ((policy=NCONF_get_string(conf,
104655714Skris			section,ENV_POLICY)) == NULL))
104755714Skris			{
104855714Skris			lookup_fail(section,ENV_POLICY);
104955714Skris			goto err;
105055714Skris			}
105155714Skris		if (verbose)
105255714Skris			BIO_printf(bio_err,"policy is %s\n",policy);
105355714Skris
1054109998Smarkm		if ((serialfile=NCONF_get_string(conf,section,ENV_SERIAL))
105555714Skris			== NULL)
105655714Skris			{
105755714Skris			lookup_fail(section,ENV_SERIAL);
105855714Skris			goto err;
105955714Skris			}
1060109998Smarkm
1061109998Smarkm		if (!extconf)
1062109998Smarkm			{
1063109998Smarkm			/* no '-extfile' option, so we look for extensions
1064109998Smarkm			 * in the main configuration file */
1065109998Smarkm			if (!extensions)
1066109998Smarkm				{
1067109998Smarkm				extensions=NCONF_get_string(conf,section,
1068109998Smarkm								ENV_EXTENSIONS);
1069109998Smarkm				if (!extensions)
1070109998Smarkm					ERR_clear_error();
1071109998Smarkm				}
1072109998Smarkm			if (extensions)
1073109998Smarkm				{
1074109998Smarkm				/* Check syntax of file */
1075109998Smarkm				X509V3_CTX ctx;
1076109998Smarkm				X509V3_set_ctx_test(&ctx);
1077109998Smarkm				X509V3_set_nconf(&ctx, conf);
1078109998Smarkm				if (!X509V3_EXT_add_nconf(conf, &ctx, extensions,
1079109998Smarkm								NULL))
1080109998Smarkm					{
1081109998Smarkm					BIO_printf(bio_err,
1082109998Smarkm				 	"Error Loading extension section %s\n",
108355714Skris								 extensions);
1084109998Smarkm					ret = 1;
1085109998Smarkm					goto err;
1086109998Smarkm					}
1087109998Smarkm				}
108855714Skris			}
108955714Skris
109055714Skris		if (startdate == NULL)
109155714Skris			{
1092109998Smarkm			startdate=NCONF_get_string(conf,section,
109355714Skris				ENV_DEFAULT_STARTDATE);
1094109998Smarkm			if (startdate == NULL)
1095109998Smarkm				ERR_clear_error();
109655714Skris			}
109755714Skris		if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
109855714Skris			{
109955714Skris			BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
110055714Skris			goto err;
110155714Skris			}
110255714Skris		if (startdate == NULL) startdate="today";
110355714Skris
110455714Skris		if (enddate == NULL)
110555714Skris			{
1106109998Smarkm			enddate=NCONF_get_string(conf,section,
110755714Skris				ENV_DEFAULT_ENDDATE);
1108109998Smarkm			if (enddate == NULL)
1109109998Smarkm				ERR_clear_error();
111055714Skris			}
111155714Skris		if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
111255714Skris			{
111355714Skris			BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
111455714Skris			goto err;
111555714Skris			}
111655714Skris
111755714Skris		if (days == 0)
111855714Skris			{
1119109998Smarkm			if(!NCONF_get_number(conf,section, ENV_DEFAULT_DAYS, &days))
1120109998Smarkm				days = 0;
112155714Skris			}
112255714Skris		if (!enddate && (days == 0))
112355714Skris			{
112455714Skris			BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
112555714Skris			goto err;
112655714Skris			}
112755714Skris
1128142425Snectar		if ((serial=load_serial(serialfile, create_ser, NULL)) == NULL)
112955714Skris			{
113055714Skris			BIO_printf(bio_err,"error while loading serial number\n");
113155714Skris			goto err;
113255714Skris			}
113355714Skris		if (verbose)
113455714Skris			{
1135109998Smarkm			if (BN_is_zero(serial))
1136109998Smarkm				BIO_printf(bio_err,"next serial number is 00\n");
1137109998Smarkm			else
1138109998Smarkm				{
1139109998Smarkm				if ((f=BN_bn2hex(serial)) == NULL) goto err;
1140109998Smarkm				BIO_printf(bio_err,"next serial number is %s\n",f);
1141109998Smarkm				OPENSSL_free(f);
1142109998Smarkm				}
114355714Skris			}
114455714Skris
1145109998Smarkm		if ((attribs=NCONF_get_section(conf,policy)) == NULL)
114655714Skris			{
114755714Skris			BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
114855714Skris			goto err;
114955714Skris			}
115055714Skris
115168651Skris		if ((cert_sk=sk_X509_new_null()) == NULL)
115255714Skris			{
115368651Skris			BIO_printf(bio_err,"Memory allocation failure\n");
115455714Skris			goto err;
115555714Skris			}
115655714Skris		if (spkac_file != NULL)
115755714Skris			{
115855714Skris			total++;
115955714Skris			j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
1160160814Ssimon				serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,extensions,
1161109998Smarkm				conf,verbose,certopt,nameopt,default_op,ext_copy);
116255714Skris			if (j < 0) goto err;
116355714Skris			if (j > 0)
116455714Skris				{
116555714Skris				total_done++;
116655714Skris				BIO_printf(bio_err,"\n");
116755714Skris				if (!BN_add_word(serial,1)) goto err;
116868651Skris				if (!sk_X509_push(cert_sk,x))
116955714Skris					{
117068651Skris					BIO_printf(bio_err,"Memory allocation failure\n");
117155714Skris					goto err;
117255714Skris					}
117355714Skris				if (outfile)
117455714Skris					{
117555714Skris					output_der = 1;
117655714Skris					batch = 1;
117755714Skris					}
117855714Skris				}
117955714Skris			}
118055714Skris		if (ss_cert_file != NULL)
118155714Skris			{
118255714Skris			total++;
118355714Skris			j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
1184160814Ssimon				db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
1185109998Smarkm				extensions,conf,verbose, certopt, nameopt,
1186109998Smarkm				default_op, ext_copy, e);
118755714Skris			if (j < 0) goto err;
118855714Skris			if (j > 0)
118955714Skris				{
119055714Skris				total_done++;
119155714Skris				BIO_printf(bio_err,"\n");
119255714Skris				if (!BN_add_word(serial,1)) goto err;
119368651Skris				if (!sk_X509_push(cert_sk,x))
119455714Skris					{
119568651Skris					BIO_printf(bio_err,"Memory allocation failure\n");
119655714Skris					goto err;
119755714Skris					}
119855714Skris				}
119955714Skris			}
120055714Skris		if (infile != NULL)
120155714Skris			{
120255714Skris			total++;
1203160814Ssimon			j=certify(&x,infile,pkey,x509p,dgst,attribs,db,
1204160814Ssimon				serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
1205109998Smarkm				extensions,conf,verbose, certopt, nameopt,
1206160814Ssimon				default_op, ext_copy, selfsign);
120755714Skris			if (j < 0) goto err;
120855714Skris			if (j > 0)
120955714Skris				{
121055714Skris				total_done++;
121155714Skris				BIO_printf(bio_err,"\n");
121255714Skris				if (!BN_add_word(serial,1)) goto err;
121368651Skris				if (!sk_X509_push(cert_sk,x))
121455714Skris					{
121568651Skris					BIO_printf(bio_err,"Memory allocation failure\n");
121655714Skris					goto err;
121755714Skris					}
121855714Skris				}
121955714Skris			}
122055714Skris		for (i=0; i<argc; i++)
122155714Skris			{
122255714Skris			total++;
1223160814Ssimon			j=certify(&x,argv[i],pkey,x509p,dgst,attribs,db,
1224160814Ssimon				serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
1225109998Smarkm				extensions,conf,verbose, certopt, nameopt,
1226160814Ssimon				default_op, ext_copy, selfsign);
122755714Skris			if (j < 0) goto err;
122855714Skris			if (j > 0)
122955714Skris				{
123055714Skris				total_done++;
123155714Skris				BIO_printf(bio_err,"\n");
123255714Skris				if (!BN_add_word(serial,1)) goto err;
123368651Skris				if (!sk_X509_push(cert_sk,x))
123455714Skris					{
123568651Skris					BIO_printf(bio_err,"Memory allocation failure\n");
123655714Skris					goto err;
123755714Skris					}
123855714Skris				}
123955714Skris			}
124055714Skris		/* we have a stack of newly certified certificates
124155714Skris		 * and a data base and serial number that need
124255714Skris		 * updating */
124355714Skris
124468651Skris		if (sk_X509_num(cert_sk) > 0)
124555714Skris			{
124655714Skris			if (!batch)
124755714Skris				{
124855714Skris				BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
124955714Skris				(void)BIO_flush(bio_err);
125055714Skris				buf[0][0]='\0';
1251205128Ssimon				if (!fgets(buf[0],10,stdin))
1252205128Ssimon					{
1253205128Ssimon					BIO_printf(bio_err,"CERTIFICATION CANCELED: I/O error\n");
1254205128Ssimon					ret=0;
1255205128Ssimon					goto err;
1256205128Ssimon					}
125755714Skris				if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
125855714Skris					{
125955714Skris					BIO_printf(bio_err,"CERTIFICATION CANCELED\n");
126055714Skris					ret=0;
126155714Skris					goto err;
126255714Skris					}
126355714Skris				}
126455714Skris
126568651Skris			BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
126655714Skris
1267127128Snectar			if (!save_serial(serialfile,"new",serial,NULL)) goto err;
126855714Skris
1269127128Snectar			if (!save_index(dbfile, "new", db)) goto err;
127055714Skris			}
127155714Skris
127255714Skris		if (verbose)
127355714Skris			BIO_printf(bio_err,"writing new certificates\n");
127468651Skris		for (i=0; i<sk_X509_num(cert_sk); i++)
127555714Skris			{
127655714Skris			int k;
1277127128Snectar			char *n;
127855714Skris
127968651Skris			x=sk_X509_value(cert_sk,i);
128055714Skris
128155714Skris			j=x->cert_info->serialNumber->length;
1282160814Ssimon			p=(const char *)x->cert_info->serialNumber->data;
128355714Skris
1284109998Smarkm			if(strlen(outdir) >= (size_t)(j ? BSIZE-j*2-6 : BSIZE-8))
1285109998Smarkm				{
1286109998Smarkm				BIO_printf(bio_err,"certificate file name too long\n");
1287109998Smarkm				goto err;
1288109998Smarkm				}
128955714Skris
1290109998Smarkm			strcpy(buf[2],outdir);
1291109998Smarkm
1292109998Smarkm#ifndef OPENSSL_SYS_VMS
1293127128Snectar			BUF_strlcat(buf[2],"/",sizeof(buf[2]));
129455714Skris#endif
129555714Skris
1296127128Snectar			n=(char *)&(buf[2][strlen(buf[2])]);
129755714Skris			if (j > 0)
129855714Skris				{
129955714Skris				for (k=0; k<j; k++)
130055714Skris					{
1301127128Snectar					if (n >= &(buf[2][sizeof(buf[2])]))
1302127128Snectar						break;
1303127128Snectar					BIO_snprintf(n,
1304127128Snectar						     &buf[2][0] + sizeof(buf[2]) - n,
1305127128Snectar						     "%02X",(unsigned char)*(p++));
130655714Skris					n+=2;
130755714Skris					}
130855714Skris				}
130955714Skris			else
131055714Skris				{
131155714Skris				*(n++)='0';
131255714Skris				*(n++)='0';
131355714Skris				}
131455714Skris			*(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
131555714Skris			*n='\0';
131655714Skris			if (verbose)
131755714Skris				BIO_printf(bio_err,"writing %s\n",buf[2]);
131855714Skris
131955714Skris			if (BIO_write_filename(Cout,buf[2]) <= 0)
132055714Skris				{
132155714Skris				perror(buf[2]);
132255714Skris				goto err;
132355714Skris				}
132459191Skris			write_new_certificate(Cout,x, 0, notext);
132559191Skris			write_new_certificate(Sout,x, output_der, notext);
132655714Skris			}
132755714Skris
132868651Skris		if (sk_X509_num(cert_sk))
132955714Skris			{
133055714Skris			/* Rename the database and the serial file */
1331127128Snectar			if (!rotate_serial(serialfile,"new","old")) goto err;
133255714Skris
1333127128Snectar			if (!rotate_index(dbfile,"new","old")) goto err;
133455714Skris
133555714Skris			BIO_printf(bio_err,"Data Base Updated\n");
133655714Skris			}
133755714Skris		}
133855714Skris
133955714Skris	/*****************************************************************/
134055714Skris	if (gencrl)
134155714Skris		{
1342109998Smarkm		int crl_v2 = 0;
1343109998Smarkm		if (!crl_ext)
1344109998Smarkm			{
1345109998Smarkm			crl_ext=NCONF_get_string(conf,section,ENV_CRLEXT);
1346109998Smarkm			if (!crl_ext)
1347109998Smarkm				ERR_clear_error();
1348109998Smarkm			}
1349109998Smarkm		if (crl_ext)
1350109998Smarkm			{
135155714Skris			/* Check syntax of file */
135255714Skris			X509V3_CTX ctx;
135355714Skris			X509V3_set_ctx_test(&ctx);
1354109998Smarkm			X509V3_set_nconf(&ctx, conf);
1355109998Smarkm			if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL))
1356109998Smarkm				{
135755714Skris				BIO_printf(bio_err,
135855714Skris				 "Error Loading CRL extension section %s\n",
135955714Skris								 crl_ext);
136055714Skris				ret = 1;
136155714Skris				goto err;
1362109998Smarkm				}
136355714Skris			}
136455714Skris
1365127128Snectar		if ((crlnumberfile=NCONF_get_string(conf,section,ENV_CRLNUMBER))
1366127128Snectar			!= NULL)
1367127128Snectar			if ((crlnumber=load_serial(crlnumberfile,0,NULL)) == NULL)
1368127128Snectar				{
1369127128Snectar				BIO_printf(bio_err,"error while loading CRL number\n");
1370127128Snectar				goto err;
1371127128Snectar				}
1372127128Snectar
137355714Skris		if (!crldays && !crlhours)
137455714Skris			{
1375109998Smarkm			if (!NCONF_get_number(conf,section,
1376109998Smarkm				ENV_DEFAULT_CRL_DAYS, &crldays))
1377109998Smarkm				crldays = 0;
1378109998Smarkm			if (!NCONF_get_number(conf,section,
1379109998Smarkm				ENV_DEFAULT_CRL_HOURS, &crlhours))
1380109998Smarkm				crlhours = 0;
138155714Skris			}
138255714Skris		if ((crldays == 0) && (crlhours == 0))
138355714Skris			{
1384100936Snectar			BIO_printf(bio_err,"cannot lookup how long until the next CRL is issued\n");
138555714Skris			goto err;
138655714Skris			}
138755714Skris
138855714Skris		if (verbose) BIO_printf(bio_err,"making CRL\n");
138955714Skris		if ((crl=X509_CRL_new()) == NULL) goto err;
1390109998Smarkm		if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) goto err;
139155714Skris
1392109998Smarkm		tmptm = ASN1_TIME_new();
1393109998Smarkm		if (!tmptm) goto err;
1394109998Smarkm		X509_gmtime_adj(tmptm,0);
1395109998Smarkm		X509_CRL_set_lastUpdate(crl, tmptm);
1396109998Smarkm		X509_gmtime_adj(tmptm,(crldays*24+crlhours)*60*60);
1397109998Smarkm		X509_CRL_set_nextUpdate(crl, tmptm);
139855714Skris
1399109998Smarkm		ASN1_TIME_free(tmptm);
1400109998Smarkm
1401127128Snectar		for (i=0; i<sk_num(db->db->data); i++)
140255714Skris			{
1403160814Ssimon			pp=(const char **)sk_value(db->db->data,i);
140455714Skris			if (pp[DB_type][0] == DB_TYPE_REV)
140555714Skris				{
140655714Skris				if ((r=X509_REVOKED_new()) == NULL) goto err;
1407109998Smarkm				j = make_revoked(r, pp[DB_rev_date]);
1408109998Smarkm				if (!j) goto err;
1409109998Smarkm				if (j == 2) crl_v2 = 1;
1410109998Smarkm				if (!BN_hex2bn(&serial, pp[DB_serial]))
141155714Skris					goto err;
1412109998Smarkm				tmpser = BN_to_ASN1_INTEGER(serial, NULL);
1413109998Smarkm				BN_free(serial);
1414109998Smarkm				serial = NULL;
1415109998Smarkm				if (!tmpser)
1416109998Smarkm					goto err;
1417109998Smarkm				X509_REVOKED_set_serialNumber(r, tmpser);
1418109998Smarkm				ASN1_INTEGER_free(tmpser);
1419109998Smarkm				X509_CRL_add0_revoked(crl,r);
142055714Skris				}
142155714Skris			}
1422109998Smarkm
142355714Skris		/* sort the data so it will be written in serial
142455714Skris		 * number order */
1425109998Smarkm		X509_CRL_sort(crl);
142655714Skris
142755714Skris		/* we now have a CRL */
142855714Skris		if (verbose) BIO_printf(bio_err,"signing CRL\n");
1429160814Ssimon#ifndef OPENSSL_NO_DSA
1430160814Ssimon		if (pkey->type == EVP_PKEY_DSA)
1431160814Ssimon			dgst=EVP_dss1();
143255714Skris		else
143355714Skris#endif
1434160814Ssimon#ifndef OPENSSL_NO_ECDSA
1435160814Ssimon		if (pkey->type == EVP_PKEY_EC)
1436160814Ssimon			dgst=EVP_ecdsa();
1437160814Ssimon#endif
143855714Skris
143955714Skris		/* Add any extensions asked for */
144055714Skris
1441127128Snectar		if (crl_ext || crlnumberfile != NULL)
1442109998Smarkm			{
1443109998Smarkm			X509V3_CTX crlctx;
1444109998Smarkm			X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1445109998Smarkm			X509V3_set_nconf(&crlctx, conf);
144655714Skris
1447127128Snectar			if (crl_ext)
1448127128Snectar				if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx,
1449127128Snectar					crl_ext, crl)) goto err;
1450127128Snectar			if (crlnumberfile != NULL)
1451127128Snectar				{
1452127128Snectar				tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL);
1453127128Snectar				if (!tmpser) goto err;
1454127128Snectar				X509_CRL_add1_ext_i2d(crl,NID_crl_number,tmpser,0,0);
1455127128Snectar				ASN1_INTEGER_free(tmpser);
1456127128Snectar				crl_v2 = 1;
1457127128Snectar				if (!BN_add_word(crlnumber,1)) goto err;
1458127128Snectar				}
1459109998Smarkm			}
1460109998Smarkm		if (crl_ext || crl_v2)
1461109998Smarkm			{
1462109998Smarkm			if (!X509_CRL_set_version(crl, 1))
1463109998Smarkm				goto err; /* version 2 CRL */
1464109998Smarkm			}
146555714Skris
1466127128Snectar
1467127128Snectar		if (crlnumberfile != NULL)	/* we have a CRL number that need updating */
1468127128Snectar			if (!save_serial(crlnumberfile,"new",crlnumber,NULL)) goto err;
1469127128Snectar
147055714Skris		if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
147155714Skris
147255714Skris		PEM_write_bio_X509_CRL(Sout,crl);
1473127128Snectar
1474127128Snectar		if (crlnumberfile != NULL)	/* Rename the crlnumber file */
1475127128Snectar			if (!rotate_serial(crlnumberfile,"new","old")) goto err;
1476127128Snectar
147755714Skris		}
147855714Skris	/*****************************************************************/
147955714Skris	if (dorevoke)
148055714Skris		{
148155714Skris		if (infile == NULL)
148255714Skris			{
148355714Skris			BIO_printf(bio_err,"no input files\n");
148455714Skris			goto err;
148555714Skris			}
148655714Skris		else
148755714Skris			{
148859191Skris			X509 *revcert;
1489109998Smarkm			revcert=load_cert(bio_err, infile, FORMAT_PEM,
1490109998Smarkm				NULL, e, infile);
149159191Skris			if (revcert == NULL)
149255714Skris				goto err;
1493109998Smarkm			j=do_revoke(revcert,db, rev_type, rev_arg);
149459191Skris			if (j <= 0) goto err;
149559191Skris			X509_free(revcert);
149655714Skris
1497127128Snectar			if (!save_index(dbfile, "new", db)) goto err;
1498109998Smarkm
1499127128Snectar			if (!rotate_index(dbfile, "new", "old")) goto err;
1500127128Snectar
150155714Skris			BIO_printf(bio_err,"Data Base Updated\n");
150255714Skris			}
150355714Skris		}
150455714Skris	/*****************************************************************/
150555714Skris	ret=0;
150655714Skriserr:
1507109998Smarkm	if(tofree)
1508109998Smarkm		OPENSSL_free(tofree);
150968651Skris	BIO_free_all(Cout);
151068651Skris	BIO_free_all(Sout);
151168651Skris	BIO_free_all(out);
1512109998Smarkm	BIO_free_all(in);
151355714Skris
1514111147Snectar	if (cert_sk)
1515111147Snectar		sk_X509_pop_free(cert_sk,X509_free);
151655714Skris
151755714Skris	if (ret) ERR_print_errors(bio_err);
151859191Skris	app_RAND_write_file(randfile, bio_err);
1519111147Snectar	if (free_key && key)
1520109998Smarkm		OPENSSL_free(key);
152155714Skris	BN_free(serial);
1522127128Snectar	free_index(db);
152355714Skris	EVP_PKEY_free(pkey);
1524160814Ssimon	if (x509) X509_free(x509);
152555714Skris	X509_CRL_free(crl);
1526109998Smarkm	NCONF_free(conf);
1527167612Ssimon	NCONF_free(extconf);
152855714Skris	OBJ_cleanup();
1529109998Smarkm	apps_shutdown();
1530109998Smarkm	OPENSSL_EXIT(ret);
153155714Skris	}
153255714Skris
1533160814Ssimonstatic void lookup_fail(const char *name, const char *tag)
153455714Skris	{
153555714Skris	BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
153655714Skris	}
153755714Skris
153855714Skrisstatic int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1539127128Snectar	     const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
1540160814Ssimon	     BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate,
1541109998Smarkm	     long days, int batch, char *ext_sect, CONF *lconf, int verbose,
1542109998Smarkm	     unsigned long certopt, unsigned long nameopt, int default_op,
1543160814Ssimon	     int ext_copy, int selfsign)
154455714Skris	{
154555714Skris	X509_REQ *req=NULL;
154655714Skris	BIO *in=NULL;
154755714Skris	EVP_PKEY *pktmp=NULL;
154855714Skris	int ok= -1,i;
154955714Skris
155055714Skris	in=BIO_new(BIO_s_file());
155155714Skris
155255714Skris	if (BIO_read_filename(in,infile) <= 0)
155355714Skris		{
155455714Skris		perror(infile);
155555714Skris		goto err;
155655714Skris		}
155755714Skris	if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
155855714Skris		{
155955714Skris		BIO_printf(bio_err,"Error reading certificate request in %s\n",
156055714Skris			infile);
156155714Skris		goto err;
156255714Skris		}
156355714Skris	if (verbose)
156455714Skris		X509_REQ_print(bio_err,req);
156555714Skris
156655714Skris	BIO_printf(bio_err,"Check that the request matches the signature\n");
156755714Skris
1568160814Ssimon	if (selfsign && !X509_REQ_check_private_key(req,pkey))
1569160814Ssimon		{
1570160814Ssimon		BIO_printf(bio_err,"Certificate request and CA private key do not match\n");
1571160814Ssimon		ok=0;
1572160814Ssimon		goto err;
1573160814Ssimon		}
157455714Skris	if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
157555714Skris		{
157655714Skris		BIO_printf(bio_err,"error unpacking public key\n");
157755714Skris		goto err;
157855714Skris		}
157955714Skris	i=X509_REQ_verify(req,pktmp);
158055714Skris	EVP_PKEY_free(pktmp);
158155714Skris	if (i < 0)
158255714Skris		{
158355714Skris		ok=0;
158455714Skris		BIO_printf(bio_err,"Signature verification problems....\n");
1585279265Sdelphij		ERR_print_errors(bio_err);
158655714Skris		goto err;
158755714Skris		}
158855714Skris	if (i == 0)
158955714Skris		{
159055714Skris		ok=0;
159155714Skris		BIO_printf(bio_err,"Signature did not match the certificate request\n");
1592279265Sdelphij		ERR_print_errors(bio_err);
159355714Skris		goto err;
159455714Skris		}
159555714Skris	else
159655714Skris		BIO_printf(bio_err,"Signature ok\n");
159755714Skris
1598160814Ssimon	ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn, email_dn,
1599109998Smarkm		startdate,enddate,days,batch,verbose,req,ext_sect,lconf,
1600160814Ssimon		certopt, nameopt, default_op, ext_copy, selfsign);
160155714Skris
160255714Skriserr:
160355714Skris	if (req != NULL) X509_REQ_free(req);
160455714Skris	if (in != NULL) BIO_free(in);
160555714Skris	return(ok);
160655714Skris	}
160755714Skris
160855714Skrisstatic int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1609127128Snectar	     const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
1610160814Ssimon	     BIGNUM *serial, char *subj, unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate,
1611109998Smarkm	     long days, int batch, char *ext_sect, CONF *lconf, int verbose,
1612109998Smarkm	     unsigned long certopt, unsigned long nameopt, int default_op,
1613109998Smarkm	     int ext_copy, ENGINE *e)
161455714Skris	{
161555714Skris	X509 *req=NULL;
161655714Skris	X509_REQ *rreq=NULL;
161755714Skris	EVP_PKEY *pktmp=NULL;
161855714Skris	int ok= -1,i;
161955714Skris
1620109998Smarkm	if ((req=load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL)
162155714Skris		goto err;
162255714Skris	if (verbose)
162355714Skris		X509_print(bio_err,req);
162455714Skris
162555714Skris	BIO_printf(bio_err,"Check that the request matches the signature\n");
162655714Skris
162755714Skris	if ((pktmp=X509_get_pubkey(req)) == NULL)
162855714Skris		{
162955714Skris		BIO_printf(bio_err,"error unpacking public key\n");
163055714Skris		goto err;
163155714Skris		}
163255714Skris	i=X509_verify(req,pktmp);
163355714Skris	EVP_PKEY_free(pktmp);
163455714Skris	if (i < 0)
163555714Skris		{
163655714Skris		ok=0;
163755714Skris		BIO_printf(bio_err,"Signature verification problems....\n");
163855714Skris		goto err;
163955714Skris		}
164055714Skris	if (i == 0)
164155714Skris		{
164255714Skris		ok=0;
164355714Skris		BIO_printf(bio_err,"Signature did not match the certificate\n");
164455714Skris		goto err;
164555714Skris		}
164655714Skris	else
164755714Skris		BIO_printf(bio_err,"Signature ok\n");
164855714Skris
164955714Skris	if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
165055714Skris		goto err;
165155714Skris
1652160814Ssimon	ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,
1653109998Smarkm		days,batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op,
1654160814Ssimon		ext_copy, 0);
165555714Skris
165655714Skriserr:
165755714Skris	if (rreq != NULL) X509_REQ_free(rreq);
165855714Skris	if (req != NULL) X509_free(req);
165955714Skris	return(ok);
166055714Skris	}
166155714Skris
166255714Skrisstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1663127128Snectar	     STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj,
1664160814Ssimon	     unsigned long chtype, int multirdn,
1665109998Smarkm	     int email_dn, char *startdate, char *enddate, long days, int batch,
1666109998Smarkm	     int verbose, X509_REQ *req, char *ext_sect, CONF *lconf,
1667109998Smarkm	     unsigned long certopt, unsigned long nameopt, int default_op,
1668160814Ssimon	     int ext_copy, int selfsign)
166955714Skris	{
1670109998Smarkm	X509_NAME *name=NULL,*CAname=NULL,*subject=NULL, *dn_subject=NULL;
167155714Skris	ASN1_UTCTIME *tm,*tmptm;
167255714Skris	ASN1_STRING *str,*str2;
167355714Skris	ASN1_OBJECT *obj;
167455714Skris	X509 *ret=NULL;
167555714Skris	X509_CINF *ci;
167655714Skris	X509_NAME_ENTRY *ne;
167755714Skris	X509_NAME_ENTRY *tne,*push;
167855714Skris	EVP_PKEY *pktmp;
167955714Skris	int ok= -1,i,j,last,nid;
1680160814Ssimon	const char *p;
168155714Skris	CONF_VALUE *cv;
1682127128Snectar	char *row[DB_NUMBER],**rrow=NULL,**irow=NULL;
1683109998Smarkm	char buf[25];
168455714Skris
168555714Skris	tmptm=ASN1_UTCTIME_new();
168655714Skris	if (tmptm == NULL)
168755714Skris		{
168855714Skris		BIO_printf(bio_err,"malloc error\n");
168955714Skris		return(0);
169055714Skris		}
169155714Skris
169255714Skris	for (i=0; i<DB_NUMBER; i++)
169355714Skris		row[i]=NULL;
169455714Skris
1695109998Smarkm	if (subj)
1696109998Smarkm		{
1697160814Ssimon		X509_NAME *n = parse_name(subj, chtype, multirdn);
1698109998Smarkm
1699109998Smarkm		if (!n)
1700109998Smarkm			{
1701109998Smarkm			ERR_print_errors(bio_err);
1702109998Smarkm			goto err;
1703109998Smarkm			}
1704109998Smarkm		X509_REQ_set_subject_name(req,n);
1705109998Smarkm		req->req_info->enc.modified = 1;
1706109998Smarkm		X509_NAME_free(n);
1707109998Smarkm		}
1708109998Smarkm
1709109998Smarkm	if (default_op)
1710109998Smarkm		BIO_printf(bio_err,"The Subject's Distinguished Name is as follows\n");
1711109998Smarkm
171255714Skris	name=X509_REQ_get_subject_name(req);
171355714Skris	for (i=0; i<X509_NAME_entry_count(name); i++)
171455714Skris		{
1715109998Smarkm		ne= X509_NAME_get_entry(name,i);
1716109998Smarkm		str=X509_NAME_ENTRY_get_data(ne);
171755714Skris		obj=X509_NAME_ENTRY_get_object(ne);
171855714Skris
171955714Skris		if (msie_hack)
172055714Skris			{
172155714Skris			/* assume all type should be strings */
172255714Skris			nid=OBJ_obj2nid(ne->object);
172355714Skris
172455714Skris			if (str->type == V_ASN1_UNIVERSALSTRING)
172555714Skris				ASN1_UNIVERSALSTRING_to_string(str);
172655714Skris
172755714Skris			if ((str->type == V_ASN1_IA5STRING) &&
172855714Skris				(nid != NID_pkcs9_emailAddress))
172955714Skris				str->type=V_ASN1_T61STRING;
173055714Skris
173155714Skris			if ((nid == NID_pkcs9_emailAddress) &&
173255714Skris				(str->type == V_ASN1_PRINTABLESTRING))
173355714Skris				str->type=V_ASN1_IA5STRING;
173455714Skris			}
173555714Skris
1736109998Smarkm		/* If no EMAIL is wanted in the subject */
1737109998Smarkm		if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn))
1738109998Smarkm			continue;
173955714Skris
174055714Skris		/* check some things */
174155714Skris		if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
174255714Skris			(str->type != V_ASN1_IA5STRING))
174355714Skris			{
174455714Skris			BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
174555714Skris			goto err;
174655714Skris			}
1747109998Smarkm		if ((str->type != V_ASN1_BMPSTRING) && (str->type != V_ASN1_UTF8STRING))
174855714Skris			{
1749109998Smarkm			j=ASN1_PRINTABLE_type(str->data,str->length);
1750109998Smarkm			if (	((j == V_ASN1_T61STRING) &&
1751109998Smarkm				 (str->type != V_ASN1_T61STRING)) ||
1752109998Smarkm				((j == V_ASN1_IA5STRING) &&
1753109998Smarkm				 (str->type == V_ASN1_PRINTABLESTRING)))
1754109998Smarkm				{
1755109998Smarkm				BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1756109998Smarkm				goto err;
1757109998Smarkm				}
175855714Skris			}
1759109998Smarkm
1760109998Smarkm		if (default_op)
1761109998Smarkm			old_entry_print(bio_err, obj, str);
176255714Skris		}
176355714Skris
176455714Skris	/* Ok, now we check the 'policy' stuff. */
176555714Skris	if ((subject=X509_NAME_new()) == NULL)
176655714Skris		{
176768651Skris		BIO_printf(bio_err,"Memory allocation failure\n");
176855714Skris		goto err;
176955714Skris		}
177055714Skris
177155714Skris	/* take a copy of the issuer name before we mess with it. */
1772160814Ssimon	if (selfsign)
1773160814Ssimon		CAname=X509_NAME_dup(name);
1774160814Ssimon	else
1775160814Ssimon		CAname=X509_NAME_dup(x509->cert_info->subject);
177655714Skris	if (CAname == NULL) goto err;
177755714Skris	str=str2=NULL;
177855714Skris
177955714Skris	for (i=0; i<sk_CONF_VALUE_num(policy); i++)
178055714Skris		{
178155714Skris		cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
178255714Skris		if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
178355714Skris			{
178455714Skris			BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
178555714Skris			goto err;
178655714Skris			}
178755714Skris		obj=OBJ_nid2obj(j);
178855714Skris
178955714Skris		last= -1;
179055714Skris		for (;;)
179155714Skris			{
179255714Skris			/* lookup the object in the supplied name list */
179355714Skris			j=X509_NAME_get_index_by_OBJ(name,obj,last);
179455714Skris			if (j < 0)
179555714Skris				{
179655714Skris				if (last != -1) break;
179755714Skris				tne=NULL;
179855714Skris				}
179955714Skris			else
180055714Skris				{
180155714Skris				tne=X509_NAME_get_entry(name,j);
180255714Skris				}
180355714Skris			last=j;
180455714Skris
180555714Skris			/* depending on the 'policy', decide what to do. */
180655714Skris			push=NULL;
180755714Skris			if (strcmp(cv->value,"optional") == 0)
180855714Skris				{
180955714Skris				if (tne != NULL)
181055714Skris					push=tne;
181155714Skris				}
181255714Skris			else if (strcmp(cv->value,"supplied") == 0)
181355714Skris				{
181455714Skris				if (tne == NULL)
181555714Skris					{
181655714Skris					BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
181755714Skris					goto err;
181855714Skris					}
181955714Skris				else
182055714Skris					push=tne;
182155714Skris				}
182255714Skris			else if (strcmp(cv->value,"match") == 0)
182355714Skris				{
182455714Skris				int last2;
182555714Skris
182655714Skris				if (tne == NULL)
182755714Skris					{
182855714Skris					BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
182955714Skris					goto err;
183055714Skris					}
183155714Skris
183255714Skris				last2= -1;
183355714Skris
183455714Skrisagain2:
183555714Skris				j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
183655714Skris				if ((j < 0) && (last2 == -1))
183755714Skris					{
183855714Skris					BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
183955714Skris					goto err;
184055714Skris					}
184155714Skris				if (j >= 0)
184255714Skris					{
184355714Skris					push=X509_NAME_get_entry(CAname,j);
184455714Skris					str=X509_NAME_ENTRY_get_data(tne);
184555714Skris					str2=X509_NAME_ENTRY_get_data(push);
184655714Skris					last2=j;
184755714Skris					if (ASN1_STRING_cmp(str,str2) != 0)
184855714Skris						goto again2;
184955714Skris					}
185055714Skris				if (j < 0)
185155714Skris					{
185259191Skris					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));
185355714Skris					goto err;
185455714Skris					}
185555714Skris				}
185655714Skris			else
185755714Skris				{
185855714Skris				BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
185955714Skris				goto err;
186055714Skris				}
186155714Skris
186255714Skris			if (push != NULL)
186355714Skris				{
186459191Skris				if (!X509_NAME_add_entry(subject,push, -1, 0))
186555714Skris					{
186655714Skris					if (push != NULL)
186755714Skris						X509_NAME_ENTRY_free(push);
186868651Skris					BIO_printf(bio_err,"Memory allocation failure\n");
186955714Skris					goto err;
187055714Skris					}
187155714Skris				}
187255714Skris			if (j < 0) break;
187355714Skris			}
187455714Skris		}
187555714Skris
187655714Skris	if (preserve)
187755714Skris		{
187855714Skris		X509_NAME_free(subject);
1879109998Smarkm		/* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */
1880109998Smarkm		subject=X509_NAME_dup(name);
188155714Skris		if (subject == NULL) goto err;
188255714Skris		}
188355714Skris
188455714Skris	if (verbose)
188559191Skris		BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
188655714Skris
1887109998Smarkm	/* Build the correct Subject if no e-mail is wanted in the subject */
1888109998Smarkm	/* and add it later on because of the method extensions are added (altName) */
1889109998Smarkm
1890109998Smarkm	if (email_dn)
1891109998Smarkm		dn_subject = subject;
1892109998Smarkm	else
189355714Skris		{
1894109998Smarkm		X509_NAME_ENTRY *tmpne;
1895109998Smarkm		/* Its best to dup the subject DN and then delete any email
1896109998Smarkm		 * addresses because this retains its structure.
1897109998Smarkm		 */
1898109998Smarkm		if (!(dn_subject = X509_NAME_dup(subject)))
1899109998Smarkm			{
1900109998Smarkm			BIO_printf(bio_err,"Memory allocation failure\n");
1901109998Smarkm			goto err;
1902109998Smarkm			}
1903109998Smarkm		while((i = X509_NAME_get_index_by_NID(dn_subject,
1904109998Smarkm					NID_pkcs9_emailAddress, -1)) >= 0)
1905109998Smarkm			{
1906109998Smarkm			tmpne = X509_NAME_get_entry(dn_subject, i);
1907109998Smarkm			X509_NAME_delete_entry(dn_subject, i);
1908109998Smarkm			X509_NAME_ENTRY_free(tmpne);
1909109998Smarkm			}
1910109998Smarkm		}
1911109998Smarkm
1912109998Smarkm	if (BN_is_zero(serial))
1913109998Smarkm		row[DB_serial]=BUF_strdup("00");
1914109998Smarkm	else
1915109998Smarkm		row[DB_serial]=BN_bn2hex(serial);
1916109998Smarkm	if (row[DB_serial] == NULL)
1917109998Smarkm		{
191868651Skris		BIO_printf(bio_err,"Memory allocation failure\n");
191955714Skris		goto err;
192055714Skris		}
192155714Skris
1922127128Snectar	if (db->attributes.unique_subject)
192355714Skris		{
1924127128Snectar		rrow=TXT_DB_get_by_index(db->db,DB_name,row);
1925127128Snectar		if (rrow != NULL)
1926127128Snectar			{
1927127128Snectar			BIO_printf(bio_err,
1928127128Snectar				"ERROR:There is already a certificate for %s\n",
1929127128Snectar				row[DB_name]);
1930127128Snectar			}
193155714Skris		}
1932127128Snectar	if (rrow == NULL)
193355714Skris		{
1934127128Snectar		rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
193555714Skris		if (rrow != NULL)
193655714Skris			{
193755714Skris			BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
193855714Skris				row[DB_serial]);
193955714Skris			BIO_printf(bio_err,"      check the database/serial_file for corruption\n");
194055714Skris			}
194155714Skris		}
194255714Skris
194355714Skris	if (rrow != NULL)
194455714Skris		{
194555714Skris		BIO_printf(bio_err,
194655714Skris			"The matching entry has the following details\n");
194755714Skris		if (rrow[DB_type][0] == 'E')
194855714Skris			p="Expired";
194955714Skris		else if (rrow[DB_type][0] == 'R')
195055714Skris			p="Revoked";
195155714Skris		else if (rrow[DB_type][0] == 'V')
195255714Skris			p="Valid";
195355714Skris		else
195455714Skris			p="\ninvalid type, Data base error\n";
195555714Skris		BIO_printf(bio_err,"Type	  :%s\n",p);;
195655714Skris		if (rrow[DB_type][0] == 'R')
195755714Skris			{
195855714Skris			p=rrow[DB_exp_date]; if (p == NULL) p="undef";
195955714Skris			BIO_printf(bio_err,"Was revoked on:%s\n",p);
196055714Skris			}
196155714Skris		p=rrow[DB_exp_date]; if (p == NULL) p="undef";
196255714Skris		BIO_printf(bio_err,"Expires on    :%s\n",p);
196355714Skris		p=rrow[DB_serial]; if (p == NULL) p="undef";
196455714Skris		BIO_printf(bio_err,"Serial Number :%s\n",p);
196555714Skris		p=rrow[DB_file]; if (p == NULL) p="undef";
196655714Skris		BIO_printf(bio_err,"File name     :%s\n",p);
196755714Skris		p=rrow[DB_name]; if (p == NULL) p="undef";
196855714Skris		BIO_printf(bio_err,"Subject Name  :%s\n",p);
196955714Skris		ok= -1; /* This is now a 'bad' error. */
197055714Skris		goto err;
197155714Skris		}
197255714Skris
197359191Skris	/* We are now totally happy, lets make and sign the certificate */
197455714Skris	if (verbose)
197555714Skris		BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
197655714Skris
197755714Skris	if ((ret=X509_new()) == NULL) goto err;
197855714Skris	ci=ret->cert_info;
197955714Skris
198055714Skris#ifdef X509_V3
198155714Skris	/* Make it an X509 v3 certificate. */
1982120631Snectar	if (!X509_set_version(ret,2)) goto err;
198355714Skris#endif
198455714Skris
198555714Skris	if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
198655714Skris		goto err;
1987160814Ssimon	if (selfsign)
1988160814Ssimon		{
1989160814Ssimon		if (!X509_set_issuer_name(ret,subject))
1990160814Ssimon			goto err;
1991160814Ssimon		}
1992160814Ssimon	else
1993160814Ssimon		{
1994160814Ssimon		if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
1995160814Ssimon			goto err;
1996160814Ssimon		}
199755714Skris
199855714Skris	if (strcmp(startdate,"today") == 0)
199955714Skris		X509_gmtime_adj(X509_get_notBefore(ret),0);
200055714Skris	else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
200155714Skris
200255714Skris	if (enddate == NULL)
200355714Skris		X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
200455714Skris	else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
200555714Skris
200655714Skris	if (!X509_set_subject_name(ret,subject)) goto err;
200755714Skris
200855714Skris	pktmp=X509_REQ_get_pubkey(req);
200955714Skris	i = X509_set_pubkey(ret,pktmp);
201055714Skris	EVP_PKEY_free(pktmp);
201155714Skris	if (!i) goto err;
201255714Skris
201355714Skris	/* Lets add the extensions, if there are any */
201455714Skris	if (ext_sect)
201555714Skris		{
201655714Skris		X509V3_CTX ctx;
201755714Skris		if (ci->version == NULL)
201855714Skris			if ((ci->version=ASN1_INTEGER_new()) == NULL)
201955714Skris				goto err;
202055714Skris		ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
202155714Skris
202255714Skris		/* Free the current entries if any, there should not
202359191Skris		 * be any I believe */
202455714Skris		if (ci->extensions != NULL)
202555714Skris			sk_X509_EXTENSION_pop_free(ci->extensions,
202655714Skris						   X509_EXTENSION_free);
202755714Skris
202855714Skris		ci->extensions = NULL;
202955714Skris
2030109998Smarkm		/* Initialize the context structure */
2031160814Ssimon		if (selfsign)
2032160814Ssimon			X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0);
2033160814Ssimon		else
2034160814Ssimon			X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
203555714Skris
2036109998Smarkm		if (extconf)
2037109998Smarkm			{
2038109998Smarkm			if (verbose)
2039109998Smarkm				BIO_printf(bio_err, "Extra configuration file found\n");
2040109998Smarkm
2041109998Smarkm			/* Use the extconf configuration db LHASH */
2042109998Smarkm			X509V3_set_nconf(&ctx, extconf);
2043109998Smarkm
2044109998Smarkm			/* Test the structure (needed?) */
2045109998Smarkm			/* X509V3_set_ctx_test(&ctx); */
204655714Skris
2047109998Smarkm			/* Adds exts contained in the configuration file */
2048109998Smarkm			if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect,ret))
2049109998Smarkm				{
2050109998Smarkm				BIO_printf(bio_err,
2051109998Smarkm				    "ERROR: adding extensions in section %s\n",
2052109998Smarkm								ext_sect);
2053109998Smarkm				ERR_print_errors(bio_err);
2054109998Smarkm				goto err;
2055109998Smarkm				}
2056109998Smarkm			if (verbose)
2057109998Smarkm				BIO_printf(bio_err, "Successfully added extensions from file.\n");
2058109998Smarkm			}
2059109998Smarkm		else if (ext_sect)
2060109998Smarkm			{
2061109998Smarkm			/* We found extensions to be set from config file */
2062109998Smarkm			X509V3_set_nconf(&ctx, lconf);
2063109998Smarkm
2064109998Smarkm			if(!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret))
2065109998Smarkm				{
2066109998Smarkm				BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2067109998Smarkm				ERR_print_errors(bio_err);
2068109998Smarkm				goto err;
2069109998Smarkm				}
2070109998Smarkm
2071109998Smarkm			if (verbose)
2072109998Smarkm				BIO_printf(bio_err, "Successfully added extensions from config\n");
2073109998Smarkm			}
207455714Skris		}
207555714Skris
2076109998Smarkm	/* Copy extensions from request (if any) */
207755714Skris
2078109998Smarkm	if (!copy_extensions(ret, req, ext_copy))
2079109998Smarkm		{
2080109998Smarkm		BIO_printf(bio_err, "ERROR: adding extensions from request\n");
2081109998Smarkm		ERR_print_errors(bio_err);
2082109998Smarkm		goto err;
2083109998Smarkm		}
2084109998Smarkm
2085109998Smarkm	/* Set the right value for the noemailDN option */
2086109998Smarkm	if( email_dn == 0 )
2087109998Smarkm		{
2088109998Smarkm		if (!X509_set_subject_name(ret,dn_subject)) goto err;
2089109998Smarkm		}
2090109998Smarkm
2091109998Smarkm	if (!default_op)
2092109998Smarkm		{
2093109998Smarkm		BIO_printf(bio_err, "Certificate Details:\n");
2094109998Smarkm		/* Never print signature details because signature not present */
2095109998Smarkm		certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
2096109998Smarkm		X509_print_ex(bio_err, ret, nameopt, certopt);
2097109998Smarkm		}
2098109998Smarkm
2099109998Smarkm	BIO_printf(bio_err,"Certificate is to be certified until ");
2100205128Ssimon	ASN1_TIME_print(bio_err,X509_get_notAfter(ret));
2101160814Ssimon	if (days) BIO_printf(bio_err," (%ld days)",days);
2102109998Smarkm	BIO_printf(bio_err, "\n");
2103109998Smarkm
210455714Skris	if (!batch)
210555714Skris		{
2106109998Smarkm
210755714Skris		BIO_printf(bio_err,"Sign the certificate? [y/n]:");
210855714Skris		(void)BIO_flush(bio_err);
210955714Skris		buf[0]='\0';
2110205128Ssimon		if (!fgets(buf,sizeof(buf)-1,stdin))
2111205128Ssimon			{
2112205128Ssimon			BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n");
2113205128Ssimon			ok=0;
2114205128Ssimon			goto err;
2115205128Ssimon			}
211655714Skris		if (!((buf[0] == 'y') || (buf[0] == 'Y')))
211755714Skris			{
211855714Skris			BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
211955714Skris			ok=0;
212055714Skris			goto err;
212155714Skris			}
212255714Skris		}
212355714Skris
212455714Skris
2125109998Smarkm#ifndef OPENSSL_NO_DSA
212655714Skris	if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
212755714Skris	pktmp=X509_get_pubkey(ret);
212855714Skris	if (EVP_PKEY_missing_parameters(pktmp) &&
212955714Skris		!EVP_PKEY_missing_parameters(pkey))
213055714Skris		EVP_PKEY_copy_parameters(pktmp,pkey);
213155714Skris	EVP_PKEY_free(pktmp);
213255714Skris#endif
2133160814Ssimon#ifndef OPENSSL_NO_ECDSA
2134160814Ssimon	if (pkey->type == EVP_PKEY_EC)
2135160814Ssimon		dgst = EVP_ecdsa();
2136160814Ssimon	pktmp = X509_get_pubkey(ret);
2137160814Ssimon	if (EVP_PKEY_missing_parameters(pktmp) &&
2138160814Ssimon		!EVP_PKEY_missing_parameters(pkey))
2139160814Ssimon		EVP_PKEY_copy_parameters(pktmp, pkey);
2140160814Ssimon	EVP_PKEY_free(pktmp);
2141160814Ssimon#endif
214255714Skris
2143160814Ssimon
214455714Skris	if (!X509_sign(ret,pkey,dgst))
214555714Skris		goto err;
214655714Skris
214755714Skris	/* We now just add it to the database */
214868651Skris	row[DB_type]=(char *)OPENSSL_malloc(2);
214955714Skris
215055714Skris	tm=X509_get_notAfter(ret);
215168651Skris	row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
215255714Skris	memcpy(row[DB_exp_date],tm->data,tm->length);
215355714Skris	row[DB_exp_date][tm->length]='\0';
215455714Skris
215555714Skris	row[DB_rev_date]=NULL;
215655714Skris
215755714Skris	/* row[DB_serial] done already */
215868651Skris	row[DB_file]=(char *)OPENSSL_malloc(8);
2159109998Smarkm	row[DB_name]=X509_NAME_oneline(X509_get_subject_name(ret),NULL,0);
216055714Skris
216155714Skris	if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2162109998Smarkm		(row[DB_file] == NULL) || (row[DB_name] == NULL))
216355714Skris		{
216468651Skris		BIO_printf(bio_err,"Memory allocation failure\n");
216555714Skris		goto err;
216655714Skris		}
2167127128Snectar	BUF_strlcpy(row[DB_file],"unknown",8);
216855714Skris	row[DB_type][0]='V';
216955714Skris	row[DB_type][1]='\0';
217055714Skris
217168651Skris	if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
217255714Skris		{
217368651Skris		BIO_printf(bio_err,"Memory allocation failure\n");
217455714Skris		goto err;
217555714Skris		}
217655714Skris
217755714Skris	for (i=0; i<DB_NUMBER; i++)
217855714Skris		{
217955714Skris		irow[i]=row[i];
218055714Skris		row[i]=NULL;
218155714Skris		}
218255714Skris	irow[DB_NUMBER]=NULL;
218355714Skris
2184127128Snectar	if (!TXT_DB_insert(db->db,irow))
218555714Skris		{
218655714Skris		BIO_printf(bio_err,"failed to update database\n");
2187127128Snectar		BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error);
218855714Skris		goto err;
218955714Skris		}
219055714Skris	ok=1;
219155714Skriserr:
219255714Skris	for (i=0; i<DB_NUMBER; i++)
219368651Skris		if (row[i] != NULL) OPENSSL_free(row[i]);
219455714Skris
219555714Skris	if (CAname != NULL)
219655714Skris		X509_NAME_free(CAname);
219755714Skris	if (subject != NULL)
219855714Skris		X509_NAME_free(subject);
2199109998Smarkm	if ((dn_subject != NULL) && !email_dn)
2200109998Smarkm		X509_NAME_free(dn_subject);
220159191Skris	if (tmptm != NULL)
220259191Skris		ASN1_UTCTIME_free(tmptm);
220355714Skris	if (ok <= 0)
220455714Skris		{
220555714Skris		if (ret != NULL) X509_free(ret);
220655714Skris		ret=NULL;
220755714Skris		}
220855714Skris	else
220955714Skris		*xret=ret;
221055714Skris	return(ok);
221155714Skris	}
221255714Skris
221359191Skrisstatic void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
221455714Skris	{
221555714Skris
221655714Skris	if (output_der)
221755714Skris		{
221855714Skris		(void)i2d_X509_bio(bp,x);
221955714Skris		return;
222055714Skris		}
222159191Skris#if 0
222259191Skris	/* ??? Not needed since X509_print prints all this stuff anyway */
222355714Skris	f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
222455714Skris	BIO_printf(bp,"issuer :%s\n",f);
222555714Skris
222655714Skris	f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
222755714Skris	BIO_printf(bp,"subject:%s\n",f);
222855714Skris
222955714Skris	BIO_puts(bp,"serial :");
223055714Skris	i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
223155714Skris	BIO_puts(bp,"\n\n");
223259191Skris#endif
2233109998Smarkm	if (!notext)X509_print(bp,x);
223455714Skris	PEM_write_bio_X509(bp,x);
223555714Skris	}
223655714Skris
223755714Skrisstatic int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
2238127128Snectar	     const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
2239160814Ssimon	     BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate,
2240109998Smarkm	     long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt,
2241109998Smarkm	     unsigned long nameopt, int default_op, int ext_copy)
224255714Skris	{
224355714Skris	STACK_OF(CONF_VALUE) *sk=NULL;
224455714Skris	LHASH *parms=NULL;
224555714Skris	X509_REQ *req=NULL;
224655714Skris	CONF_VALUE *cv=NULL;
224755714Skris	NETSCAPE_SPKI *spki = NULL;
224855714Skris	X509_REQ_INFO *ri;
224955714Skris	char *type,*buf;
225055714Skris	EVP_PKEY *pktmp=NULL;
225155714Skris	X509_NAME *n=NULL;
225255714Skris	X509_NAME_ENTRY *ne=NULL;
225355714Skris	int ok= -1,i,j;
225455714Skris	long errline;
225555714Skris	int nid;
225655714Skris
225755714Skris	/*
225855714Skris	 * Load input file into a hash table.  (This is just an easy
225955714Skris	 * way to read and parse the file, then put it into a convenient
226055714Skris	 * STACK format).
226155714Skris	 */
226255714Skris	parms=CONF_load(NULL,infile,&errline);
226355714Skris	if (parms == NULL)
226455714Skris		{
226555714Skris		BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
226655714Skris		ERR_print_errors(bio_err);
226755714Skris		goto err;
226855714Skris		}
226955714Skris
227055714Skris	sk=CONF_get_section(parms, "default");
227155714Skris	if (sk_CONF_VALUE_num(sk) == 0)
227255714Skris		{
227355714Skris		BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
227455714Skris		CONF_free(parms);
227555714Skris		goto err;
227655714Skris		}
227755714Skris
227855714Skris	/*
227955714Skris	 * Now create a dummy X509 request structure.  We don't actually
228055714Skris	 * have an X509 request, but we have many of the components
228155714Skris	 * (a public key, various DN components).  The idea is that we
228255714Skris	 * put these components into the right X509 request structure
228355714Skris	 * and we can use the same code as if you had a real X509 request.
228455714Skris	 */
228555714Skris	req=X509_REQ_new();
228655714Skris	if (req == NULL)
228755714Skris		{
228855714Skris		ERR_print_errors(bio_err);
228955714Skris		goto err;
229055714Skris		}
229155714Skris
229255714Skris	/*
229355714Skris	 * Build up the subject name set.
229455714Skris	 */
229555714Skris	ri=req->req_info;
229655714Skris	n = ri->subject;
229755714Skris
229855714Skris	for (i = 0; ; i++)
229955714Skris		{
230055714Skris		if (sk_CONF_VALUE_num(sk) <= i) break;
230155714Skris
230255714Skris		cv=sk_CONF_VALUE_value(sk,i);
230355714Skris		type=cv->name;
230459191Skris		/* Skip past any leading X. X: X, etc to allow for
230559191Skris		 * multiple instances
230659191Skris		 */
2307109998Smarkm		for (buf = cv->name; *buf ; buf++)
2308109998Smarkm			if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2309109998Smarkm				{
2310109998Smarkm				buf++;
2311109998Smarkm				if (*buf) type = buf;
2312109998Smarkm				break;
2313109998Smarkm				}
231459191Skris
231555714Skris		buf=cv->value;
231655714Skris		if ((nid=OBJ_txt2nid(type)) == NID_undef)
231755714Skris			{
231855714Skris			if (strcmp(type, "SPKAC") == 0)
231955714Skris				{
232059191Skris				spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
232155714Skris				if (spki == NULL)
232255714Skris					{
232355714Skris					BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
232455714Skris					ERR_print_errors(bio_err);
232555714Skris					goto err;
232655714Skris					}
232755714Skris				}
232855714Skris			continue;
232955714Skris			}
233055714Skris
2331205128Ssimon		if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
2332205128Ssimon				(unsigned char *)buf, -1, -1, 0))
233355714Skris			goto err;
233455714Skris		}
233555714Skris	if (spki == NULL)
233655714Skris		{
233755714Skris		BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
233855714Skris			infile);
233955714Skris		goto err;
234055714Skris		}
234155714Skris
234255714Skris	/*
234355714Skris	 * Now extract the key from the SPKI structure.
234455714Skris	 */
234555714Skris
234655714Skris	BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
234755714Skris
234859191Skris	if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
234955714Skris		{
235055714Skris		BIO_printf(bio_err,"error unpacking SPKAC public key\n");
235155714Skris		goto err;
235255714Skris		}
235355714Skris
235455714Skris	j = NETSCAPE_SPKI_verify(spki, pktmp);
235555714Skris	if (j <= 0)
235655714Skris		{
235755714Skris		BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
235855714Skris		goto err;
235955714Skris		}
236055714Skris	BIO_printf(bio_err,"Signature ok\n");
236155714Skris
236255714Skris	X509_REQ_set_pubkey(req,pktmp);
236355714Skris	EVP_PKEY_free(pktmp);
2364160814Ssimon	ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,
2365109998Smarkm		   days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op,
2366160814Ssimon			ext_copy, 0);
236755714Skriserr:
236855714Skris	if (req != NULL) X509_REQ_free(req);
236955714Skris	if (parms != NULL) CONF_free(parms);
237055714Skris	if (spki != NULL) NETSCAPE_SPKI_free(spki);
237155714Skris	if (ne != NULL) X509_NAME_ENTRY_free(ne);
237255714Skris
237355714Skris	return(ok);
237455714Skris	}
237555714Skris
2376205128Ssimonstatic int check_time_format(const char *str)
237755714Skris	{
2378205128Ssimon	ASN1_TIME tm;
237955714Skris
238055714Skris	tm.data=(unsigned char *)str;
238155714Skris	tm.length=strlen(str);
238255714Skris	tm.type=V_ASN1_UTCTIME;
2383205128Ssimon	if (ASN1_TIME_check(&tm))
2384205128Ssimon		return 1;
2385205128Ssimon	tm.type=V_ASN1_GENERALIZEDTIME;
2386205128Ssimon	return ASN1_TIME_check(&tm);
238755714Skris	}
238855714Skris
2389127128Snectarstatic int do_revoke(X509 *x509, CA_DB *db, int type, char *value)
2390109998Smarkm	{
2391109998Smarkm	ASN1_UTCTIME *tm=NULL;
239255714Skris	char *row[DB_NUMBER],**rrow,**irow;
2393109998Smarkm	char *rev_str = NULL;
239459191Skris	BIGNUM *bn = NULL;
239555714Skris	int ok=-1,i;
239655714Skris
239755714Skris	for (i=0; i<DB_NUMBER; i++)
239855714Skris		row[i]=NULL;
239959191Skris	row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
240059191Skris	bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2401109998Smarkm	if (BN_is_zero(bn))
2402109998Smarkm		row[DB_serial]=BUF_strdup("00");
2403109998Smarkm	else
2404109998Smarkm		row[DB_serial]=BN_bn2hex(bn);
240559191Skris	BN_free(bn);
240655714Skris	if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
240755714Skris		{
240868651Skris		BIO_printf(bio_err,"Memory allocation failure\n");
240955714Skris		goto err;
241055714Skris		}
241159191Skris	/* We have to lookup by serial number because name lookup
241259191Skris	 * skips revoked certs
241359191Skris 	 */
2414127128Snectar	rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
241555714Skris	if (rrow == NULL)
241655714Skris		{
2417127128Snectar		BIO_printf(bio_err,"Adding Entry with serial number %s to DB for %s\n", row[DB_serial], row[DB_name]);
241855714Skris
241955714Skris		/* We now just add it to the database */
242068651Skris		row[DB_type]=(char *)OPENSSL_malloc(2);
242155714Skris
242255714Skris		tm=X509_get_notAfter(x509);
242368651Skris		row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
242455714Skris		memcpy(row[DB_exp_date],tm->data,tm->length);
242555714Skris		row[DB_exp_date][tm->length]='\0';
242655714Skris
242755714Skris		row[DB_rev_date]=NULL;
242855714Skris
242955714Skris		/* row[DB_serial] done already */
243068651Skris		row[DB_file]=(char *)OPENSSL_malloc(8);
243155714Skris
243255714Skris		/* row[DB_name] done already */
243355714Skris
243455714Skris		if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
243555714Skris			(row[DB_file] == NULL))
243655714Skris			{
243768651Skris			BIO_printf(bio_err,"Memory allocation failure\n");
243855714Skris			goto err;
243955714Skris			}
2440127128Snectar		BUF_strlcpy(row[DB_file],"unknown",8);
244155714Skris		row[DB_type][0]='V';
244255714Skris		row[DB_type][1]='\0';
244355714Skris
244468651Skris		if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
244555714Skris			{
244668651Skris			BIO_printf(bio_err,"Memory allocation failure\n");
244755714Skris			goto err;
244855714Skris			}
244955714Skris
245055714Skris		for (i=0; i<DB_NUMBER; i++)
245155714Skris			{
245255714Skris			irow[i]=row[i];
245355714Skris			row[i]=NULL;
245455714Skris			}
245555714Skris		irow[DB_NUMBER]=NULL;
245655714Skris
2457127128Snectar		if (!TXT_DB_insert(db->db,irow))
245855714Skris			{
245955714Skris			BIO_printf(bio_err,"failed to update database\n");
2460127128Snectar			BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error);
246155714Skris			goto err;
246255714Skris			}
246355714Skris
246455714Skris		/* Revoke Certificate */
2465109998Smarkm		ok = do_revoke(x509,db, type, value);
246655714Skris
246755714Skris		goto err;
246855714Skris
246955714Skris		}
2470109998Smarkm	else if (index_name_cmp((const char **)row,(const char **)rrow))
247155714Skris		{
247259191Skris		BIO_printf(bio_err,"ERROR:name does not match %s\n",
247359191Skris			   row[DB_name]);
247455714Skris		goto err;
247555714Skris		}
247655714Skris	else if (rrow[DB_type][0]=='R')
247755714Skris		{
247855714Skris		BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
247955714Skris			   row[DB_serial]);
248055714Skris		goto err;
248155714Skris		}
248255714Skris	else
248355714Skris		{
248455714Skris		BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2485109998Smarkm		rev_str = make_revocation_str(type, value);
2486109998Smarkm		if (!rev_str)
2487109998Smarkm			{
2488109998Smarkm			BIO_printf(bio_err, "Error in revocation arguments\n");
2489109998Smarkm			goto err;
2490109998Smarkm			}
249155714Skris		rrow[DB_type][0]='R';
249255714Skris		rrow[DB_type][1]='\0';
2493109998Smarkm		rrow[DB_rev_date] = rev_str;
249455714Skris		}
249555714Skris	ok=1;
249655714Skriserr:
249755714Skris	for (i=0; i<DB_NUMBER; i++)
249855714Skris		{
249955714Skris		if (row[i] != NULL)
250068651Skris			OPENSSL_free(row[i]);
250155714Skris		}
250255714Skris	return(ok);
2503109998Smarkm	}
2504109998Smarkm
2505127128Snectarstatic int get_certificate_status(const char *serial, CA_DB *db)
2506109998Smarkm	{
2507109998Smarkm	char *row[DB_NUMBER],**rrow;
2508109998Smarkm	int ok=-1,i;
2509109998Smarkm
2510109998Smarkm	/* Free Resources */
2511109998Smarkm	for (i=0; i<DB_NUMBER; i++)
2512109998Smarkm		row[i]=NULL;
2513109998Smarkm
2514109998Smarkm	/* Malloc needed char spaces */
2515109998Smarkm	row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2516109998Smarkm	if (row[DB_serial] == NULL)
2517109998Smarkm		{
2518109998Smarkm		BIO_printf(bio_err,"Malloc failure\n");
2519109998Smarkm		goto err;
2520109998Smarkm		}
2521109998Smarkm
2522109998Smarkm	if (strlen(serial) % 2)
2523109998Smarkm		{
2524109998Smarkm		/* Set the first char to 0 */;
2525109998Smarkm		row[DB_serial][0]='0';
2526109998Smarkm
2527109998Smarkm		/* Copy String from serial to row[DB_serial] */
2528109998Smarkm		memcpy(row[DB_serial]+1, serial, strlen(serial));
2529109998Smarkm		row[DB_serial][strlen(serial)+1]='\0';
2530109998Smarkm		}
2531109998Smarkm	else
2532109998Smarkm		{
2533109998Smarkm		/* Copy String from serial to row[DB_serial] */
2534109998Smarkm		memcpy(row[DB_serial], serial, strlen(serial));
2535109998Smarkm		row[DB_serial][strlen(serial)]='\0';
2536109998Smarkm		}
2537109998Smarkm
2538109998Smarkm	/* Make it Upper Case */
2539109998Smarkm	for (i=0; row[DB_serial][i] != '\0'; i++)
2540109998Smarkm		row[DB_serial][i] = toupper(row[DB_serial][i]);
2541109998Smarkm
2542109998Smarkm
2543109998Smarkm	ok=1;
2544109998Smarkm
2545109998Smarkm	/* Search for the certificate */
2546127128Snectar	rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
2547109998Smarkm	if (rrow == NULL)
2548109998Smarkm		{
2549109998Smarkm		BIO_printf(bio_err,"Serial %s not present in db.\n",
2550109998Smarkm				 row[DB_serial]);
2551109998Smarkm		ok=-1;
2552109998Smarkm		goto err;
2553109998Smarkm		}
2554109998Smarkm	else if (rrow[DB_type][0]=='V')
2555109998Smarkm		{
2556109998Smarkm		BIO_printf(bio_err,"%s=Valid (%c)\n",
2557109998Smarkm			row[DB_serial], rrow[DB_type][0]);
2558109998Smarkm		goto err;
2559109998Smarkm		}
2560109998Smarkm	else if (rrow[DB_type][0]=='R')
2561109998Smarkm		{
2562109998Smarkm		BIO_printf(bio_err,"%s=Revoked (%c)\n",
2563109998Smarkm			row[DB_serial], rrow[DB_type][0]);
2564109998Smarkm		goto err;
2565109998Smarkm		}
2566109998Smarkm	else if (rrow[DB_type][0]=='E')
2567109998Smarkm		{
2568109998Smarkm		BIO_printf(bio_err,"%s=Expired (%c)\n",
2569109998Smarkm			row[DB_serial], rrow[DB_type][0]);
2570109998Smarkm		goto err;
2571109998Smarkm		}
2572109998Smarkm	else if (rrow[DB_type][0]=='S')
2573109998Smarkm		{
2574109998Smarkm		BIO_printf(bio_err,"%s=Suspended (%c)\n",
2575109998Smarkm			row[DB_serial], rrow[DB_type][0]);
2576109998Smarkm		goto err;
2577109998Smarkm		}
2578109998Smarkm	else
2579109998Smarkm		{
2580109998Smarkm		BIO_printf(bio_err,"%s=Unknown (%c).\n",
2581109998Smarkm			row[DB_serial], rrow[DB_type][0]);
2582109998Smarkm		ok=-1;
2583109998Smarkm		}
2584109998Smarkmerr:
2585109998Smarkm	for (i=0; i<DB_NUMBER; i++)
2586109998Smarkm		{
2587109998Smarkm		if (row[i] != NULL)
2588109998Smarkm			OPENSSL_free(row[i]);
2589109998Smarkm		}
2590109998Smarkm	return(ok);
2591109998Smarkm	}
2592109998Smarkm
2593127128Snectarstatic int do_updatedb (CA_DB *db)
2594109998Smarkm	{
2595109998Smarkm	ASN1_UTCTIME	*a_tm = NULL;
2596109998Smarkm	int i, cnt = 0;
2597109998Smarkm	int db_y2k, a_y2k;  /* flags = 1 if y >= 2000 */
2598109998Smarkm	char **rrow, *a_tm_s;
2599109998Smarkm
2600109998Smarkm	a_tm = ASN1_UTCTIME_new();
2601109998Smarkm
2602109998Smarkm	/* get actual time and make a string */
2603109998Smarkm	a_tm = X509_gmtime_adj(a_tm, 0);
2604109998Smarkm	a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2605109998Smarkm	if (a_tm_s == NULL)
2606109998Smarkm		{
2607109998Smarkm		cnt = -1;
2608109998Smarkm		goto err;
2609109998Smarkm		}
2610109998Smarkm
2611109998Smarkm	memcpy(a_tm_s, a_tm->data, a_tm->length);
2612109998Smarkm	a_tm_s[a_tm->length] = '\0';
2613109998Smarkm
2614109998Smarkm	if (strncmp(a_tm_s, "49", 2) <= 0)
2615109998Smarkm		a_y2k = 1;
2616109998Smarkm	else
2617109998Smarkm		a_y2k = 0;
2618109998Smarkm
2619127128Snectar	for (i = 0; i < sk_num(db->db->data); i++)
2620109998Smarkm		{
2621127128Snectar		rrow = (char **) sk_value(db->db->data, i);
2622109998Smarkm
2623109998Smarkm		if (rrow[DB_type][0] == 'V')
2624109998Smarkm		 	{
2625109998Smarkm			/* ignore entries that are not valid */
2626109998Smarkm			if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2627109998Smarkm				db_y2k = 1;
2628109998Smarkm			else
2629109998Smarkm				db_y2k = 0;
2630109998Smarkm
2631109998Smarkm			if (db_y2k == a_y2k)
2632109998Smarkm				{
2633109998Smarkm				/* all on the same y2k side */
2634109998Smarkm				if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2635109998Smarkm				       	{
2636109998Smarkm				       	rrow[DB_type][0]  = 'E';
2637109998Smarkm				       	rrow[DB_type][1]  = '\0';
2638109998Smarkm	  				cnt++;
2639109998Smarkm
2640109998Smarkm					BIO_printf(bio_err, "%s=Expired\n",
2641109998Smarkm							rrow[DB_serial]);
2642109998Smarkm					}
2643109998Smarkm				}
2644109998Smarkm			else if (db_y2k < a_y2k)
2645109998Smarkm				{
2646109998Smarkm		  		rrow[DB_type][0]  = 'E';
2647109998Smarkm		  		rrow[DB_type][1]  = '\0';
2648109998Smarkm	  			cnt++;
2649109998Smarkm
2650109998Smarkm				BIO_printf(bio_err, "%s=Expired\n",
2651109998Smarkm							rrow[DB_serial]);
2652109998Smarkm				}
2653109998Smarkm
2654109998Smarkm			}
2655109998Smarkm    		}
2656109998Smarkm
2657109998Smarkmerr:
2658109998Smarkm
2659109998Smarkm	ASN1_UTCTIME_free(a_tm);
2660109998Smarkm	OPENSSL_free(a_tm_s);
2661109998Smarkm
2662109998Smarkm	return (cnt);
2663109998Smarkm	}
2664109998Smarkm
2665160814Ssimonstatic const char *crl_reasons[] = {
2666109998Smarkm	/* CRL reason strings */
2667109998Smarkm	"unspecified",
2668109998Smarkm	"keyCompromise",
2669109998Smarkm	"CACompromise",
2670109998Smarkm	"affiliationChanged",
2671109998Smarkm	"superseded",
2672109998Smarkm	"cessationOfOperation",
2673109998Smarkm	"certificateHold",
2674109998Smarkm	"removeFromCRL",
2675109998Smarkm	/* Additional pseudo reasons */
2676109998Smarkm	"holdInstruction",
2677109998Smarkm	"keyTime",
2678109998Smarkm	"CAkeyTime"
2679109998Smarkm};
2680109998Smarkm
2681109998Smarkm#define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2682109998Smarkm
2683109998Smarkm/* Given revocation information convert to a DB string.
2684109998Smarkm * The format of the string is:
2685109998Smarkm * revtime[,reason,extra]. Where 'revtime' is the
2686109998Smarkm * revocation time (the current time). 'reason' is the
2687109998Smarkm * optional CRL reason and 'extra' is any additional
2688109998Smarkm * argument
2689109998Smarkm */
2690109998Smarkm
2691109998Smarkmchar *make_revocation_str(int rev_type, char *rev_arg)
2692109998Smarkm	{
2693160814Ssimon	char *other = NULL, *str;
2694160814Ssimon	const char *reason = NULL;
2695109998Smarkm	ASN1_OBJECT *otmp;
2696109998Smarkm	ASN1_UTCTIME *revtm = NULL;
2697109998Smarkm	int i;
2698109998Smarkm	switch (rev_type)
2699109998Smarkm		{
2700109998Smarkm	case REV_NONE:
2701109998Smarkm		break;
2702109998Smarkm
2703109998Smarkm	case REV_CRL_REASON:
2704109998Smarkm		for (i = 0; i < 8; i++)
2705109998Smarkm			{
2706109998Smarkm			if (!strcasecmp(rev_arg, crl_reasons[i]))
2707109998Smarkm				{
2708109998Smarkm				reason = crl_reasons[i];
2709109998Smarkm				break;
2710109998Smarkm				}
2711109998Smarkm			}
2712109998Smarkm		if (reason == NULL)
2713109998Smarkm			{
2714109998Smarkm			BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2715109998Smarkm			return NULL;
2716109998Smarkm			}
2717109998Smarkm		break;
2718109998Smarkm
2719109998Smarkm	case REV_HOLD:
2720109998Smarkm		/* Argument is an OID */
2721109998Smarkm
2722109998Smarkm		otmp = OBJ_txt2obj(rev_arg, 0);
2723109998Smarkm		ASN1_OBJECT_free(otmp);
2724109998Smarkm
2725109998Smarkm		if (otmp == NULL)
2726109998Smarkm			{
2727109998Smarkm			BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2728109998Smarkm			return NULL;
2729109998Smarkm			}
2730109998Smarkm
2731109998Smarkm		reason = "holdInstruction";
2732109998Smarkm		other = rev_arg;
2733109998Smarkm		break;
2734109998Smarkm
2735109998Smarkm	case REV_KEY_COMPROMISE:
2736109998Smarkm	case REV_CA_COMPROMISE:
2737109998Smarkm
2738109998Smarkm		/* Argument is the key compromise time  */
2739109998Smarkm		if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg))
2740109998Smarkm			{
2741109998Smarkm			BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg);
2742109998Smarkm			return NULL;
2743109998Smarkm			}
2744109998Smarkm		other = rev_arg;
2745109998Smarkm		if (rev_type == REV_KEY_COMPROMISE)
2746109998Smarkm			reason = "keyTime";
2747109998Smarkm		else
2748109998Smarkm			reason = "CAkeyTime";
2749109998Smarkm
2750109998Smarkm		break;
2751109998Smarkm
2752109998Smarkm		}
2753109998Smarkm
2754109998Smarkm	revtm = X509_gmtime_adj(NULL, 0);
2755109998Smarkm
2756279265Sdelphij	if (!revtm)
2757279265Sdelphij		return NULL;
2758279265Sdelphij
2759109998Smarkm	i = revtm->length + 1;
2760109998Smarkm
2761109998Smarkm	if (reason) i += strlen(reason) + 1;
2762109998Smarkm	if (other) i += strlen(other) + 1;
2763109998Smarkm
2764109998Smarkm	str = OPENSSL_malloc(i);
2765109998Smarkm
2766109998Smarkm	if (!str) return NULL;
2767109998Smarkm
2768127128Snectar	BUF_strlcpy(str, (char *)revtm->data, i);
2769109998Smarkm	if (reason)
2770109998Smarkm		{
2771127128Snectar		BUF_strlcat(str, ",", i);
2772127128Snectar		BUF_strlcat(str, reason, i);
2773109998Smarkm		}
2774109998Smarkm	if (other)
2775109998Smarkm		{
2776127128Snectar		BUF_strlcat(str, ",", i);
2777127128Snectar		BUF_strlcat(str, other, i);
2778109998Smarkm		}
2779109998Smarkm	ASN1_UTCTIME_free(revtm);
2780109998Smarkm	return str;
2781109998Smarkm	}
2782109998Smarkm
2783109998Smarkm/* Convert revocation field to X509_REVOKED entry
2784109998Smarkm * return code:
2785109998Smarkm * 0 error
2786109998Smarkm * 1 OK
2787109998Smarkm * 2 OK and some extensions added (i.e. V2 CRL)
2788109998Smarkm */
2789109998Smarkm
2790109998Smarkm
2791160814Ssimonint make_revoked(X509_REVOKED *rev, const char *str)
2792109998Smarkm	{
2793109998Smarkm	char *tmp = NULL;
2794109998Smarkm	int reason_code = -1;
2795109998Smarkm	int i, ret = 0;
2796109998Smarkm	ASN1_OBJECT *hold = NULL;
2797109998Smarkm	ASN1_GENERALIZEDTIME *comp_time = NULL;
2798109998Smarkm	ASN1_ENUMERATED *rtmp = NULL;
2799109998Smarkm
2800109998Smarkm	ASN1_TIME *revDate = NULL;
2801109998Smarkm
2802109998Smarkm	i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str);
2803109998Smarkm
2804109998Smarkm	if (i == 0)
2805109998Smarkm		goto err;
2806109998Smarkm
2807109998Smarkm	if (rev && !X509_REVOKED_set_revocationDate(rev, revDate))
2808109998Smarkm		goto err;
2809109998Smarkm
2810109998Smarkm	if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
2811109998Smarkm		{
2812109998Smarkm		rtmp = ASN1_ENUMERATED_new();
2813109998Smarkm		if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
2814109998Smarkm			goto err;
2815109998Smarkm		if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
2816109998Smarkm			goto err;
2817109998Smarkm		}
2818109998Smarkm
2819109998Smarkm	if (rev && comp_time)
2820109998Smarkm		{
2821109998Smarkm		if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
2822109998Smarkm			goto err;
2823109998Smarkm		}
2824109998Smarkm	if (rev && hold)
2825109998Smarkm		{
2826109998Smarkm		if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
2827109998Smarkm			goto err;
2828109998Smarkm		}
2829109998Smarkm
2830109998Smarkm	if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
2831109998Smarkm		ret = 2;
2832109998Smarkm	else ret = 1;
2833109998Smarkm
2834109998Smarkm	err:
2835109998Smarkm
2836109998Smarkm	if (tmp) OPENSSL_free(tmp);
2837109998Smarkm	ASN1_OBJECT_free(hold);
2838109998Smarkm	ASN1_GENERALIZEDTIME_free(comp_time);
2839109998Smarkm	ASN1_ENUMERATED_free(rtmp);
2840109998Smarkm	ASN1_TIME_free(revDate);
2841109998Smarkm
2842109998Smarkm	return ret;
2843109998Smarkm	}
2844109998Smarkm
2845109998Smarkmint old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
2846109998Smarkm	{
2847109998Smarkm	char buf[25],*pbuf, *p;
2848109998Smarkm	int j;
2849109998Smarkm	j=i2a_ASN1_OBJECT(bp,obj);
2850109998Smarkm	pbuf=buf;
2851109998Smarkm	for (j=22-j; j>0; j--)
2852109998Smarkm		*(pbuf++)=' ';
2853109998Smarkm	*(pbuf++)=':';
2854109998Smarkm	*(pbuf++)='\0';
2855109998Smarkm	BIO_puts(bp,buf);
2856109998Smarkm
2857109998Smarkm	if (str->type == V_ASN1_PRINTABLESTRING)
2858109998Smarkm		BIO_printf(bp,"PRINTABLE:'");
2859109998Smarkm	else if (str->type == V_ASN1_T61STRING)
2860109998Smarkm		BIO_printf(bp,"T61STRING:'");
2861109998Smarkm	else if (str->type == V_ASN1_IA5STRING)
2862109998Smarkm		BIO_printf(bp,"IA5STRING:'");
2863109998Smarkm	else if (str->type == V_ASN1_UNIVERSALSTRING)
2864109998Smarkm		BIO_printf(bp,"UNIVERSALSTRING:'");
2865109998Smarkm	else
2866109998Smarkm		BIO_printf(bp,"ASN.1 %2d:'",str->type);
2867109998Smarkm
2868109998Smarkm	p=(char *)str->data;
2869109998Smarkm	for (j=str->length; j>0; j--)
2870109998Smarkm		{
2871194206Ssimon#ifdef CHARSET_EBCDIC
2872194206Ssimon		if ((*p >= 0x20) && (*p <= 0x7e))
2873194206Ssimon			BIO_printf(bp,"%c",os_toebcdic[*p]);
2874194206Ssimon#else
2875109998Smarkm		if ((*p >= ' ') && (*p <= '~'))
2876109998Smarkm			BIO_printf(bp,"%c",*p);
2877194206Ssimon#endif
2878109998Smarkm		else if (*p & 0x80)
2879109998Smarkm			BIO_printf(bp,"\\0x%02X",*p);
2880109998Smarkm		else if ((unsigned char)*p == 0xf7)
2881109998Smarkm			BIO_printf(bp,"^?");
2882194206Ssimon#ifdef CHARSET_EBCDIC
2883194206Ssimon		else	BIO_printf(bp,"^%c",os_toebcdic[*p+0x40]);
2884194206Ssimon#else
2885109998Smarkm		else	BIO_printf(bp,"^%c",*p+'@');
2886194206Ssimon#endif
2887109998Smarkm		p++;
2888109998Smarkm		}
2889109998Smarkm	BIO_printf(bp,"'\n");
2890109998Smarkm	return 1;
2891109998Smarkm	}
2892109998Smarkm
2893160814Ssimonint unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, const char *str)
2894109998Smarkm	{
2895109998Smarkm	char *tmp = NULL;
2896109998Smarkm	char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
2897109998Smarkm	int reason_code = -1;
2898160814Ssimon	int ret = 0;
2899160814Ssimon	unsigned int i;
2900109998Smarkm	ASN1_OBJECT *hold = NULL;
2901109998Smarkm	ASN1_GENERALIZEDTIME *comp_time = NULL;
2902109998Smarkm	tmp = BUF_strdup(str);
2903109998Smarkm
2904109998Smarkm	p = strchr(tmp, ',');
2905109998Smarkm
2906109998Smarkm	rtime_str = tmp;
2907109998Smarkm
2908109998Smarkm	if (p)
2909109998Smarkm		{
2910109998Smarkm		*p = '\0';
2911109998Smarkm		p++;
2912109998Smarkm		reason_str = p;
2913109998Smarkm		p = strchr(p, ',');
2914109998Smarkm		if (p)
2915109998Smarkm			{
2916109998Smarkm			*p = '\0';
2917109998Smarkm			arg_str = p + 1;
2918109998Smarkm			}
2919109998Smarkm		}
2920109998Smarkm
2921109998Smarkm	if (prevtm)
2922109998Smarkm		{
2923109998Smarkm		*prevtm = ASN1_UTCTIME_new();
2924109998Smarkm		if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str))
2925109998Smarkm			{
2926109998Smarkm			BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
2927109998Smarkm			goto err;
2928109998Smarkm			}
2929109998Smarkm		}
2930109998Smarkm	if (reason_str)
2931109998Smarkm		{
2932109998Smarkm		for (i = 0; i < NUM_REASONS; i++)
2933109998Smarkm			{
2934109998Smarkm			if(!strcasecmp(reason_str, crl_reasons[i]))
2935109998Smarkm				{
2936109998Smarkm				reason_code = i;
2937109998Smarkm				break;
2938109998Smarkm				}
2939109998Smarkm			}
2940109998Smarkm		if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS)
2941109998Smarkm			{
2942109998Smarkm			BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
2943109998Smarkm			goto err;
2944109998Smarkm			}
2945109998Smarkm
2946109998Smarkm		if (reason_code == 7)
2947109998Smarkm			reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
2948109998Smarkm		else if (reason_code == 8)		/* Hold instruction */
2949109998Smarkm			{
2950109998Smarkm			if (!arg_str)
2951109998Smarkm				{
2952109998Smarkm				BIO_printf(bio_err, "missing hold instruction\n");
2953109998Smarkm				goto err;
2954109998Smarkm				}
2955109998Smarkm			reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
2956109998Smarkm			hold = OBJ_txt2obj(arg_str, 0);
2957109998Smarkm
2958109998Smarkm			if (!hold)
2959109998Smarkm				{
2960109998Smarkm				BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
2961109998Smarkm				goto err;
2962109998Smarkm				}
2963109998Smarkm			if (phold) *phold = hold;
2964109998Smarkm			}
2965109998Smarkm		else if ((reason_code == 9) || (reason_code == 10))
2966109998Smarkm			{
2967109998Smarkm			if (!arg_str)
2968109998Smarkm				{
2969109998Smarkm				BIO_printf(bio_err, "missing compromised time\n");
2970109998Smarkm				goto err;
2971109998Smarkm				}
2972109998Smarkm			comp_time = ASN1_GENERALIZEDTIME_new();
2973109998Smarkm			if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str))
2974109998Smarkm				{
2975109998Smarkm				BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
2976109998Smarkm				goto err;
2977109998Smarkm				}
2978109998Smarkm			if (reason_code == 9)
2979109998Smarkm				reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
2980109998Smarkm			else
2981109998Smarkm				reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
2982109998Smarkm			}
2983109998Smarkm		}
2984109998Smarkm
2985109998Smarkm	if (preason) *preason = reason_code;
2986109998Smarkm	if (pinvtm) *pinvtm = comp_time;
2987109998Smarkm	else ASN1_GENERALIZEDTIME_free(comp_time);
2988109998Smarkm
2989109998Smarkm	ret = 1;
2990109998Smarkm
2991109998Smarkm	err:
2992109998Smarkm
2993109998Smarkm	if (tmp) OPENSSL_free(tmp);
2994109998Smarkm	if (!phold) ASN1_OBJECT_free(hold);
2995109998Smarkm	if (!pinvtm) ASN1_GENERALIZEDTIME_free(comp_time);
2996109998Smarkm
2997109998Smarkm	return ret;
2998109998Smarkm	}
2999