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