ca.c revision 55714
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>
6455714Skris#include <sys/types.h>
6555714Skris#include <sys/stat.h>
6655714Skris#include "apps.h"
6755714Skris#include <openssl/conf.h>
6855714Skris#include <openssl/bio.h>
6955714Skris#include <openssl/err.h>
7055714Skris#include <openssl/bn.h>
7155714Skris#include <openssl/txt_db.h>
7255714Skris#include <openssl/evp.h>
7355714Skris#include <openssl/x509.h>
7455714Skris#include <openssl/x509v3.h>
7555714Skris#include <openssl/objects.h>
7655714Skris#include <openssl/pem.h>
7755714Skris
7855714Skris#ifndef W_OK
7955714Skris#  ifdef VMS
8055714Skris#    if defined(__DECC)
8155714Skris#      include <unistd.h>
8255714Skris#    else
8355714Skris#      include <unixlib.h>
8455714Skris#    endif
8555714Skris#  else
8655714Skris#    include <sys/file.h>
8755714Skris#  endif
8855714Skris#endif
8955714Skris
9055714Skris#ifndef W_OK
9155714Skris#  define F_OK 0
9255714Skris#  define X_OK 1
9355714Skris#  define W_OK 2
9455714Skris#  define R_OK 4
9555714Skris#endif
9655714Skris
9755714Skris#undef PROG
9855714Skris#define PROG ca_main
9955714Skris
10055714Skris#define BASE_SECTION	"ca"
10155714Skris#define CONFIG_FILE "openssl.cnf"
10255714Skris
10355714Skris#define ENV_DEFAULT_CA		"default_ca"
10455714Skris
10555714Skris#define ENV_DIR			"dir"
10655714Skris#define ENV_CERTS		"certs"
10755714Skris#define ENV_CRL_DIR		"crl_dir"
10855714Skris#define ENV_CA_DB		"CA_DB"
10955714Skris#define ENV_NEW_CERTS_DIR	"new_certs_dir"
11055714Skris#define ENV_CERTIFICATE 	"certificate"
11155714Skris#define ENV_SERIAL		"serial"
11255714Skris#define ENV_CRL			"crl"
11355714Skris#define ENV_PRIVATE_KEY		"private_key"
11455714Skris#define ENV_RANDFILE		"RANDFILE"
11555714Skris#define ENV_DEFAULT_DAYS 	"default_days"
11655714Skris#define ENV_DEFAULT_STARTDATE 	"default_startdate"
11755714Skris#define ENV_DEFAULT_ENDDATE 	"default_enddate"
11855714Skris#define ENV_DEFAULT_CRL_DAYS 	"default_crl_days"
11955714Skris#define ENV_DEFAULT_CRL_HOURS 	"default_crl_hours"
12055714Skris#define ENV_DEFAULT_MD		"default_md"
12155714Skris#define ENV_PRESERVE		"preserve"
12255714Skris#define ENV_POLICY      	"policy"
12355714Skris#define ENV_EXTENSIONS      	"x509_extensions"
12455714Skris#define ENV_CRLEXT      	"crl_extensions"
12555714Skris#define ENV_MSIE_HACK		"msie_hack"
12655714Skris
12755714Skris#define ENV_DATABASE		"database"
12855714Skris
12955714Skris#define DB_type         0
13055714Skris#define DB_exp_date     1
13155714Skris#define DB_rev_date     2
13255714Skris#define DB_serial       3       /* index - unique */
13355714Skris#define DB_file         4
13455714Skris#define DB_name         5       /* index - unique for active */
13555714Skris#define DB_NUMBER       6
13655714Skris
13755714Skris#define DB_TYPE_REV	'R'
13855714Skris#define DB_TYPE_EXP	'E'
13955714Skris#define DB_TYPE_VAL	'V'
14055714Skris
14155714Skrisstatic char *ca_usage[]={
14255714Skris"usage: ca args\n",
14355714Skris"\n",
14455714Skris" -verbose        - Talk alot while doing things\n",
14555714Skris" -config file    - A config file\n",
14655714Skris" -name arg       - The particular CA definition to use\n",
14755714Skris" -gencrl         - Generate a new CRL\n",
14855714Skris" -crldays days   - Days is when the next CRL is due\n",
14955714Skris" -crlhours hours - Hours is when the next CRL is due\n",
15055714Skris" -days arg       - number of days to certify the certificate for\n",
15155714Skris" -md arg         - md to use, one of md2, md5, sha or sha1\n",
15255714Skris" -policy arg     - The CA 'policy' to support\n",
15355714Skris" -keyfile arg    - PEM private key file\n",
15455714Skris" -key arg        - key to decode the private key if it is encrypted\n",
15555714Skris" -cert file      - The CA certificate\n",
15655714Skris" -in file        - The input PEM encoded certificate request(s)\n",
15755714Skris" -out file       - Where to put the output file(s)\n",
15855714Skris" -outdir dir     - Where to put output certificates\n",
15955714Skris" -infiles ....   - The last argument, requests to process\n",
16055714Skris" -spkac file     - File contains DN and signed public key and challenge\n",
16155714Skris" -ss_cert file   - File contains a self signed cert to sign\n",
16255714Skris" -preserveDN     - Don't re-order the DN\n",
16355714Skris" -batch          - Don't ask questions\n",
16455714Skris" -msie_hack      - msie modifications to handle all those universal strings\n",
16555714Skris" -revoke file    - Revoke a certificate (given in file)\n",
16655714SkrisNULL
16755714Skris};
16855714Skris
16955714Skris#ifdef EFENCE
17055714Skrisextern int EF_PROTECT_FREE;
17155714Skrisextern int EF_PROTECT_BELOW;
17255714Skrisextern int EF_ALIGNMENT;
17355714Skris#endif
17455714Skris
17555714Skrisstatic int add_oid_section(LHASH *conf);
17655714Skrisstatic void lookup_fail(char *name,char *tag);
17755714Skrisstatic int MS_CALLBACK key_callback(char *buf,int len,int verify,void *u);
17855714Skrisstatic unsigned long index_serial_hash(char **a);
17955714Skrisstatic int index_serial_cmp(char **a, char **b);
18055714Skrisstatic unsigned long index_name_hash(char **a);
18155714Skrisstatic int index_name_qual(char **a);
18255714Skrisstatic int index_name_cmp(char **a,char **b);
18355714Skrisstatic BIGNUM *load_serial(char *serialfile);
18455714Skrisstatic int save_serial(char *serialfile, BIGNUM *serial);
18555714Skrisstatic int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
18655714Skris		   const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,TXT_DB *db,
18755714Skris		   BIGNUM *serial, char *startdate,char *enddate, int days,
18855714Skris		   int batch, char *ext_sect, LHASH *conf,int verbose);
18955714Skrisstatic int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
19055714Skris			const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
19155714Skris			TXT_DB *db, BIGNUM *serial,char *startdate,
19255714Skris			char *enddate, int days, int batch, char *ext_sect,
19355714Skris			LHASH *conf,int verbose);
19455714Skrisstatic int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
19555714Skris			 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
19655714Skris			 TXT_DB *db, BIGNUM *serial,char *startdate,
19755714Skris			 char *enddate, int days, char *ext_sect,LHASH *conf,
19855714Skris				int verbose);
19955714Skrisstatic int fix_data(int nid, int *type);
20055714Skrisstatic void write_new_certificate(BIO *bp, X509 *x, int output_der);
20155714Skrisstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
20255714Skris	STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
20355714Skris	char *startdate, char *enddate, int days, int batch, int verbose,
20455714Skris	X509_REQ *req, char *ext_sect, LHASH *conf);
20555714Skrisstatic int do_revoke(X509 *x509, TXT_DB *db);
20655714Skrisstatic int check_time_format(char *str);
20755714Skrisstatic LHASH *conf;
20855714Skrisstatic char *key=NULL;
20955714Skrisstatic char *section=NULL;
21055714Skris
21155714Skrisstatic int preserve=0;
21255714Skrisstatic int msie_hack=0;
21355714Skris
21455714Skrisint MAIN(int argc, char **argv)
21555714Skris	{
21655714Skris	int total=0;
21755714Skris	int total_done=0;
21855714Skris	int badops=0;
21955714Skris	int ret=1;
22055714Skris	int req=0;
22155714Skris	int verbose=0;
22255714Skris	int gencrl=0;
22355714Skris	int dorevoke=0;
22455714Skris	long crldays=0;
22555714Skris	long crlhours=0;
22655714Skris	long errorline= -1;
22755714Skris	char *configfile=NULL;
22855714Skris	char *md=NULL;
22955714Skris	char *policy=NULL;
23055714Skris	char *keyfile=NULL;
23155714Skris	char *certfile=NULL;
23255714Skris	char *infile=NULL;
23355714Skris	char *spkac_file=NULL;
23455714Skris	char *ss_cert_file=NULL;
23555714Skris	EVP_PKEY *pkey=NULL;
23655714Skris	int output_der = 0;
23755714Skris	char *outfile=NULL;
23855714Skris	char *outdir=NULL;
23955714Skris	char *serialfile=NULL;
24055714Skris	char *extensions=NULL;
24155714Skris	char *crl_ext=NULL;
24255714Skris	BIGNUM *serial=NULL;
24355714Skris	char *startdate=NULL;
24455714Skris	char *enddate=NULL;
24555714Skris	int days=0;
24655714Skris	int batch=0;
24755714Skris	X509 *x509=NULL;
24855714Skris	X509 *x=NULL;
24955714Skris	BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
25055714Skris	char *dbfile=NULL;
25155714Skris	TXT_DB *db=NULL;
25255714Skris	X509_CRL *crl=NULL;
25355714Skris	X509_CRL_INFO *ci=NULL;
25455714Skris	X509_REVOKED *r=NULL;
25555714Skris	char **pp,*p,*f;
25655714Skris	int i,j;
25755714Skris	long l;
25855714Skris	const EVP_MD *dgst=NULL;
25955714Skris	STACK_OF(CONF_VALUE) *attribs=NULL;
26055714Skris	STACK *cert_sk=NULL;
26155714Skris	BIO *hex=NULL;
26255714Skris#undef BSIZE
26355714Skris#define BSIZE 256
26455714Skris	MS_STATIC char buf[3][BSIZE];
26555714Skris
26655714Skris#ifdef EFENCE
26755714SkrisEF_PROTECT_FREE=1;
26855714SkrisEF_PROTECT_BELOW=1;
26955714SkrisEF_ALIGNMENT=0;
27055714Skris#endif
27155714Skris
27255714Skris	apps_startup();
27355714Skris
27455714Skris	X509V3_add_standard_extensions();
27555714Skris
27655714Skris	preserve=0;
27755714Skris	if (bio_err == NULL)
27855714Skris		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
27955714Skris			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
28055714Skris
28155714Skris	argc--;
28255714Skris	argv++;
28355714Skris	while (argc >= 1)
28455714Skris		{
28555714Skris		if	(strcmp(*argv,"-verbose") == 0)
28655714Skris			verbose=1;
28755714Skris		else if	(strcmp(*argv,"-config") == 0)
28855714Skris			{
28955714Skris			if (--argc < 1) goto bad;
29055714Skris			configfile= *(++argv);
29155714Skris			}
29255714Skris		else if (strcmp(*argv,"-name") == 0)
29355714Skris			{
29455714Skris			if (--argc < 1) goto bad;
29555714Skris			section= *(++argv);
29655714Skris			}
29755714Skris		else if (strcmp(*argv,"-startdate") == 0)
29855714Skris			{
29955714Skris			if (--argc < 1) goto bad;
30055714Skris			startdate= *(++argv);
30155714Skris			}
30255714Skris		else if (strcmp(*argv,"-enddate") == 0)
30355714Skris			{
30455714Skris			if (--argc < 1) goto bad;
30555714Skris			enddate= *(++argv);
30655714Skris			}
30755714Skris		else if (strcmp(*argv,"-days") == 0)
30855714Skris			{
30955714Skris			if (--argc < 1) goto bad;
31055714Skris			days=atoi(*(++argv));
31155714Skris			}
31255714Skris		else if (strcmp(*argv,"-md") == 0)
31355714Skris			{
31455714Skris			if (--argc < 1) goto bad;
31555714Skris			md= *(++argv);
31655714Skris			}
31755714Skris		else if (strcmp(*argv,"-policy") == 0)
31855714Skris			{
31955714Skris			if (--argc < 1) goto bad;
32055714Skris			policy= *(++argv);
32155714Skris			}
32255714Skris		else if (strcmp(*argv,"-keyfile") == 0)
32355714Skris			{
32455714Skris			if (--argc < 1) goto bad;
32555714Skris			keyfile= *(++argv);
32655714Skris			}
32755714Skris		else if (strcmp(*argv,"-key") == 0)
32855714Skris			{
32955714Skris			if (--argc < 1) goto bad;
33055714Skris			key= *(++argv);
33155714Skris			}
33255714Skris		else if (strcmp(*argv,"-cert") == 0)
33355714Skris			{
33455714Skris			if (--argc < 1) goto bad;
33555714Skris			certfile= *(++argv);
33655714Skris			}
33755714Skris		else if (strcmp(*argv,"-in") == 0)
33855714Skris			{
33955714Skris			if (--argc < 1) goto bad;
34055714Skris			infile= *(++argv);
34155714Skris			req=1;
34255714Skris			}
34355714Skris		else if (strcmp(*argv,"-out") == 0)
34455714Skris			{
34555714Skris			if (--argc < 1) goto bad;
34655714Skris			outfile= *(++argv);
34755714Skris			}
34855714Skris		else if (strcmp(*argv,"-outdir") == 0)
34955714Skris			{
35055714Skris			if (--argc < 1) goto bad;
35155714Skris			outdir= *(++argv);
35255714Skris			}
35355714Skris		else if (strcmp(*argv,"-batch") == 0)
35455714Skris			batch=1;
35555714Skris		else if (strcmp(*argv,"-preserveDN") == 0)
35655714Skris			preserve=1;
35755714Skris		else if (strcmp(*argv,"-gencrl") == 0)
35855714Skris			gencrl=1;
35955714Skris		else if (strcmp(*argv,"-msie_hack") == 0)
36055714Skris			msie_hack=1;
36155714Skris		else if (strcmp(*argv,"-crldays") == 0)
36255714Skris			{
36355714Skris			if (--argc < 1) goto bad;
36455714Skris			crldays= atol(*(++argv));
36555714Skris			}
36655714Skris		else if (strcmp(*argv,"-crlhours") == 0)
36755714Skris			{
36855714Skris			if (--argc < 1) goto bad;
36955714Skris			crlhours= atol(*(++argv));
37055714Skris			}
37155714Skris		else if (strcmp(*argv,"-infiles") == 0)
37255714Skris			{
37355714Skris			argc--;
37455714Skris			argv++;
37555714Skris			req=1;
37655714Skris			break;
37755714Skris			}
37855714Skris		else if (strcmp(*argv, "-ss_cert") == 0)
37955714Skris			{
38055714Skris			if (--argc < 1) goto bad;
38155714Skris			ss_cert_file = *(++argv);
38255714Skris			req=1;
38355714Skris			}
38455714Skris		else if (strcmp(*argv, "-spkac") == 0)
38555714Skris			{
38655714Skris			if (--argc < 1) goto bad;
38755714Skris			spkac_file = *(++argv);
38855714Skris			req=1;
38955714Skris			}
39055714Skris		else if (strcmp(*argv,"-revoke") == 0)
39155714Skris			{
39255714Skris			if (--argc < 1) goto bad;
39355714Skris			infile= *(++argv);
39455714Skris			dorevoke=1;
39555714Skris			}
39655714Skris		else
39755714Skris			{
39855714Skrisbad:
39955714Skris			BIO_printf(bio_err,"unknown option %s\n",*argv);
40055714Skris			badops=1;
40155714Skris			break;
40255714Skris			}
40355714Skris		argc--;
40455714Skris		argv++;
40555714Skris		}
40655714Skris
40755714Skris	if (badops)
40855714Skris		{
40955714Skris		for (pp=ca_usage; (*pp != NULL); pp++)
41055714Skris			BIO_printf(bio_err,*pp);
41155714Skris		goto err;
41255714Skris		}
41355714Skris
41455714Skris	ERR_load_crypto_strings();
41555714Skris
41655714Skris	/*****************************************************************/
41755714Skris	if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
41855714Skris	if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
41955714Skris	if (configfile == NULL)
42055714Skris		{
42155714Skris		/* We will just use 'buf[0]' as a temporary buffer.  */
42255714Skris#ifdef VMS
42355714Skris		strncpy(buf[0],X509_get_default_cert_area(),
42455714Skris			sizeof(buf[0])-1-sizeof(CONFIG_FILE));
42555714Skris#else
42655714Skris		strncpy(buf[0],X509_get_default_cert_area(),
42755714Skris			sizeof(buf[0])-2-sizeof(CONFIG_FILE));
42855714Skris		strcat(buf[0],"/");
42955714Skris#endif
43055714Skris		strcat(buf[0],CONFIG_FILE);
43155714Skris		configfile=buf[0];
43255714Skris		}
43355714Skris
43455714Skris	BIO_printf(bio_err,"Using configuration from %s\n",configfile);
43555714Skris	if ((conf=CONF_load(NULL,configfile,&errorline)) == NULL)
43655714Skris		{
43755714Skris		if (errorline <= 0)
43855714Skris			BIO_printf(bio_err,"error loading the config file '%s'\n",
43955714Skris				configfile);
44055714Skris		else
44155714Skris			BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
44255714Skris				,errorline,configfile);
44355714Skris		goto err;
44455714Skris		}
44555714Skris
44655714Skris	/* Lets get the config section we are using */
44755714Skris	if (section == NULL)
44855714Skris		{
44955714Skris		section=CONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
45055714Skris		if (section == NULL)
45155714Skris			{
45255714Skris			lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
45355714Skris			goto err;
45455714Skris			}
45555714Skris		}
45655714Skris
45755714Skris	if (conf != NULL)
45855714Skris		{
45955714Skris		p=CONF_get_string(conf,NULL,"oid_file");
46055714Skris		if (p != NULL)
46155714Skris			{
46255714Skris			BIO *oid_bio;
46355714Skris
46455714Skris			oid_bio=BIO_new_file(p,"r");
46555714Skris			if (oid_bio == NULL)
46655714Skris				{
46755714Skris				/*
46855714Skris				BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
46955714Skris				ERR_print_errors(bio_err);
47055714Skris				*/
47155714Skris				ERR_clear_error();
47255714Skris				}
47355714Skris			else
47455714Skris				{
47555714Skris				OBJ_create_objects(oid_bio);
47655714Skris				BIO_free(oid_bio);
47755714Skris				}
47855714Skris			}
47955714Skris		}
48055714Skris		if(!add_oid_section(conf)) {
48155714Skris			ERR_print_errors(bio_err);
48255714Skris			goto err;
48355714Skris		}
48455714Skris
48555714Skris	in=BIO_new(BIO_s_file());
48655714Skris	out=BIO_new(BIO_s_file());
48755714Skris	Sout=BIO_new(BIO_s_file());
48855714Skris	Cout=BIO_new(BIO_s_file());
48955714Skris	if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL))
49055714Skris		{
49155714Skris		ERR_print_errors(bio_err);
49255714Skris		goto err;
49355714Skris		}
49455714Skris
49555714Skris	/*****************************************************************/
49655714Skris	/* we definitly need an public key, so lets get it */
49755714Skris
49855714Skris	if ((keyfile == NULL) && ((keyfile=CONF_get_string(conf,
49955714Skris		section,ENV_PRIVATE_KEY)) == NULL))
50055714Skris		{
50155714Skris		lookup_fail(section,ENV_PRIVATE_KEY);
50255714Skris		goto err;
50355714Skris		}
50455714Skris	if (BIO_read_filename(in,keyfile) <= 0)
50555714Skris		{
50655714Skris		perror(keyfile);
50755714Skris		BIO_printf(bio_err,"trying to load CA private key\n");
50855714Skris		goto err;
50955714Skris		}
51055714Skris	if (key == NULL)
51155714Skris		pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,NULL);
51255714Skris	else
51355714Skris		{
51455714Skris		pkey=PEM_read_bio_PrivateKey(in,NULL,key_callback,NULL);
51555714Skris		memset(key,0,strlen(key));
51655714Skris		}
51755714Skris	if (pkey == NULL)
51855714Skris		{
51955714Skris		BIO_printf(bio_err,"unable to load CA private key\n");
52055714Skris		goto err;
52155714Skris		}
52255714Skris
52355714Skris	/*****************************************************************/
52455714Skris	/* we need a certificate */
52555714Skris	if ((certfile == NULL) && ((certfile=CONF_get_string(conf,
52655714Skris		section,ENV_CERTIFICATE)) == NULL))
52755714Skris		{
52855714Skris		lookup_fail(section,ENV_CERTIFICATE);
52955714Skris		goto err;
53055714Skris		}
53155714Skris        if (BIO_read_filename(in,certfile) <= 0)
53255714Skris		{
53355714Skris		perror(certfile);
53455714Skris		BIO_printf(bio_err,"trying to load CA certificate\n");
53555714Skris		goto err;
53655714Skris		}
53755714Skris	x509=PEM_read_bio_X509(in,NULL,NULL,NULL);
53855714Skris	if (x509 == NULL)
53955714Skris		{
54055714Skris		BIO_printf(bio_err,"unable to load CA certificate\n");
54155714Skris		goto err;
54255714Skris		}
54355714Skris
54455714Skris	if (!X509_check_private_key(x509,pkey))
54555714Skris		{
54655714Skris		BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
54755714Skris		goto err;
54855714Skris		}
54955714Skris
55055714Skris	f=CONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
55155714Skris	if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
55255714Skris		preserve=1;
55355714Skris	f=CONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
55455714Skris	if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
55555714Skris		msie_hack=1;
55655714Skris
55755714Skris	/*****************************************************************/
55855714Skris	/* lookup where to write new certificates */
55955714Skris	if ((outdir == NULL) && (req))
56055714Skris		{
56155714Skris		struct stat sb;
56255714Skris
56355714Skris		if ((outdir=CONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
56455714Skris			== NULL)
56555714Skris			{
56655714Skris			BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
56755714Skris			goto err;
56855714Skris			}
56955714Skris#ifdef VMS
57055714Skris		/* For technical reasons, VMS misbehaves with X_OK */
57155714Skris		if (access(outdir,R_OK|W_OK) != 0)
57255714Skris#else
57355714Skris		if (access(outdir,R_OK|W_OK|X_OK) != 0)
57455714Skris#endif
57555714Skris			{
57655714Skris			BIO_printf(bio_err,"I am unable to acces the %s directory\n",outdir);
57755714Skris			perror(outdir);
57855714Skris			goto err;
57955714Skris			}
58055714Skris
58155714Skris		if (stat(outdir,&sb) != 0)
58255714Skris			{
58355714Skris			BIO_printf(bio_err,"unable to stat(%s)\n",outdir);
58455714Skris			perror(outdir);
58555714Skris			goto err;
58655714Skris			}
58755714Skris		if (!(sb.st_mode & S_IFDIR))
58855714Skris			{
58955714Skris			BIO_printf(bio_err,"%s need to be a directory\n",outdir);
59055714Skris			perror(outdir);
59155714Skris			goto err;
59255714Skris			}
59355714Skris		}
59455714Skris
59555714Skris	/*****************************************************************/
59655714Skris	/* we need to load the database file */
59755714Skris	if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL)
59855714Skris		{
59955714Skris		lookup_fail(section,ENV_DATABASE);
60055714Skris		goto err;
60155714Skris		}
60255714Skris	if (BIO_read_filename(in,dbfile) <= 0)
60355714Skris		{
60455714Skris		perror(dbfile);
60555714Skris		BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
60655714Skris		goto err;
60755714Skris		}
60855714Skris	db=TXT_DB_read(in,DB_NUMBER);
60955714Skris	if (db == NULL) goto err;
61055714Skris
61155714Skris	/* Lets check some fields */
61255714Skris	for (i=0; i<sk_num(db->data); i++)
61355714Skris		{
61455714Skris		pp=(char **)sk_value(db->data,i);
61555714Skris		if ((pp[DB_type][0] != DB_TYPE_REV) &&
61655714Skris			(pp[DB_rev_date][0] != '\0'))
61755714Skris			{
61855714Skris			BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
61955714Skris			goto err;
62055714Skris			}
62155714Skris		if ((pp[DB_type][0] == DB_TYPE_REV) &&
62255714Skris			!check_time_format(pp[DB_rev_date]))
62355714Skris			{
62455714Skris			BIO_printf(bio_err,"entry %d: invalid revocation date\n",
62555714Skris				i+1);
62655714Skris			goto err;
62755714Skris			}
62855714Skris		if (!check_time_format(pp[DB_exp_date]))
62955714Skris			{
63055714Skris			BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
63155714Skris			goto err;
63255714Skris			}
63355714Skris		p=pp[DB_serial];
63455714Skris		j=strlen(p);
63555714Skris		if ((j&1) || (j < 2))
63655714Skris			{
63755714Skris			BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
63855714Skris			goto err;
63955714Skris			}
64055714Skris		while (*p)
64155714Skris			{
64255714Skris			if (!(	((*p >= '0') && (*p <= '9')) ||
64355714Skris				((*p >= 'A') && (*p <= 'F')) ||
64455714Skris				((*p >= 'a') && (*p <= 'f')))  )
64555714Skris				{
64655714Skris				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);
64755714Skris				goto err;
64855714Skris				}
64955714Skris			p++;
65055714Skris			}
65155714Skris		}
65255714Skris	if (verbose)
65355714Skris		{
65455714Skris		BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
65555714Skris		TXT_DB_write(out,db);
65655714Skris		BIO_printf(bio_err,"%d entries loaded from the database\n",
65755714Skris			db->data->num);
65855714Skris		BIO_printf(bio_err,"generating indexs\n");
65955714Skris		}
66055714Skris
66155714Skris	if (!TXT_DB_create_index(db,DB_serial,NULL,index_serial_hash,
66255714Skris		index_serial_cmp))
66355714Skris		{
66455714Skris		BIO_printf(bio_err,"error creating serial number index:(%ld,%ld,%ld)\n",db->error,db->arg1,db->arg2);
66555714Skris		goto err;
66655714Skris		}
66755714Skris
66855714Skris	if (!TXT_DB_create_index(db,DB_name,index_name_qual,index_name_hash,
66955714Skris		index_name_cmp))
67055714Skris		{
67155714Skris		BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
67255714Skris			db->error,db->arg1,db->arg2);
67355714Skris		goto err;
67455714Skris		}
67555714Skris
67655714Skris	/*****************************************************************/
67755714Skris	if (req || gencrl)
67855714Skris		{
67955714Skris		if (outfile != NULL)
68055714Skris			{
68155714Skris
68255714Skris			if (BIO_write_filename(Sout,outfile) <= 0)
68355714Skris				{
68455714Skris				perror(outfile);
68555714Skris				goto err;
68655714Skris				}
68755714Skris			}
68855714Skris		else
68955714Skris			BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
69055714Skris		}
69155714Skris
69255714Skris	if (req)
69355714Skris		{
69455714Skris		if ((md == NULL) && ((md=CONF_get_string(conf,
69555714Skris			section,ENV_DEFAULT_MD)) == NULL))
69655714Skris			{
69755714Skris			lookup_fail(section,ENV_DEFAULT_MD);
69855714Skris			goto err;
69955714Skris			}
70055714Skris		if ((dgst=EVP_get_digestbyname(md)) == NULL)
70155714Skris			{
70255714Skris			BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
70355714Skris			goto err;
70455714Skris			}
70555714Skris		if (verbose)
70655714Skris			BIO_printf(bio_err,"message digest is %s\n",
70755714Skris				OBJ_nid2ln(dgst->type));
70855714Skris		if ((policy == NULL) && ((policy=CONF_get_string(conf,
70955714Skris			section,ENV_POLICY)) == NULL))
71055714Skris			{
71155714Skris			lookup_fail(section,ENV_POLICY);
71255714Skris			goto err;
71355714Skris			}
71455714Skris		if (verbose)
71555714Skris			BIO_printf(bio_err,"policy is %s\n",policy);
71655714Skris
71755714Skris		if ((serialfile=CONF_get_string(conf,section,ENV_SERIAL))
71855714Skris			== NULL)
71955714Skris			{
72055714Skris			lookup_fail(section,ENV_SERIAL);
72155714Skris			goto err;
72255714Skris			}
72355714Skris
72455714Skris		extensions=CONF_get_string(conf,section,ENV_EXTENSIONS);
72555714Skris		if(extensions) {
72655714Skris			/* Check syntax of file */
72755714Skris			X509V3_CTX ctx;
72855714Skris			X509V3_set_ctx_test(&ctx);
72955714Skris			X509V3_set_conf_lhash(&ctx, conf);
73055714Skris			if(!X509V3_EXT_add_conf(conf, &ctx, extensions, NULL)) {
73155714Skris				BIO_printf(bio_err,
73255714Skris				 "Error Loading extension section %s\n",
73355714Skris								 extensions);
73455714Skris				ret = 1;
73555714Skris				goto err;
73655714Skris			}
73755714Skris		}
73855714Skris
73955714Skris		if (startdate == NULL)
74055714Skris			{
74155714Skris			startdate=CONF_get_string(conf,section,
74255714Skris				ENV_DEFAULT_STARTDATE);
74355714Skris			}
74455714Skris		if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
74555714Skris			{
74655714Skris			BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
74755714Skris			goto err;
74855714Skris			}
74955714Skris		if (startdate == NULL) startdate="today";
75055714Skris
75155714Skris		if (enddate == NULL)
75255714Skris			{
75355714Skris			enddate=CONF_get_string(conf,section,
75455714Skris				ENV_DEFAULT_ENDDATE);
75555714Skris			}
75655714Skris		if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
75755714Skris			{
75855714Skris			BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
75955714Skris			goto err;
76055714Skris			}
76155714Skris
76255714Skris		if (days == 0)
76355714Skris			{
76455714Skris			days=(int)CONF_get_number(conf,section,
76555714Skris				ENV_DEFAULT_DAYS);
76655714Skris			}
76755714Skris		if (!enddate && (days == 0))
76855714Skris			{
76955714Skris			BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
77055714Skris			goto err;
77155714Skris			}
77255714Skris
77355714Skris		if ((serial=load_serial(serialfile)) == NULL)
77455714Skris			{
77555714Skris			BIO_printf(bio_err,"error while loading serial number\n");
77655714Skris			goto err;
77755714Skris			}
77855714Skris		if (verbose)
77955714Skris			{
78055714Skris			if ((f=BN_bn2hex(serial)) == NULL) goto err;
78155714Skris			BIO_printf(bio_err,"next serial number is %s\n",f);
78255714Skris			Free(f);
78355714Skris			}
78455714Skris
78555714Skris		if ((attribs=CONF_get_section(conf,policy)) == NULL)
78655714Skris			{
78755714Skris			BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
78855714Skris			goto err;
78955714Skris			}
79055714Skris
79155714Skris		if ((cert_sk=sk_new_null()) == NULL)
79255714Skris			{
79355714Skris			BIO_printf(bio_err,"Malloc failure\n");
79455714Skris			goto err;
79555714Skris			}
79655714Skris		if (spkac_file != NULL)
79755714Skris			{
79855714Skris			total++;
79955714Skris			j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
80055714Skris				serial,startdate,enddate, days,extensions,conf,
80155714Skris				verbose);
80255714Skris			if (j < 0) goto err;
80355714Skris			if (j > 0)
80455714Skris				{
80555714Skris				total_done++;
80655714Skris				BIO_printf(bio_err,"\n");
80755714Skris				if (!BN_add_word(serial,1)) goto err;
80855714Skris				if (!sk_push(cert_sk,(char *)x))
80955714Skris					{
81055714Skris					BIO_printf(bio_err,"Malloc failure\n");
81155714Skris					goto err;
81255714Skris					}
81355714Skris				if (outfile)
81455714Skris					{
81555714Skris					output_der = 1;
81655714Skris					batch = 1;
81755714Skris					}
81855714Skris				}
81955714Skris			}
82055714Skris		if (ss_cert_file != NULL)
82155714Skris			{
82255714Skris			total++;
82355714Skris			j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
82455714Skris				db,serial,startdate,enddate,days,batch,
82555714Skris				extensions,conf,verbose);
82655714Skris			if (j < 0) goto err;
82755714Skris			if (j > 0)
82855714Skris				{
82955714Skris				total_done++;
83055714Skris				BIO_printf(bio_err,"\n");
83155714Skris				if (!BN_add_word(serial,1)) goto err;
83255714Skris				if (!sk_push(cert_sk,(char *)x))
83355714Skris					{
83455714Skris					BIO_printf(bio_err,"Malloc failure\n");
83555714Skris					goto err;
83655714Skris					}
83755714Skris				}
83855714Skris			}
83955714Skris		if (infile != NULL)
84055714Skris			{
84155714Skris			total++;
84255714Skris			j=certify(&x,infile,pkey,x509,dgst,attribs,db,
84355714Skris				serial,startdate,enddate,days,batch,
84455714Skris				extensions,conf,verbose);
84555714Skris			if (j < 0) goto err;
84655714Skris			if (j > 0)
84755714Skris				{
84855714Skris				total_done++;
84955714Skris				BIO_printf(bio_err,"\n");
85055714Skris				if (!BN_add_word(serial,1)) goto err;
85155714Skris				if (!sk_push(cert_sk,(char *)x))
85255714Skris					{
85355714Skris					BIO_printf(bio_err,"Malloc failure\n");
85455714Skris					goto err;
85555714Skris					}
85655714Skris				}
85755714Skris			}
85855714Skris		for (i=0; i<argc; i++)
85955714Skris			{
86055714Skris			total++;
86155714Skris			j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
86255714Skris				serial,startdate,enddate,days,batch,
86355714Skris				extensions,conf,verbose);
86455714Skris			if (j < 0) goto err;
86555714Skris			if (j > 0)
86655714Skris				{
86755714Skris				total_done++;
86855714Skris				BIO_printf(bio_err,"\n");
86955714Skris				if (!BN_add_word(serial,1)) goto err;
87055714Skris				if (!sk_push(cert_sk,(char *)x))
87155714Skris					{
87255714Skris					BIO_printf(bio_err,"Malloc failure\n");
87355714Skris					goto err;
87455714Skris					}
87555714Skris				}
87655714Skris			}
87755714Skris		/* we have a stack of newly certified certificates
87855714Skris		 * and a data base and serial number that need
87955714Skris		 * updating */
88055714Skris
88155714Skris		if (sk_num(cert_sk) > 0)
88255714Skris			{
88355714Skris			if (!batch)
88455714Skris				{
88555714Skris				BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
88655714Skris				(void)BIO_flush(bio_err);
88755714Skris				buf[0][0]='\0';
88855714Skris				fgets(buf[0],10,stdin);
88955714Skris				if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
89055714Skris					{
89155714Skris					BIO_printf(bio_err,"CERTIFICATION CANCELED\n");
89255714Skris					ret=0;
89355714Skris					goto err;
89455714Skris					}
89555714Skris				}
89655714Skris
89755714Skris			BIO_printf(bio_err,"Write out database with %d new entries\n",sk_num(cert_sk));
89855714Skris
89955714Skris			strncpy(buf[0],serialfile,BSIZE-4);
90055714Skris
90155714Skris#ifdef VMS
90255714Skris			strcat(buf[0],"-new");
90355714Skris#else
90455714Skris			strcat(buf[0],".new");
90555714Skris#endif
90655714Skris
90755714Skris			if (!save_serial(buf[0],serial)) goto err;
90855714Skris
90955714Skris			strncpy(buf[1],dbfile,BSIZE-4);
91055714Skris
91155714Skris#ifdef VMS
91255714Skris			strcat(buf[1],"-new");
91355714Skris#else
91455714Skris			strcat(buf[1],".new");
91555714Skris#endif
91655714Skris
91755714Skris			if (BIO_write_filename(out,buf[1]) <= 0)
91855714Skris				{
91955714Skris				perror(dbfile);
92055714Skris				BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
92155714Skris				goto err;
92255714Skris				}
92355714Skris			l=TXT_DB_write(out,db);
92455714Skris			if (l <= 0) goto err;
92555714Skris			}
92655714Skris
92755714Skris		if (verbose)
92855714Skris			BIO_printf(bio_err,"writing new certificates\n");
92955714Skris		for (i=0; i<sk_num(cert_sk); i++)
93055714Skris			{
93155714Skris			int k;
93255714Skris			unsigned char *n;
93355714Skris
93455714Skris			x=(X509 *)sk_value(cert_sk,i);
93555714Skris
93655714Skris			j=x->cert_info->serialNumber->length;
93755714Skris			p=(char *)x->cert_info->serialNumber->data;
93855714Skris
93955714Skris			strncpy(buf[2],outdir,BSIZE-(j*2)-6);
94055714Skris
94155714Skris#ifndef VMS
94255714Skris			strcat(buf[2],"/");
94355714Skris#endif
94455714Skris
94555714Skris			n=(unsigned char *)&(buf[2][strlen(buf[2])]);
94655714Skris			if (j > 0)
94755714Skris				{
94855714Skris				for (k=0; k<j; k++)
94955714Skris					{
95055714Skris					sprintf((char *)n,"%02X",(unsigned char)*(p++));
95155714Skris					n+=2;
95255714Skris					}
95355714Skris				}
95455714Skris			else
95555714Skris				{
95655714Skris				*(n++)='0';
95755714Skris				*(n++)='0';
95855714Skris				}
95955714Skris			*(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
96055714Skris			*n='\0';
96155714Skris			if (verbose)
96255714Skris				BIO_printf(bio_err,"writing %s\n",buf[2]);
96355714Skris
96455714Skris			if (BIO_write_filename(Cout,buf[2]) <= 0)
96555714Skris				{
96655714Skris				perror(buf[2]);
96755714Skris				goto err;
96855714Skris				}
96955714Skris			write_new_certificate(Cout,x, 0);
97055714Skris			write_new_certificate(Sout,x, output_der);
97155714Skris			}
97255714Skris
97355714Skris		if (sk_num(cert_sk))
97455714Skris			{
97555714Skris			/* Rename the database and the serial file */
97655714Skris			strncpy(buf[2],serialfile,BSIZE-4);
97755714Skris
97855714Skris#ifdef VMS
97955714Skris			strcat(buf[2],"-old");
98055714Skris#else
98155714Skris			strcat(buf[2],".old");
98255714Skris#endif
98355714Skris
98455714Skris			BIO_free(in);
98555714Skris			BIO_free(out);
98655714Skris			in=NULL;
98755714Skris			out=NULL;
98855714Skris			if (rename(serialfile,buf[2]) < 0)
98955714Skris				{
99055714Skris				BIO_printf(bio_err,"unabel to rename %s to %s\n",
99155714Skris					serialfile,buf[2]);
99255714Skris				perror("reason");
99355714Skris				goto err;
99455714Skris				}
99555714Skris			if (rename(buf[0],serialfile) < 0)
99655714Skris				{
99755714Skris				BIO_printf(bio_err,"unabel to rename %s to %s\n",
99855714Skris					buf[0],serialfile);
99955714Skris				perror("reason");
100055714Skris				rename(buf[2],serialfile);
100155714Skris				goto err;
100255714Skris				}
100355714Skris
100455714Skris			strncpy(buf[2],dbfile,BSIZE-4);
100555714Skris
100655714Skris#ifdef VMS
100755714Skris			strcat(buf[2],"-old");
100855714Skris#else
100955714Skris			strcat(buf[2],".old");
101055714Skris#endif
101155714Skris
101255714Skris			if (rename(dbfile,buf[2]) < 0)
101355714Skris				{
101455714Skris				BIO_printf(bio_err,"unabel to rename %s to %s\n",
101555714Skris					dbfile,buf[2]);
101655714Skris				perror("reason");
101755714Skris				goto err;
101855714Skris				}
101955714Skris			if (rename(buf[1],dbfile) < 0)
102055714Skris				{
102155714Skris				BIO_printf(bio_err,"unabel to rename %s to %s\n",
102255714Skris					buf[1],dbfile);
102355714Skris				perror("reason");
102455714Skris				rename(buf[2],dbfile);
102555714Skris				goto err;
102655714Skris				}
102755714Skris			BIO_printf(bio_err,"Data Base Updated\n");
102855714Skris			}
102955714Skris		}
103055714Skris
103155714Skris	/*****************************************************************/
103255714Skris	if (gencrl)
103355714Skris		{
103455714Skris		crl_ext=CONF_get_string(conf,section,ENV_CRLEXT);
103555714Skris		if(crl_ext) {
103655714Skris			/* Check syntax of file */
103755714Skris			X509V3_CTX ctx;
103855714Skris			X509V3_set_ctx_test(&ctx);
103955714Skris			X509V3_set_conf_lhash(&ctx, conf);
104055714Skris			if(!X509V3_EXT_add_conf(conf, &ctx, crl_ext, NULL)) {
104155714Skris				BIO_printf(bio_err,
104255714Skris				 "Error Loading CRL extension section %s\n",
104355714Skris								 crl_ext);
104455714Skris				ret = 1;
104555714Skris				goto err;
104655714Skris			}
104755714Skris		}
104855714Skris		if ((hex=BIO_new(BIO_s_mem())) == NULL) goto err;
104955714Skris
105055714Skris		if (!crldays && !crlhours)
105155714Skris			{
105255714Skris			crldays=CONF_get_number(conf,section,
105355714Skris				ENV_DEFAULT_CRL_DAYS);
105455714Skris			crlhours=CONF_get_number(conf,section,
105555714Skris				ENV_DEFAULT_CRL_HOURS);
105655714Skris			}
105755714Skris		if ((crldays == 0) && (crlhours == 0))
105855714Skris			{
105955714Skris			BIO_printf(bio_err,"cannot lookup how long until the next CRL is issuer\n");
106055714Skris			goto err;
106155714Skris			}
106255714Skris
106355714Skris		if (verbose) BIO_printf(bio_err,"making CRL\n");
106455714Skris		if ((crl=X509_CRL_new()) == NULL) goto err;
106555714Skris		ci=crl->crl;
106655714Skris		X509_NAME_free(ci->issuer);
106755714Skris		ci->issuer=X509_NAME_dup(x509->cert_info->subject);
106855714Skris		if (ci->issuer == NULL) goto err;
106955714Skris
107055714Skris		X509_gmtime_adj(ci->lastUpdate,0);
107155714Skris		if (ci->nextUpdate == NULL)
107255714Skris			ci->nextUpdate=ASN1_UTCTIME_new();
107355714Skris		X509_gmtime_adj(ci->nextUpdate,(crldays*24+crlhours)*60*60);
107455714Skris
107555714Skris		for (i=0; i<sk_num(db->data); i++)
107655714Skris			{
107755714Skris			pp=(char **)sk_value(db->data,i);
107855714Skris			if (pp[DB_type][0] == DB_TYPE_REV)
107955714Skris				{
108055714Skris				if ((r=X509_REVOKED_new()) == NULL) goto err;
108155714Skris				ASN1_STRING_set((ASN1_STRING *)
108255714Skris					r->revocationDate,
108355714Skris					(unsigned char *)pp[DB_rev_date],
108455714Skris					strlen(pp[DB_rev_date]));
108555714Skris				/* strcpy(r->revocationDate,pp[DB_rev_date]);*/
108655714Skris
108755714Skris				(void)BIO_reset(hex);
108855714Skris				if (!BIO_puts(hex,pp[DB_serial]))
108955714Skris					goto err;
109055714Skris				if (!a2i_ASN1_INTEGER(hex,r->serialNumber,
109155714Skris					buf[0],BSIZE)) goto err;
109255714Skris
109355714Skris				sk_X509_REVOKED_push(ci->revoked,r);
109455714Skris				}
109555714Skris			}
109655714Skris		/* sort the data so it will be written in serial
109755714Skris		 * number order */
109855714Skris		sk_X509_REVOKED_sort(ci->revoked);
109955714Skris		for (i=0; i<sk_X509_REVOKED_num(ci->revoked); i++)
110055714Skris			{
110155714Skris			r=sk_X509_REVOKED_value(ci->revoked,i);
110255714Skris			r->sequence=i;
110355714Skris			}
110455714Skris
110555714Skris		/* we now have a CRL */
110655714Skris		if (verbose) BIO_printf(bio_err,"signing CRL\n");
110755714Skris		if (md != NULL)
110855714Skris			{
110955714Skris			if ((dgst=EVP_get_digestbyname(md)) == NULL)
111055714Skris				{
111155714Skris				BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
111255714Skris				goto err;
111355714Skris				}
111455714Skris			}
111555714Skris		else
111655714Skris		    {
111755714Skris#ifndef NO_DSA
111855714Skris		    if (pkey->type == EVP_PKEY_DSA)
111955714Skris			dgst=EVP_dss1();
112055714Skris		    else
112155714Skris#endif
112255714Skris			dgst=EVP_md5();
112355714Skris		    }
112455714Skris
112555714Skris		/* Add any extensions asked for */
112655714Skris
112755714Skris		if(crl_ext) {
112855714Skris		    X509V3_CTX crlctx;
112955714Skris		    if (ci->version == NULL)
113055714Skris		    if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
113155714Skris		    ASN1_INTEGER_set(ci->version,1); /* version 2 CRL */
113255714Skris		    X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
113355714Skris		    X509V3_set_conf_lhash(&crlctx, conf);
113455714Skris
113555714Skris		    if(!X509V3_EXT_CRL_add_conf(conf, &crlctx,
113655714Skris						 crl_ext, crl)) goto err;
113755714Skris		}
113855714Skris
113955714Skris		if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
114055714Skris
114155714Skris		PEM_write_bio_X509_CRL(Sout,crl);
114255714Skris		}
114355714Skris	/*****************************************************************/
114455714Skris	if (dorevoke)
114555714Skris		{
114655714Skris		in=BIO_new(BIO_s_file());
114755714Skris		out=BIO_new(BIO_s_file());
114855714Skris		if ((in == NULL) || (out == NULL))
114955714Skris			{
115055714Skris			ERR_print_errors(bio_err);
115155714Skris			goto err;
115255714Skris			}
115355714Skris		if (infile == NULL)
115455714Skris			{
115555714Skris			BIO_printf(bio_err,"no input files\n");
115655714Skris			goto err;
115755714Skris			}
115855714Skris		else
115955714Skris			{
116055714Skris			if (BIO_read_filename(in,infile) <= 0)
116155714Skris				{
116255714Skris				perror(infile);
116355714Skris				BIO_printf(bio_err,"error trying to load '%s' certificate\n",infile);
116455714Skris				goto err;
116555714Skris				}
116655714Skris			x509=PEM_read_bio_X509(in,NULL,NULL,NULL);
116755714Skris			if (x509 == NULL)
116855714Skris				{
116955714Skris				BIO_printf(bio_err,"unable to load '%s' certificate\n",infile);
117055714Skris				goto err;
117155714Skris				}
117255714Skris			j=do_revoke(x509,db);
117355714Skris
117455714Skris			strncpy(buf[0],dbfile,BSIZE-4);
117555714Skris			strcat(buf[0],".new");
117655714Skris			if (BIO_write_filename(out,buf[0]) <= 0)
117755714Skris				{
117855714Skris				perror(dbfile);
117955714Skris				BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
118055714Skris				goto err;
118155714Skris				}
118255714Skris			j=TXT_DB_write(out,db);
118355714Skris			if (j <= 0) goto err;
118455714Skris			BIO_free(in);
118555714Skris			BIO_free(out);
118655714Skris			in=NULL;
118755714Skris			out=NULL;
118855714Skris			strncpy(buf[1],dbfile,BSIZE-4);
118955714Skris			strcat(buf[1],".old");
119055714Skris			if (rename(dbfile,buf[1]) < 0)
119155714Skris				{
119255714Skris				BIO_printf(bio_err,"unable to rename %s to %s\n", dbfile, buf[1]);
119355714Skris				perror("reason");
119455714Skris				goto err;
119555714Skris				}
119655714Skris			if (rename(buf[0],dbfile) < 0)
119755714Skris				{
119855714Skris				BIO_printf(bio_err,"unable to rename %s to %s\n", buf[0],dbfile);
119955714Skris				perror("reason");
120055714Skris				rename(buf[1],dbfile);
120155714Skris				goto err;
120255714Skris				}
120355714Skris			BIO_printf(bio_err,"Data Base Updated\n");
120455714Skris			}
120555714Skris		}
120655714Skris	/*****************************************************************/
120755714Skris	ret=0;
120855714Skriserr:
120955714Skris	BIO_free(hex);
121055714Skris	BIO_free(Cout);
121155714Skris	BIO_free(Sout);
121255714Skris	BIO_free(out);
121355714Skris	BIO_free(in);
121455714Skris
121555714Skris	sk_pop_free(cert_sk,X509_free);
121655714Skris
121755714Skris	if (ret) ERR_print_errors(bio_err);
121855714Skris	BN_free(serial);
121955714Skris	TXT_DB_free(db);
122055714Skris	EVP_PKEY_free(pkey);
122155714Skris	X509_free(x509);
122255714Skris	X509_CRL_free(crl);
122355714Skris	CONF_free(conf);
122455714Skris	X509V3_EXT_cleanup();
122555714Skris	OBJ_cleanup();
122655714Skris	EXIT(ret);
122755714Skris	}
122855714Skris
122955714Skrisstatic void lookup_fail(char *name, char *tag)
123055714Skris	{
123155714Skris	BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
123255714Skris	}
123355714Skris
123455714Skrisstatic int MS_CALLBACK key_callback(char *buf, int len, int verify, void *u)
123555714Skris	{
123655714Skris	int i;
123755714Skris
123855714Skris	if (key == NULL) return(0);
123955714Skris	i=strlen(key);
124055714Skris	i=(i > len)?len:i;
124155714Skris	memcpy(buf,key,i);
124255714Skris	return(i);
124355714Skris	}
124455714Skris
124555714Skrisstatic unsigned long index_serial_hash(char **a)
124655714Skris	{
124755714Skris	char *n;
124855714Skris
124955714Skris	n=a[DB_serial];
125055714Skris	while (*n == '0') n++;
125155714Skris	return(lh_strhash(n));
125255714Skris	}
125355714Skris
125455714Skrisstatic int index_serial_cmp(char **a, char **b)
125555714Skris	{
125655714Skris	char *aa,*bb;
125755714Skris
125855714Skris	for (aa=a[DB_serial]; *aa == '0'; aa++);
125955714Skris	for (bb=b[DB_serial]; *bb == '0'; bb++);
126055714Skris	return(strcmp(aa,bb));
126155714Skris	}
126255714Skris
126355714Skrisstatic unsigned long index_name_hash(char **a)
126455714Skris	{ return(lh_strhash(a[DB_name])); }
126555714Skris
126655714Skrisstatic int index_name_qual(char **a)
126755714Skris	{ return(a[0][0] == 'V'); }
126855714Skris
126955714Skrisstatic int index_name_cmp(char **a, char **b)
127055714Skris	{ return(strcmp(a[DB_name],
127155714Skris	     b[DB_name])); }
127255714Skris
127355714Skrisstatic BIGNUM *load_serial(char *serialfile)
127455714Skris	{
127555714Skris	BIO *in=NULL;
127655714Skris	BIGNUM *ret=NULL;
127755714Skris	MS_STATIC char buf[1024];
127855714Skris	ASN1_INTEGER *ai=NULL;
127955714Skris
128055714Skris	if ((in=BIO_new(BIO_s_file())) == NULL)
128155714Skris		{
128255714Skris		ERR_print_errors(bio_err);
128355714Skris		goto err;
128455714Skris		}
128555714Skris
128655714Skris	if (BIO_read_filename(in,serialfile) <= 0)
128755714Skris		{
128855714Skris		perror(serialfile);
128955714Skris		goto err;
129055714Skris		}
129155714Skris	ai=ASN1_INTEGER_new();
129255714Skris	if (ai == NULL) goto err;
129355714Skris	if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
129455714Skris		{
129555714Skris		BIO_printf(bio_err,"unable to load number from %s\n",
129655714Skris			serialfile);
129755714Skris		goto err;
129855714Skris		}
129955714Skris	ret=ASN1_INTEGER_to_BN(ai,NULL);
130055714Skris	if (ret == NULL)
130155714Skris		{
130255714Skris		BIO_printf(bio_err,"error converting number from bin to BIGNUM");
130355714Skris		goto err;
130455714Skris		}
130555714Skriserr:
130655714Skris	if (in != NULL) BIO_free(in);
130755714Skris	if (ai != NULL) ASN1_INTEGER_free(ai);
130855714Skris	return(ret);
130955714Skris	}
131055714Skris
131155714Skrisstatic int save_serial(char *serialfile, BIGNUM *serial)
131255714Skris	{
131355714Skris	BIO *out;
131455714Skris	int ret=0;
131555714Skris	ASN1_INTEGER *ai=NULL;
131655714Skris
131755714Skris	out=BIO_new(BIO_s_file());
131855714Skris	if (out == NULL)
131955714Skris		{
132055714Skris		ERR_print_errors(bio_err);
132155714Skris		goto err;
132255714Skris		}
132355714Skris	if (BIO_write_filename(out,serialfile) <= 0)
132455714Skris		{
132555714Skris		perror(serialfile);
132655714Skris		goto err;
132755714Skris		}
132855714Skris
132955714Skris	if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
133055714Skris		{
133155714Skris		BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
133255714Skris		goto err;
133355714Skris		}
133455714Skris	i2a_ASN1_INTEGER(out,ai);
133555714Skris	BIO_puts(out,"\n");
133655714Skris	ret=1;
133755714Skriserr:
133855714Skris	if (out != NULL) BIO_free(out);
133955714Skris	if (ai != NULL) ASN1_INTEGER_free(ai);
134055714Skris	return(ret);
134155714Skris	}
134255714Skris
134355714Skrisstatic int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
134455714Skris	     const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
134555714Skris	     BIGNUM *serial, char *startdate, char *enddate, int days,
134655714Skris	     int batch, char *ext_sect, LHASH *lconf, int verbose)
134755714Skris	{
134855714Skris	X509_REQ *req=NULL;
134955714Skris	BIO *in=NULL;
135055714Skris	EVP_PKEY *pktmp=NULL;
135155714Skris	int ok= -1,i;
135255714Skris
135355714Skris	in=BIO_new(BIO_s_file());
135455714Skris
135555714Skris	if (BIO_read_filename(in,infile) <= 0)
135655714Skris		{
135755714Skris		perror(infile);
135855714Skris		goto err;
135955714Skris		}
136055714Skris	if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
136155714Skris		{
136255714Skris		BIO_printf(bio_err,"Error reading certificate request in %s\n",
136355714Skris			infile);
136455714Skris		goto err;
136555714Skris		}
136655714Skris	if (verbose)
136755714Skris		X509_REQ_print(bio_err,req);
136855714Skris
136955714Skris	BIO_printf(bio_err,"Check that the request matches the signature\n");
137055714Skris
137155714Skris	if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
137255714Skris		{
137355714Skris		BIO_printf(bio_err,"error unpacking public key\n");
137455714Skris		goto err;
137555714Skris		}
137655714Skris	i=X509_REQ_verify(req,pktmp);
137755714Skris	EVP_PKEY_free(pktmp);
137855714Skris	if (i < 0)
137955714Skris		{
138055714Skris		ok=0;
138155714Skris		BIO_printf(bio_err,"Signature verification problems....\n");
138255714Skris		goto err;
138355714Skris		}
138455714Skris	if (i == 0)
138555714Skris		{
138655714Skris		ok=0;
138755714Skris		BIO_printf(bio_err,"Signature did not match the certificate request\n");
138855714Skris		goto err;
138955714Skris		}
139055714Skris	else
139155714Skris		BIO_printf(bio_err,"Signature ok\n");
139255714Skris
139355714Skris	ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate, enddate,
139455714Skris		days,batch,verbose,req,ext_sect,lconf);
139555714Skris
139655714Skriserr:
139755714Skris	if (req != NULL) X509_REQ_free(req);
139855714Skris	if (in != NULL) BIO_free(in);
139955714Skris	return(ok);
140055714Skris	}
140155714Skris
140255714Skrisstatic int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
140355714Skris	     const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
140455714Skris	     BIGNUM *serial, char *startdate, char *enddate, int days,
140555714Skris	     int batch, char *ext_sect, LHASH *lconf, int verbose)
140655714Skris	{
140755714Skris	X509 *req=NULL;
140855714Skris	X509_REQ *rreq=NULL;
140955714Skris	BIO *in=NULL;
141055714Skris	EVP_PKEY *pktmp=NULL;
141155714Skris	int ok= -1,i;
141255714Skris
141355714Skris	in=BIO_new(BIO_s_file());
141455714Skris
141555714Skris	if (BIO_read_filename(in,infile) <= 0)
141655714Skris		{
141755714Skris		perror(infile);
141855714Skris		goto err;
141955714Skris		}
142055714Skris	if ((req=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
142155714Skris		{
142255714Skris		BIO_printf(bio_err,"Error reading self signed certificate in %s\n",infile);
142355714Skris		goto err;
142455714Skris		}
142555714Skris	if (verbose)
142655714Skris		X509_print(bio_err,req);
142755714Skris
142855714Skris	BIO_printf(bio_err,"Check that the request matches the signature\n");
142955714Skris
143055714Skris	if ((pktmp=X509_get_pubkey(req)) == NULL)
143155714Skris		{
143255714Skris		BIO_printf(bio_err,"error unpacking public key\n");
143355714Skris		goto err;
143455714Skris		}
143555714Skris	i=X509_verify(req,pktmp);
143655714Skris	EVP_PKEY_free(pktmp);
143755714Skris	if (i < 0)
143855714Skris		{
143955714Skris		ok=0;
144055714Skris		BIO_printf(bio_err,"Signature verification problems....\n");
144155714Skris		goto err;
144255714Skris		}
144355714Skris	if (i == 0)
144455714Skris		{
144555714Skris		ok=0;
144655714Skris		BIO_printf(bio_err,"Signature did not match the certificate\n");
144755714Skris		goto err;
144855714Skris		}
144955714Skris	else
145055714Skris		BIO_printf(bio_err,"Signature ok\n");
145155714Skris
145255714Skris	if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
145355714Skris		goto err;
145455714Skris
145555714Skris	ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,days,
145655714Skris		batch,verbose,rreq,ext_sect,lconf);
145755714Skris
145855714Skriserr:
145955714Skris	if (rreq != NULL) X509_REQ_free(rreq);
146055714Skris	if (req != NULL) X509_free(req);
146155714Skris	if (in != NULL) BIO_free(in);
146255714Skris	return(ok);
146355714Skris	}
146455714Skris
146555714Skrisstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
146655714Skris	     STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
146755714Skris	     char *startdate, char *enddate, int days, int batch, int verbose,
146855714Skris	     X509_REQ *req, char *ext_sect, LHASH *lconf)
146955714Skris	{
147055714Skris	X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
147155714Skris	ASN1_UTCTIME *tm,*tmptm;
147255714Skris	ASN1_STRING *str,*str2;
147355714Skris	ASN1_OBJECT *obj;
147455714Skris	X509 *ret=NULL;
147555714Skris	X509_CINF *ci;
147655714Skris	X509_NAME_ENTRY *ne;
147755714Skris	X509_NAME_ENTRY *tne,*push;
147855714Skris	EVP_PKEY *pktmp;
147955714Skris	int ok= -1,i,j,last,nid;
148055714Skris	char *p;
148155714Skris	CONF_VALUE *cv;
148255714Skris	char *row[DB_NUMBER],**rrow,**irow=NULL;
148355714Skris	char buf[25],*pbuf;
148455714Skris
148555714Skris	tmptm=ASN1_UTCTIME_new();
148655714Skris	if (tmptm == NULL)
148755714Skris		{
148855714Skris		BIO_printf(bio_err,"malloc error\n");
148955714Skris		return(0);
149055714Skris		}
149155714Skris
149255714Skris	for (i=0; i<DB_NUMBER; i++)
149355714Skris		row[i]=NULL;
149455714Skris
149555714Skris	BIO_printf(bio_err,"The Subjects Distinguished Name is as follows\n");
149655714Skris	name=X509_REQ_get_subject_name(req);
149755714Skris	for (i=0; i<X509_NAME_entry_count(name); i++)
149855714Skris		{
149955714Skris		ne=(X509_NAME_ENTRY *)X509_NAME_get_entry(name,i);
150055714Skris		obj=X509_NAME_ENTRY_get_object(ne);
150155714Skris		j=i2a_ASN1_OBJECT(bio_err,obj);
150255714Skris		str=X509_NAME_ENTRY_get_data(ne);
150355714Skris		pbuf=buf;
150455714Skris		for (j=22-j; j>0; j--)
150555714Skris			*(pbuf++)=' ';
150655714Skris		*(pbuf++)=':';
150755714Skris		*(pbuf++)='\0';
150855714Skris		BIO_puts(bio_err,buf);
150955714Skris
151055714Skris		if (msie_hack)
151155714Skris			{
151255714Skris			/* assume all type should be strings */
151355714Skris			nid=OBJ_obj2nid(ne->object);
151455714Skris
151555714Skris			if (str->type == V_ASN1_UNIVERSALSTRING)
151655714Skris				ASN1_UNIVERSALSTRING_to_string(str);
151755714Skris
151855714Skris			if ((str->type == V_ASN1_IA5STRING) &&
151955714Skris				(nid != NID_pkcs9_emailAddress))
152055714Skris				str->type=V_ASN1_T61STRING;
152155714Skris
152255714Skris			if ((nid == NID_pkcs9_emailAddress) &&
152355714Skris				(str->type == V_ASN1_PRINTABLESTRING))
152455714Skris				str->type=V_ASN1_IA5STRING;
152555714Skris			}
152655714Skris
152755714Skris		if (str->type == V_ASN1_PRINTABLESTRING)
152855714Skris			BIO_printf(bio_err,"PRINTABLE:'");
152955714Skris		else if (str->type == V_ASN1_T61STRING)
153055714Skris			BIO_printf(bio_err,"T61STRING:'");
153155714Skris		else if (str->type == V_ASN1_IA5STRING)
153255714Skris			BIO_printf(bio_err,"IA5STRING:'");
153355714Skris		else if (str->type == V_ASN1_UNIVERSALSTRING)
153455714Skris			BIO_printf(bio_err,"UNIVERSALSTRING:'");
153555714Skris		else
153655714Skris			BIO_printf(bio_err,"ASN.1 %2d:'",str->type);
153755714Skris
153855714Skris		/* check some things */
153955714Skris		if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
154055714Skris			(str->type != V_ASN1_IA5STRING))
154155714Skris			{
154255714Skris			BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
154355714Skris			goto err;
154455714Skris			}
154555714Skris		j=ASN1_PRINTABLE_type(str->data,str->length);
154655714Skris		if (	((j == V_ASN1_T61STRING) &&
154755714Skris			 (str->type != V_ASN1_T61STRING)) ||
154855714Skris			((j == V_ASN1_IA5STRING) &&
154955714Skris			 (str->type == V_ASN1_PRINTABLESTRING)))
155055714Skris			{
155155714Skris			BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
155255714Skris			goto err;
155355714Skris			}
155455714Skris
155555714Skris		p=(char *)str->data;
155655714Skris		for (j=str->length; j>0; j--)
155755714Skris			{
155855714Skris			if ((*p >= ' ') && (*p <= '~'))
155955714Skris				BIO_printf(bio_err,"%c",*p);
156055714Skris			else if (*p & 0x80)
156155714Skris				BIO_printf(bio_err,"\\0x%02X",*p);
156255714Skris			else if ((unsigned char)*p == 0xf7)
156355714Skris				BIO_printf(bio_err,"^?");
156455714Skris			else	BIO_printf(bio_err,"^%c",*p+'@');
156555714Skris			p++;
156655714Skris			}
156755714Skris		BIO_printf(bio_err,"'\n");
156855714Skris		}
156955714Skris
157055714Skris	/* Ok, now we check the 'policy' stuff. */
157155714Skris	if ((subject=X509_NAME_new()) == NULL)
157255714Skris		{
157355714Skris		BIO_printf(bio_err,"Malloc failure\n");
157455714Skris		goto err;
157555714Skris		}
157655714Skris
157755714Skris	/* take a copy of the issuer name before we mess with it. */
157855714Skris	CAname=X509_NAME_dup(x509->cert_info->subject);
157955714Skris	if (CAname == NULL) goto err;
158055714Skris	str=str2=NULL;
158155714Skris
158255714Skris	for (i=0; i<sk_CONF_VALUE_num(policy); i++)
158355714Skris		{
158455714Skris		cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
158555714Skris		if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
158655714Skris			{
158755714Skris			BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
158855714Skris			goto err;
158955714Skris			}
159055714Skris		obj=OBJ_nid2obj(j);
159155714Skris
159255714Skris		last= -1;
159355714Skris		for (;;)
159455714Skris			{
159555714Skris			/* lookup the object in the supplied name list */
159655714Skris			j=X509_NAME_get_index_by_OBJ(name,obj,last);
159755714Skris			if (j < 0)
159855714Skris				{
159955714Skris				if (last != -1) break;
160055714Skris				tne=NULL;
160155714Skris				}
160255714Skris			else
160355714Skris				{
160455714Skris				tne=X509_NAME_get_entry(name,j);
160555714Skris				}
160655714Skris			last=j;
160755714Skris
160855714Skris			/* depending on the 'policy', decide what to do. */
160955714Skris			push=NULL;
161055714Skris			if (strcmp(cv->value,"optional") == 0)
161155714Skris				{
161255714Skris				if (tne != NULL)
161355714Skris					push=tne;
161455714Skris				}
161555714Skris			else if (strcmp(cv->value,"supplied") == 0)
161655714Skris				{
161755714Skris				if (tne == NULL)
161855714Skris					{
161955714Skris					BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
162055714Skris					goto err;
162155714Skris					}
162255714Skris				else
162355714Skris					push=tne;
162455714Skris				}
162555714Skris			else if (strcmp(cv->value,"match") == 0)
162655714Skris				{
162755714Skris				int last2;
162855714Skris
162955714Skris				if (tne == NULL)
163055714Skris					{
163155714Skris					BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
163255714Skris					goto err;
163355714Skris					}
163455714Skris
163555714Skris				last2= -1;
163655714Skris
163755714Skrisagain2:
163855714Skris				j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
163955714Skris				if ((j < 0) && (last2 == -1))
164055714Skris					{
164155714Skris					BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
164255714Skris					goto err;
164355714Skris					}
164455714Skris				if (j >= 0)
164555714Skris					{
164655714Skris					push=X509_NAME_get_entry(CAname,j);
164755714Skris					str=X509_NAME_ENTRY_get_data(tne);
164855714Skris					str2=X509_NAME_ENTRY_get_data(push);
164955714Skris					last2=j;
165055714Skris					if (ASN1_STRING_cmp(str,str2) != 0)
165155714Skris						goto again2;
165255714Skris					}
165355714Skris				if (j < 0)
165455714Skris					{
165555714Skris					BIO_printf(bio_err,"The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n",cv->name,((str == NULL)?"NULL":(char *)str->data),((str2 == NULL)?"NULL":(char *)str2->data));
165655714Skris					goto err;
165755714Skris					}
165855714Skris				}
165955714Skris			else
166055714Skris				{
166155714Skris				BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
166255714Skris				goto err;
166355714Skris				}
166455714Skris
166555714Skris			if (push != NULL)
166655714Skris				{
166755714Skris				if (!X509_NAME_add_entry(subject,push,
166855714Skris					X509_NAME_entry_count(subject),0))
166955714Skris					{
167055714Skris					if (push != NULL)
167155714Skris						X509_NAME_ENTRY_free(push);
167255714Skris					BIO_printf(bio_err,"Malloc failure\n");
167355714Skris					goto err;
167455714Skris					}
167555714Skris				}
167655714Skris			if (j < 0) break;
167755714Skris			}
167855714Skris		}
167955714Skris
168055714Skris	if (preserve)
168155714Skris		{
168255714Skris		X509_NAME_free(subject);
168355714Skris		subject=X509_NAME_dup(X509_REQ_get_subject_name(req));
168455714Skris		if (subject == NULL) goto err;
168555714Skris		}
168655714Skris
168755714Skris	if (verbose)
168855714Skris		BIO_printf(bio_err,"The subject name apears to be ok, checking data base for clashes\n");
168955714Skris
169055714Skris	row[DB_name]=X509_NAME_oneline(subject,NULL,0);
169155714Skris	row[DB_serial]=BN_bn2hex(serial);
169255714Skris	if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
169355714Skris		{
169455714Skris		BIO_printf(bio_err,"Malloc failure\n");
169555714Skris		goto err;
169655714Skris		}
169755714Skris
169855714Skris	rrow=TXT_DB_get_by_index(db,DB_name,row);
169955714Skris	if (rrow != NULL)
170055714Skris		{
170155714Skris		BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n",
170255714Skris			row[DB_name]);
170355714Skris		}
170455714Skris	else
170555714Skris		{
170655714Skris		rrow=TXT_DB_get_by_index(db,DB_serial,row);
170755714Skris		if (rrow != NULL)
170855714Skris			{
170955714Skris			BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
171055714Skris				row[DB_serial]);
171155714Skris			BIO_printf(bio_err,"      check the database/serial_file for corruption\n");
171255714Skris			}
171355714Skris		}
171455714Skris
171555714Skris	if (rrow != NULL)
171655714Skris		{
171755714Skris		BIO_printf(bio_err,
171855714Skris			"The matching entry has the following details\n");
171955714Skris		if (rrow[DB_type][0] == 'E')
172055714Skris			p="Expired";
172155714Skris		else if (rrow[DB_type][0] == 'R')
172255714Skris			p="Revoked";
172355714Skris		else if (rrow[DB_type][0] == 'V')
172455714Skris			p="Valid";
172555714Skris		else
172655714Skris			p="\ninvalid type, Data base error\n";
172755714Skris		BIO_printf(bio_err,"Type	  :%s\n",p);;
172855714Skris		if (rrow[DB_type][0] == 'R')
172955714Skris			{
173055714Skris			p=rrow[DB_exp_date]; if (p == NULL) p="undef";
173155714Skris			BIO_printf(bio_err,"Was revoked on:%s\n",p);
173255714Skris			}
173355714Skris		p=rrow[DB_exp_date]; if (p == NULL) p="undef";
173455714Skris		BIO_printf(bio_err,"Expires on    :%s\n",p);
173555714Skris		p=rrow[DB_serial]; if (p == NULL) p="undef";
173655714Skris		BIO_printf(bio_err,"Serial Number :%s\n",p);
173755714Skris		p=rrow[DB_file]; if (p == NULL) p="undef";
173855714Skris		BIO_printf(bio_err,"File name     :%s\n",p);
173955714Skris		p=rrow[DB_name]; if (p == NULL) p="undef";
174055714Skris		BIO_printf(bio_err,"Subject Name  :%s\n",p);
174155714Skris		ok= -1; /* This is now a 'bad' error. */
174255714Skris		goto err;
174355714Skris		}
174455714Skris
174555714Skris	/* We are now totaly happy, lets make and sign the certificate */
174655714Skris	if (verbose)
174755714Skris		BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
174855714Skris
174955714Skris	if ((ret=X509_new()) == NULL) goto err;
175055714Skris	ci=ret->cert_info;
175155714Skris
175255714Skris#ifdef X509_V3
175355714Skris	/* Make it an X509 v3 certificate. */
175455714Skris	if (!X509_set_version(x509,2)) goto err;
175555714Skris#endif
175655714Skris
175755714Skris	if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
175855714Skris		goto err;
175955714Skris	if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
176055714Skris		goto err;
176155714Skris
176255714Skris	BIO_printf(bio_err,"Certificate is to be certified until ");
176355714Skris	if (strcmp(startdate,"today") == 0)
176455714Skris		X509_gmtime_adj(X509_get_notBefore(ret),0);
176555714Skris	else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
176655714Skris
176755714Skris	if (enddate == NULL)
176855714Skris		X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
176955714Skris	else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
177055714Skris
177155714Skris	ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
177255714Skris	if(days) BIO_printf(bio_err," (%d days)",days);
177355714Skris	BIO_printf(bio_err, "\n");
177455714Skris
177555714Skris	if (!X509_set_subject_name(ret,subject)) goto err;
177655714Skris
177755714Skris	pktmp=X509_REQ_get_pubkey(req);
177855714Skris	i = X509_set_pubkey(ret,pktmp);
177955714Skris	EVP_PKEY_free(pktmp);
178055714Skris	if (!i) goto err;
178155714Skris
178255714Skris	/* Lets add the extensions, if there are any */
178355714Skris	if (ext_sect)
178455714Skris		{
178555714Skris		X509V3_CTX ctx;
178655714Skris		if (ci->version == NULL)
178755714Skris			if ((ci->version=ASN1_INTEGER_new()) == NULL)
178855714Skris				goto err;
178955714Skris		ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
179055714Skris
179155714Skris		/* Free the current entries if any, there should not
179255714Skris		 * be any I belive */
179355714Skris		if (ci->extensions != NULL)
179455714Skris			sk_X509_EXTENSION_pop_free(ci->extensions,
179555714Skris						   X509_EXTENSION_free);
179655714Skris
179755714Skris		ci->extensions = NULL;
179855714Skris
179955714Skris		X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
180055714Skris		X509V3_set_conf_lhash(&ctx, lconf);
180155714Skris
180255714Skris		if(!X509V3_EXT_add_conf(lconf, &ctx, ext_sect, ret)) goto err;
180355714Skris
180455714Skris		}
180555714Skris
180655714Skris
180755714Skris	if (!batch)
180855714Skris		{
180955714Skris		BIO_printf(bio_err,"Sign the certificate? [y/n]:");
181055714Skris		(void)BIO_flush(bio_err);
181155714Skris		buf[0]='\0';
181255714Skris		fgets(buf,sizeof(buf)-1,stdin);
181355714Skris		if (!((buf[0] == 'y') || (buf[0] == 'Y')))
181455714Skris			{
181555714Skris			BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
181655714Skris			ok=0;
181755714Skris			goto err;
181855714Skris			}
181955714Skris		}
182055714Skris
182155714Skris
182255714Skris#ifndef NO_DSA
182355714Skris	if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
182455714Skris	pktmp=X509_get_pubkey(ret);
182555714Skris	if (EVP_PKEY_missing_parameters(pktmp) &&
182655714Skris		!EVP_PKEY_missing_parameters(pkey))
182755714Skris		EVP_PKEY_copy_parameters(pktmp,pkey);
182855714Skris	EVP_PKEY_free(pktmp);
182955714Skris#endif
183055714Skris
183155714Skris	if (!X509_sign(ret,pkey,dgst))
183255714Skris		goto err;
183355714Skris
183455714Skris	/* We now just add it to the database */
183555714Skris	row[DB_type]=(char *)Malloc(2);
183655714Skris
183755714Skris	tm=X509_get_notAfter(ret);
183855714Skris	row[DB_exp_date]=(char *)Malloc(tm->length+1);
183955714Skris	memcpy(row[DB_exp_date],tm->data,tm->length);
184055714Skris	row[DB_exp_date][tm->length]='\0';
184155714Skris
184255714Skris	row[DB_rev_date]=NULL;
184355714Skris
184455714Skris	/* row[DB_serial] done already */
184555714Skris	row[DB_file]=(char *)Malloc(8);
184655714Skris	/* row[DB_name] done already */
184755714Skris
184855714Skris	if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
184955714Skris		(row[DB_file] == NULL))
185055714Skris		{
185155714Skris		BIO_printf(bio_err,"Malloc failure\n");
185255714Skris		goto err;
185355714Skris		}
185455714Skris	strcpy(row[DB_file],"unknown");
185555714Skris	row[DB_type][0]='V';
185655714Skris	row[DB_type][1]='\0';
185755714Skris
185855714Skris	if ((irow=(char **)Malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
185955714Skris		{
186055714Skris		BIO_printf(bio_err,"Malloc failure\n");
186155714Skris		goto err;
186255714Skris		}
186355714Skris
186455714Skris	for (i=0; i<DB_NUMBER; i++)
186555714Skris		{
186655714Skris		irow[i]=row[i];
186755714Skris		row[i]=NULL;
186855714Skris		}
186955714Skris	irow[DB_NUMBER]=NULL;
187055714Skris
187155714Skris	if (!TXT_DB_insert(db,irow))
187255714Skris		{
187355714Skris		BIO_printf(bio_err,"failed to update database\n");
187455714Skris		BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
187555714Skris		goto err;
187655714Skris		}
187755714Skris	ok=1;
187855714Skriserr:
187955714Skris	for (i=0; i<DB_NUMBER; i++)
188055714Skris		if (row[i] != NULL) Free(row[i]);
188155714Skris
188255714Skris	if (CAname != NULL)
188355714Skris		X509_NAME_free(CAname);
188455714Skris	if (subject != NULL)
188555714Skris		X509_NAME_free(subject);
188655714Skris	if (ok <= 0)
188755714Skris		{
188855714Skris		if (ret != NULL) X509_free(ret);
188955714Skris		ret=NULL;
189055714Skris		}
189155714Skris	else
189255714Skris		*xret=ret;
189355714Skris	return(ok);
189455714Skris	}
189555714Skris
189655714Skrisstatic void write_new_certificate(BIO *bp, X509 *x, int output_der)
189755714Skris	{
189855714Skris	char *f;
189955714Skris	char buf[256];
190055714Skris
190155714Skris	if (output_der)
190255714Skris		{
190355714Skris		(void)i2d_X509_bio(bp,x);
190455714Skris		return;
190555714Skris		}
190655714Skris
190755714Skris	f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
190855714Skris	BIO_printf(bp,"issuer :%s\n",f);
190955714Skris
191055714Skris	f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
191155714Skris	BIO_printf(bp,"subject:%s\n",f);
191255714Skris
191355714Skris	BIO_puts(bp,"serial :");
191455714Skris	i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
191555714Skris	BIO_puts(bp,"\n\n");
191655714Skris	X509_print(bp,x);
191755714Skris	BIO_puts(bp,"\n");
191855714Skris	PEM_write_bio_X509(bp,x);
191955714Skris	BIO_puts(bp,"\n");
192055714Skris	}
192155714Skris
192255714Skrisstatic int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
192355714Skris	     const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
192455714Skris	     BIGNUM *serial, char *startdate, char *enddate, int days,
192555714Skris	     char *ext_sect, LHASH *lconf, int verbose)
192655714Skris	{
192755714Skris	STACK_OF(CONF_VALUE) *sk=NULL;
192855714Skris	LHASH *parms=NULL;
192955714Skris	X509_REQ *req=NULL;
193055714Skris	CONF_VALUE *cv=NULL;
193155714Skris	NETSCAPE_SPKI *spki = NULL;
193255714Skris	unsigned char *spki_der = NULL,*p;
193355714Skris	X509_REQ_INFO *ri;
193455714Skris	char *type,*buf;
193555714Skris	EVP_PKEY *pktmp=NULL;
193655714Skris	X509_NAME *n=NULL;
193755714Skris	X509_NAME_ENTRY *ne=NULL;
193855714Skris	int ok= -1,i,j;
193955714Skris	long errline;
194055714Skris	int nid;
194155714Skris
194255714Skris	/*
194355714Skris	 * Load input file into a hash table.  (This is just an easy
194455714Skris	 * way to read and parse the file, then put it into a convenient
194555714Skris	 * STACK format).
194655714Skris	 */
194755714Skris	parms=CONF_load(NULL,infile,&errline);
194855714Skris	if (parms == NULL)
194955714Skris		{
195055714Skris		BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
195155714Skris		ERR_print_errors(bio_err);
195255714Skris		goto err;
195355714Skris		}
195455714Skris
195555714Skris	sk=CONF_get_section(parms, "default");
195655714Skris	if (sk_CONF_VALUE_num(sk) == 0)
195755714Skris		{
195855714Skris		BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
195955714Skris		CONF_free(parms);
196055714Skris		goto err;
196155714Skris		}
196255714Skris
196355714Skris	/*
196455714Skris	 * Now create a dummy X509 request structure.  We don't actually
196555714Skris	 * have an X509 request, but we have many of the components
196655714Skris	 * (a public key, various DN components).  The idea is that we
196755714Skris	 * put these components into the right X509 request structure
196855714Skris	 * and we can use the same code as if you had a real X509 request.
196955714Skris	 */
197055714Skris	req=X509_REQ_new();
197155714Skris	if (req == NULL)
197255714Skris		{
197355714Skris		ERR_print_errors(bio_err);
197455714Skris		goto err;
197555714Skris		}
197655714Skris
197755714Skris	/*
197855714Skris	 * Build up the subject name set.
197955714Skris	 */
198055714Skris	ri=req->req_info;
198155714Skris	n = ri->subject;
198255714Skris
198355714Skris	for (i = 0; ; i++)
198455714Skris		{
198555714Skris		if (sk_CONF_VALUE_num(sk) <= i) break;
198655714Skris
198755714Skris		cv=sk_CONF_VALUE_value(sk,i);
198855714Skris		type=cv->name;
198955714Skris		buf=cv->value;
199055714Skris
199155714Skris		if ((nid=OBJ_txt2nid(type)) == NID_undef)
199255714Skris			{
199355714Skris			if (strcmp(type, "SPKAC") == 0)
199455714Skris				{
199555714Skris				spki_der=(unsigned char *)Malloc(
199655714Skris					strlen(cv->value)+1);
199755714Skris				if (spki_der == NULL)
199855714Skris					{
199955714Skris					BIO_printf(bio_err,"Malloc failure\n");
200055714Skris					goto err;
200155714Skris					}
200255714Skris				j = EVP_DecodeBlock(spki_der, (unsigned char *)cv->value,
200355714Skris					strlen(cv->value));
200455714Skris				if (j <= 0)
200555714Skris					{
200655714Skris					BIO_printf(bio_err, "Can't b64 decode SPKAC structure\n");
200755714Skris					goto err;
200855714Skris					}
200955714Skris
201055714Skris				p=spki_der;
201155714Skris				spki = d2i_NETSCAPE_SPKI(&spki, &p, j);
201255714Skris				Free(spki_der);
201355714Skris				spki_der = NULL;
201455714Skris				if (spki == NULL)
201555714Skris					{
201655714Skris					BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
201755714Skris					ERR_print_errors(bio_err);
201855714Skris					goto err;
201955714Skris					}
202055714Skris				}
202155714Skris			continue;
202255714Skris			}
202355714Skris
202455714Skris		j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
202555714Skris		if (fix_data(nid, &j) == 0)
202655714Skris			{
202755714Skris			BIO_printf(bio_err,
202855714Skris				"invalid characters in string %s\n",buf);
202955714Skris			goto err;
203055714Skris			}
203155714Skris
203255714Skris		if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
203355714Skris			(unsigned char *)buf,
203455714Skris			strlen(buf))) == NULL)
203555714Skris			goto err;
203655714Skris
203755714Skris		if (!X509_NAME_add_entry(n,ne,X509_NAME_entry_count(n),0))
203855714Skris			goto err;
203955714Skris		}
204055714Skris	if (spki == NULL)
204155714Skris		{
204255714Skris		BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
204355714Skris			infile);
204455714Skris		goto err;
204555714Skris		}
204655714Skris
204755714Skris	/*
204855714Skris	 * Now extract the key from the SPKI structure.
204955714Skris	 */
205055714Skris
205155714Skris	BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
205255714Skris
205355714Skris	if ((pktmp=X509_PUBKEY_get(spki->spkac->pubkey)) == NULL)
205455714Skris		{
205555714Skris		BIO_printf(bio_err,"error unpacking SPKAC public key\n");
205655714Skris		goto err;
205755714Skris		}
205855714Skris
205955714Skris	j = NETSCAPE_SPKI_verify(spki, pktmp);
206055714Skris	if (j <= 0)
206155714Skris		{
206255714Skris		BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
206355714Skris		goto err;
206455714Skris		}
206555714Skris	BIO_printf(bio_err,"Signature ok\n");
206655714Skris
206755714Skris	X509_REQ_set_pubkey(req,pktmp);
206855714Skris	EVP_PKEY_free(pktmp);
206955714Skris	ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,
207055714Skris		   days,1,verbose,req,ext_sect,lconf);
207155714Skriserr:
207255714Skris	if (req != NULL) X509_REQ_free(req);
207355714Skris	if (parms != NULL) CONF_free(parms);
207455714Skris	if (spki_der != NULL) Free(spki_der);
207555714Skris	if (spki != NULL) NETSCAPE_SPKI_free(spki);
207655714Skris	if (ne != NULL) X509_NAME_ENTRY_free(ne);
207755714Skris
207855714Skris	return(ok);
207955714Skris	}
208055714Skris
208155714Skrisstatic int fix_data(int nid, int *type)
208255714Skris	{
208355714Skris	if (nid == NID_pkcs9_emailAddress)
208455714Skris		*type=V_ASN1_IA5STRING;
208555714Skris	if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
208655714Skris		*type=V_ASN1_T61STRING;
208755714Skris	if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
208855714Skris		*type=V_ASN1_T61STRING;
208955714Skris	if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
209055714Skris		return(0);
209155714Skris	if (nid == NID_pkcs9_unstructuredName)
209255714Skris		*type=V_ASN1_IA5STRING;
209355714Skris	return(1);
209455714Skris	}
209555714Skris
209655714Skrisstatic int check_time_format(char *str)
209755714Skris	{
209855714Skris	ASN1_UTCTIME tm;
209955714Skris
210055714Skris	tm.data=(unsigned char *)str;
210155714Skris	tm.length=strlen(str);
210255714Skris	tm.type=V_ASN1_UTCTIME;
210355714Skris	return(ASN1_UTCTIME_check(&tm));
210455714Skris	}
210555714Skris
210655714Skrisstatic int add_oid_section(LHASH *hconf)
210755714Skris{
210855714Skris	char *p;
210955714Skris	STACK_OF(CONF_VALUE) *sktmp;
211055714Skris	CONF_VALUE *cnf;
211155714Skris	int i;
211255714Skris	if(!(p=CONF_get_string(hconf,NULL,"oid_section"))) return 1;
211355714Skris	if(!(sktmp = CONF_get_section(hconf, p))) {
211455714Skris		BIO_printf(bio_err, "problem loading oid section %s\n", p);
211555714Skris		return 0;
211655714Skris	}
211755714Skris	for(i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
211855714Skris		cnf = sk_CONF_VALUE_value(sktmp, i);
211955714Skris		if(OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
212055714Skris			BIO_printf(bio_err, "problem creating object %s=%s\n",
212155714Skris							 cnf->name, cnf->value);
212255714Skris			return 0;
212355714Skris		}
212455714Skris	}
212555714Skris	return 1;
212655714Skris}
212755714Skris
212855714Skrisstatic int do_revoke(X509 *x509, TXT_DB *db)
212955714Skris{
213055714Skris	ASN1_UTCTIME *tm=NULL;
213155714Skris	char *row[DB_NUMBER],**rrow,**irow;
213255714Skris	int ok=-1,i;
213355714Skris
213455714Skris	for (i=0; i<DB_NUMBER; i++)
213555714Skris		row[i]=NULL;
213655714Skris	row[DB_name]=X509_NAME_oneline(x509->cert_info->subject,NULL,0);
213755714Skris	row[DB_serial]=BN_bn2hex(ASN1_INTEGER_to_BN(x509->cert_info->serialNumber,NULL));
213855714Skris	if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
213955714Skris		{
214055714Skris		BIO_printf(bio_err,"Malloc failure\n");
214155714Skris		goto err;
214255714Skris		}
214355714Skris	rrow=TXT_DB_get_by_index(db,DB_name,row);
214455714Skris	if (rrow == NULL)
214555714Skris		{
214655714Skris		BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]);
214755714Skris
214855714Skris		/* We now just add it to the database */
214955714Skris		row[DB_type]=(char *)Malloc(2);
215055714Skris
215155714Skris		tm=X509_get_notAfter(x509);
215255714Skris		row[DB_exp_date]=(char *)Malloc(tm->length+1);
215355714Skris		memcpy(row[DB_exp_date],tm->data,tm->length);
215455714Skris		row[DB_exp_date][tm->length]='\0';
215555714Skris
215655714Skris		row[DB_rev_date]=NULL;
215755714Skris
215855714Skris		/* row[DB_serial] done already */
215955714Skris		row[DB_file]=(char *)Malloc(8);
216055714Skris
216155714Skris		/* row[DB_name] done already */
216255714Skris
216355714Skris		if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
216455714Skris			(row[DB_file] == NULL))
216555714Skris			{
216655714Skris			BIO_printf(bio_err,"Malloc failure\n");
216755714Skris			goto err;
216855714Skris			}
216955714Skris		strcpy(row[DB_file],"unknown");
217055714Skris		row[DB_type][0]='V';
217155714Skris		row[DB_type][1]='\0';
217255714Skris
217355714Skris		if ((irow=(char **)Malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
217455714Skris			{
217555714Skris			BIO_printf(bio_err,"Malloc failure\n");
217655714Skris			goto err;
217755714Skris			}
217855714Skris
217955714Skris		for (i=0; i<DB_NUMBER; i++)
218055714Skris			{
218155714Skris			irow[i]=row[i];
218255714Skris			row[i]=NULL;
218355714Skris			}
218455714Skris		irow[DB_NUMBER]=NULL;
218555714Skris
218655714Skris		if (!TXT_DB_insert(db,irow))
218755714Skris			{
218855714Skris			BIO_printf(bio_err,"failed to update database\n");
218955714Skris			BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
219055714Skris			goto err;
219155714Skris			}
219255714Skris
219355714Skris		/* Revoke Certificate */
219455714Skris		do_revoke(x509,db);
219555714Skris
219655714Skris		ok=1;
219755714Skris		goto err;
219855714Skris
219955714Skris		}
220055714Skris	else if (index_serial_cmp(row,rrow))
220155714Skris		{
220255714Skris		BIO_printf(bio_err,"ERROR:no same serial number %s\n",
220355714Skris			   row[DB_serial]);
220455714Skris		goto err;
220555714Skris		}
220655714Skris	else if (rrow[DB_type][0]=='R')
220755714Skris		{
220855714Skris		BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
220955714Skris			   row[DB_serial]);
221055714Skris		goto err;
221155714Skris		}
221255714Skris	else
221355714Skris		{
221455714Skris		BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
221555714Skris		tm=X509_gmtime_adj(tm,0);
221655714Skris		rrow[DB_type][0]='R';
221755714Skris		rrow[DB_type][1]='\0';
221855714Skris		rrow[DB_rev_date]=(char *)Malloc(tm->length+1);
221955714Skris		memcpy(rrow[DB_rev_date],tm->data,tm->length);
222055714Skris		rrow[DB_rev_date][tm->length]='\0';
222155714Skris		}
222255714Skris	ok=1;
222355714Skriserr:
222455714Skris	for (i=0; i<DB_NUMBER; i++)
222555714Skris		{
222655714Skris		if (row[i] != NULL)
222755714Skris			Free(row[i]);
222855714Skris		}
222955714Skris	ASN1_UTCTIME_free(tm);
223055714Skris	return(ok);
223155714Skris}
223255714Skris
2233