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