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 <openssl/conf.h>
6755714Skris#include <openssl/bio.h>
6855714Skris#include <openssl/err.h>
6955714Skris#include <openssl/bn.h>
7055714Skris#include <openssl/txt_db.h>
7155714Skris#include <openssl/evp.h>
7255714Skris#include <openssl/x509.h>
7355714Skris#include <openssl/x509v3.h>
7455714Skris#include <openssl/objects.h>
75109998Smarkm#include <openssl/ocsp.h>
7655714Skris#include <openssl/pem.h>
7755714Skris
7855714Skris#ifndef W_OK
79109998Smarkm#  ifdef OPENSSL_SYS_VMS
8055714Skris#    if defined(__DECC)
8155714Skris#      include <unistd.h>
8255714Skris#    else
8355714Skris#      include <unixlib.h>
8455714Skris#    endif
85238405Sjkim#  elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_NETWARE)
8655714Skris#    include <sys/file.h>
8755714Skris#  endif
8855714Skris#endif
8955714Skris
90109998Smarkm#include "apps.h"
91109998Smarkm
9255714Skris#ifndef W_OK
9355714Skris#  define F_OK 0
9455714Skris#  define X_OK 1
9555714Skris#  define W_OK 2
9655714Skris#  define R_OK 4
9755714Skris#endif
9855714Skris
9955714Skris#undef PROG
10055714Skris#define PROG ca_main
10155714Skris
10255714Skris#define BASE_SECTION	"ca"
10355714Skris#define CONFIG_FILE "openssl.cnf"
10455714Skris
10555714Skris#define ENV_DEFAULT_CA		"default_ca"
10655714Skris
107160814Ssimon#define STRING_MASK	"string_mask"
108160814Ssimon#define UTF8_IN			"utf8"
109160814Ssimon
11055714Skris#define ENV_DIR			"dir"
11155714Skris#define ENV_CERTS		"certs"
11255714Skris#define ENV_CRL_DIR		"crl_dir"
11355714Skris#define ENV_CA_DB		"CA_DB"
11455714Skris#define ENV_NEW_CERTS_DIR	"new_certs_dir"
11555714Skris#define ENV_CERTIFICATE 	"certificate"
11655714Skris#define ENV_SERIAL		"serial"
117127128Snectar#define ENV_CRLNUMBER		"crlnumber"
11855714Skris#define ENV_CRL			"crl"
11955714Skris#define ENV_PRIVATE_KEY		"private_key"
12055714Skris#define ENV_RANDFILE		"RANDFILE"
12155714Skris#define ENV_DEFAULT_DAYS 	"default_days"
12255714Skris#define ENV_DEFAULT_STARTDATE 	"default_startdate"
12355714Skris#define ENV_DEFAULT_ENDDATE 	"default_enddate"
12455714Skris#define ENV_DEFAULT_CRL_DAYS 	"default_crl_days"
12555714Skris#define ENV_DEFAULT_CRL_HOURS 	"default_crl_hours"
12655714Skris#define ENV_DEFAULT_MD		"default_md"
127109998Smarkm#define ENV_DEFAULT_EMAIL_DN	"email_in_dn"
12855714Skris#define ENV_PRESERVE		"preserve"
12955714Skris#define ENV_POLICY      	"policy"
13055714Skris#define ENV_EXTENSIONS      	"x509_extensions"
13155714Skris#define ENV_CRLEXT      	"crl_extensions"
13255714Skris#define ENV_MSIE_HACK		"msie_hack"
133109998Smarkm#define ENV_NAMEOPT		"name_opt"
134109998Smarkm#define ENV_CERTOPT		"cert_opt"
135109998Smarkm#define ENV_EXTCOPY		"copy_extensions"
136160814Ssimon#define ENV_UNIQUE_SUBJECT	"unique_subject"
13755714Skris
13855714Skris#define ENV_DATABASE		"database"
13955714Skris
140109998Smarkm/* Additional revocation information types */
141109998Smarkm
142109998Smarkm#define REV_NONE		0	/* No addditional information */
143109998Smarkm#define REV_CRL_REASON		1	/* Value is CRL reason code */
144109998Smarkm#define REV_HOLD		2	/* Value is hold instruction */
145109998Smarkm#define REV_KEY_COMPROMISE	3	/* Value is cert key compromise time */
146109998Smarkm#define REV_CA_COMPROMISE	4	/* Value is CA key compromise time */
147109998Smarkm
148160814Ssimonstatic const char *ca_usage[]={
14955714Skris"usage: ca args\n",
15055714Skris"\n",
15155714Skris" -verbose        - Talk alot while doing things\n",
15255714Skris" -config file    - A config file\n",
15355714Skris" -name arg       - The particular CA definition to use\n",
15455714Skris" -gencrl         - Generate a new CRL\n",
15555714Skris" -crldays days   - Days is when the next CRL is due\n",
15655714Skris" -crlhours hours - Hours is when the next CRL is due\n",
15759191Skris" -startdate YYMMDDHHMMSSZ  - certificate validity notBefore\n",
15859191Skris" -enddate YYMMDDHHMMSSZ    - certificate validity notAfter (overrides -days)\n",
15955714Skris" -days arg       - number of days to certify the certificate for\n",
16055714Skris" -md arg         - md to use, one of md2, md5, sha or sha1\n",
16155714Skris" -policy arg     - The CA 'policy' to support\n",
162109998Smarkm" -keyfile arg    - private key file\n",
163109998Smarkm" -keyform arg    - private key file format (PEM or ENGINE)\n",
16455714Skris" -key arg        - key to decode the private key if it is encrypted\n",
16555714Skris" -cert file      - The CA certificate\n",
166160814Ssimon" -selfsign       - sign a certificate with the key associated with it\n",
16755714Skris" -in file        - The input PEM encoded certificate request(s)\n",
16855714Skris" -out file       - Where to put the output file(s)\n",
16955714Skris" -outdir dir     - Where to put output certificates\n",
17055714Skris" -infiles ....   - The last argument, requests to process\n",
17155714Skris" -spkac file     - File contains DN and signed public key and challenge\n",
17255714Skris" -ss_cert file   - File contains a self signed cert to sign\n",
17355714Skris" -preserveDN     - Don't re-order the DN\n",
174109998Smarkm" -noemailDN      - Don't add the EMAIL field into certificate' subject\n",
17555714Skris" -batch          - Don't ask questions\n",
17655714Skris" -msie_hack      - msie modifications to handle all those universal strings\n",
17755714Skris" -revoke file    - Revoke a certificate (given in file)\n",
178109998Smarkm" -subj arg       - Use arg instead of request's subject\n",
179160814Ssimon" -utf8           - input characters are UTF8 (default ASCII)\n",
180160814Ssimon" -multivalue-rdn - enable support for multivalued RDNs\n",
18159191Skris" -extensions ..  - Extension section (override value in config file)\n",
182109998Smarkm" -extfile file   - Configuration file with X509v3 extentions to add\n",
18359191Skris" -crlexts ..     - CRL extension section (override value in config file)\n",
184111147Snectar#ifndef OPENSSL_NO_ENGINE
185109998Smarkm" -engine e       - use engine e, possibly a hardware device.\n",
186111147Snectar#endif
187109998Smarkm" -status serial  - Shows certificate status given the serial number\n",
188109998Smarkm" -updatedb       - Updates db for expired certificates\n",
18955714SkrisNULL
19055714Skris};
19155714Skris
19255714Skris#ifdef EFENCE
19355714Skrisextern int EF_PROTECT_FREE;
19455714Skrisextern int EF_PROTECT_BELOW;
19555714Skrisextern int EF_ALIGNMENT;
19655714Skris#endif
19755714Skris
198160814Ssimonstatic void lookup_fail(const char *name, const char *tag);
19955714Skrisstatic int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
200238405Sjkim		   const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts,
201238405Sjkim		   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,
207238405Sjkim			const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts,
208238405Sjkim			STACK_OF(CONF_VALUE) *policy,
209160814Ssimon			CA_DB *db, BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn,
210109998Smarkm			char *startdate, char *enddate, long days, int batch,
211109998Smarkm			char *ext_sect, CONF *conf,int verbose, unsigned long certopt,
212109998Smarkm			unsigned long nameopt, int default_op, int ext_copy,
213109998Smarkm			ENGINE *e);
21455714Skrisstatic int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
215238405Sjkim			 const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts,
216238405Sjkim			 STACK_OF(CONF_VALUE) *policy,
217160814Ssimon			 CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn, int email_dn,
218109998Smarkm			 char *startdate, char *enddate, long days, char *ext_sect,
219109998Smarkm			 CONF *conf, int verbose, unsigned long certopt,
220109998Smarkm			 unsigned long nameopt, int default_op, int ext_copy);
22159191Skrisstatic void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
22255714Skrisstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
223238405Sjkim	STACK_OF(OPENSSL_STRING) *sigopts,
224160814Ssimon	STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn,
225109998Smarkm	int email_dn, char *startdate, char *enddate, long days, int batch,
226109998Smarkm       	int verbose, X509_REQ *req, char *ext_sect, CONF *conf,
227109998Smarkm	unsigned long certopt, unsigned long nameopt, int default_op,
228160814Ssimon	int ext_copy, int selfsign);
229127128Snectarstatic int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval);
230127128Snectarstatic int get_certificate_status(const char *ser_status, CA_DB *db);
231127128Snectarstatic int do_updatedb(CA_DB *db);
232205128Ssimonstatic int check_time_format(const char *str);
233109998Smarkmchar *make_revocation_str(int rev_type, char *rev_arg);
234160814Ssimonint make_revoked(X509_REVOKED *rev, const char *str);
235109998Smarkmint old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str);
236109998Smarkmstatic CONF *conf=NULL;
237109998Smarkmstatic CONF *extconf=NULL;
23855714Skrisstatic char *section=NULL;
23955714Skris
24055714Skrisstatic int preserve=0;
24155714Skrisstatic int msie_hack=0;
24255714Skris
243109998Smarkm
24459191Skrisint MAIN(int, char **);
24559191Skris
24655714Skrisint MAIN(int argc, char **argv)
24755714Skris	{
248109998Smarkm	ENGINE *e = NULL;
24968651Skris	char *key=NULL,*passargin=NULL;
250142425Snectar	int create_ser = 0;
251109998Smarkm	int free_key = 0;
25255714Skris	int total=0;
25355714Skris	int total_done=0;
25455714Skris	int badops=0;
25555714Skris	int ret=1;
256109998Smarkm	int email_dn=1;
25755714Skris	int req=0;
25855714Skris	int verbose=0;
25955714Skris	int gencrl=0;
26055714Skris	int dorevoke=0;
261109998Smarkm	int doupdatedb=0;
26255714Skris	long crldays=0;
26355714Skris	long crlhours=0;
264238405Sjkim	long crlsec=0;
26555714Skris	long errorline= -1;
26655714Skris	char *configfile=NULL;
26755714Skris	char *md=NULL;
26855714Skris	char *policy=NULL;
26955714Skris	char *keyfile=NULL;
27055714Skris	char *certfile=NULL;
271109998Smarkm	int keyform=FORMAT_PEM;
27255714Skris	char *infile=NULL;
27355714Skris	char *spkac_file=NULL;
27455714Skris	char *ss_cert_file=NULL;
275109998Smarkm	char *ser_status=NULL;
27655714Skris	EVP_PKEY *pkey=NULL;
27755714Skris	int output_der = 0;
27855714Skris	char *outfile=NULL;
27955714Skris	char *outdir=NULL;
28055714Skris	char *serialfile=NULL;
281127128Snectar	char *crlnumberfile=NULL;
28255714Skris	char *extensions=NULL;
283109998Smarkm	char *extfile=NULL;
284109998Smarkm	char *subj=NULL;
285160814Ssimon	unsigned long chtype = MBSTRING_ASC;
286160814Ssimon	int multirdn = 0;
287109998Smarkm	char *tmp_email_dn=NULL;
28855714Skris	char *crl_ext=NULL;
289109998Smarkm	int rev_type = REV_NONE;
290109998Smarkm	char *rev_arg = NULL;
29155714Skris	BIGNUM *serial=NULL;
292127128Snectar	BIGNUM *crlnumber=NULL;
29355714Skris	char *startdate=NULL;
29455714Skris	char *enddate=NULL;
295109998Smarkm	long days=0;
29655714Skris	int batch=0;
29759191Skris	int notext=0;
298109998Smarkm	unsigned long nameopt = 0, certopt = 0;
299109998Smarkm	int default_op = 1;
300109998Smarkm	int ext_copy = EXT_COPY_NONE;
301160814Ssimon	int selfsign = 0;
302160814Ssimon	X509 *x509=NULL, *x509p = NULL;
30355714Skris	X509 *x=NULL;
30455714Skris	BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
30555714Skris	char *dbfile=NULL;
306127128Snectar	CA_DB *db=NULL;
30755714Skris	X509_CRL *crl=NULL;
30855714Skris	X509_REVOKED *r=NULL;
309109998Smarkm	ASN1_TIME *tmptm;
310109998Smarkm	ASN1_INTEGER *tmpser;
311160814Ssimon	char *f;
312238405Sjkim	const char *p;
313238405Sjkim	char * const *pp;
31455714Skris	int i,j;
31555714Skris	const EVP_MD *dgst=NULL;
31655714Skris	STACK_OF(CONF_VALUE) *attribs=NULL;
31768651Skris	STACK_OF(X509) *cert_sk=NULL;
318238405Sjkim	STACK_OF(OPENSSL_STRING) *sigopts = NULL;
31955714Skris#undef BSIZE
32055714Skris#define BSIZE 256
32155714Skris	MS_STATIC char buf[3][BSIZE];
32259191Skris	char *randfile=NULL;
323111147Snectar#ifndef OPENSSL_NO_ENGINE
324109998Smarkm	char *engine = NULL;
325111147Snectar#endif
326109998Smarkm	char *tofree=NULL;
327127128Snectar	DB_ATTR db_attr;
32855714Skris
32955714Skris#ifdef EFENCE
33055714SkrisEF_PROTECT_FREE=1;
33155714SkrisEF_PROTECT_BELOW=1;
33255714SkrisEF_ALIGNMENT=0;
33355714Skris#endif
33455714Skris
33555714Skris	apps_startup();
33655714Skris
33759191Skris	conf = NULL;
33859191Skris	key = NULL;
33959191Skris	section = NULL;
34055714Skris
34155714Skris	preserve=0;
34259191Skris	msie_hack=0;
34355714Skris	if (bio_err == NULL)
34455714Skris		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
34555714Skris			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
34655714Skris
34755714Skris	argc--;
34855714Skris	argv++;
34955714Skris	while (argc >= 1)
35055714Skris		{
35155714Skris		if	(strcmp(*argv,"-verbose") == 0)
35255714Skris			verbose=1;
35355714Skris		else if	(strcmp(*argv,"-config") == 0)
35455714Skris			{
35555714Skris			if (--argc < 1) goto bad;
35655714Skris			configfile= *(++argv);
35755714Skris			}
35855714Skris		else if (strcmp(*argv,"-name") == 0)
35955714Skris			{
36055714Skris			if (--argc < 1) goto bad;
36155714Skris			section= *(++argv);
36255714Skris			}
363109998Smarkm		else if (strcmp(*argv,"-subj") == 0)
364109998Smarkm			{
365109998Smarkm			if (--argc < 1) goto bad;
366109998Smarkm			subj= *(++argv);
367109998Smarkm			/* preserve=1; */
368109998Smarkm			}
369160814Ssimon		else if (strcmp(*argv,"-utf8") == 0)
370160814Ssimon			chtype = MBSTRING_UTF8;
371160814Ssimon		else if (strcmp(*argv,"-create_serial") == 0)
372160814Ssimon			create_ser = 1;
373160814Ssimon		else if (strcmp(*argv,"-multivalue-rdn") == 0)
374160814Ssimon			multirdn=1;
37555714Skris		else if (strcmp(*argv,"-startdate") == 0)
37655714Skris			{
37755714Skris			if (--argc < 1) goto bad;
37855714Skris			startdate= *(++argv);
37955714Skris			}
38055714Skris		else if (strcmp(*argv,"-enddate") == 0)
38155714Skris			{
38255714Skris			if (--argc < 1) goto bad;
38355714Skris			enddate= *(++argv);
38455714Skris			}
38555714Skris		else if (strcmp(*argv,"-days") == 0)
38655714Skris			{
38755714Skris			if (--argc < 1) goto bad;
38855714Skris			days=atoi(*(++argv));
38955714Skris			}
39055714Skris		else if (strcmp(*argv,"-md") == 0)
39155714Skris			{
39255714Skris			if (--argc < 1) goto bad;
39355714Skris			md= *(++argv);
39455714Skris			}
39555714Skris		else if (strcmp(*argv,"-policy") == 0)
39655714Skris			{
39755714Skris			if (--argc < 1) goto bad;
39855714Skris			policy= *(++argv);
39955714Skris			}
40055714Skris		else if (strcmp(*argv,"-keyfile") == 0)
40155714Skris			{
40255714Skris			if (--argc < 1) goto bad;
40355714Skris			keyfile= *(++argv);
40455714Skris			}
405109998Smarkm		else if (strcmp(*argv,"-keyform") == 0)
406109998Smarkm			{
407109998Smarkm			if (--argc < 1) goto bad;
408109998Smarkm			keyform=str2fmt(*(++argv));
409109998Smarkm			}
41068651Skris		else if (strcmp(*argv,"-passin") == 0)
41168651Skris			{
41268651Skris			if (--argc < 1) goto bad;
41368651Skris			passargin= *(++argv);
41468651Skris			}
41555714Skris		else if (strcmp(*argv,"-key") == 0)
41655714Skris			{
41755714Skris			if (--argc < 1) goto bad;
41855714Skris			key= *(++argv);
41955714Skris			}
42055714Skris		else if (strcmp(*argv,"-cert") == 0)
42155714Skris			{
42255714Skris			if (--argc < 1) goto bad;
42355714Skris			certfile= *(++argv);
42455714Skris			}
425160814Ssimon		else if (strcmp(*argv,"-selfsign") == 0)
426160814Ssimon			selfsign=1;
42755714Skris		else if (strcmp(*argv,"-in") == 0)
42855714Skris			{
42955714Skris			if (--argc < 1) goto bad;
43055714Skris			infile= *(++argv);
43155714Skris			req=1;
43255714Skris			}
43355714Skris		else if (strcmp(*argv,"-out") == 0)
43455714Skris			{
43555714Skris			if (--argc < 1) goto bad;
43655714Skris			outfile= *(++argv);
43755714Skris			}
43855714Skris		else if (strcmp(*argv,"-outdir") == 0)
43955714Skris			{
44055714Skris			if (--argc < 1) goto bad;
44155714Skris			outdir= *(++argv);
44255714Skris			}
443238405Sjkim		else if (strcmp(*argv,"-sigopt") == 0)
444238405Sjkim			{
445238405Sjkim			if (--argc < 1)
446238405Sjkim				goto bad;
447238405Sjkim			if (!sigopts)
448238405Sjkim				sigopts = sk_OPENSSL_STRING_new_null();
449238405Sjkim			if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
450238405Sjkim				goto bad;
451238405Sjkim			}
45259191Skris		else if (strcmp(*argv,"-notext") == 0)
45359191Skris			notext=1;
45455714Skris		else if (strcmp(*argv,"-batch") == 0)
45555714Skris			batch=1;
45655714Skris		else if (strcmp(*argv,"-preserveDN") == 0)
45755714Skris			preserve=1;
458109998Smarkm		else if (strcmp(*argv,"-noemailDN") == 0)
459109998Smarkm			email_dn=0;
46055714Skris		else if (strcmp(*argv,"-gencrl") == 0)
46155714Skris			gencrl=1;
46255714Skris		else if (strcmp(*argv,"-msie_hack") == 0)
46355714Skris			msie_hack=1;
46455714Skris		else if (strcmp(*argv,"-crldays") == 0)
46555714Skris			{
46655714Skris			if (--argc < 1) goto bad;
46755714Skris			crldays= atol(*(++argv));
46855714Skris			}
46955714Skris		else if (strcmp(*argv,"-crlhours") == 0)
47055714Skris			{
47155714Skris			if (--argc < 1) goto bad;
47255714Skris			crlhours= atol(*(++argv));
47355714Skris			}
474238405Sjkim		else if (strcmp(*argv,"-crlsec") == 0)
475238405Sjkim			{
476238405Sjkim			if (--argc < 1) goto bad;
477238405Sjkim			crlsec = atol(*(++argv));
478238405Sjkim			}
47955714Skris		else if (strcmp(*argv,"-infiles") == 0)
48055714Skris			{
48155714Skris			argc--;
48255714Skris			argv++;
48355714Skris			req=1;
48455714Skris			break;
48555714Skris			}
48655714Skris		else if (strcmp(*argv, "-ss_cert") == 0)
48755714Skris			{
48855714Skris			if (--argc < 1) goto bad;
48955714Skris			ss_cert_file = *(++argv);
49055714Skris			req=1;
49155714Skris			}
49255714Skris		else if (strcmp(*argv, "-spkac") == 0)
49355714Skris			{
49455714Skris			if (--argc < 1) goto bad;
49555714Skris			spkac_file = *(++argv);
49655714Skris			req=1;
49755714Skris			}
49855714Skris		else if (strcmp(*argv,"-revoke") == 0)
49955714Skris			{
50055714Skris			if (--argc < 1) goto bad;
50155714Skris			infile= *(++argv);
50255714Skris			dorevoke=1;
50355714Skris			}
50459191Skris		else if (strcmp(*argv,"-extensions") == 0)
50559191Skris			{
50659191Skris			if (--argc < 1) goto bad;
50759191Skris			extensions= *(++argv);
50859191Skris			}
509109998Smarkm		else if (strcmp(*argv,"-extfile") == 0)
510109998Smarkm			{
511109998Smarkm			if (--argc < 1) goto bad;
512109998Smarkm			extfile= *(++argv);
513109998Smarkm			}
514109998Smarkm		else if (strcmp(*argv,"-status") == 0)
515109998Smarkm			{
516109998Smarkm			if (--argc < 1) goto bad;
517109998Smarkm			ser_status= *(++argv);
518109998Smarkm			}
519109998Smarkm		else if (strcmp(*argv,"-updatedb") == 0)
520109998Smarkm			{
521109998Smarkm			doupdatedb=1;
522109998Smarkm			}
52359191Skris		else if (strcmp(*argv,"-crlexts") == 0)
52459191Skris			{
52559191Skris			if (--argc < 1) goto bad;
52659191Skris			crl_ext= *(++argv);
52759191Skris			}
528109998Smarkm		else if (strcmp(*argv,"-crl_reason") == 0)
529109998Smarkm			{
530109998Smarkm			if (--argc < 1) goto bad;
531109998Smarkm			rev_arg = *(++argv);
532109998Smarkm			rev_type = REV_CRL_REASON;
533109998Smarkm			}
534109998Smarkm		else if (strcmp(*argv,"-crl_hold") == 0)
535109998Smarkm			{
536109998Smarkm			if (--argc < 1) goto bad;
537109998Smarkm			rev_arg = *(++argv);
538109998Smarkm			rev_type = REV_HOLD;
539109998Smarkm			}
540109998Smarkm		else if (strcmp(*argv,"-crl_compromise") == 0)
541109998Smarkm			{
542109998Smarkm			if (--argc < 1) goto bad;
543109998Smarkm			rev_arg = *(++argv);
544109998Smarkm			rev_type = REV_KEY_COMPROMISE;
545109998Smarkm			}
546109998Smarkm		else if (strcmp(*argv,"-crl_CA_compromise") == 0)
547109998Smarkm			{
548109998Smarkm			if (--argc < 1) goto bad;
549109998Smarkm			rev_arg = *(++argv);
550109998Smarkm			rev_type = REV_CA_COMPROMISE;
551109998Smarkm			}
552111147Snectar#ifndef OPENSSL_NO_ENGINE
553109998Smarkm		else if (strcmp(*argv,"-engine") == 0)
554109998Smarkm			{
555109998Smarkm			if (--argc < 1) goto bad;
556109998Smarkm			engine= *(++argv);
557109998Smarkm			}
558111147Snectar#endif
55955714Skris		else
56055714Skris			{
56155714Skrisbad:
56255714Skris			BIO_printf(bio_err,"unknown option %s\n",*argv);
56355714Skris			badops=1;
56455714Skris			break;
56555714Skris			}
56655714Skris		argc--;
56755714Skris		argv++;
56855714Skris		}
56955714Skris
57055714Skris	if (badops)
57155714Skris		{
572238405Sjkim		const char **pp2;
573238405Sjkim
574238405Sjkim		for (pp2=ca_usage; (*pp2 != NULL); pp2++)
575238405Sjkim			BIO_printf(bio_err,"%s",*pp2);
57655714Skris		goto err;
57755714Skris		}
57855714Skris
57955714Skris	ERR_load_crypto_strings();
58055714Skris
58155714Skris	/*****************************************************************/
582109998Smarkm	tofree=NULL;
58355714Skris	if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
58455714Skris	if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
58555714Skris	if (configfile == NULL)
58655714Skris		{
587109998Smarkm		const char *s=X509_get_default_cert_area();
588127128Snectar		size_t len;
589109998Smarkm
590109998Smarkm#ifdef OPENSSL_SYS_VMS
591127128Snectar		len = strlen(s)+sizeof(CONFIG_FILE);
592127128Snectar		tofree=OPENSSL_malloc(len);
593109998Smarkm		strcpy(tofree,s);
59455714Skris#else
595127128Snectar		len = strlen(s)+sizeof(CONFIG_FILE)+1;
596127128Snectar		tofree=OPENSSL_malloc(len);
597127128Snectar		BUF_strlcpy(tofree,s,len);
598127128Snectar		BUF_strlcat(tofree,"/",len);
59955714Skris#endif
600127128Snectar		BUF_strlcat(tofree,CONFIG_FILE,len);
601109998Smarkm		configfile=tofree;
60255714Skris		}
60355714Skris
60455714Skris	BIO_printf(bio_err,"Using configuration from %s\n",configfile);
605109998Smarkm	conf = NCONF_new(NULL);
606109998Smarkm	if (NCONF_load(conf,configfile,&errorline) <= 0)
60755714Skris		{
60855714Skris		if (errorline <= 0)
60955714Skris			BIO_printf(bio_err,"error loading the config file '%s'\n",
61055714Skris				configfile);
61155714Skris		else
61255714Skris			BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
61355714Skris				,errorline,configfile);
61455714Skris		goto err;
61555714Skris		}
616109998Smarkm	if(tofree)
617111147Snectar		{
618109998Smarkm		OPENSSL_free(tofree);
619111147Snectar		tofree = NULL;
620111147Snectar		}
62155714Skris
622109998Smarkm	if (!load_config(bio_err, conf))
623109998Smarkm		goto err;
624109998Smarkm
625142425Snectar#ifndef OPENSSL_NO_ENGINE
626142425Snectar	e = setup_engine(bio_err, engine, 0);
627142425Snectar#endif
628142425Snectar
62955714Skris	/* Lets get the config section we are using */
63055714Skris	if (section == NULL)
63155714Skris		{
632109998Smarkm		section=NCONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
63355714Skris		if (section == NULL)
63455714Skris			{
63555714Skris			lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
63655714Skris			goto err;
63755714Skris			}
63855714Skris		}
63955714Skris
64055714Skris	if (conf != NULL)
64155714Skris		{
642109998Smarkm		p=NCONF_get_string(conf,NULL,"oid_file");
643109998Smarkm		if (p == NULL)
644109998Smarkm			ERR_clear_error();
64555714Skris		if (p != NULL)
64655714Skris			{
64755714Skris			BIO *oid_bio;
64855714Skris
64955714Skris			oid_bio=BIO_new_file(p,"r");
65055714Skris			if (oid_bio == NULL)
65155714Skris				{
65255714Skris				/*
65355714Skris				BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
65455714Skris				ERR_print_errors(bio_err);
65555714Skris				*/
65655714Skris				ERR_clear_error();
65755714Skris				}
65855714Skris			else
65955714Skris				{
66055714Skris				OBJ_create_objects(oid_bio);
66155714Skris				BIO_free(oid_bio);
66255714Skris				}
66355714Skris			}
664109998Smarkm		if (!add_oid_section(bio_err,conf))
66559191Skris			{
66655714Skris			ERR_print_errors(bio_err);
66755714Skris			goto err;
66859191Skris			}
66955714Skris		}
67055714Skris
671109998Smarkm	randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
672109998Smarkm	if (randfile == NULL)
673109998Smarkm		ERR_clear_error();
67459191Skris	app_RAND_load_file(randfile, bio_err, 0);
675127128Snectar
676160814Ssimon	f = NCONF_get_string(conf, section, STRING_MASK);
677160814Ssimon	if (!f)
678160814Ssimon		ERR_clear_error();
679160814Ssimon
680160814Ssimon	if(f && !ASN1_STRING_set_default_mask_asc(f)) {
681160814Ssimon		BIO_printf(bio_err, "Invalid global string mask setting %s\n", f);
682160814Ssimon		goto err;
683160814Ssimon	}
684160814Ssimon
685160814Ssimon	if (chtype != MBSTRING_UTF8){
686160814Ssimon		f = NCONF_get_string(conf, section, UTF8_IN);
687160814Ssimon		if (!f)
688160814Ssimon			ERR_clear_error();
689160814Ssimon		else if (!strcmp(f, "yes"))
690160814Ssimon			chtype = MBSTRING_UTF8;
691160814Ssimon	}
692160814Ssimon
693127128Snectar	db_attr.unique_subject = 1;
694160814Ssimon	p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT);
695127128Snectar	if (p)
696127128Snectar		{
697127128Snectar#ifdef RL_DEBUG
698127128Snectar		BIO_printf(bio_err, "DEBUG: unique_subject = \"%s\"\n", p);
699127128Snectar#endif
700160814Ssimon		db_attr.unique_subject = parse_yesno(p,1);
701127128Snectar		}
702142425Snectar	else
703142425Snectar		ERR_clear_error();
704127128Snectar#ifdef RL_DEBUG
705142425Snectar	if (!p)
706279264Sdelphij		BIO_printf(bio_err, "DEBUG: unique_subject undefined\n");
707127128Snectar#endif
708127128Snectar#ifdef RL_DEBUG
709127128Snectar	BIO_printf(bio_err, "DEBUG: configured unique_subject is %d\n",
710127128Snectar		db_attr.unique_subject);
711127128Snectar#endif
71259191Skris
71355714Skris	in=BIO_new(BIO_s_file());
71455714Skris	out=BIO_new(BIO_s_file());
71555714Skris	Sout=BIO_new(BIO_s_file());
71655714Skris	Cout=BIO_new(BIO_s_file());
71755714Skris	if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL))
71855714Skris		{
71955714Skris		ERR_print_errors(bio_err);
72055714Skris		goto err;
72155714Skris		}
72255714Skris
72355714Skris	/*****************************************************************/
724109998Smarkm	/* report status of cert with serial number given on command line */
725109998Smarkm	if (ser_status)
726109998Smarkm	{
727109998Smarkm		if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
728109998Smarkm			{
729109998Smarkm			lookup_fail(section,ENV_DATABASE);
730109998Smarkm			goto err;
731109998Smarkm			}
732127128Snectar		db = load_index(dbfile,&db_attr);
733109998Smarkm		if (db == NULL) goto err;
73455714Skris
735127128Snectar		if (!index_index(db)) goto err;
736109998Smarkm
737109998Smarkm		if (get_certificate_status(ser_status,db) != 1)
738109998Smarkm			BIO_printf(bio_err,"Error verifying serial %s!\n",
739109998Smarkm				 ser_status);
740109998Smarkm		goto err;
741109998Smarkm	}
742109998Smarkm
743109998Smarkm	/*****************************************************************/
744160814Ssimon	/* we definitely need a private key, so let's get it */
745109998Smarkm
746109998Smarkm	if ((keyfile == NULL) && ((keyfile=NCONF_get_string(conf,
74755714Skris		section,ENV_PRIVATE_KEY)) == NULL))
74855714Skris		{
74955714Skris		lookup_fail(section,ENV_PRIVATE_KEY);
75055714Skris		goto err;
75155714Skris		}
752109998Smarkm	if (!key)
75368651Skris		{
754109998Smarkm		free_key = 1;
755109998Smarkm		if (!app_passwd(bio_err, passargin, NULL, &key, NULL))
756109998Smarkm			{
757109998Smarkm			BIO_printf(bio_err,"Error getting password\n");
758109998Smarkm			goto err;
759109998Smarkm			}
76068651Skris		}
761109998Smarkm	pkey = load_key(bio_err, keyfile, keyform, 0, key, e,
762109998Smarkm		"CA private key");
763109998Smarkm	if (key) OPENSSL_cleanse(key,strlen(key));
76455714Skris	if (pkey == NULL)
76555714Skris		{
766109998Smarkm		/* load_key() has already printed an appropriate message */
76755714Skris		goto err;
76855714Skris		}
76955714Skris
77055714Skris	/*****************************************************************/
77155714Skris	/* we need a certificate */
772160814Ssimon	if (!selfsign || spkac_file || ss_cert_file || gencrl)
77355714Skris		{
774160814Ssimon		if ((certfile == NULL)
775160814Ssimon			&& ((certfile=NCONF_get_string(conf,
776160814Ssimon				     section,ENV_CERTIFICATE)) == NULL))
777160814Ssimon			{
778160814Ssimon			lookup_fail(section,ENV_CERTIFICATE);
779160814Ssimon			goto err;
780160814Ssimon			}
781160814Ssimon		x509=load_cert(bio_err, certfile, FORMAT_PEM, NULL, e,
782160814Ssimon			"CA certificate");
783160814Ssimon		if (x509 == NULL)
784160814Ssimon			goto err;
78555714Skris
786160814Ssimon		if (!X509_check_private_key(x509,pkey))
787160814Ssimon			{
788160814Ssimon			BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
789160814Ssimon			goto err;
790160814Ssimon			}
79155714Skris		}
792160814Ssimon	if (!selfsign) x509p = x509;
79355714Skris
794109998Smarkm	f=NCONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
795109998Smarkm	if (f == NULL)
796109998Smarkm		ERR_clear_error();
79755714Skris	if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
79855714Skris		preserve=1;
799109998Smarkm	f=NCONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
800109998Smarkm	if (f == NULL)
801109998Smarkm		ERR_clear_error();
80255714Skris	if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
80355714Skris		msie_hack=1;
80455714Skris
805109998Smarkm	f=NCONF_get_string(conf,section,ENV_NAMEOPT);
806109998Smarkm
807109998Smarkm	if (f)
808109998Smarkm		{
809109998Smarkm		if (!set_name_ex(&nameopt, f))
810109998Smarkm			{
811109998Smarkm			BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f);
812109998Smarkm			goto err;
813109998Smarkm			}
814109998Smarkm		default_op = 0;
815109998Smarkm		}
816109998Smarkm	else
817109998Smarkm		ERR_clear_error();
818109998Smarkm
819109998Smarkm	f=NCONF_get_string(conf,section,ENV_CERTOPT);
820109998Smarkm
821109998Smarkm	if (f)
822109998Smarkm		{
823109998Smarkm		if (!set_cert_ex(&certopt, f))
824109998Smarkm			{
825109998Smarkm			BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f);
826109998Smarkm			goto err;
827109998Smarkm			}
828109998Smarkm		default_op = 0;
829109998Smarkm		}
830109998Smarkm	else
831109998Smarkm		ERR_clear_error();
832109998Smarkm
833109998Smarkm	f=NCONF_get_string(conf,section,ENV_EXTCOPY);
834109998Smarkm
835109998Smarkm	if (f)
836109998Smarkm		{
837109998Smarkm		if (!set_ext_copy(&ext_copy, f))
838109998Smarkm			{
839109998Smarkm			BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f);
840109998Smarkm			goto err;
841109998Smarkm			}
842109998Smarkm		}
843109998Smarkm	else
844109998Smarkm		ERR_clear_error();
845109998Smarkm
84655714Skris	/*****************************************************************/
84755714Skris	/* lookup where to write new certificates */
84855714Skris	if ((outdir == NULL) && (req))
84955714Skris		{
85055714Skris
851109998Smarkm		if ((outdir=NCONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
85255714Skris			== NULL)
85355714Skris			{
85455714Skris			BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
85555714Skris			goto err;
85655714Skris			}
857109998Smarkm#ifndef OPENSSL_SYS_VMS
858109998Smarkm	    /* outdir is a directory spec, but access() for VMS demands a
85959191Skris	       filename.  In any case, stat(), below, will catch the problem
86059191Skris	       if outdir is not a directory spec, and the fopen() or open()
86159191Skris	       will catch an error if there is no write access.
86259191Skris
86359191Skris	       Presumably, this problem could also be solved by using the DEC
86459191Skris	       C routines to convert the directory syntax to Unixly, and give
86559191Skris	       that to access().  However, time's too short to do that just
86659191Skris	       now.
867109998Smarkm	    */
868238405Sjkim#ifndef _WIN32
86955714Skris		if (access(outdir,R_OK|W_OK|X_OK) != 0)
870238405Sjkim#else
871238405Sjkim		if (_access(outdir,R_OK|W_OK|X_OK) != 0)
872238405Sjkim#endif
87355714Skris			{
87459191Skris			BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
87555714Skris			perror(outdir);
87655714Skris			goto err;
87755714Skris			}
87855714Skris
879238405Sjkim		if (app_isdir(outdir)<=0)
88055714Skris			{
88155714Skris			BIO_printf(bio_err,"%s need to be a directory\n",outdir);
88255714Skris			perror(outdir);
88355714Skris			goto err;
88455714Skris			}
88559191Skris#endif
88655714Skris		}
88755714Skris
88855714Skris	/*****************************************************************/
88955714Skris	/* we need to load the database file */
890109998Smarkm	if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
89155714Skris		{
89255714Skris		lookup_fail(section,ENV_DATABASE);
89355714Skris		goto err;
89455714Skris		}
895127128Snectar	db = load_index(dbfile, &db_attr);
89655714Skris	if (db == NULL) goto err;
89755714Skris
89855714Skris	/* Lets check some fields */
899238405Sjkim	for (i=0; i<sk_OPENSSL_PSTRING_num(db->db->data); i++)
90055714Skris		{
901238405Sjkim		pp=sk_OPENSSL_PSTRING_value(db->db->data,i);
90255714Skris		if ((pp[DB_type][0] != DB_TYPE_REV) &&
90355714Skris			(pp[DB_rev_date][0] != '\0'))
90455714Skris			{
90555714Skris			BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
90655714Skris			goto err;
90755714Skris			}
90855714Skris		if ((pp[DB_type][0] == DB_TYPE_REV) &&
909109998Smarkm			!make_revoked(NULL, pp[DB_rev_date]))
91055714Skris			{
911109998Smarkm			BIO_printf(bio_err," in entry %d\n", i+1);
91255714Skris			goto err;
91355714Skris			}
914238405Sjkim		if (!check_time_format((char *)pp[DB_exp_date]))
91555714Skris			{
91655714Skris			BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
91755714Skris			goto err;
91855714Skris			}
91955714Skris		p=pp[DB_serial];
92055714Skris		j=strlen(p);
921109998Smarkm		if (*p == '-')
922109998Smarkm			{
923109998Smarkm			p++;
924109998Smarkm			j--;
925109998Smarkm			}
92655714Skris		if ((j&1) || (j < 2))
92755714Skris			{
92855714Skris			BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
92955714Skris			goto err;
93055714Skris			}
93155714Skris		while (*p)
93255714Skris			{
93355714Skris			if (!(	((*p >= '0') && (*p <= '9')) ||
93455714Skris				((*p >= 'A') && (*p <= 'F')) ||
93555714Skris				((*p >= 'a') && (*p <= 'f')))  )
93655714Skris				{
93755714Skris				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);
93855714Skris				goto err;
93955714Skris				}
94055714Skris			p++;
94155714Skris			}
94255714Skris		}
94355714Skris	if (verbose)
94455714Skris		{
94555714Skris		BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
946109998Smarkm#ifdef OPENSSL_SYS_VMS
94768651Skris		{
94868651Skris		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
94968651Skris		out = BIO_push(tmpbio, out);
95068651Skris		}
95168651Skris#endif
952127128Snectar		TXT_DB_write(out,db->db);
95355714Skris		BIO_printf(bio_err,"%d entries loaded from the database\n",
954238405Sjkim			   sk_OPENSSL_PSTRING_num(db->db->data));
95559191Skris		BIO_printf(bio_err,"generating index\n");
95655714Skris		}
95755714Skris
958127128Snectar	if (!index_index(db)) goto err;
95955714Skris
96055714Skris	/*****************************************************************/
961109998Smarkm	/* Update the db file for expired certificates */
962109998Smarkm	if (doupdatedb)
963109998Smarkm		{
964109998Smarkm		if (verbose)
965109998Smarkm			BIO_printf(bio_err, "Updating %s ...\n",
966109998Smarkm							dbfile);
967109998Smarkm
968109998Smarkm		i = do_updatedb(db);
969109998Smarkm		if (i == -1)
970109998Smarkm			{
971109998Smarkm			BIO_printf(bio_err,"Malloc failure\n");
972109998Smarkm			goto err;
973109998Smarkm			}
974109998Smarkm		else if (i == 0)
975109998Smarkm			{
976109998Smarkm			if (verbose) BIO_printf(bio_err,
977109998Smarkm					"No entries found to mark expired\n");
978109998Smarkm			}
979109998Smarkm	    	else
980109998Smarkm			{
981127128Snectar			if (!save_index(dbfile,"new",db)) goto err;
982109998Smarkm
983127128Snectar			if (!rotate_index(dbfile,"new","old")) goto err;
984127128Snectar
985109998Smarkm			if (verbose) BIO_printf(bio_err,
986109998Smarkm				"Done. %d entries marked as expired\n",i);
987109998Smarkm	      		}
988109998Smarkm	  	}
989109998Smarkm
990109998Smarkm 	/*****************************************************************/
991109998Smarkm	/* Read extentions config file                                   */
992109998Smarkm	if (extfile)
993109998Smarkm		{
994109998Smarkm		extconf = NCONF_new(NULL);
995109998Smarkm		if (NCONF_load(extconf,extfile,&errorline) <= 0)
996109998Smarkm			{
997109998Smarkm			if (errorline <= 0)
998109998Smarkm				BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
999109998Smarkm					extfile);
1000109998Smarkm			else
1001109998Smarkm				BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n",
1002109998Smarkm					errorline,extfile);
1003109998Smarkm			ret = 1;
1004109998Smarkm			goto err;
1005109998Smarkm			}
1006109998Smarkm
1007109998Smarkm		if (verbose)
1008109998Smarkm			BIO_printf(bio_err, "Successfully loaded extensions file %s\n", extfile);
1009109998Smarkm
1010109998Smarkm		/* We can have sections in the ext file */
1011109998Smarkm		if (!extensions && !(extensions = NCONF_get_string(extconf, "default", "extensions")))
1012109998Smarkm			extensions = "default";
1013109998Smarkm		}
1014109998Smarkm
1015109998Smarkm	/*****************************************************************/
101655714Skris	if (req || gencrl)
101755714Skris		{
101855714Skris		if (outfile != NULL)
101955714Skris			{
102055714Skris			if (BIO_write_filename(Sout,outfile) <= 0)
102155714Skris				{
102255714Skris				perror(outfile);
102355714Skris				goto err;
102455714Skris				}
102555714Skris			}
102655714Skris		else
102768651Skris			{
102855714Skris			BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
1029109998Smarkm#ifdef OPENSSL_SYS_VMS
103068651Skris			{
103168651Skris			BIO *tmpbio = BIO_new(BIO_f_linebuffer());
103268651Skris			Sout = BIO_push(tmpbio, Sout);
103368651Skris			}
103468651Skris#endif
103568651Skris			}
103655714Skris		}
103755714Skris
1038160814Ssimon	if ((md == NULL) && ((md=NCONF_get_string(conf,
1039160814Ssimon		section,ENV_DEFAULT_MD)) == NULL))
1040160814Ssimon		{
1041160814Ssimon		lookup_fail(section,ENV_DEFAULT_MD);
1042160814Ssimon		goto err;
1043160814Ssimon		}
1044160814Ssimon
1045238405Sjkim	if (!strcmp(md, "default"))
1046238405Sjkim		{
1047238405Sjkim		int def_nid;
1048238405Sjkim		if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0)
1049238405Sjkim			{
1050238405Sjkim			BIO_puts(bio_err,"no default digest\n");
1051238405Sjkim			goto err;
1052238405Sjkim			}
1053238405Sjkim		md = (char *)OBJ_nid2sn(def_nid);
1054238405Sjkim		}
1055238405Sjkim
1056160814Ssimon	if ((dgst=EVP_get_digestbyname(md)) == NULL)
1057160814Ssimon		{
1058160814Ssimon		BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1059160814Ssimon		goto err;
1060160814Ssimon		}
1061160814Ssimon
106255714Skris	if (req)
106355714Skris		{
1064109998Smarkm		if ((email_dn == 1) && ((tmp_email_dn=NCONF_get_string(conf,
1065109998Smarkm			section,ENV_DEFAULT_EMAIL_DN)) != NULL ))
1066109998Smarkm			{
1067109998Smarkm			if(strcmp(tmp_email_dn,"no") == 0)
1068109998Smarkm				email_dn=0;
1069109998Smarkm			}
107055714Skris		if (verbose)
107155714Skris			BIO_printf(bio_err,"message digest is %s\n",
107255714Skris				OBJ_nid2ln(dgst->type));
1073109998Smarkm		if ((policy == NULL) && ((policy=NCONF_get_string(conf,
107455714Skris			section,ENV_POLICY)) == NULL))
107555714Skris			{
107655714Skris			lookup_fail(section,ENV_POLICY);
107755714Skris			goto err;
107855714Skris			}
107955714Skris		if (verbose)
108055714Skris			BIO_printf(bio_err,"policy is %s\n",policy);
108155714Skris
1082109998Smarkm		if ((serialfile=NCONF_get_string(conf,section,ENV_SERIAL))
108355714Skris			== NULL)
108455714Skris			{
108555714Skris			lookup_fail(section,ENV_SERIAL);
108655714Skris			goto err;
108755714Skris			}
1088109998Smarkm
1089109998Smarkm		if (!extconf)
1090109998Smarkm			{
1091109998Smarkm			/* no '-extfile' option, so we look for extensions
1092109998Smarkm			 * in the main configuration file */
1093109998Smarkm			if (!extensions)
1094109998Smarkm				{
1095109998Smarkm				extensions=NCONF_get_string(conf,section,
1096109998Smarkm								ENV_EXTENSIONS);
1097109998Smarkm				if (!extensions)
1098109998Smarkm					ERR_clear_error();
1099109998Smarkm				}
1100109998Smarkm			if (extensions)
1101109998Smarkm				{
1102109998Smarkm				/* Check syntax of file */
1103109998Smarkm				X509V3_CTX ctx;
1104109998Smarkm				X509V3_set_ctx_test(&ctx);
1105109998Smarkm				X509V3_set_nconf(&ctx, conf);
1106109998Smarkm				if (!X509V3_EXT_add_nconf(conf, &ctx, extensions,
1107109998Smarkm								NULL))
1108109998Smarkm					{
1109109998Smarkm					BIO_printf(bio_err,
1110109998Smarkm				 	"Error Loading extension section %s\n",
111155714Skris								 extensions);
1112109998Smarkm					ret = 1;
1113109998Smarkm					goto err;
1114109998Smarkm					}
1115109998Smarkm				}
111655714Skris			}
111755714Skris
111855714Skris		if (startdate == NULL)
111955714Skris			{
1120109998Smarkm			startdate=NCONF_get_string(conf,section,
112155714Skris				ENV_DEFAULT_STARTDATE);
1122109998Smarkm			if (startdate == NULL)
1123109998Smarkm				ERR_clear_error();
112455714Skris			}
1125238405Sjkim		if (startdate && !ASN1_TIME_set_string(NULL, startdate))
112655714Skris			{
1127238405Sjkim			BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
112855714Skris			goto err;
112955714Skris			}
113055714Skris		if (startdate == NULL) startdate="today";
113155714Skris
113255714Skris		if (enddate == NULL)
113355714Skris			{
1134109998Smarkm			enddate=NCONF_get_string(conf,section,
113555714Skris				ENV_DEFAULT_ENDDATE);
1136109998Smarkm			if (enddate == NULL)
1137109998Smarkm				ERR_clear_error();
113855714Skris			}
1139238405Sjkim		if (enddate && !ASN1_TIME_set_string(NULL, enddate))
114055714Skris			{
1141238405Sjkim			BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
114255714Skris			goto err;
114355714Skris			}
114455714Skris
114555714Skris		if (days == 0)
114655714Skris			{
1147109998Smarkm			if(!NCONF_get_number(conf,section, ENV_DEFAULT_DAYS, &days))
1148109998Smarkm				days = 0;
114955714Skris			}
115055714Skris		if (!enddate && (days == 0))
115155714Skris			{
115255714Skris			BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
115355714Skris			goto err;
115455714Skris			}
115555714Skris
1156142425Snectar		if ((serial=load_serial(serialfile, create_ser, NULL)) == NULL)
115755714Skris			{
115855714Skris			BIO_printf(bio_err,"error while loading serial number\n");
115955714Skris			goto err;
116055714Skris			}
116155714Skris		if (verbose)
116255714Skris			{
1163109998Smarkm			if (BN_is_zero(serial))
1164109998Smarkm				BIO_printf(bio_err,"next serial number is 00\n");
1165109998Smarkm			else
1166109998Smarkm				{
1167109998Smarkm				if ((f=BN_bn2hex(serial)) == NULL) goto err;
1168109998Smarkm				BIO_printf(bio_err,"next serial number is %s\n",f);
1169109998Smarkm				OPENSSL_free(f);
1170109998Smarkm				}
117155714Skris			}
117255714Skris
1173109998Smarkm		if ((attribs=NCONF_get_section(conf,policy)) == NULL)
117455714Skris			{
117555714Skris			BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
117655714Skris			goto err;
117755714Skris			}
117855714Skris
117968651Skris		if ((cert_sk=sk_X509_new_null()) == NULL)
118055714Skris			{
118168651Skris			BIO_printf(bio_err,"Memory allocation failure\n");
118255714Skris			goto err;
118355714Skris			}
118455714Skris		if (spkac_file != NULL)
118555714Skris			{
118655714Skris			total++;
1187238405Sjkim			j=certify_spkac(&x,spkac_file,pkey,x509,dgst,sigopts,
1188238405Sjkim				attribs,db, serial,subj,chtype,multirdn,
1189238405Sjkim				email_dn,startdate,enddate,days,extensions,
1190109998Smarkm				conf,verbose,certopt,nameopt,default_op,ext_copy);
119155714Skris			if (j < 0) goto err;
119255714Skris			if (j > 0)
119355714Skris				{
119455714Skris				total_done++;
119555714Skris				BIO_printf(bio_err,"\n");
119655714Skris				if (!BN_add_word(serial,1)) goto err;
119768651Skris				if (!sk_X509_push(cert_sk,x))
119855714Skris					{
119968651Skris					BIO_printf(bio_err,"Memory allocation failure\n");
120055714Skris					goto err;
120155714Skris					}
120255714Skris				if (outfile)
120355714Skris					{
120455714Skris					output_der = 1;
120555714Skris					batch = 1;
120655714Skris					}
120755714Skris				}
120855714Skris			}
120955714Skris		if (ss_cert_file != NULL)
121055714Skris			{
121155714Skris			total++;
1212238405Sjkim			j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,sigopts,
1213238405Sjkim				attribs,
1214160814Ssimon				db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
1215109998Smarkm				extensions,conf,verbose, certopt, nameopt,
1216109998Smarkm				default_op, ext_copy, e);
121755714Skris			if (j < 0) goto err;
121855714Skris			if (j > 0)
121955714Skris				{
122055714Skris				total_done++;
122155714Skris				BIO_printf(bio_err,"\n");
122255714Skris				if (!BN_add_word(serial,1)) goto err;
122368651Skris				if (!sk_X509_push(cert_sk,x))
122455714Skris					{
122568651Skris					BIO_printf(bio_err,"Memory allocation failure\n");
122655714Skris					goto err;
122755714Skris					}
122855714Skris				}
122955714Skris			}
123055714Skris		if (infile != NULL)
123155714Skris			{
123255714Skris			total++;
1233238405Sjkim			j=certify(&x,infile,pkey,x509p,dgst,sigopts, attribs,db,
1234160814Ssimon				serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
1235109998Smarkm				extensions,conf,verbose, certopt, nameopt,
1236160814Ssimon				default_op, ext_copy, selfsign);
123755714Skris			if (j < 0) goto err;
123855714Skris			if (j > 0)
123955714Skris				{
124055714Skris				total_done++;
124155714Skris				BIO_printf(bio_err,"\n");
124255714Skris				if (!BN_add_word(serial,1)) goto err;
124368651Skris				if (!sk_X509_push(cert_sk,x))
124455714Skris					{
124568651Skris					BIO_printf(bio_err,"Memory allocation failure\n");
124655714Skris					goto err;
124755714Skris					}
124855714Skris				}
124955714Skris			}
125055714Skris		for (i=0; i<argc; i++)
125155714Skris			{
125255714Skris			total++;
1253238405Sjkim			j=certify(&x,argv[i],pkey,x509p,dgst,sigopts,attribs,db,
1254160814Ssimon				serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
1255109998Smarkm				extensions,conf,verbose, certopt, nameopt,
1256160814Ssimon				default_op, ext_copy, selfsign);
125755714Skris			if (j < 0) goto err;
125855714Skris			if (j > 0)
125955714Skris				{
126055714Skris				total_done++;
126155714Skris				BIO_printf(bio_err,"\n");
126255714Skris				if (!BN_add_word(serial,1)) goto err;
126368651Skris				if (!sk_X509_push(cert_sk,x))
126455714Skris					{
126568651Skris					BIO_printf(bio_err,"Memory allocation failure\n");
126655714Skris					goto err;
126755714Skris					}
126855714Skris				}
126955714Skris			}
127055714Skris		/* we have a stack of newly certified certificates
127155714Skris		 * and a data base and serial number that need
127255714Skris		 * updating */
127355714Skris
127468651Skris		if (sk_X509_num(cert_sk) > 0)
127555714Skris			{
127655714Skris			if (!batch)
127755714Skris				{
127855714Skris				BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
127955714Skris				(void)BIO_flush(bio_err);
128055714Skris				buf[0][0]='\0';
1281205128Ssimon				if (!fgets(buf[0],10,stdin))
1282205128Ssimon					{
1283205128Ssimon					BIO_printf(bio_err,"CERTIFICATION CANCELED: I/O error\n");
1284205128Ssimon					ret=0;
1285205128Ssimon					goto err;
1286205128Ssimon					}
128755714Skris				if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
128855714Skris					{
128955714Skris					BIO_printf(bio_err,"CERTIFICATION CANCELED\n");
129055714Skris					ret=0;
129155714Skris					goto err;
129255714Skris					}
129355714Skris				}
129455714Skris
129568651Skris			BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
129655714Skris
1297127128Snectar			if (!save_serial(serialfile,"new",serial,NULL)) goto err;
129855714Skris
1299127128Snectar			if (!save_index(dbfile, "new", db)) goto err;
130055714Skris			}
130155714Skris
130255714Skris		if (verbose)
130355714Skris			BIO_printf(bio_err,"writing new certificates\n");
130468651Skris		for (i=0; i<sk_X509_num(cert_sk); i++)
130555714Skris			{
130655714Skris			int k;
1307127128Snectar			char *n;
130855714Skris
130968651Skris			x=sk_X509_value(cert_sk,i);
131055714Skris
131155714Skris			j=x->cert_info->serialNumber->length;
1312160814Ssimon			p=(const char *)x->cert_info->serialNumber->data;
131355714Skris
1314109998Smarkm			if(strlen(outdir) >= (size_t)(j ? BSIZE-j*2-6 : BSIZE-8))
1315109998Smarkm				{
1316109998Smarkm				BIO_printf(bio_err,"certificate file name too long\n");
1317109998Smarkm				goto err;
1318109998Smarkm				}
131955714Skris
1320109998Smarkm			strcpy(buf[2],outdir);
1321109998Smarkm
1322109998Smarkm#ifndef OPENSSL_SYS_VMS
1323127128Snectar			BUF_strlcat(buf[2],"/",sizeof(buf[2]));
132455714Skris#endif
132555714Skris
1326127128Snectar			n=(char *)&(buf[2][strlen(buf[2])]);
132755714Skris			if (j > 0)
132855714Skris				{
132955714Skris				for (k=0; k<j; k++)
133055714Skris					{
1331127128Snectar					if (n >= &(buf[2][sizeof(buf[2])]))
1332127128Snectar						break;
1333127128Snectar					BIO_snprintf(n,
1334127128Snectar						     &buf[2][0] + sizeof(buf[2]) - n,
1335127128Snectar						     "%02X",(unsigned char)*(p++));
133655714Skris					n+=2;
133755714Skris					}
133855714Skris				}
133955714Skris			else
134055714Skris				{
134155714Skris				*(n++)='0';
134255714Skris				*(n++)='0';
134355714Skris				}
134455714Skris			*(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
134555714Skris			*n='\0';
134655714Skris			if (verbose)
134755714Skris				BIO_printf(bio_err,"writing %s\n",buf[2]);
134855714Skris
134955714Skris			if (BIO_write_filename(Cout,buf[2]) <= 0)
135055714Skris				{
135155714Skris				perror(buf[2]);
135255714Skris				goto err;
135355714Skris				}
135459191Skris			write_new_certificate(Cout,x, 0, notext);
135559191Skris			write_new_certificate(Sout,x, output_der, notext);
135655714Skris			}
135755714Skris
135868651Skris		if (sk_X509_num(cert_sk))
135955714Skris			{
136055714Skris			/* Rename the database and the serial file */
1361127128Snectar			if (!rotate_serial(serialfile,"new","old")) goto err;
136255714Skris
1363127128Snectar			if (!rotate_index(dbfile,"new","old")) goto err;
136455714Skris
136555714Skris			BIO_printf(bio_err,"Data Base Updated\n");
136655714Skris			}
136755714Skris		}
136855714Skris
136955714Skris	/*****************************************************************/
137055714Skris	if (gencrl)
137155714Skris		{
1372109998Smarkm		int crl_v2 = 0;
1373109998Smarkm		if (!crl_ext)
1374109998Smarkm			{
1375109998Smarkm			crl_ext=NCONF_get_string(conf,section,ENV_CRLEXT);
1376109998Smarkm			if (!crl_ext)
1377109998Smarkm				ERR_clear_error();
1378109998Smarkm			}
1379109998Smarkm		if (crl_ext)
1380109998Smarkm			{
138155714Skris			/* Check syntax of file */
138255714Skris			X509V3_CTX ctx;
138355714Skris			X509V3_set_ctx_test(&ctx);
1384109998Smarkm			X509V3_set_nconf(&ctx, conf);
1385109998Smarkm			if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL))
1386109998Smarkm				{
138755714Skris				BIO_printf(bio_err,
138855714Skris				 "Error Loading CRL extension section %s\n",
138955714Skris								 crl_ext);
139055714Skris				ret = 1;
139155714Skris				goto err;
1392109998Smarkm				}
139355714Skris			}
139455714Skris
1395127128Snectar		if ((crlnumberfile=NCONF_get_string(conf,section,ENV_CRLNUMBER))
1396127128Snectar			!= NULL)
1397127128Snectar			if ((crlnumber=load_serial(crlnumberfile,0,NULL)) == NULL)
1398127128Snectar				{
1399127128Snectar				BIO_printf(bio_err,"error while loading CRL number\n");
1400127128Snectar				goto err;
1401127128Snectar				}
1402127128Snectar
1403238405Sjkim		if (!crldays && !crlhours && !crlsec)
140455714Skris			{
1405109998Smarkm			if (!NCONF_get_number(conf,section,
1406109998Smarkm				ENV_DEFAULT_CRL_DAYS, &crldays))
1407109998Smarkm				crldays = 0;
1408109998Smarkm			if (!NCONF_get_number(conf,section,
1409109998Smarkm				ENV_DEFAULT_CRL_HOURS, &crlhours))
1410109998Smarkm				crlhours = 0;
1411246772Sjkim			ERR_clear_error();
141255714Skris			}
1413238405Sjkim		if ((crldays == 0) && (crlhours == 0) && (crlsec == 0))
141455714Skris			{
1415100936Snectar			BIO_printf(bio_err,"cannot lookup how long until the next CRL is issued\n");
141655714Skris			goto err;
141755714Skris			}
141855714Skris
141955714Skris		if (verbose) BIO_printf(bio_err,"making CRL\n");
142055714Skris		if ((crl=X509_CRL_new()) == NULL) goto err;
1421109998Smarkm		if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) goto err;
142255714Skris
1423109998Smarkm		tmptm = ASN1_TIME_new();
1424109998Smarkm		if (!tmptm) goto err;
1425109998Smarkm		X509_gmtime_adj(tmptm,0);
1426109998Smarkm		X509_CRL_set_lastUpdate(crl, tmptm);
1427238405Sjkim		if (!X509_time_adj_ex(tmptm, crldays, crlhours*60*60 + crlsec,
1428238405Sjkim			NULL))
1429238405Sjkim			{
1430238405Sjkim			BIO_puts(bio_err, "error setting CRL nextUpdate\n");
1431238405Sjkim			goto err;
1432238405Sjkim			}
1433109998Smarkm		X509_CRL_set_nextUpdate(crl, tmptm);
143455714Skris
1435109998Smarkm		ASN1_TIME_free(tmptm);
1436109998Smarkm
1437238405Sjkim		for (i=0; i<sk_OPENSSL_PSTRING_num(db->db->data); i++)
143855714Skris			{
1439238405Sjkim			pp=sk_OPENSSL_PSTRING_value(db->db->data,i);
144055714Skris			if (pp[DB_type][0] == DB_TYPE_REV)
144155714Skris				{
144255714Skris				if ((r=X509_REVOKED_new()) == NULL) goto err;
1443109998Smarkm				j = make_revoked(r, pp[DB_rev_date]);
1444109998Smarkm				if (!j) goto err;
1445109998Smarkm				if (j == 2) crl_v2 = 1;
1446109998Smarkm				if (!BN_hex2bn(&serial, pp[DB_serial]))
144755714Skris					goto err;
1448109998Smarkm				tmpser = BN_to_ASN1_INTEGER(serial, NULL);
1449109998Smarkm				BN_free(serial);
1450109998Smarkm				serial = NULL;
1451109998Smarkm				if (!tmpser)
1452109998Smarkm					goto err;
1453109998Smarkm				X509_REVOKED_set_serialNumber(r, tmpser);
1454109998Smarkm				ASN1_INTEGER_free(tmpser);
1455109998Smarkm				X509_CRL_add0_revoked(crl,r);
145655714Skris				}
145755714Skris			}
1458109998Smarkm
145955714Skris		/* sort the data so it will be written in serial
146055714Skris		 * number order */
1461109998Smarkm		X509_CRL_sort(crl);
146255714Skris
146355714Skris		/* we now have a CRL */
146455714Skris		if (verbose) BIO_printf(bio_err,"signing CRL\n");
146555714Skris
146655714Skris		/* Add any extensions asked for */
146755714Skris
1468127128Snectar		if (crl_ext || crlnumberfile != NULL)
1469109998Smarkm			{
1470109998Smarkm			X509V3_CTX crlctx;
1471109998Smarkm			X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1472109998Smarkm			X509V3_set_nconf(&crlctx, conf);
147355714Skris
1474127128Snectar			if (crl_ext)
1475127128Snectar				if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx,
1476127128Snectar					crl_ext, crl)) goto err;
1477127128Snectar			if (crlnumberfile != NULL)
1478127128Snectar				{
1479127128Snectar				tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL);
1480127128Snectar				if (!tmpser) goto err;
1481127128Snectar				X509_CRL_add1_ext_i2d(crl,NID_crl_number,tmpser,0,0);
1482127128Snectar				ASN1_INTEGER_free(tmpser);
1483127128Snectar				crl_v2 = 1;
1484127128Snectar				if (!BN_add_word(crlnumber,1)) goto err;
1485127128Snectar				}
1486109998Smarkm			}
1487109998Smarkm		if (crl_ext || crl_v2)
1488109998Smarkm			{
1489109998Smarkm			if (!X509_CRL_set_version(crl, 1))
1490109998Smarkm				goto err; /* version 2 CRL */
1491109998Smarkm			}
149255714Skris
1493127128Snectar
1494127128Snectar		if (crlnumberfile != NULL)	/* we have a CRL number that need updating */
1495127128Snectar			if (!save_serial(crlnumberfile,"new",crlnumber,NULL)) goto err;
1496127128Snectar
1497238405Sjkim		if (crlnumber)
1498238405Sjkim			{
1499238405Sjkim			BN_free(crlnumber);
1500238405Sjkim			crlnumber = NULL;
1501238405Sjkim			}
150255714Skris
1503238405Sjkim		if (!do_X509_CRL_sign(bio_err,crl,pkey,dgst,sigopts)) goto err;
1504238405Sjkim
150555714Skris		PEM_write_bio_X509_CRL(Sout,crl);
1506127128Snectar
1507127128Snectar		if (crlnumberfile != NULL)	/* Rename the crlnumber file */
1508127128Snectar			if (!rotate_serial(crlnumberfile,"new","old")) goto err;
1509127128Snectar
151055714Skris		}
151155714Skris	/*****************************************************************/
151255714Skris	if (dorevoke)
151355714Skris		{
151455714Skris		if (infile == NULL)
151555714Skris			{
151655714Skris			BIO_printf(bio_err,"no input files\n");
151755714Skris			goto err;
151855714Skris			}
151955714Skris		else
152055714Skris			{
152159191Skris			X509 *revcert;
1522109998Smarkm			revcert=load_cert(bio_err, infile, FORMAT_PEM,
1523109998Smarkm				NULL, e, infile);
152459191Skris			if (revcert == NULL)
152555714Skris				goto err;
1526109998Smarkm			j=do_revoke(revcert,db, rev_type, rev_arg);
152759191Skris			if (j <= 0) goto err;
152859191Skris			X509_free(revcert);
152955714Skris
1530127128Snectar			if (!save_index(dbfile, "new", db)) goto err;
1531109998Smarkm
1532127128Snectar			if (!rotate_index(dbfile, "new", "old")) goto err;
1533127128Snectar
153455714Skris			BIO_printf(bio_err,"Data Base Updated\n");
153555714Skris			}
153655714Skris		}
153755714Skris	/*****************************************************************/
153855714Skris	ret=0;
153955714Skriserr:
1540109998Smarkm	if(tofree)
1541109998Smarkm		OPENSSL_free(tofree);
154268651Skris	BIO_free_all(Cout);
154368651Skris	BIO_free_all(Sout);
154468651Skris	BIO_free_all(out);
1545109998Smarkm	BIO_free_all(in);
154655714Skris
1547111147Snectar	if (cert_sk)
1548111147Snectar		sk_X509_pop_free(cert_sk,X509_free);
154955714Skris
155055714Skris	if (ret) ERR_print_errors(bio_err);
155159191Skris	app_RAND_write_file(randfile, bio_err);
1552111147Snectar	if (free_key && key)
1553109998Smarkm		OPENSSL_free(key);
155455714Skris	BN_free(serial);
1555238405Sjkim	BN_free(crlnumber);
1556127128Snectar	free_index(db);
1557238405Sjkim	if (sigopts)
1558238405Sjkim		sk_OPENSSL_STRING_free(sigopts);
155955714Skris	EVP_PKEY_free(pkey);
1560160814Ssimon	if (x509) X509_free(x509);
156155714Skris	X509_CRL_free(crl);
1562109998Smarkm	NCONF_free(conf);
1563167612Ssimon	NCONF_free(extconf);
156455714Skris	OBJ_cleanup();
1565109998Smarkm	apps_shutdown();
1566109998Smarkm	OPENSSL_EXIT(ret);
156755714Skris	}
156855714Skris
1569160814Ssimonstatic void lookup_fail(const char *name, const char *tag)
157055714Skris	{
157155714Skris	BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
157255714Skris	}
157355714Skris
157455714Skrisstatic int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1575238405Sjkim	     const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
1576238405Sjkim	     STACK_OF(CONF_VALUE) *policy, CA_DB *db,
1577238405Sjkim	     BIGNUM *serial, char *subj,unsigned long chtype, int multirdn,
1578238405Sjkim	     int email_dn, char *startdate, char *enddate,
1579109998Smarkm	     long days, int batch, char *ext_sect, CONF *lconf, int verbose,
1580109998Smarkm	     unsigned long certopt, unsigned long nameopt, int default_op,
1581160814Ssimon	     int ext_copy, int selfsign)
158255714Skris	{
158355714Skris	X509_REQ *req=NULL;
158455714Skris	BIO *in=NULL;
158555714Skris	EVP_PKEY *pktmp=NULL;
158655714Skris	int ok= -1,i;
158755714Skris
158855714Skris	in=BIO_new(BIO_s_file());
158955714Skris
159055714Skris	if (BIO_read_filename(in,infile) <= 0)
159155714Skris		{
159255714Skris		perror(infile);
159355714Skris		goto err;
159455714Skris		}
159555714Skris	if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
159655714Skris		{
159755714Skris		BIO_printf(bio_err,"Error reading certificate request in %s\n",
159855714Skris			infile);
159955714Skris		goto err;
160055714Skris		}
160155714Skris	if (verbose)
160255714Skris		X509_REQ_print(bio_err,req);
160355714Skris
160455714Skris	BIO_printf(bio_err,"Check that the request matches the signature\n");
160555714Skris
1606160814Ssimon	if (selfsign && !X509_REQ_check_private_key(req,pkey))
1607160814Ssimon		{
1608160814Ssimon		BIO_printf(bio_err,"Certificate request and CA private key do not match\n");
1609160814Ssimon		ok=0;
1610160814Ssimon		goto err;
1611160814Ssimon		}
161255714Skris	if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
161355714Skris		{
161455714Skris		BIO_printf(bio_err,"error unpacking public key\n");
161555714Skris		goto err;
161655714Skris		}
161755714Skris	i=X509_REQ_verify(req,pktmp);
161855714Skris	EVP_PKEY_free(pktmp);
161955714Skris	if (i < 0)
162055714Skris		{
162155714Skris		ok=0;
162255714Skris		BIO_printf(bio_err,"Signature verification problems....\n");
1623279264Sdelphij		ERR_print_errors(bio_err);
162455714Skris		goto err;
162555714Skris		}
162655714Skris	if (i == 0)
162755714Skris		{
162855714Skris		ok=0;
162955714Skris		BIO_printf(bio_err,"Signature did not match the certificate request\n");
1630279264Sdelphij		ERR_print_errors(bio_err);
163155714Skris		goto err;
163255714Skris		}
163355714Skris	else
163455714Skris		BIO_printf(bio_err,"Signature ok\n");
163555714Skris
1636238405Sjkim	ok=do_body(xret,pkey,x509,dgst,sigopts, policy,db,serial,subj,chtype,
1637238405Sjkim		multirdn, email_dn,
1638109998Smarkm		startdate,enddate,days,batch,verbose,req,ext_sect,lconf,
1639160814Ssimon		certopt, nameopt, default_op, ext_copy, selfsign);
164055714Skris
164155714Skriserr:
164255714Skris	if (req != NULL) X509_REQ_free(req);
164355714Skris	if (in != NULL) BIO_free(in);
164455714Skris	return(ok);
164555714Skris	}
164655714Skris
164755714Skrisstatic int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1648238405Sjkim	     const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
1649238405Sjkim	     STACK_OF(CONF_VALUE) *policy, CA_DB *db,
1650160814Ssimon	     BIGNUM *serial, char *subj, unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate,
1651109998Smarkm	     long days, int batch, char *ext_sect, CONF *lconf, int verbose,
1652109998Smarkm	     unsigned long certopt, unsigned long nameopt, int default_op,
1653109998Smarkm	     int ext_copy, ENGINE *e)
165455714Skris	{
165555714Skris	X509 *req=NULL;
165655714Skris	X509_REQ *rreq=NULL;
165755714Skris	EVP_PKEY *pktmp=NULL;
165855714Skris	int ok= -1,i;
165955714Skris
1660109998Smarkm	if ((req=load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL)
166155714Skris		goto err;
166255714Skris	if (verbose)
166355714Skris		X509_print(bio_err,req);
166455714Skris
166555714Skris	BIO_printf(bio_err,"Check that the request matches the signature\n");
166655714Skris
166755714Skris	if ((pktmp=X509_get_pubkey(req)) == NULL)
166855714Skris		{
166955714Skris		BIO_printf(bio_err,"error unpacking public key\n");
167055714Skris		goto err;
167155714Skris		}
167255714Skris	i=X509_verify(req,pktmp);
167355714Skris	EVP_PKEY_free(pktmp);
167455714Skris	if (i < 0)
167555714Skris		{
167655714Skris		ok=0;
167755714Skris		BIO_printf(bio_err,"Signature verification problems....\n");
167855714Skris		goto err;
167955714Skris		}
168055714Skris	if (i == 0)
168155714Skris		{
168255714Skris		ok=0;
168355714Skris		BIO_printf(bio_err,"Signature did not match the certificate\n");
168455714Skris		goto err;
168555714Skris		}
168655714Skris	else
168755714Skris		BIO_printf(bio_err,"Signature ok\n");
168855714Skris
168955714Skris	if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
169055714Skris		goto err;
169155714Skris
1692238405Sjkim	ok=do_body(xret,pkey,x509,dgst,sigopts,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,
1693109998Smarkm		days,batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op,
1694160814Ssimon		ext_copy, 0);
169555714Skris
169655714Skriserr:
169755714Skris	if (rreq != NULL) X509_REQ_free(rreq);
169855714Skris	if (req != NULL) X509_free(req);
169955714Skris	return(ok);
170055714Skris	}
170155714Skris
170255714Skrisstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1703238405Sjkim	     STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy,
1704238405Sjkim             CA_DB *db, BIGNUM *serial, char *subj,
1705160814Ssimon	     unsigned long chtype, int multirdn,
1706109998Smarkm	     int email_dn, char *startdate, char *enddate, long days, int batch,
1707109998Smarkm	     int verbose, X509_REQ *req, char *ext_sect, CONF *lconf,
1708109998Smarkm	     unsigned long certopt, unsigned long nameopt, int default_op,
1709160814Ssimon	     int ext_copy, int selfsign)
171055714Skris	{
1711109998Smarkm	X509_NAME *name=NULL,*CAname=NULL,*subject=NULL, *dn_subject=NULL;
171255714Skris	ASN1_UTCTIME *tm,*tmptm;
171355714Skris	ASN1_STRING *str,*str2;
171455714Skris	ASN1_OBJECT *obj;
171555714Skris	X509 *ret=NULL;
171655714Skris	X509_CINF *ci;
171755714Skris	X509_NAME_ENTRY *ne;
171855714Skris	X509_NAME_ENTRY *tne,*push;
171955714Skris	EVP_PKEY *pktmp;
172055714Skris	int ok= -1,i,j,last,nid;
1721160814Ssimon	const char *p;
172255714Skris	CONF_VALUE *cv;
1723238405Sjkim	OPENSSL_STRING row[DB_NUMBER];
1724238405Sjkim	OPENSSL_STRING *irow=NULL;
1725238405Sjkim	OPENSSL_STRING *rrow=NULL;
1726109998Smarkm	char buf[25];
172755714Skris
172855714Skris	tmptm=ASN1_UTCTIME_new();
172955714Skris	if (tmptm == NULL)
173055714Skris		{
173155714Skris		BIO_printf(bio_err,"malloc error\n");
173255714Skris		return(0);
173355714Skris		}
173455714Skris
173555714Skris	for (i=0; i<DB_NUMBER; i++)
173655714Skris		row[i]=NULL;
173755714Skris
1738109998Smarkm	if (subj)
1739109998Smarkm		{
1740160814Ssimon		X509_NAME *n = parse_name(subj, chtype, multirdn);
1741109998Smarkm
1742109998Smarkm		if (!n)
1743109998Smarkm			{
1744109998Smarkm			ERR_print_errors(bio_err);
1745109998Smarkm			goto err;
1746109998Smarkm			}
1747109998Smarkm		X509_REQ_set_subject_name(req,n);
1748109998Smarkm		req->req_info->enc.modified = 1;
1749109998Smarkm		X509_NAME_free(n);
1750109998Smarkm		}
1751109998Smarkm
1752109998Smarkm	if (default_op)
1753109998Smarkm		BIO_printf(bio_err,"The Subject's Distinguished Name is as follows\n");
1754109998Smarkm
175555714Skris	name=X509_REQ_get_subject_name(req);
175655714Skris	for (i=0; i<X509_NAME_entry_count(name); i++)
175755714Skris		{
1758109998Smarkm		ne= X509_NAME_get_entry(name,i);
1759109998Smarkm		str=X509_NAME_ENTRY_get_data(ne);
176055714Skris		obj=X509_NAME_ENTRY_get_object(ne);
176155714Skris
176255714Skris		if (msie_hack)
176355714Skris			{
176455714Skris			/* assume all type should be strings */
176555714Skris			nid=OBJ_obj2nid(ne->object);
176655714Skris
176755714Skris			if (str->type == V_ASN1_UNIVERSALSTRING)
176855714Skris				ASN1_UNIVERSALSTRING_to_string(str);
176955714Skris
177055714Skris			if ((str->type == V_ASN1_IA5STRING) &&
177155714Skris				(nid != NID_pkcs9_emailAddress))
177255714Skris				str->type=V_ASN1_T61STRING;
177355714Skris
177455714Skris			if ((nid == NID_pkcs9_emailAddress) &&
177555714Skris				(str->type == V_ASN1_PRINTABLESTRING))
177655714Skris				str->type=V_ASN1_IA5STRING;
177755714Skris			}
177855714Skris
1779109998Smarkm		/* If no EMAIL is wanted in the subject */
1780109998Smarkm		if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn))
1781109998Smarkm			continue;
178255714Skris
178355714Skris		/* check some things */
178455714Skris		if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
178555714Skris			(str->type != V_ASN1_IA5STRING))
178655714Skris			{
178755714Skris			BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
178855714Skris			goto err;
178955714Skris			}
1790109998Smarkm		if ((str->type != V_ASN1_BMPSTRING) && (str->type != V_ASN1_UTF8STRING))
179155714Skris			{
1792109998Smarkm			j=ASN1_PRINTABLE_type(str->data,str->length);
1793109998Smarkm			if (	((j == V_ASN1_T61STRING) &&
1794109998Smarkm				 (str->type != V_ASN1_T61STRING)) ||
1795109998Smarkm				((j == V_ASN1_IA5STRING) &&
1796109998Smarkm				 (str->type == V_ASN1_PRINTABLESTRING)))
1797109998Smarkm				{
1798109998Smarkm				BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1799109998Smarkm				goto err;
1800109998Smarkm				}
180155714Skris			}
1802109998Smarkm
1803109998Smarkm		if (default_op)
1804109998Smarkm			old_entry_print(bio_err, obj, str);
180555714Skris		}
180655714Skris
180755714Skris	/* Ok, now we check the 'policy' stuff. */
180855714Skris	if ((subject=X509_NAME_new()) == NULL)
180955714Skris		{
181068651Skris		BIO_printf(bio_err,"Memory allocation failure\n");
181155714Skris		goto err;
181255714Skris		}
181355714Skris
181455714Skris	/* take a copy of the issuer name before we mess with it. */
1815160814Ssimon	if (selfsign)
1816160814Ssimon		CAname=X509_NAME_dup(name);
1817160814Ssimon	else
1818160814Ssimon		CAname=X509_NAME_dup(x509->cert_info->subject);
181955714Skris	if (CAname == NULL) goto err;
182055714Skris	str=str2=NULL;
182155714Skris
182255714Skris	for (i=0; i<sk_CONF_VALUE_num(policy); i++)
182355714Skris		{
182455714Skris		cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
182555714Skris		if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
182655714Skris			{
182755714Skris			BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
182855714Skris			goto err;
182955714Skris			}
183055714Skris		obj=OBJ_nid2obj(j);
183155714Skris
183255714Skris		last= -1;
183355714Skris		for (;;)
183455714Skris			{
183555714Skris			/* lookup the object in the supplied name list */
183655714Skris			j=X509_NAME_get_index_by_OBJ(name,obj,last);
183755714Skris			if (j < 0)
183855714Skris				{
183955714Skris				if (last != -1) break;
184055714Skris				tne=NULL;
184155714Skris				}
184255714Skris			else
184355714Skris				{
184455714Skris				tne=X509_NAME_get_entry(name,j);
184555714Skris				}
184655714Skris			last=j;
184755714Skris
184855714Skris			/* depending on the 'policy', decide what to do. */
184955714Skris			push=NULL;
185055714Skris			if (strcmp(cv->value,"optional") == 0)
185155714Skris				{
185255714Skris				if (tne != NULL)
185355714Skris					push=tne;
185455714Skris				}
185555714Skris			else if (strcmp(cv->value,"supplied") == 0)
185655714Skris				{
185755714Skris				if (tne == NULL)
185855714Skris					{
185955714Skris					BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
186055714Skris					goto err;
186155714Skris					}
186255714Skris				else
186355714Skris					push=tne;
186455714Skris				}
186555714Skris			else if (strcmp(cv->value,"match") == 0)
186655714Skris				{
186755714Skris				int last2;
186855714Skris
186955714Skris				if (tne == NULL)
187055714Skris					{
187155714Skris					BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
187255714Skris					goto err;
187355714Skris					}
187455714Skris
187555714Skris				last2= -1;
187655714Skris
187755714Skrisagain2:
187855714Skris				j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
187955714Skris				if ((j < 0) && (last2 == -1))
188055714Skris					{
188155714Skris					BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
188255714Skris					goto err;
188355714Skris					}
188455714Skris				if (j >= 0)
188555714Skris					{
188655714Skris					push=X509_NAME_get_entry(CAname,j);
188755714Skris					str=X509_NAME_ENTRY_get_data(tne);
188855714Skris					str2=X509_NAME_ENTRY_get_data(push);
188955714Skris					last2=j;
189055714Skris					if (ASN1_STRING_cmp(str,str2) != 0)
189155714Skris						goto again2;
189255714Skris					}
189355714Skris				if (j < 0)
189455714Skris					{
189559191Skris					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));
189655714Skris					goto err;
189755714Skris					}
189855714Skris				}
189955714Skris			else
190055714Skris				{
190155714Skris				BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
190255714Skris				goto err;
190355714Skris				}
190455714Skris
190555714Skris			if (push != NULL)
190655714Skris				{
190759191Skris				if (!X509_NAME_add_entry(subject,push, -1, 0))
190855714Skris					{
190955714Skris					if (push != NULL)
191055714Skris						X509_NAME_ENTRY_free(push);
191168651Skris					BIO_printf(bio_err,"Memory allocation failure\n");
191255714Skris					goto err;
191355714Skris					}
191455714Skris				}
191555714Skris			if (j < 0) break;
191655714Skris			}
191755714Skris		}
191855714Skris
191955714Skris	if (preserve)
192055714Skris		{
192155714Skris		X509_NAME_free(subject);
1922109998Smarkm		/* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */
1923109998Smarkm		subject=X509_NAME_dup(name);
192455714Skris		if (subject == NULL) goto err;
192555714Skris		}
192655714Skris
192755714Skris	if (verbose)
192859191Skris		BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
192955714Skris
1930109998Smarkm	/* Build the correct Subject if no e-mail is wanted in the subject */
1931109998Smarkm	/* and add it later on because of the method extensions are added (altName) */
1932109998Smarkm
1933109998Smarkm	if (email_dn)
1934109998Smarkm		dn_subject = subject;
1935109998Smarkm	else
193655714Skris		{
1937109998Smarkm		X509_NAME_ENTRY *tmpne;
1938109998Smarkm		/* Its best to dup the subject DN and then delete any email
1939109998Smarkm		 * addresses because this retains its structure.
1940109998Smarkm		 */
1941109998Smarkm		if (!(dn_subject = X509_NAME_dup(subject)))
1942109998Smarkm			{
1943109998Smarkm			BIO_printf(bio_err,"Memory allocation failure\n");
1944109998Smarkm			goto err;
1945109998Smarkm			}
1946109998Smarkm		while((i = X509_NAME_get_index_by_NID(dn_subject,
1947109998Smarkm					NID_pkcs9_emailAddress, -1)) >= 0)
1948109998Smarkm			{
1949109998Smarkm			tmpne = X509_NAME_get_entry(dn_subject, i);
1950109998Smarkm			X509_NAME_delete_entry(dn_subject, i);
1951109998Smarkm			X509_NAME_ENTRY_free(tmpne);
1952109998Smarkm			}
1953109998Smarkm		}
1954109998Smarkm
1955109998Smarkm	if (BN_is_zero(serial))
1956109998Smarkm		row[DB_serial]=BUF_strdup("00");
1957109998Smarkm	else
1958109998Smarkm		row[DB_serial]=BN_bn2hex(serial);
1959109998Smarkm	if (row[DB_serial] == NULL)
1960109998Smarkm		{
196168651Skris		BIO_printf(bio_err,"Memory allocation failure\n");
196255714Skris		goto err;
196355714Skris		}
196455714Skris
1965127128Snectar	if (db->attributes.unique_subject)
196655714Skris		{
1967238405Sjkim		OPENSSL_STRING *crow=row;
1968238405Sjkim
1969238405Sjkim		rrow=TXT_DB_get_by_index(db->db,DB_name,crow);
1970127128Snectar		if (rrow != NULL)
1971127128Snectar			{
1972127128Snectar			BIO_printf(bio_err,
1973127128Snectar				"ERROR:There is already a certificate for %s\n",
1974127128Snectar				row[DB_name]);
1975127128Snectar			}
197655714Skris		}
1977127128Snectar	if (rrow == NULL)
197855714Skris		{
1979127128Snectar		rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
198055714Skris		if (rrow != NULL)
198155714Skris			{
198255714Skris			BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
198355714Skris				row[DB_serial]);
198455714Skris			BIO_printf(bio_err,"      check the database/serial_file for corruption\n");
198555714Skris			}
198655714Skris		}
198755714Skris
198855714Skris	if (rrow != NULL)
198955714Skris		{
199055714Skris		BIO_printf(bio_err,
199155714Skris			"The matching entry has the following details\n");
199255714Skris		if (rrow[DB_type][0] == 'E')
199355714Skris			p="Expired";
199455714Skris		else if (rrow[DB_type][0] == 'R')
199555714Skris			p="Revoked";
199655714Skris		else if (rrow[DB_type][0] == 'V')
199755714Skris			p="Valid";
199855714Skris		else
199955714Skris			p="\ninvalid type, Data base error\n";
200055714Skris		BIO_printf(bio_err,"Type	  :%s\n",p);;
200155714Skris		if (rrow[DB_type][0] == 'R')
200255714Skris			{
200355714Skris			p=rrow[DB_exp_date]; if (p == NULL) p="undef";
200455714Skris			BIO_printf(bio_err,"Was revoked on:%s\n",p);
200555714Skris			}
200655714Skris		p=rrow[DB_exp_date]; if (p == NULL) p="undef";
200755714Skris		BIO_printf(bio_err,"Expires on    :%s\n",p);
200855714Skris		p=rrow[DB_serial]; if (p == NULL) p="undef";
200955714Skris		BIO_printf(bio_err,"Serial Number :%s\n",p);
201055714Skris		p=rrow[DB_file]; if (p == NULL) p="undef";
201155714Skris		BIO_printf(bio_err,"File name     :%s\n",p);
201255714Skris		p=rrow[DB_name]; if (p == NULL) p="undef";
201355714Skris		BIO_printf(bio_err,"Subject Name  :%s\n",p);
201455714Skris		ok= -1; /* This is now a 'bad' error. */
201555714Skris		goto err;
201655714Skris		}
201755714Skris
201859191Skris	/* We are now totally happy, lets make and sign the certificate */
201955714Skris	if (verbose)
202055714Skris		BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
202155714Skris
202255714Skris	if ((ret=X509_new()) == NULL) goto err;
202355714Skris	ci=ret->cert_info;
202455714Skris
202555714Skris#ifdef X509_V3
202655714Skris	/* Make it an X509 v3 certificate. */
2027120631Snectar	if (!X509_set_version(ret,2)) goto err;
202855714Skris#endif
202955714Skris
203055714Skris	if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
203155714Skris		goto err;
2032160814Ssimon	if (selfsign)
2033160814Ssimon		{
2034160814Ssimon		if (!X509_set_issuer_name(ret,subject))
2035160814Ssimon			goto err;
2036160814Ssimon		}
2037160814Ssimon	else
2038160814Ssimon		{
2039160814Ssimon		if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
2040160814Ssimon			goto err;
2041160814Ssimon		}
204255714Skris
204355714Skris	if (strcmp(startdate,"today") == 0)
204455714Skris		X509_gmtime_adj(X509_get_notBefore(ret),0);
2045238405Sjkim	else ASN1_TIME_set_string(X509_get_notBefore(ret),startdate);
204655714Skris
204755714Skris	if (enddate == NULL)
2048238405Sjkim		X509_time_adj_ex(X509_get_notAfter(ret),days, 0, NULL);
2049238405Sjkim	else ASN1_TIME_set_string(X509_get_notAfter(ret),enddate);
205055714Skris
205155714Skris	if (!X509_set_subject_name(ret,subject)) goto err;
205255714Skris
205355714Skris	pktmp=X509_REQ_get_pubkey(req);
205455714Skris	i = X509_set_pubkey(ret,pktmp);
205555714Skris	EVP_PKEY_free(pktmp);
205655714Skris	if (!i) goto err;
205755714Skris
205855714Skris	/* Lets add the extensions, if there are any */
205955714Skris	if (ext_sect)
206055714Skris		{
206155714Skris		X509V3_CTX ctx;
206255714Skris		if (ci->version == NULL)
206355714Skris			if ((ci->version=ASN1_INTEGER_new()) == NULL)
206455714Skris				goto err;
206555714Skris		ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
206655714Skris
206755714Skris		/* Free the current entries if any, there should not
206859191Skris		 * be any I believe */
206955714Skris		if (ci->extensions != NULL)
207055714Skris			sk_X509_EXTENSION_pop_free(ci->extensions,
207155714Skris						   X509_EXTENSION_free);
207255714Skris
207355714Skris		ci->extensions = NULL;
207455714Skris
2075109998Smarkm		/* Initialize the context structure */
2076160814Ssimon		if (selfsign)
2077160814Ssimon			X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0);
2078160814Ssimon		else
2079160814Ssimon			X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
208055714Skris
2081109998Smarkm		if (extconf)
2082109998Smarkm			{
2083109998Smarkm			if (verbose)
2084109998Smarkm				BIO_printf(bio_err, "Extra configuration file found\n");
2085109998Smarkm
2086109998Smarkm			/* Use the extconf configuration db LHASH */
2087109998Smarkm			X509V3_set_nconf(&ctx, extconf);
2088109998Smarkm
2089109998Smarkm			/* Test the structure (needed?) */
2090109998Smarkm			/* X509V3_set_ctx_test(&ctx); */
209155714Skris
2092109998Smarkm			/* Adds exts contained in the configuration file */
2093109998Smarkm			if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect,ret))
2094109998Smarkm				{
2095109998Smarkm				BIO_printf(bio_err,
2096109998Smarkm				    "ERROR: adding extensions in section %s\n",
2097109998Smarkm								ext_sect);
2098109998Smarkm				ERR_print_errors(bio_err);
2099109998Smarkm				goto err;
2100109998Smarkm				}
2101109998Smarkm			if (verbose)
2102109998Smarkm				BIO_printf(bio_err, "Successfully added extensions from file.\n");
2103109998Smarkm			}
2104109998Smarkm		else if (ext_sect)
2105109998Smarkm			{
2106109998Smarkm			/* We found extensions to be set from config file */
2107109998Smarkm			X509V3_set_nconf(&ctx, lconf);
2108109998Smarkm
2109109998Smarkm			if(!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret))
2110109998Smarkm				{
2111109998Smarkm				BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2112109998Smarkm				ERR_print_errors(bio_err);
2113109998Smarkm				goto err;
2114109998Smarkm				}
2115109998Smarkm
2116109998Smarkm			if (verbose)
2117109998Smarkm				BIO_printf(bio_err, "Successfully added extensions from config\n");
2118109998Smarkm			}
211955714Skris		}
212055714Skris
2121109998Smarkm	/* Copy extensions from request (if any) */
212255714Skris
2123109998Smarkm	if (!copy_extensions(ret, req, ext_copy))
2124109998Smarkm		{
2125109998Smarkm		BIO_printf(bio_err, "ERROR: adding extensions from request\n");
2126109998Smarkm		ERR_print_errors(bio_err);
2127109998Smarkm		goto err;
2128109998Smarkm		}
2129109998Smarkm
2130109998Smarkm	/* Set the right value for the noemailDN option */
2131109998Smarkm	if( email_dn == 0 )
2132109998Smarkm		{
2133109998Smarkm		if (!X509_set_subject_name(ret,dn_subject)) goto err;
2134109998Smarkm		}
2135109998Smarkm
2136109998Smarkm	if (!default_op)
2137109998Smarkm		{
2138109998Smarkm		BIO_printf(bio_err, "Certificate Details:\n");
2139109998Smarkm		/* Never print signature details because signature not present */
2140109998Smarkm		certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
2141109998Smarkm		X509_print_ex(bio_err, ret, nameopt, certopt);
2142109998Smarkm		}
2143109998Smarkm
2144109998Smarkm	BIO_printf(bio_err,"Certificate is to be certified until ");
2145205128Ssimon	ASN1_TIME_print(bio_err,X509_get_notAfter(ret));
2146160814Ssimon	if (days) BIO_printf(bio_err," (%ld days)",days);
2147109998Smarkm	BIO_printf(bio_err, "\n");
2148109998Smarkm
214955714Skris	if (!batch)
215055714Skris		{
2151109998Smarkm
215255714Skris		BIO_printf(bio_err,"Sign the certificate? [y/n]:");
215355714Skris		(void)BIO_flush(bio_err);
215455714Skris		buf[0]='\0';
2155205128Ssimon		if (!fgets(buf,sizeof(buf)-1,stdin))
2156205128Ssimon			{
2157205128Ssimon			BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n");
2158205128Ssimon			ok=0;
2159205128Ssimon			goto err;
2160205128Ssimon			}
216155714Skris		if (!((buf[0] == 'y') || (buf[0] == 'Y')))
216255714Skris			{
216355714Skris			BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
216455714Skris			ok=0;
216555714Skris			goto err;
216655714Skris			}
216755714Skris		}
216855714Skris
216955714Skris	pktmp=X509_get_pubkey(ret);
217055714Skris	if (EVP_PKEY_missing_parameters(pktmp) &&
217155714Skris		!EVP_PKEY_missing_parameters(pkey))
217255714Skris		EVP_PKEY_copy_parameters(pktmp,pkey);
217355714Skris	EVP_PKEY_free(pktmp);
217455714Skris
2175238405Sjkim	if (!do_X509_sign(bio_err, ret,pkey,dgst, sigopts))
217655714Skris		goto err;
217755714Skris
217855714Skris	/* We now just add it to the database */
217968651Skris	row[DB_type]=(char *)OPENSSL_malloc(2);
218055714Skris
218155714Skris	tm=X509_get_notAfter(ret);
218268651Skris	row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
218355714Skris	memcpy(row[DB_exp_date],tm->data,tm->length);
218455714Skris	row[DB_exp_date][tm->length]='\0';
218555714Skris
218655714Skris	row[DB_rev_date]=NULL;
218755714Skris
218855714Skris	/* row[DB_serial] done already */
218968651Skris	row[DB_file]=(char *)OPENSSL_malloc(8);
2190109998Smarkm	row[DB_name]=X509_NAME_oneline(X509_get_subject_name(ret),NULL,0);
219155714Skris
219255714Skris	if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2193109998Smarkm		(row[DB_file] == NULL) || (row[DB_name] == NULL))
219455714Skris		{
219568651Skris		BIO_printf(bio_err,"Memory allocation failure\n");
219655714Skris		goto err;
219755714Skris		}
2198127128Snectar	BUF_strlcpy(row[DB_file],"unknown",8);
219955714Skris	row[DB_type][0]='V';
220055714Skris	row[DB_type][1]='\0';
220155714Skris
220268651Skris	if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
220355714Skris		{
220468651Skris		BIO_printf(bio_err,"Memory allocation failure\n");
220555714Skris		goto err;
220655714Skris		}
220755714Skris
220855714Skris	for (i=0; i<DB_NUMBER; i++)
220955714Skris		{
221055714Skris		irow[i]=row[i];
221155714Skris		row[i]=NULL;
221255714Skris		}
221355714Skris	irow[DB_NUMBER]=NULL;
221455714Skris
2215127128Snectar	if (!TXT_DB_insert(db->db,irow))
221655714Skris		{
221755714Skris		BIO_printf(bio_err,"failed to update database\n");
2218127128Snectar		BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error);
221955714Skris		goto err;
222055714Skris		}
222155714Skris	ok=1;
222255714Skriserr:
222355714Skris	for (i=0; i<DB_NUMBER; i++)
222468651Skris		if (row[i] != NULL) OPENSSL_free(row[i]);
222555714Skris
222655714Skris	if (CAname != NULL)
222755714Skris		X509_NAME_free(CAname);
222855714Skris	if (subject != NULL)
222955714Skris		X509_NAME_free(subject);
2230109998Smarkm	if ((dn_subject != NULL) && !email_dn)
2231109998Smarkm		X509_NAME_free(dn_subject);
223259191Skris	if (tmptm != NULL)
223359191Skris		ASN1_UTCTIME_free(tmptm);
223455714Skris	if (ok <= 0)
223555714Skris		{
223655714Skris		if (ret != NULL) X509_free(ret);
223755714Skris		ret=NULL;
223855714Skris		}
223955714Skris	else
224055714Skris		*xret=ret;
224155714Skris	return(ok);
224255714Skris	}
224355714Skris
224459191Skrisstatic void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
224555714Skris	{
224655714Skris
224755714Skris	if (output_der)
224855714Skris		{
224955714Skris		(void)i2d_X509_bio(bp,x);
225055714Skris		return;
225155714Skris		}
225259191Skris#if 0
225359191Skris	/* ??? Not needed since X509_print prints all this stuff anyway */
225455714Skris	f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
225555714Skris	BIO_printf(bp,"issuer :%s\n",f);
225655714Skris
225755714Skris	f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
225855714Skris	BIO_printf(bp,"subject:%s\n",f);
225955714Skris
226055714Skris	BIO_puts(bp,"serial :");
226155714Skris	i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
226255714Skris	BIO_puts(bp,"\n\n");
226359191Skris#endif
2264109998Smarkm	if (!notext)X509_print(bp,x);
226555714Skris	PEM_write_bio_X509(bp,x);
226655714Skris	}
226755714Skris
226855714Skrisstatic int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
2269238405Sjkim	     const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
2270238405Sjkim	     STACK_OF(CONF_VALUE) *policy, CA_DB *db,
2271160814Ssimon	     BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate,
2272109998Smarkm	     long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt,
2273109998Smarkm	     unsigned long nameopt, int default_op, int ext_copy)
227455714Skris	{
227555714Skris	STACK_OF(CONF_VALUE) *sk=NULL;
2276238405Sjkim	LHASH_OF(CONF_VALUE) *parms=NULL;
227755714Skris	X509_REQ *req=NULL;
227855714Skris	CONF_VALUE *cv=NULL;
227955714Skris	NETSCAPE_SPKI *spki = NULL;
228055714Skris	X509_REQ_INFO *ri;
228155714Skris	char *type,*buf;
228255714Skris	EVP_PKEY *pktmp=NULL;
228355714Skris	X509_NAME *n=NULL;
228455714Skris	X509_NAME_ENTRY *ne=NULL;
228555714Skris	int ok= -1,i,j;
228655714Skris	long errline;
228755714Skris	int nid;
228855714Skris
228955714Skris	/*
229055714Skris	 * Load input file into a hash table.  (This is just an easy
229155714Skris	 * way to read and parse the file, then put it into a convenient
229255714Skris	 * STACK format).
229355714Skris	 */
229455714Skris	parms=CONF_load(NULL,infile,&errline);
229555714Skris	if (parms == NULL)
229655714Skris		{
229755714Skris		BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
229855714Skris		ERR_print_errors(bio_err);
229955714Skris		goto err;
230055714Skris		}
230155714Skris
230255714Skris	sk=CONF_get_section(parms, "default");
230355714Skris	if (sk_CONF_VALUE_num(sk) == 0)
230455714Skris		{
230555714Skris		BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
230655714Skris		CONF_free(parms);
230755714Skris		goto err;
230855714Skris		}
230955714Skris
231055714Skris	/*
231155714Skris	 * Now create a dummy X509 request structure.  We don't actually
231255714Skris	 * have an X509 request, but we have many of the components
231355714Skris	 * (a public key, various DN components).  The idea is that we
231455714Skris	 * put these components into the right X509 request structure
231555714Skris	 * and we can use the same code as if you had a real X509 request.
231655714Skris	 */
231755714Skris	req=X509_REQ_new();
231855714Skris	if (req == NULL)
231955714Skris		{
232055714Skris		ERR_print_errors(bio_err);
232155714Skris		goto err;
232255714Skris		}
232355714Skris
232455714Skris	/*
232555714Skris	 * Build up the subject name set.
232655714Skris	 */
232755714Skris	ri=req->req_info;
232855714Skris	n = ri->subject;
232955714Skris
233055714Skris	for (i = 0; ; i++)
233155714Skris		{
233255714Skris		if (sk_CONF_VALUE_num(sk) <= i) break;
233355714Skris
233455714Skris		cv=sk_CONF_VALUE_value(sk,i);
233555714Skris		type=cv->name;
233659191Skris		/* Skip past any leading X. X: X, etc to allow for
233759191Skris		 * multiple instances
233859191Skris		 */
2339109998Smarkm		for (buf = cv->name; *buf ; buf++)
2340109998Smarkm			if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2341109998Smarkm				{
2342109998Smarkm				buf++;
2343109998Smarkm				if (*buf) type = buf;
2344109998Smarkm				break;
2345109998Smarkm				}
234659191Skris
234755714Skris		buf=cv->value;
234855714Skris		if ((nid=OBJ_txt2nid(type)) == NID_undef)
234955714Skris			{
235055714Skris			if (strcmp(type, "SPKAC") == 0)
235155714Skris				{
235259191Skris				spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
235355714Skris				if (spki == NULL)
235455714Skris					{
235555714Skris					BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
235655714Skris					ERR_print_errors(bio_err);
235755714Skris					goto err;
235855714Skris					}
235955714Skris				}
236055714Skris			continue;
236155714Skris			}
236255714Skris
2363205128Ssimon		if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
2364205128Ssimon				(unsigned char *)buf, -1, -1, 0))
236555714Skris			goto err;
236655714Skris		}
236755714Skris	if (spki == NULL)
236855714Skris		{
236955714Skris		BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
237055714Skris			infile);
237155714Skris		goto err;
237255714Skris		}
237355714Skris
237455714Skris	/*
237555714Skris	 * Now extract the key from the SPKI structure.
237655714Skris	 */
237755714Skris
237855714Skris	BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
237955714Skris
238059191Skris	if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
238155714Skris		{
238255714Skris		BIO_printf(bio_err,"error unpacking SPKAC public key\n");
238355714Skris		goto err;
238455714Skris		}
238555714Skris
238655714Skris	j = NETSCAPE_SPKI_verify(spki, pktmp);
238755714Skris	if (j <= 0)
238855714Skris		{
238955714Skris		BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
239055714Skris		goto err;
239155714Skris		}
239255714Skris	BIO_printf(bio_err,"Signature ok\n");
239355714Skris
239455714Skris	X509_REQ_set_pubkey(req,pktmp);
239555714Skris	EVP_PKEY_free(pktmp);
2396238405Sjkim	ok=do_body(xret,pkey,x509,dgst,sigopts,policy,db,serial,subj,chtype,
2397238405Sjkim		   multirdn,email_dn,startdate,enddate, days,1,verbose,req,
2398238405Sjkim		   ext_sect,lconf, certopt, nameopt, default_op, ext_copy, 0);
239955714Skriserr:
240055714Skris	if (req != NULL) X509_REQ_free(req);
240155714Skris	if (parms != NULL) CONF_free(parms);
240255714Skris	if (spki != NULL) NETSCAPE_SPKI_free(spki);
240355714Skris	if (ne != NULL) X509_NAME_ENTRY_free(ne);
240455714Skris
240555714Skris	return(ok);
240655714Skris	}
240755714Skris
2408205128Ssimonstatic int check_time_format(const char *str)
240955714Skris	{
2410238405Sjkim	return ASN1_TIME_set_string(NULL, str);
241155714Skris	}
241255714Skris
2413127128Snectarstatic int do_revoke(X509 *x509, CA_DB *db, int type, char *value)
2414109998Smarkm	{
2415109998Smarkm	ASN1_UTCTIME *tm=NULL;
241655714Skris	char *row[DB_NUMBER],**rrow,**irow;
2417109998Smarkm	char *rev_str = NULL;
241859191Skris	BIGNUM *bn = NULL;
241955714Skris	int ok=-1,i;
242055714Skris
242155714Skris	for (i=0; i<DB_NUMBER; i++)
242255714Skris		row[i]=NULL;
242359191Skris	row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
242459191Skris	bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2425238405Sjkim	if (!bn)
2426238405Sjkim		goto err;
2427109998Smarkm	if (BN_is_zero(bn))
2428109998Smarkm		row[DB_serial]=BUF_strdup("00");
2429109998Smarkm	else
2430109998Smarkm		row[DB_serial]=BN_bn2hex(bn);
243159191Skris	BN_free(bn);
243255714Skris	if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
243355714Skris		{
243468651Skris		BIO_printf(bio_err,"Memory allocation failure\n");
243555714Skris		goto err;
243655714Skris		}
243759191Skris	/* We have to lookup by serial number because name lookup
243859191Skris	 * skips revoked certs
243959191Skris 	 */
2440127128Snectar	rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
244155714Skris	if (rrow == NULL)
244255714Skris		{
2443127128Snectar		BIO_printf(bio_err,"Adding Entry with serial number %s to DB for %s\n", row[DB_serial], row[DB_name]);
244455714Skris
244555714Skris		/* We now just add it to the database */
244668651Skris		row[DB_type]=(char *)OPENSSL_malloc(2);
244755714Skris
244855714Skris		tm=X509_get_notAfter(x509);
244968651Skris		row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
245055714Skris		memcpy(row[DB_exp_date],tm->data,tm->length);
245155714Skris		row[DB_exp_date][tm->length]='\0';
245255714Skris
245355714Skris		row[DB_rev_date]=NULL;
245455714Skris
245555714Skris		/* row[DB_serial] done already */
245668651Skris		row[DB_file]=(char *)OPENSSL_malloc(8);
245755714Skris
245855714Skris		/* row[DB_name] done already */
245955714Skris
246055714Skris		if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
246155714Skris			(row[DB_file] == NULL))
246255714Skris			{
246368651Skris			BIO_printf(bio_err,"Memory allocation failure\n");
246455714Skris			goto err;
246555714Skris			}
2466127128Snectar		BUF_strlcpy(row[DB_file],"unknown",8);
246755714Skris		row[DB_type][0]='V';
246855714Skris		row[DB_type][1]='\0';
246955714Skris
247068651Skris		if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
247155714Skris			{
247268651Skris			BIO_printf(bio_err,"Memory allocation failure\n");
247355714Skris			goto err;
247455714Skris			}
247555714Skris
247655714Skris		for (i=0; i<DB_NUMBER; i++)
247755714Skris			{
247855714Skris			irow[i]=row[i];
247955714Skris			row[i]=NULL;
248055714Skris			}
248155714Skris		irow[DB_NUMBER]=NULL;
248255714Skris
2483127128Snectar		if (!TXT_DB_insert(db->db,irow))
248455714Skris			{
248555714Skris			BIO_printf(bio_err,"failed to update database\n");
2486127128Snectar			BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error);
248755714Skris			goto err;
248855714Skris			}
248955714Skris
249055714Skris		/* Revoke Certificate */
2491109998Smarkm		ok = do_revoke(x509,db, type, value);
249255714Skris
249355714Skris		goto err;
249455714Skris
249555714Skris		}
2496238405Sjkim	else if (index_name_cmp_noconst(row, rrow))
249755714Skris		{
249859191Skris		BIO_printf(bio_err,"ERROR:name does not match %s\n",
249959191Skris			   row[DB_name]);
250055714Skris		goto err;
250155714Skris		}
250255714Skris	else if (rrow[DB_type][0]=='R')
250355714Skris		{
250455714Skris		BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
250555714Skris			   row[DB_serial]);
250655714Skris		goto err;
250755714Skris		}
250855714Skris	else
250955714Skris		{
251055714Skris		BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2511109998Smarkm		rev_str = make_revocation_str(type, value);
2512109998Smarkm		if (!rev_str)
2513109998Smarkm			{
2514109998Smarkm			BIO_printf(bio_err, "Error in revocation arguments\n");
2515109998Smarkm			goto err;
2516109998Smarkm			}
251755714Skris		rrow[DB_type][0]='R';
251855714Skris		rrow[DB_type][1]='\0';
2519109998Smarkm		rrow[DB_rev_date] = rev_str;
252055714Skris		}
252155714Skris	ok=1;
252255714Skriserr:
252355714Skris	for (i=0; i<DB_NUMBER; i++)
252455714Skris		{
252555714Skris		if (row[i] != NULL)
252668651Skris			OPENSSL_free(row[i]);
252755714Skris		}
252855714Skris	return(ok);
2529109998Smarkm	}
2530109998Smarkm
2531127128Snectarstatic int get_certificate_status(const char *serial, CA_DB *db)
2532109998Smarkm	{
2533109998Smarkm	char *row[DB_NUMBER],**rrow;
2534109998Smarkm	int ok=-1,i;
2535109998Smarkm
2536109998Smarkm	/* Free Resources */
2537109998Smarkm	for (i=0; i<DB_NUMBER; i++)
2538109998Smarkm		row[i]=NULL;
2539109998Smarkm
2540109998Smarkm	/* Malloc needed char spaces */
2541109998Smarkm	row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2542109998Smarkm	if (row[DB_serial] == NULL)
2543109998Smarkm		{
2544109998Smarkm		BIO_printf(bio_err,"Malloc failure\n");
2545109998Smarkm		goto err;
2546109998Smarkm		}
2547109998Smarkm
2548109998Smarkm	if (strlen(serial) % 2)
2549109998Smarkm		{
2550109998Smarkm		/* Set the first char to 0 */;
2551109998Smarkm		row[DB_serial][0]='0';
2552109998Smarkm
2553109998Smarkm		/* Copy String from serial to row[DB_serial] */
2554109998Smarkm		memcpy(row[DB_serial]+1, serial, strlen(serial));
2555109998Smarkm		row[DB_serial][strlen(serial)+1]='\0';
2556109998Smarkm		}
2557109998Smarkm	else
2558109998Smarkm		{
2559109998Smarkm		/* Copy String from serial to row[DB_serial] */
2560109998Smarkm		memcpy(row[DB_serial], serial, strlen(serial));
2561109998Smarkm		row[DB_serial][strlen(serial)]='\0';
2562109998Smarkm		}
2563109998Smarkm
2564109998Smarkm	/* Make it Upper Case */
2565109998Smarkm	for (i=0; row[DB_serial][i] != '\0'; i++)
2566238405Sjkim		row[DB_serial][i] = toupper((unsigned char)row[DB_serial][i]);
2567109998Smarkm
2568109998Smarkm
2569109998Smarkm	ok=1;
2570109998Smarkm
2571109998Smarkm	/* Search for the certificate */
2572127128Snectar	rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
2573109998Smarkm	if (rrow == NULL)
2574109998Smarkm		{
2575109998Smarkm		BIO_printf(bio_err,"Serial %s not present in db.\n",
2576109998Smarkm				 row[DB_serial]);
2577109998Smarkm		ok=-1;
2578109998Smarkm		goto err;
2579109998Smarkm		}
2580109998Smarkm	else if (rrow[DB_type][0]=='V')
2581109998Smarkm		{
2582109998Smarkm		BIO_printf(bio_err,"%s=Valid (%c)\n",
2583109998Smarkm			row[DB_serial], rrow[DB_type][0]);
2584109998Smarkm		goto err;
2585109998Smarkm		}
2586109998Smarkm	else if (rrow[DB_type][0]=='R')
2587109998Smarkm		{
2588109998Smarkm		BIO_printf(bio_err,"%s=Revoked (%c)\n",
2589109998Smarkm			row[DB_serial], rrow[DB_type][0]);
2590109998Smarkm		goto err;
2591109998Smarkm		}
2592109998Smarkm	else if (rrow[DB_type][0]=='E')
2593109998Smarkm		{
2594109998Smarkm		BIO_printf(bio_err,"%s=Expired (%c)\n",
2595109998Smarkm			row[DB_serial], rrow[DB_type][0]);
2596109998Smarkm		goto err;
2597109998Smarkm		}
2598109998Smarkm	else if (rrow[DB_type][0]=='S')
2599109998Smarkm		{
2600109998Smarkm		BIO_printf(bio_err,"%s=Suspended (%c)\n",
2601109998Smarkm			row[DB_serial], rrow[DB_type][0]);
2602109998Smarkm		goto err;
2603109998Smarkm		}
2604109998Smarkm	else
2605109998Smarkm		{
2606109998Smarkm		BIO_printf(bio_err,"%s=Unknown (%c).\n",
2607109998Smarkm			row[DB_serial], rrow[DB_type][0]);
2608109998Smarkm		ok=-1;
2609109998Smarkm		}
2610109998Smarkmerr:
2611109998Smarkm	for (i=0; i<DB_NUMBER; i++)
2612109998Smarkm		{
2613109998Smarkm		if (row[i] != NULL)
2614109998Smarkm			OPENSSL_free(row[i]);
2615109998Smarkm		}
2616109998Smarkm	return(ok);
2617109998Smarkm	}
2618109998Smarkm
2619127128Snectarstatic int do_updatedb (CA_DB *db)
2620109998Smarkm	{
2621109998Smarkm	ASN1_UTCTIME	*a_tm = NULL;
2622109998Smarkm	int i, cnt = 0;
2623109998Smarkm	int db_y2k, a_y2k;  /* flags = 1 if y >= 2000 */
2624109998Smarkm	char **rrow, *a_tm_s;
2625109998Smarkm
2626109998Smarkm	a_tm = ASN1_UTCTIME_new();
2627109998Smarkm
2628109998Smarkm	/* get actual time and make a string */
2629109998Smarkm	a_tm = X509_gmtime_adj(a_tm, 0);
2630109998Smarkm	a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2631109998Smarkm	if (a_tm_s == NULL)
2632109998Smarkm		{
2633109998Smarkm		cnt = -1;
2634109998Smarkm		goto err;
2635109998Smarkm		}
2636109998Smarkm
2637109998Smarkm	memcpy(a_tm_s, a_tm->data, a_tm->length);
2638109998Smarkm	a_tm_s[a_tm->length] = '\0';
2639109998Smarkm
2640109998Smarkm	if (strncmp(a_tm_s, "49", 2) <= 0)
2641109998Smarkm		a_y2k = 1;
2642109998Smarkm	else
2643109998Smarkm		a_y2k = 0;
2644109998Smarkm
2645238405Sjkim	for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
2646109998Smarkm		{
2647238405Sjkim		rrow = sk_OPENSSL_PSTRING_value(db->db->data, i);
2648109998Smarkm
2649109998Smarkm		if (rrow[DB_type][0] == 'V')
2650109998Smarkm		 	{
2651109998Smarkm			/* ignore entries that are not valid */
2652109998Smarkm			if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2653109998Smarkm				db_y2k = 1;
2654109998Smarkm			else
2655109998Smarkm				db_y2k = 0;
2656109998Smarkm
2657109998Smarkm			if (db_y2k == a_y2k)
2658109998Smarkm				{
2659109998Smarkm				/* all on the same y2k side */
2660109998Smarkm				if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2661109998Smarkm				       	{
2662109998Smarkm				       	rrow[DB_type][0]  = 'E';
2663109998Smarkm				       	rrow[DB_type][1]  = '\0';
2664109998Smarkm	  				cnt++;
2665109998Smarkm
2666109998Smarkm					BIO_printf(bio_err, "%s=Expired\n",
2667109998Smarkm							rrow[DB_serial]);
2668109998Smarkm					}
2669109998Smarkm				}
2670109998Smarkm			else if (db_y2k < a_y2k)
2671109998Smarkm				{
2672109998Smarkm		  		rrow[DB_type][0]  = 'E';
2673109998Smarkm		  		rrow[DB_type][1]  = '\0';
2674109998Smarkm	  			cnt++;
2675109998Smarkm
2676109998Smarkm				BIO_printf(bio_err, "%s=Expired\n",
2677109998Smarkm							rrow[DB_serial]);
2678109998Smarkm				}
2679109998Smarkm
2680109998Smarkm			}
2681109998Smarkm    		}
2682109998Smarkm
2683109998Smarkmerr:
2684109998Smarkm
2685109998Smarkm	ASN1_UTCTIME_free(a_tm);
2686109998Smarkm	OPENSSL_free(a_tm_s);
2687109998Smarkm
2688109998Smarkm	return (cnt);
2689109998Smarkm	}
2690109998Smarkm
2691160814Ssimonstatic const char *crl_reasons[] = {
2692109998Smarkm	/* CRL reason strings */
2693109998Smarkm	"unspecified",
2694109998Smarkm	"keyCompromise",
2695109998Smarkm	"CACompromise",
2696109998Smarkm	"affiliationChanged",
2697109998Smarkm	"superseded",
2698109998Smarkm	"cessationOfOperation",
2699109998Smarkm	"certificateHold",
2700109998Smarkm	"removeFromCRL",
2701109998Smarkm	/* Additional pseudo reasons */
2702109998Smarkm	"holdInstruction",
2703109998Smarkm	"keyTime",
2704109998Smarkm	"CAkeyTime"
2705109998Smarkm};
2706109998Smarkm
2707109998Smarkm#define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2708109998Smarkm
2709109998Smarkm/* Given revocation information convert to a DB string.
2710109998Smarkm * The format of the string is:
2711109998Smarkm * revtime[,reason,extra]. Where 'revtime' is the
2712109998Smarkm * revocation time (the current time). 'reason' is the
2713109998Smarkm * optional CRL reason and 'extra' is any additional
2714109998Smarkm * argument
2715109998Smarkm */
2716109998Smarkm
2717109998Smarkmchar *make_revocation_str(int rev_type, char *rev_arg)
2718109998Smarkm	{
2719160814Ssimon	char *other = NULL, *str;
2720160814Ssimon	const char *reason = NULL;
2721109998Smarkm	ASN1_OBJECT *otmp;
2722109998Smarkm	ASN1_UTCTIME *revtm = NULL;
2723109998Smarkm	int i;
2724109998Smarkm	switch (rev_type)
2725109998Smarkm		{
2726109998Smarkm	case REV_NONE:
2727109998Smarkm		break;
2728109998Smarkm
2729109998Smarkm	case REV_CRL_REASON:
2730109998Smarkm		for (i = 0; i < 8; i++)
2731109998Smarkm			{
2732109998Smarkm			if (!strcasecmp(rev_arg, crl_reasons[i]))
2733109998Smarkm				{
2734109998Smarkm				reason = crl_reasons[i];
2735109998Smarkm				break;
2736109998Smarkm				}
2737109998Smarkm			}
2738109998Smarkm		if (reason == NULL)
2739109998Smarkm			{
2740109998Smarkm			BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2741109998Smarkm			return NULL;
2742109998Smarkm			}
2743109998Smarkm		break;
2744109998Smarkm
2745109998Smarkm	case REV_HOLD:
2746109998Smarkm		/* Argument is an OID */
2747109998Smarkm
2748109998Smarkm		otmp = OBJ_txt2obj(rev_arg, 0);
2749109998Smarkm		ASN1_OBJECT_free(otmp);
2750109998Smarkm
2751109998Smarkm		if (otmp == NULL)
2752109998Smarkm			{
2753109998Smarkm			BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2754109998Smarkm			return NULL;
2755109998Smarkm			}
2756109998Smarkm
2757109998Smarkm		reason = "holdInstruction";
2758109998Smarkm		other = rev_arg;
2759109998Smarkm		break;
2760109998Smarkm
2761109998Smarkm	case REV_KEY_COMPROMISE:
2762109998Smarkm	case REV_CA_COMPROMISE:
2763109998Smarkm
2764109998Smarkm		/* Argument is the key compromise time  */
2765109998Smarkm		if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg))
2766109998Smarkm			{
2767109998Smarkm			BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg);
2768109998Smarkm			return NULL;
2769109998Smarkm			}
2770109998Smarkm		other = rev_arg;
2771109998Smarkm		if (rev_type == REV_KEY_COMPROMISE)
2772109998Smarkm			reason = "keyTime";
2773109998Smarkm		else
2774109998Smarkm			reason = "CAkeyTime";
2775109998Smarkm
2776109998Smarkm		break;
2777109998Smarkm
2778109998Smarkm		}
2779109998Smarkm
2780109998Smarkm	revtm = X509_gmtime_adj(NULL, 0);
2781109998Smarkm
2782279264Sdelphij	if (!revtm)
2783279264Sdelphij		return NULL;
2784279264Sdelphij
2785109998Smarkm	i = revtm->length + 1;
2786109998Smarkm
2787109998Smarkm	if (reason) i += strlen(reason) + 1;
2788109998Smarkm	if (other) i += strlen(other) + 1;
2789109998Smarkm
2790109998Smarkm	str = OPENSSL_malloc(i);
2791109998Smarkm
2792109998Smarkm	if (!str) return NULL;
2793109998Smarkm
2794127128Snectar	BUF_strlcpy(str, (char *)revtm->data, i);
2795109998Smarkm	if (reason)
2796109998Smarkm		{
2797127128Snectar		BUF_strlcat(str, ",", i);
2798127128Snectar		BUF_strlcat(str, reason, i);
2799109998Smarkm		}
2800109998Smarkm	if (other)
2801109998Smarkm		{
2802127128Snectar		BUF_strlcat(str, ",", i);
2803127128Snectar		BUF_strlcat(str, other, i);
2804109998Smarkm		}
2805109998Smarkm	ASN1_UTCTIME_free(revtm);
2806109998Smarkm	return str;
2807109998Smarkm	}
2808109998Smarkm
2809109998Smarkm/* Convert revocation field to X509_REVOKED entry
2810109998Smarkm * return code:
2811109998Smarkm * 0 error
2812109998Smarkm * 1 OK
2813109998Smarkm * 2 OK and some extensions added (i.e. V2 CRL)
2814109998Smarkm */
2815109998Smarkm
2816109998Smarkm
2817160814Ssimonint make_revoked(X509_REVOKED *rev, const char *str)
2818109998Smarkm	{
2819109998Smarkm	char *tmp = NULL;
2820109998Smarkm	int reason_code = -1;
2821109998Smarkm	int i, ret = 0;
2822109998Smarkm	ASN1_OBJECT *hold = NULL;
2823109998Smarkm	ASN1_GENERALIZEDTIME *comp_time = NULL;
2824109998Smarkm	ASN1_ENUMERATED *rtmp = NULL;
2825109998Smarkm
2826109998Smarkm	ASN1_TIME *revDate = NULL;
2827109998Smarkm
2828109998Smarkm	i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str);
2829109998Smarkm
2830109998Smarkm	if (i == 0)
2831109998Smarkm		goto err;
2832109998Smarkm
2833109998Smarkm	if (rev && !X509_REVOKED_set_revocationDate(rev, revDate))
2834109998Smarkm		goto err;
2835109998Smarkm
2836109998Smarkm	if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
2837109998Smarkm		{
2838109998Smarkm		rtmp = ASN1_ENUMERATED_new();
2839109998Smarkm		if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
2840109998Smarkm			goto err;
2841109998Smarkm		if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
2842109998Smarkm			goto err;
2843109998Smarkm		}
2844109998Smarkm
2845109998Smarkm	if (rev && comp_time)
2846109998Smarkm		{
2847109998Smarkm		if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
2848109998Smarkm			goto err;
2849109998Smarkm		}
2850109998Smarkm	if (rev && hold)
2851109998Smarkm		{
2852109998Smarkm		if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
2853109998Smarkm			goto err;
2854109998Smarkm		}
2855109998Smarkm
2856109998Smarkm	if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
2857109998Smarkm		ret = 2;
2858109998Smarkm	else ret = 1;
2859109998Smarkm
2860109998Smarkm	err:
2861109998Smarkm
2862109998Smarkm	if (tmp) OPENSSL_free(tmp);
2863109998Smarkm	ASN1_OBJECT_free(hold);
2864109998Smarkm	ASN1_GENERALIZEDTIME_free(comp_time);
2865109998Smarkm	ASN1_ENUMERATED_free(rtmp);
2866109998Smarkm	ASN1_TIME_free(revDate);
2867109998Smarkm
2868109998Smarkm	return ret;
2869109998Smarkm	}
2870109998Smarkm
2871109998Smarkmint old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
2872109998Smarkm	{
2873109998Smarkm	char buf[25],*pbuf, *p;
2874109998Smarkm	int j;
2875109998Smarkm	j=i2a_ASN1_OBJECT(bp,obj);
2876109998Smarkm	pbuf=buf;
2877109998Smarkm	for (j=22-j; j>0; j--)
2878109998Smarkm		*(pbuf++)=' ';
2879109998Smarkm	*(pbuf++)=':';
2880109998Smarkm	*(pbuf++)='\0';
2881109998Smarkm	BIO_puts(bp,buf);
2882109998Smarkm
2883109998Smarkm	if (str->type == V_ASN1_PRINTABLESTRING)
2884109998Smarkm		BIO_printf(bp,"PRINTABLE:'");
2885109998Smarkm	else if (str->type == V_ASN1_T61STRING)
2886109998Smarkm		BIO_printf(bp,"T61STRING:'");
2887109998Smarkm	else if (str->type == V_ASN1_IA5STRING)
2888109998Smarkm		BIO_printf(bp,"IA5STRING:'");
2889109998Smarkm	else if (str->type == V_ASN1_UNIVERSALSTRING)
2890109998Smarkm		BIO_printf(bp,"UNIVERSALSTRING:'");
2891109998Smarkm	else
2892109998Smarkm		BIO_printf(bp,"ASN.1 %2d:'",str->type);
2893109998Smarkm
2894109998Smarkm	p=(char *)str->data;
2895109998Smarkm	for (j=str->length; j>0; j--)
2896109998Smarkm		{
2897109998Smarkm		if ((*p >= ' ') && (*p <= '~'))
2898109998Smarkm			BIO_printf(bp,"%c",*p);
2899109998Smarkm		else if (*p & 0x80)
2900109998Smarkm			BIO_printf(bp,"\\0x%02X",*p);
2901109998Smarkm		else if ((unsigned char)*p == 0xf7)
2902109998Smarkm			BIO_printf(bp,"^?");
2903109998Smarkm		else	BIO_printf(bp,"^%c",*p+'@');
2904109998Smarkm		p++;
2905109998Smarkm		}
2906109998Smarkm	BIO_printf(bp,"'\n");
2907109998Smarkm	return 1;
2908109998Smarkm	}
2909109998Smarkm
2910160814Ssimonint unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, const char *str)
2911109998Smarkm	{
2912109998Smarkm	char *tmp = NULL;
2913109998Smarkm	char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
2914109998Smarkm	int reason_code = -1;
2915160814Ssimon	int ret = 0;
2916160814Ssimon	unsigned int i;
2917109998Smarkm	ASN1_OBJECT *hold = NULL;
2918109998Smarkm	ASN1_GENERALIZEDTIME *comp_time = NULL;
2919109998Smarkm	tmp = BUF_strdup(str);
2920109998Smarkm
2921109998Smarkm	p = strchr(tmp, ',');
2922109998Smarkm
2923109998Smarkm	rtime_str = tmp;
2924109998Smarkm
2925109998Smarkm	if (p)
2926109998Smarkm		{
2927109998Smarkm		*p = '\0';
2928109998Smarkm		p++;
2929109998Smarkm		reason_str = p;
2930109998Smarkm		p = strchr(p, ',');
2931109998Smarkm		if (p)
2932109998Smarkm			{
2933109998Smarkm			*p = '\0';
2934109998Smarkm			arg_str = p + 1;
2935109998Smarkm			}
2936109998Smarkm		}
2937109998Smarkm
2938109998Smarkm	if (prevtm)
2939109998Smarkm		{
2940109998Smarkm		*prevtm = ASN1_UTCTIME_new();
2941109998Smarkm		if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str))
2942109998Smarkm			{
2943109998Smarkm			BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
2944109998Smarkm			goto err;
2945109998Smarkm			}
2946109998Smarkm		}
2947109998Smarkm	if (reason_str)
2948109998Smarkm		{
2949109998Smarkm		for (i = 0; i < NUM_REASONS; i++)
2950109998Smarkm			{
2951109998Smarkm			if(!strcasecmp(reason_str, crl_reasons[i]))
2952109998Smarkm				{
2953109998Smarkm				reason_code = i;
2954109998Smarkm				break;
2955109998Smarkm				}
2956109998Smarkm			}
2957109998Smarkm		if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS)
2958109998Smarkm			{
2959109998Smarkm			BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
2960109998Smarkm			goto err;
2961109998Smarkm			}
2962109998Smarkm
2963109998Smarkm		if (reason_code == 7)
2964109998Smarkm			reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
2965109998Smarkm		else if (reason_code == 8)		/* Hold instruction */
2966109998Smarkm			{
2967109998Smarkm			if (!arg_str)
2968109998Smarkm				{
2969109998Smarkm				BIO_printf(bio_err, "missing hold instruction\n");
2970109998Smarkm				goto err;
2971109998Smarkm				}
2972109998Smarkm			reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
2973109998Smarkm			hold = OBJ_txt2obj(arg_str, 0);
2974109998Smarkm
2975109998Smarkm			if (!hold)
2976109998Smarkm				{
2977109998Smarkm				BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
2978109998Smarkm				goto err;
2979109998Smarkm				}
2980109998Smarkm			if (phold) *phold = hold;
2981109998Smarkm			}
2982109998Smarkm		else if ((reason_code == 9) || (reason_code == 10))
2983109998Smarkm			{
2984109998Smarkm			if (!arg_str)
2985109998Smarkm				{
2986109998Smarkm				BIO_printf(bio_err, "missing compromised time\n");
2987109998Smarkm				goto err;
2988109998Smarkm				}
2989109998Smarkm			comp_time = ASN1_GENERALIZEDTIME_new();
2990109998Smarkm			if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str))
2991109998Smarkm				{
2992109998Smarkm				BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
2993109998Smarkm				goto err;
2994109998Smarkm				}
2995109998Smarkm			if (reason_code == 9)
2996109998Smarkm				reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
2997109998Smarkm			else
2998109998Smarkm				reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
2999109998Smarkm			}
3000109998Smarkm		}
3001109998Smarkm
3002109998Smarkm	if (preason) *preason = reason_code;
3003109998Smarkm	if (pinvtm) *pinvtm = comp_time;
3004109998Smarkm	else ASN1_GENERALIZEDTIME_free(comp_time);
3005109998Smarkm
3006109998Smarkm	ret = 1;
3007109998Smarkm
3008109998Smarkm	err:
3009109998Smarkm
3010109998Smarkm	if (tmp) OPENSSL_free(tmp);
3011109998Smarkm	if (!phold) ASN1_OBJECT_free(hold);
3012109998Smarkm	if (!pinvtm) ASN1_GENERALIZEDTIME_free(comp_time);
3013109998Smarkm
3014109998Smarkm	return ret;
3015109998Smarkm	}
3016