xref: /freebsd/crypto/openssl/apps/ca.c (revision 23f282aa31e9b6fceacd449020e936e98d6f2298)
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 <sys/types.h>
65 #include <sys/stat.h>
66 #include "apps.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/pem.h>
77 
78 #ifndef W_OK
79 #  ifdef VMS
80 #    if defined(__DECC)
81 #      include <unistd.h>
82 #    else
83 #      include <unixlib.h>
84 #    endif
85 #  else
86 #    include <sys/file.h>
87 #  endif
88 #endif
89 
90 #ifndef W_OK
91 #  define F_OK 0
92 #  define X_OK 1
93 #  define W_OK 2
94 #  define R_OK 4
95 #endif
96 
97 #undef PROG
98 #define PROG ca_main
99 
100 #define BASE_SECTION	"ca"
101 #define CONFIG_FILE "openssl.cnf"
102 
103 #define ENV_DEFAULT_CA		"default_ca"
104 
105 #define ENV_DIR			"dir"
106 #define ENV_CERTS		"certs"
107 #define ENV_CRL_DIR		"crl_dir"
108 #define ENV_CA_DB		"CA_DB"
109 #define ENV_NEW_CERTS_DIR	"new_certs_dir"
110 #define ENV_CERTIFICATE 	"certificate"
111 #define ENV_SERIAL		"serial"
112 #define ENV_CRL			"crl"
113 #define ENV_PRIVATE_KEY		"private_key"
114 #define ENV_RANDFILE		"RANDFILE"
115 #define ENV_DEFAULT_DAYS 	"default_days"
116 #define ENV_DEFAULT_STARTDATE 	"default_startdate"
117 #define ENV_DEFAULT_ENDDATE 	"default_enddate"
118 #define ENV_DEFAULT_CRL_DAYS 	"default_crl_days"
119 #define ENV_DEFAULT_CRL_HOURS 	"default_crl_hours"
120 #define ENV_DEFAULT_MD		"default_md"
121 #define ENV_PRESERVE		"preserve"
122 #define ENV_POLICY      	"policy"
123 #define ENV_EXTENSIONS      	"x509_extensions"
124 #define ENV_CRLEXT      	"crl_extensions"
125 #define ENV_MSIE_HACK		"msie_hack"
126 
127 #define ENV_DATABASE		"database"
128 
129 #define DB_type         0
130 #define DB_exp_date     1
131 #define DB_rev_date     2
132 #define DB_serial       3       /* index - unique */
133 #define DB_file         4
134 #define DB_name         5       /* index - unique for active */
135 #define DB_NUMBER       6
136 
137 #define DB_TYPE_REV	'R'
138 #define DB_TYPE_EXP	'E'
139 #define DB_TYPE_VAL	'V'
140 
141 static char *ca_usage[]={
142 "usage: ca args\n",
143 "\n",
144 " -verbose        - Talk alot while doing things\n",
145 " -config file    - A config file\n",
146 " -name arg       - The particular CA definition to use\n",
147 " -gencrl         - Generate a new CRL\n",
148 " -crldays days   - Days is when the next CRL is due\n",
149 " -crlhours hours - Hours is when the next CRL is due\n",
150 " -startdate YYMMDDHHMMSSZ  - certificate validity notBefore\n",
151 " -enddate YYMMDDHHMMSSZ    - certificate validity notAfter (overrides -days)\n",
152 " -days arg       - number of days to certify the certificate for\n",
153 " -md arg         - md to use, one of md2, md5, sha or sha1\n",
154 " -policy arg     - The CA 'policy' to support\n",
155 " -keyfile arg    - PEM private key file\n",
156 " -key arg        - key to decode the private key if it is encrypted\n",
157 " -cert file      - The CA certificate\n",
158 " -in file        - The input PEM encoded certificate request(s)\n",
159 " -out file       - Where to put the output file(s)\n",
160 " -outdir dir     - Where to put output certificates\n",
161 " -infiles ....   - The last argument, requests to process\n",
162 " -spkac file     - File contains DN and signed public key and challenge\n",
163 " -ss_cert file   - File contains a self signed cert to sign\n",
164 " -preserveDN     - Don't re-order the DN\n",
165 " -batch          - Don't ask questions\n",
166 " -msie_hack      - msie modifications to handle all those universal strings\n",
167 " -revoke file    - Revoke a certificate (given in file)\n",
168 " -extensions ..  - Extension section (override value in config file)\n",
169 " -crlexts ..     - CRL extension section (override value in config file)\n",
170 NULL
171 };
172 
173 #ifdef EFENCE
174 extern int EF_PROTECT_FREE;
175 extern int EF_PROTECT_BELOW;
176 extern int EF_ALIGNMENT;
177 #endif
178 
179 static int add_oid_section(LHASH *conf);
180 static void lookup_fail(char *name,char *tag);
181 static unsigned long index_serial_hash(char **a);
182 static int index_serial_cmp(char **a, char **b);
183 static unsigned long index_name_hash(char **a);
184 static int index_name_qual(char **a);
185 static int index_name_cmp(char **a,char **b);
186 static BIGNUM *load_serial(char *serialfile);
187 static int save_serial(char *serialfile, BIGNUM *serial);
188 static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
189 		   const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,TXT_DB *db,
190 		   BIGNUM *serial, char *startdate,char *enddate, int days,
191 		   int batch, char *ext_sect, LHASH *conf,int verbose);
192 static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
193 			const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
194 			TXT_DB *db, BIGNUM *serial,char *startdate,
195 			char *enddate, int days, int batch, char *ext_sect,
196 			LHASH *conf,int verbose);
197 static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
198 			 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
199 			 TXT_DB *db, BIGNUM *serial,char *startdate,
200 			 char *enddate, int days, char *ext_sect,LHASH *conf,
201 				int verbose);
202 static int fix_data(int nid, int *type);
203 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
204 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
205 	STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
206 	char *startdate, char *enddate, int days, int batch, int verbose,
207 	X509_REQ *req, char *ext_sect, LHASH *conf);
208 static int do_revoke(X509 *x509, TXT_DB *db);
209 static int check_time_format(char *str);
210 static LHASH *conf=NULL;
211 static char *section=NULL;
212 
213 static int preserve=0;
214 static int msie_hack=0;
215 
216 int MAIN(int, char **);
217 
218 int MAIN(int argc, char **argv)
219 	{
220 	char *key=NULL;
221 	int total=0;
222 	int total_done=0;
223 	int badops=0;
224 	int ret=1;
225 	int req=0;
226 	int verbose=0;
227 	int gencrl=0;
228 	int dorevoke=0;
229 	long crldays=0;
230 	long crlhours=0;
231 	long errorline= -1;
232 	char *configfile=NULL;
233 	char *md=NULL;
234 	char *policy=NULL;
235 	char *keyfile=NULL;
236 	char *certfile=NULL;
237 	char *infile=NULL;
238 	char *spkac_file=NULL;
239 	char *ss_cert_file=NULL;
240 	EVP_PKEY *pkey=NULL;
241 	int output_der = 0;
242 	char *outfile=NULL;
243 	char *outdir=NULL;
244 	char *serialfile=NULL;
245 	char *extensions=NULL;
246 	char *crl_ext=NULL;
247 	BIGNUM *serial=NULL;
248 	char *startdate=NULL;
249 	char *enddate=NULL;
250 	int days=0;
251 	int batch=0;
252 	int notext=0;
253 	X509 *x509=NULL;
254 	X509 *x=NULL;
255 	BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
256 	char *dbfile=NULL;
257 	TXT_DB *db=NULL;
258 	X509_CRL *crl=NULL;
259 	X509_CRL_INFO *ci=NULL;
260 	X509_REVOKED *r=NULL;
261 	char **pp,*p,*f;
262 	int i,j;
263 	long l;
264 	const EVP_MD *dgst=NULL;
265 	STACK_OF(CONF_VALUE) *attribs=NULL;
266 	STACK *cert_sk=NULL;
267 	BIO *hex=NULL;
268 #undef BSIZE
269 #define BSIZE 256
270 	MS_STATIC char buf[3][BSIZE];
271 	char *randfile=NULL;
272 
273 #ifdef EFENCE
274 EF_PROTECT_FREE=1;
275 EF_PROTECT_BELOW=1;
276 EF_ALIGNMENT=0;
277 #endif
278 
279 	apps_startup();
280 
281 	conf = NULL;
282 	key = NULL;
283 	section = NULL;
284 
285 	preserve=0;
286 	msie_hack=0;
287 	if (bio_err == NULL)
288 		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
289 			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
290 
291 	argc--;
292 	argv++;
293 	while (argc >= 1)
294 		{
295 		if	(strcmp(*argv,"-verbose") == 0)
296 			verbose=1;
297 		else if	(strcmp(*argv,"-config") == 0)
298 			{
299 			if (--argc < 1) goto bad;
300 			configfile= *(++argv);
301 			}
302 		else if (strcmp(*argv,"-name") == 0)
303 			{
304 			if (--argc < 1) goto bad;
305 			section= *(++argv);
306 			}
307 		else if (strcmp(*argv,"-startdate") == 0)
308 			{
309 			if (--argc < 1) goto bad;
310 			startdate= *(++argv);
311 			}
312 		else if (strcmp(*argv,"-enddate") == 0)
313 			{
314 			if (--argc < 1) goto bad;
315 			enddate= *(++argv);
316 			}
317 		else if (strcmp(*argv,"-days") == 0)
318 			{
319 			if (--argc < 1) goto bad;
320 			days=atoi(*(++argv));
321 			}
322 		else if (strcmp(*argv,"-md") == 0)
323 			{
324 			if (--argc < 1) goto bad;
325 			md= *(++argv);
326 			}
327 		else if (strcmp(*argv,"-policy") == 0)
328 			{
329 			if (--argc < 1) goto bad;
330 			policy= *(++argv);
331 			}
332 		else if (strcmp(*argv,"-keyfile") == 0)
333 			{
334 			if (--argc < 1) goto bad;
335 			keyfile= *(++argv);
336 			}
337 		else if (strcmp(*argv,"-key") == 0)
338 			{
339 			if (--argc < 1) goto bad;
340 			key= *(++argv);
341 			}
342 		else if (strcmp(*argv,"-cert") == 0)
343 			{
344 			if (--argc < 1) goto bad;
345 			certfile= *(++argv);
346 			}
347 		else if (strcmp(*argv,"-in") == 0)
348 			{
349 			if (--argc < 1) goto bad;
350 			infile= *(++argv);
351 			req=1;
352 			}
353 		else if (strcmp(*argv,"-out") == 0)
354 			{
355 			if (--argc < 1) goto bad;
356 			outfile= *(++argv);
357 			}
358 		else if (strcmp(*argv,"-outdir") == 0)
359 			{
360 			if (--argc < 1) goto bad;
361 			outdir= *(++argv);
362 			}
363 		else if (strcmp(*argv,"-notext") == 0)
364 			notext=1;
365 		else if (strcmp(*argv,"-batch") == 0)
366 			batch=1;
367 		else if (strcmp(*argv,"-preserveDN") == 0)
368 			preserve=1;
369 		else if (strcmp(*argv,"-gencrl") == 0)
370 			gencrl=1;
371 		else if (strcmp(*argv,"-msie_hack") == 0)
372 			msie_hack=1;
373 		else if (strcmp(*argv,"-crldays") == 0)
374 			{
375 			if (--argc < 1) goto bad;
376 			crldays= atol(*(++argv));
377 			}
378 		else if (strcmp(*argv,"-crlhours") == 0)
379 			{
380 			if (--argc < 1) goto bad;
381 			crlhours= atol(*(++argv));
382 			}
383 		else if (strcmp(*argv,"-infiles") == 0)
384 			{
385 			argc--;
386 			argv++;
387 			req=1;
388 			break;
389 			}
390 		else if (strcmp(*argv, "-ss_cert") == 0)
391 			{
392 			if (--argc < 1) goto bad;
393 			ss_cert_file = *(++argv);
394 			req=1;
395 			}
396 		else if (strcmp(*argv, "-spkac") == 0)
397 			{
398 			if (--argc < 1) goto bad;
399 			spkac_file = *(++argv);
400 			req=1;
401 			}
402 		else if (strcmp(*argv,"-revoke") == 0)
403 			{
404 			if (--argc < 1) goto bad;
405 			infile= *(++argv);
406 			dorevoke=1;
407 			}
408 		else if (strcmp(*argv,"-extensions") == 0)
409 			{
410 			if (--argc < 1) goto bad;
411 			extensions= *(++argv);
412 			}
413 		else if (strcmp(*argv,"-crlexts") == 0)
414 			{
415 			if (--argc < 1) goto bad;
416 			crl_ext= *(++argv);
417 			}
418 		else
419 			{
420 bad:
421 			BIO_printf(bio_err,"unknown option %s\n",*argv);
422 			badops=1;
423 			break;
424 			}
425 		argc--;
426 		argv++;
427 		}
428 
429 	if (badops)
430 		{
431 		for (pp=ca_usage; (*pp != NULL); pp++)
432 			BIO_printf(bio_err,*pp);
433 		goto err;
434 		}
435 
436 	ERR_load_crypto_strings();
437 
438 	/*****************************************************************/
439 	if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
440 	if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
441 	if (configfile == NULL)
442 		{
443 		/* We will just use 'buf[0]' as a temporary buffer.  */
444 #ifdef VMS
445 		strncpy(buf[0],X509_get_default_cert_area(),
446 			sizeof(buf[0])-1-sizeof(CONFIG_FILE));
447 #else
448 		strncpy(buf[0],X509_get_default_cert_area(),
449 			sizeof(buf[0])-2-sizeof(CONFIG_FILE));
450 		strcat(buf[0],"/");
451 #endif
452 		strcat(buf[0],CONFIG_FILE);
453 		configfile=buf[0];
454 		}
455 
456 	BIO_printf(bio_err,"Using configuration from %s\n",configfile);
457 	if ((conf=CONF_load(NULL,configfile,&errorline)) == NULL)
458 		{
459 		if (errorline <= 0)
460 			BIO_printf(bio_err,"error loading the config file '%s'\n",
461 				configfile);
462 		else
463 			BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
464 				,errorline,configfile);
465 		goto err;
466 		}
467 
468 	/* Lets get the config section we are using */
469 	if (section == NULL)
470 		{
471 		section=CONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
472 		if (section == NULL)
473 			{
474 			lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
475 			goto err;
476 			}
477 		}
478 
479 	if (conf != NULL)
480 		{
481 		p=CONF_get_string(conf,NULL,"oid_file");
482 		if (p != NULL)
483 			{
484 			BIO *oid_bio;
485 
486 			oid_bio=BIO_new_file(p,"r");
487 			if (oid_bio == NULL)
488 				{
489 				/*
490 				BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
491 				ERR_print_errors(bio_err);
492 				*/
493 				ERR_clear_error();
494 				}
495 			else
496 				{
497 				OBJ_create_objects(oid_bio);
498 				BIO_free(oid_bio);
499 				}
500 			}
501 		if(!add_oid_section(conf))
502 			{
503 			ERR_print_errors(bio_err);
504 			goto err;
505 			}
506 		}
507 
508 	randfile = CONF_get_string(conf, BASE_SECTION, "RANDFILE");
509 	app_RAND_load_file(randfile, bio_err, 0);
510 
511 	in=BIO_new(BIO_s_file());
512 	out=BIO_new(BIO_s_file());
513 	Sout=BIO_new(BIO_s_file());
514 	Cout=BIO_new(BIO_s_file());
515 	if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL))
516 		{
517 		ERR_print_errors(bio_err);
518 		goto err;
519 		}
520 
521 	/*****************************************************************/
522 	/* we definitely need an public key, so lets get it */
523 
524 	if ((keyfile == NULL) && ((keyfile=CONF_get_string(conf,
525 		section,ENV_PRIVATE_KEY)) == NULL))
526 		{
527 		lookup_fail(section,ENV_PRIVATE_KEY);
528 		goto err;
529 		}
530 	if (BIO_read_filename(in,keyfile) <= 0)
531 		{
532 		perror(keyfile);
533 		BIO_printf(bio_err,"trying to load CA private key\n");
534 		goto err;
535 		}
536 		pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,key);
537 		if(key) memset(key,0,strlen(key));
538 	if (pkey == NULL)
539 		{
540 		BIO_printf(bio_err,"unable to load CA private key\n");
541 		goto err;
542 		}
543 
544 	/*****************************************************************/
545 	/* we need a certificate */
546 	if ((certfile == NULL) && ((certfile=CONF_get_string(conf,
547 		section,ENV_CERTIFICATE)) == NULL))
548 		{
549 		lookup_fail(section,ENV_CERTIFICATE);
550 		goto err;
551 		}
552         if (BIO_read_filename(in,certfile) <= 0)
553 		{
554 		perror(certfile);
555 		BIO_printf(bio_err,"trying to load CA certificate\n");
556 		goto err;
557 		}
558 	x509=PEM_read_bio_X509(in,NULL,NULL,NULL);
559 	if (x509 == NULL)
560 		{
561 		BIO_printf(bio_err,"unable to load CA certificate\n");
562 		goto err;
563 		}
564 
565 	if (!X509_check_private_key(x509,pkey))
566 		{
567 		BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
568 		goto err;
569 		}
570 
571 	f=CONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
572 	if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
573 		preserve=1;
574 	f=CONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
575 	if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
576 		msie_hack=1;
577 
578 	/*****************************************************************/
579 	/* lookup where to write new certificates */
580 	if ((outdir == NULL) && (req))
581 		{
582 		struct stat sb;
583 
584 		if ((outdir=CONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
585 			== NULL)
586 			{
587 			BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
588 			goto err;
589 			}
590 #ifndef VMS /* outdir is a directory spec, but access() for VMS demands a
591 	       filename.  In any case, stat(), below, will catch the problem
592 	       if outdir is not a directory spec, and the fopen() or open()
593 	       will catch an error if there is no write access.
594 
595 	       Presumably, this problem could also be solved by using the DEC
596 	       C routines to convert the directory syntax to Unixly, and give
597 	       that to access().  However, time's too short to do that just
598 	       now.
599             */
600 		if (access(outdir,R_OK|W_OK|X_OK) != 0)
601 			{
602 			BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
603 			perror(outdir);
604 			goto err;
605 			}
606 
607 		if (stat(outdir,&sb) != 0)
608 			{
609 			BIO_printf(bio_err,"unable to stat(%s)\n",outdir);
610 			perror(outdir);
611 			goto err;
612 			}
613 #ifdef S_IFDIR
614 		if (!(sb.st_mode & S_IFDIR))
615 			{
616 			BIO_printf(bio_err,"%s need to be a directory\n",outdir);
617 			perror(outdir);
618 			goto err;
619 			}
620 #endif
621 #endif
622 		}
623 
624 	/*****************************************************************/
625 	/* we need to load the database file */
626 	if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL)
627 		{
628 		lookup_fail(section,ENV_DATABASE);
629 		goto err;
630 		}
631 	if (BIO_read_filename(in,dbfile) <= 0)
632 		{
633 		perror(dbfile);
634 		BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
635 		goto err;
636 		}
637 	db=TXT_DB_read(in,DB_NUMBER);
638 	if (db == NULL) goto err;
639 
640 	/* Lets check some fields */
641 	for (i=0; i<sk_num(db->data); i++)
642 		{
643 		pp=(char **)sk_value(db->data,i);
644 		if ((pp[DB_type][0] != DB_TYPE_REV) &&
645 			(pp[DB_rev_date][0] != '\0'))
646 			{
647 			BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
648 			goto err;
649 			}
650 		if ((pp[DB_type][0] == DB_TYPE_REV) &&
651 			!check_time_format(pp[DB_rev_date]))
652 			{
653 			BIO_printf(bio_err,"entry %d: invalid revocation date\n",
654 				i+1);
655 			goto err;
656 			}
657 		if (!check_time_format(pp[DB_exp_date]))
658 			{
659 			BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
660 			goto err;
661 			}
662 		p=pp[DB_serial];
663 		j=strlen(p);
664 		if ((j&1) || (j < 2))
665 			{
666 			BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
667 			goto err;
668 			}
669 		while (*p)
670 			{
671 			if (!(	((*p >= '0') && (*p <= '9')) ||
672 				((*p >= 'A') && (*p <= 'F')) ||
673 				((*p >= 'a') && (*p <= 'f')))  )
674 				{
675 				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);
676 				goto err;
677 				}
678 			p++;
679 			}
680 		}
681 	if (verbose)
682 		{
683 		BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
684 		TXT_DB_write(out,db);
685 		BIO_printf(bio_err,"%d entries loaded from the database\n",
686 			db->data->num);
687 		BIO_printf(bio_err,"generating index\n");
688 		}
689 
690 	if (!TXT_DB_create_index(db,DB_serial,NULL,index_serial_hash,
691 		index_serial_cmp))
692 		{
693 		BIO_printf(bio_err,"error creating serial number index:(%ld,%ld,%ld)\n",db->error,db->arg1,db->arg2);
694 		goto err;
695 		}
696 
697 	if (!TXT_DB_create_index(db,DB_name,index_name_qual,index_name_hash,
698 		index_name_cmp))
699 		{
700 		BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
701 			db->error,db->arg1,db->arg2);
702 		goto err;
703 		}
704 
705 	/*****************************************************************/
706 	if (req || gencrl)
707 		{
708 		if (outfile != NULL)
709 			{
710 
711 			if (BIO_write_filename(Sout,outfile) <= 0)
712 				{
713 				perror(outfile);
714 				goto err;
715 				}
716 			}
717 		else
718 			BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
719 		}
720 
721 	if (req)
722 		{
723 		if ((md == NULL) && ((md=CONF_get_string(conf,
724 			section,ENV_DEFAULT_MD)) == NULL))
725 			{
726 			lookup_fail(section,ENV_DEFAULT_MD);
727 			goto err;
728 			}
729 		if ((dgst=EVP_get_digestbyname(md)) == NULL)
730 			{
731 			BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
732 			goto err;
733 			}
734 		if (verbose)
735 			BIO_printf(bio_err,"message digest is %s\n",
736 				OBJ_nid2ln(dgst->type));
737 		if ((policy == NULL) && ((policy=CONF_get_string(conf,
738 			section,ENV_POLICY)) == NULL))
739 			{
740 			lookup_fail(section,ENV_POLICY);
741 			goto err;
742 			}
743 		if (verbose)
744 			BIO_printf(bio_err,"policy is %s\n",policy);
745 
746 		if ((serialfile=CONF_get_string(conf,section,ENV_SERIAL))
747 			== NULL)
748 			{
749 			lookup_fail(section,ENV_SERIAL);
750 			goto err;
751 			}
752 		if(!extensions)
753 			extensions=CONF_get_string(conf,section,ENV_EXTENSIONS);
754 		if(extensions) {
755 			/* Check syntax of file */
756 			X509V3_CTX ctx;
757 			X509V3_set_ctx_test(&ctx);
758 			X509V3_set_conf_lhash(&ctx, conf);
759 			if(!X509V3_EXT_add_conf(conf, &ctx, extensions, NULL)) {
760 				BIO_printf(bio_err,
761 				 "Error Loading extension section %s\n",
762 								 extensions);
763 				ret = 1;
764 				goto err;
765 			}
766 		}
767 
768 		if (startdate == NULL)
769 			{
770 			startdate=CONF_get_string(conf,section,
771 				ENV_DEFAULT_STARTDATE);
772 			}
773 		if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
774 			{
775 			BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
776 			goto err;
777 			}
778 		if (startdate == NULL) startdate="today";
779 
780 		if (enddate == NULL)
781 			{
782 			enddate=CONF_get_string(conf,section,
783 				ENV_DEFAULT_ENDDATE);
784 			}
785 		if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
786 			{
787 			BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
788 			goto err;
789 			}
790 
791 		if (days == 0)
792 			{
793 			days=(int)CONF_get_number(conf,section,
794 				ENV_DEFAULT_DAYS);
795 			}
796 		if (!enddate && (days == 0))
797 			{
798 			BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
799 			goto err;
800 			}
801 
802 		if ((serial=load_serial(serialfile)) == NULL)
803 			{
804 			BIO_printf(bio_err,"error while loading serial number\n");
805 			goto err;
806 			}
807 		if (verbose)
808 			{
809 			if ((f=BN_bn2hex(serial)) == NULL) goto err;
810 			BIO_printf(bio_err,"next serial number is %s\n",f);
811 			Free(f);
812 			}
813 
814 		if ((attribs=CONF_get_section(conf,policy)) == NULL)
815 			{
816 			BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
817 			goto err;
818 			}
819 
820 		if ((cert_sk=sk_new_null()) == NULL)
821 			{
822 			BIO_printf(bio_err,"Malloc failure\n");
823 			goto err;
824 			}
825 		if (spkac_file != NULL)
826 			{
827 			total++;
828 			j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
829 				serial,startdate,enddate, days,extensions,conf,
830 				verbose);
831 			if (j < 0) goto err;
832 			if (j > 0)
833 				{
834 				total_done++;
835 				BIO_printf(bio_err,"\n");
836 				if (!BN_add_word(serial,1)) goto err;
837 				if (!sk_push(cert_sk,(char *)x))
838 					{
839 					BIO_printf(bio_err,"Malloc failure\n");
840 					goto err;
841 					}
842 				if (outfile)
843 					{
844 					output_der = 1;
845 					batch = 1;
846 					}
847 				}
848 			}
849 		if (ss_cert_file != NULL)
850 			{
851 			total++;
852 			j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
853 				db,serial,startdate,enddate,days,batch,
854 				extensions,conf,verbose);
855 			if (j < 0) goto err;
856 			if (j > 0)
857 				{
858 				total_done++;
859 				BIO_printf(bio_err,"\n");
860 				if (!BN_add_word(serial,1)) goto err;
861 				if (!sk_push(cert_sk,(char *)x))
862 					{
863 					BIO_printf(bio_err,"Malloc failure\n");
864 					goto err;
865 					}
866 				}
867 			}
868 		if (infile != NULL)
869 			{
870 			total++;
871 			j=certify(&x,infile,pkey,x509,dgst,attribs,db,
872 				serial,startdate,enddate,days,batch,
873 				extensions,conf,verbose);
874 			if (j < 0) goto err;
875 			if (j > 0)
876 				{
877 				total_done++;
878 				BIO_printf(bio_err,"\n");
879 				if (!BN_add_word(serial,1)) goto err;
880 				if (!sk_push(cert_sk,(char *)x))
881 					{
882 					BIO_printf(bio_err,"Malloc failure\n");
883 					goto err;
884 					}
885 				}
886 			}
887 		for (i=0; i<argc; i++)
888 			{
889 			total++;
890 			j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
891 				serial,startdate,enddate,days,batch,
892 				extensions,conf,verbose);
893 			if (j < 0) goto err;
894 			if (j > 0)
895 				{
896 				total_done++;
897 				BIO_printf(bio_err,"\n");
898 				if (!BN_add_word(serial,1)) goto err;
899 				if (!sk_push(cert_sk,(char *)x))
900 					{
901 					BIO_printf(bio_err,"Malloc failure\n");
902 					goto err;
903 					}
904 				}
905 			}
906 		/* we have a stack of newly certified certificates
907 		 * and a data base and serial number that need
908 		 * updating */
909 
910 		if (sk_num(cert_sk) > 0)
911 			{
912 			if (!batch)
913 				{
914 				BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
915 				(void)BIO_flush(bio_err);
916 				buf[0][0]='\0';
917 				fgets(buf[0],10,stdin);
918 				if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
919 					{
920 					BIO_printf(bio_err,"CERTIFICATION CANCELED\n");
921 					ret=0;
922 					goto err;
923 					}
924 				}
925 
926 			BIO_printf(bio_err,"Write out database with %d new entries\n",sk_num(cert_sk));
927 
928 			strncpy(buf[0],serialfile,BSIZE-4);
929 
930 #ifdef VMS
931 			strcat(buf[0],"-new");
932 #else
933 			strcat(buf[0],".new");
934 #endif
935 
936 			if (!save_serial(buf[0],serial)) goto err;
937 
938 			strncpy(buf[1],dbfile,BSIZE-4);
939 
940 #ifdef VMS
941 			strcat(buf[1],"-new");
942 #else
943 			strcat(buf[1],".new");
944 #endif
945 
946 			if (BIO_write_filename(out,buf[1]) <= 0)
947 				{
948 				perror(dbfile);
949 				BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
950 				goto err;
951 				}
952 			l=TXT_DB_write(out,db);
953 			if (l <= 0) goto err;
954 			}
955 
956 		if (verbose)
957 			BIO_printf(bio_err,"writing new certificates\n");
958 		for (i=0; i<sk_num(cert_sk); i++)
959 			{
960 			int k;
961 			unsigned char *n;
962 
963 			x=(X509 *)sk_value(cert_sk,i);
964 
965 			j=x->cert_info->serialNumber->length;
966 			p=(char *)x->cert_info->serialNumber->data;
967 
968 			strncpy(buf[2],outdir,BSIZE-(j*2)-6);
969 
970 #ifndef VMS
971 			strcat(buf[2],"/");
972 #endif
973 
974 			n=(unsigned char *)&(buf[2][strlen(buf[2])]);
975 			if (j > 0)
976 				{
977 				for (k=0; k<j; k++)
978 					{
979 					sprintf((char *)n,"%02X",(unsigned char)*(p++));
980 					n+=2;
981 					}
982 				}
983 			else
984 				{
985 				*(n++)='0';
986 				*(n++)='0';
987 				}
988 			*(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
989 			*n='\0';
990 			if (verbose)
991 				BIO_printf(bio_err,"writing %s\n",buf[2]);
992 
993 			if (BIO_write_filename(Cout,buf[2]) <= 0)
994 				{
995 				perror(buf[2]);
996 				goto err;
997 				}
998 			write_new_certificate(Cout,x, 0, notext);
999 			write_new_certificate(Sout,x, output_der, notext);
1000 			}
1001 
1002 		if (sk_num(cert_sk))
1003 			{
1004 			/* Rename the database and the serial file */
1005 			strncpy(buf[2],serialfile,BSIZE-4);
1006 
1007 #ifdef VMS
1008 			strcat(buf[2],"-old");
1009 #else
1010 			strcat(buf[2],".old");
1011 #endif
1012 
1013 			BIO_free(in);
1014 			BIO_free(out);
1015 			in=NULL;
1016 			out=NULL;
1017 			if (rename(serialfile,buf[2]) < 0)
1018 				{
1019 				BIO_printf(bio_err,"unable to rename %s to %s\n",
1020 					serialfile,buf[2]);
1021 				perror("reason");
1022 				goto err;
1023 				}
1024 			if (rename(buf[0],serialfile) < 0)
1025 				{
1026 				BIO_printf(bio_err,"unable to rename %s to %s\n",
1027 					buf[0],serialfile);
1028 				perror("reason");
1029 				rename(buf[2],serialfile);
1030 				goto err;
1031 				}
1032 
1033 			strncpy(buf[2],dbfile,BSIZE-4);
1034 
1035 #ifdef VMS
1036 			strcat(buf[2],"-old");
1037 #else
1038 			strcat(buf[2],".old");
1039 #endif
1040 
1041 			if (rename(dbfile,buf[2]) < 0)
1042 				{
1043 				BIO_printf(bio_err,"unable to rename %s to %s\n",
1044 					dbfile,buf[2]);
1045 				perror("reason");
1046 				goto err;
1047 				}
1048 			if (rename(buf[1],dbfile) < 0)
1049 				{
1050 				BIO_printf(bio_err,"unable to rename %s to %s\n",
1051 					buf[1],dbfile);
1052 				perror("reason");
1053 				rename(buf[2],dbfile);
1054 				goto err;
1055 				}
1056 			BIO_printf(bio_err,"Data Base Updated\n");
1057 			}
1058 		}
1059 
1060 	/*****************************************************************/
1061 	if (gencrl)
1062 		{
1063 		if(!crl_ext) crl_ext=CONF_get_string(conf,section,ENV_CRLEXT);
1064 		if(crl_ext) {
1065 			/* Check syntax of file */
1066 			X509V3_CTX ctx;
1067 			X509V3_set_ctx_test(&ctx);
1068 			X509V3_set_conf_lhash(&ctx, conf);
1069 			if(!X509V3_EXT_add_conf(conf, &ctx, crl_ext, NULL)) {
1070 				BIO_printf(bio_err,
1071 				 "Error Loading CRL extension section %s\n",
1072 								 crl_ext);
1073 				ret = 1;
1074 				goto err;
1075 			}
1076 		}
1077 		if ((hex=BIO_new(BIO_s_mem())) == NULL) goto err;
1078 
1079 		if (!crldays && !crlhours)
1080 			{
1081 			crldays=CONF_get_number(conf,section,
1082 				ENV_DEFAULT_CRL_DAYS);
1083 			crlhours=CONF_get_number(conf,section,
1084 				ENV_DEFAULT_CRL_HOURS);
1085 			}
1086 		if ((crldays == 0) && (crlhours == 0))
1087 			{
1088 			BIO_printf(bio_err,"cannot lookup how long until the next CRL is issuer\n");
1089 			goto err;
1090 			}
1091 
1092 		if (verbose) BIO_printf(bio_err,"making CRL\n");
1093 		if ((crl=X509_CRL_new()) == NULL) goto err;
1094 		ci=crl->crl;
1095 		X509_NAME_free(ci->issuer);
1096 		ci->issuer=X509_NAME_dup(x509->cert_info->subject);
1097 		if (ci->issuer == NULL) goto err;
1098 
1099 		X509_gmtime_adj(ci->lastUpdate,0);
1100 		if (ci->nextUpdate == NULL)
1101 			ci->nextUpdate=ASN1_UTCTIME_new();
1102 		X509_gmtime_adj(ci->nextUpdate,(crldays*24+crlhours)*60*60);
1103 
1104 		for (i=0; i<sk_num(db->data); i++)
1105 			{
1106 			pp=(char **)sk_value(db->data,i);
1107 			if (pp[DB_type][0] == DB_TYPE_REV)
1108 				{
1109 				if ((r=X509_REVOKED_new()) == NULL) goto err;
1110 				ASN1_STRING_set((ASN1_STRING *)
1111 					r->revocationDate,
1112 					(unsigned char *)pp[DB_rev_date],
1113 					strlen(pp[DB_rev_date]));
1114 				/* strcpy(r->revocationDate,pp[DB_rev_date]);*/
1115 
1116 				(void)BIO_reset(hex);
1117 				if (!BIO_puts(hex,pp[DB_serial]))
1118 					goto err;
1119 				if (!a2i_ASN1_INTEGER(hex,r->serialNumber,
1120 					buf[0],BSIZE)) goto err;
1121 
1122 				sk_X509_REVOKED_push(ci->revoked,r);
1123 				}
1124 			}
1125 		/* sort the data so it will be written in serial
1126 		 * number order */
1127 		sk_X509_REVOKED_sort(ci->revoked);
1128 		for (i=0; i<sk_X509_REVOKED_num(ci->revoked); i++)
1129 			{
1130 			r=sk_X509_REVOKED_value(ci->revoked,i);
1131 			r->sequence=i;
1132 			}
1133 
1134 		/* we now have a CRL */
1135 		if (verbose) BIO_printf(bio_err,"signing CRL\n");
1136 		if (md != NULL)
1137 			{
1138 			if ((dgst=EVP_get_digestbyname(md)) == NULL)
1139 				{
1140 				BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1141 				goto err;
1142 				}
1143 			}
1144 		else
1145 		    {
1146 #ifndef NO_DSA
1147 		    if (pkey->type == EVP_PKEY_DSA)
1148 			dgst=EVP_dss1();
1149 		    else
1150 #endif
1151 			dgst=EVP_md5();
1152 		    }
1153 
1154 		/* Add any extensions asked for */
1155 
1156 		if(crl_ext) {
1157 		    X509V3_CTX crlctx;
1158 		    if (ci->version == NULL)
1159 		    if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
1160 		    ASN1_INTEGER_set(ci->version,1); /* version 2 CRL */
1161 		    X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1162 		    X509V3_set_conf_lhash(&crlctx, conf);
1163 
1164 		    if(!X509V3_EXT_CRL_add_conf(conf, &crlctx,
1165 						 crl_ext, crl)) goto err;
1166 		}
1167 
1168 		if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1169 
1170 		PEM_write_bio_X509_CRL(Sout,crl);
1171 		}
1172 	/*****************************************************************/
1173 	if (dorevoke)
1174 		{
1175 		if (infile == NULL)
1176 			{
1177 			BIO_printf(bio_err,"no input files\n");
1178 			goto err;
1179 			}
1180 		else
1181 			{
1182 			X509 *revcert;
1183 			if (BIO_read_filename(in,infile) <= 0)
1184 				{
1185 				perror(infile);
1186 				BIO_printf(bio_err,"error trying to load '%s' certificate\n",infile);
1187 				goto err;
1188 				}
1189 			revcert=PEM_read_bio_X509(in,NULL,NULL,NULL);
1190 			if (revcert == NULL)
1191 				{
1192 				BIO_printf(bio_err,"unable to load '%s' certificate\n",infile);
1193 				goto err;
1194 				}
1195 			j=do_revoke(revcert,db);
1196 			if (j <= 0) goto err;
1197 			X509_free(revcert);
1198 
1199 			strncpy(buf[0],dbfile,BSIZE-4);
1200 			strcat(buf[0],".new");
1201 			if (BIO_write_filename(out,buf[0]) <= 0)
1202 				{
1203 				perror(dbfile);
1204 				BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1205 				goto err;
1206 				}
1207 			j=TXT_DB_write(out,db);
1208 			if (j <= 0) goto err;
1209 			strncpy(buf[1],dbfile,BSIZE-4);
1210 			strcat(buf[1],".old");
1211 			if (rename(dbfile,buf[1]) < 0)
1212 				{
1213 				BIO_printf(bio_err,"unable to rename %s to %s\n", dbfile, buf[1]);
1214 				perror("reason");
1215 				goto err;
1216 				}
1217 			if (rename(buf[0],dbfile) < 0)
1218 				{
1219 				BIO_printf(bio_err,"unable to rename %s to %s\n", buf[0],dbfile);
1220 				perror("reason");
1221 				rename(buf[1],dbfile);
1222 				goto err;
1223 				}
1224 			BIO_printf(bio_err,"Data Base Updated\n");
1225 			}
1226 		}
1227 	/*****************************************************************/
1228 	ret=0;
1229 err:
1230 	BIO_free(hex);
1231 	BIO_free(Cout);
1232 	BIO_free(Sout);
1233 	BIO_free(out);
1234 	BIO_free(in);
1235 
1236 	sk_pop_free(cert_sk,X509_free);
1237 
1238 	if (ret) ERR_print_errors(bio_err);
1239 	app_RAND_write_file(randfile, bio_err);
1240 	BN_free(serial);
1241 	TXT_DB_free(db);
1242 	EVP_PKEY_free(pkey);
1243 	X509_free(x509);
1244 	X509_CRL_free(crl);
1245 	CONF_free(conf);
1246 	OBJ_cleanup();
1247 	EXIT(ret);
1248 	}
1249 
1250 static void lookup_fail(char *name, char *tag)
1251 	{
1252 	BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1253 	}
1254 
1255 static unsigned long index_serial_hash(char **a)
1256 	{
1257 	char *n;
1258 
1259 	n=a[DB_serial];
1260 	while (*n == '0') n++;
1261 	return(lh_strhash(n));
1262 	}
1263 
1264 static int index_serial_cmp(char **a, char **b)
1265 	{
1266 	char *aa,*bb;
1267 
1268 	for (aa=a[DB_serial]; *aa == '0'; aa++);
1269 	for (bb=b[DB_serial]; *bb == '0'; bb++);
1270 	return(strcmp(aa,bb));
1271 	}
1272 
1273 static unsigned long index_name_hash(char **a)
1274 	{ return(lh_strhash(a[DB_name])); }
1275 
1276 static int index_name_qual(char **a)
1277 	{ return(a[0][0] == 'V'); }
1278 
1279 static int index_name_cmp(char **a, char **b)
1280 	{ return(strcmp(a[DB_name],
1281 	     b[DB_name])); }
1282 
1283 static BIGNUM *load_serial(char *serialfile)
1284 	{
1285 	BIO *in=NULL;
1286 	BIGNUM *ret=NULL;
1287 	MS_STATIC char buf[1024];
1288 	ASN1_INTEGER *ai=NULL;
1289 
1290 	if ((in=BIO_new(BIO_s_file())) == NULL)
1291 		{
1292 		ERR_print_errors(bio_err);
1293 		goto err;
1294 		}
1295 
1296 	if (BIO_read_filename(in,serialfile) <= 0)
1297 		{
1298 		perror(serialfile);
1299 		goto err;
1300 		}
1301 	ai=ASN1_INTEGER_new();
1302 	if (ai == NULL) goto err;
1303 	if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
1304 		{
1305 		BIO_printf(bio_err,"unable to load number from %s\n",
1306 			serialfile);
1307 		goto err;
1308 		}
1309 	ret=ASN1_INTEGER_to_BN(ai,NULL);
1310 	if (ret == NULL)
1311 		{
1312 		BIO_printf(bio_err,"error converting number from bin to BIGNUM");
1313 		goto err;
1314 		}
1315 err:
1316 	if (in != NULL) BIO_free(in);
1317 	if (ai != NULL) ASN1_INTEGER_free(ai);
1318 	return(ret);
1319 	}
1320 
1321 static int save_serial(char *serialfile, BIGNUM *serial)
1322 	{
1323 	BIO *out;
1324 	int ret=0;
1325 	ASN1_INTEGER *ai=NULL;
1326 
1327 	out=BIO_new(BIO_s_file());
1328 	if (out == NULL)
1329 		{
1330 		ERR_print_errors(bio_err);
1331 		goto err;
1332 		}
1333 	if (BIO_write_filename(out,serialfile) <= 0)
1334 		{
1335 		perror(serialfile);
1336 		goto err;
1337 		}
1338 
1339 	if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
1340 		{
1341 		BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
1342 		goto err;
1343 		}
1344 	i2a_ASN1_INTEGER(out,ai);
1345 	BIO_puts(out,"\n");
1346 	ret=1;
1347 err:
1348 	if (out != NULL) BIO_free(out);
1349 	if (ai != NULL) ASN1_INTEGER_free(ai);
1350 	return(ret);
1351 	}
1352 
1353 static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1354 	     const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1355 	     BIGNUM *serial, char *startdate, char *enddate, int days,
1356 	     int batch, char *ext_sect, LHASH *lconf, int verbose)
1357 	{
1358 	X509_REQ *req=NULL;
1359 	BIO *in=NULL;
1360 	EVP_PKEY *pktmp=NULL;
1361 	int ok= -1,i;
1362 
1363 	in=BIO_new(BIO_s_file());
1364 
1365 	if (BIO_read_filename(in,infile) <= 0)
1366 		{
1367 		perror(infile);
1368 		goto err;
1369 		}
1370 	if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
1371 		{
1372 		BIO_printf(bio_err,"Error reading certificate request in %s\n",
1373 			infile);
1374 		goto err;
1375 		}
1376 	if (verbose)
1377 		X509_REQ_print(bio_err,req);
1378 
1379 	BIO_printf(bio_err,"Check that the request matches the signature\n");
1380 
1381 	if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
1382 		{
1383 		BIO_printf(bio_err,"error unpacking public key\n");
1384 		goto err;
1385 		}
1386 	i=X509_REQ_verify(req,pktmp);
1387 	EVP_PKEY_free(pktmp);
1388 	if (i < 0)
1389 		{
1390 		ok=0;
1391 		BIO_printf(bio_err,"Signature verification problems....\n");
1392 		goto err;
1393 		}
1394 	if (i == 0)
1395 		{
1396 		ok=0;
1397 		BIO_printf(bio_err,"Signature did not match the certificate request\n");
1398 		goto err;
1399 		}
1400 	else
1401 		BIO_printf(bio_err,"Signature ok\n");
1402 
1403 	ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate, enddate,
1404 		days,batch,verbose,req,ext_sect,lconf);
1405 
1406 err:
1407 	if (req != NULL) X509_REQ_free(req);
1408 	if (in != NULL) BIO_free(in);
1409 	return(ok);
1410 	}
1411 
1412 static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1413 	     const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1414 	     BIGNUM *serial, char *startdate, char *enddate, int days,
1415 	     int batch, char *ext_sect, LHASH *lconf, int verbose)
1416 	{
1417 	X509 *req=NULL;
1418 	X509_REQ *rreq=NULL;
1419 	BIO *in=NULL;
1420 	EVP_PKEY *pktmp=NULL;
1421 	int ok= -1,i;
1422 
1423 	in=BIO_new(BIO_s_file());
1424 
1425 	if (BIO_read_filename(in,infile) <= 0)
1426 		{
1427 		perror(infile);
1428 		goto err;
1429 		}
1430 	if ((req=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
1431 		{
1432 		BIO_printf(bio_err,"Error reading self signed certificate in %s\n",infile);
1433 		goto err;
1434 		}
1435 	if (verbose)
1436 		X509_print(bio_err,req);
1437 
1438 	BIO_printf(bio_err,"Check that the request matches the signature\n");
1439 
1440 	if ((pktmp=X509_get_pubkey(req)) == NULL)
1441 		{
1442 		BIO_printf(bio_err,"error unpacking public key\n");
1443 		goto err;
1444 		}
1445 	i=X509_verify(req,pktmp);
1446 	EVP_PKEY_free(pktmp);
1447 	if (i < 0)
1448 		{
1449 		ok=0;
1450 		BIO_printf(bio_err,"Signature verification problems....\n");
1451 		goto err;
1452 		}
1453 	if (i == 0)
1454 		{
1455 		ok=0;
1456 		BIO_printf(bio_err,"Signature did not match the certificate\n");
1457 		goto err;
1458 		}
1459 	else
1460 		BIO_printf(bio_err,"Signature ok\n");
1461 
1462 	if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
1463 		goto err;
1464 
1465 	ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,days,
1466 		batch,verbose,rreq,ext_sect,lconf);
1467 
1468 err:
1469 	if (rreq != NULL) X509_REQ_free(rreq);
1470 	if (req != NULL) X509_free(req);
1471 	if (in != NULL) BIO_free(in);
1472 	return(ok);
1473 	}
1474 
1475 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1476 	     STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
1477 	     char *startdate, char *enddate, int days, int batch, int verbose,
1478 	     X509_REQ *req, char *ext_sect, LHASH *lconf)
1479 	{
1480 	X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
1481 	ASN1_UTCTIME *tm,*tmptm;
1482 	ASN1_STRING *str,*str2;
1483 	ASN1_OBJECT *obj;
1484 	X509 *ret=NULL;
1485 	X509_CINF *ci;
1486 	X509_NAME_ENTRY *ne;
1487 	X509_NAME_ENTRY *tne,*push;
1488 	EVP_PKEY *pktmp;
1489 	int ok= -1,i,j,last,nid;
1490 	char *p;
1491 	CONF_VALUE *cv;
1492 	char *row[DB_NUMBER],**rrow,**irow=NULL;
1493 	char buf[25],*pbuf;
1494 
1495 	tmptm=ASN1_UTCTIME_new();
1496 	if (tmptm == NULL)
1497 		{
1498 		BIO_printf(bio_err,"malloc error\n");
1499 		return(0);
1500 		}
1501 
1502 	for (i=0; i<DB_NUMBER; i++)
1503 		row[i]=NULL;
1504 
1505 	BIO_printf(bio_err,"The Subjects Distinguished Name is as follows\n");
1506 	name=X509_REQ_get_subject_name(req);
1507 	for (i=0; i<X509_NAME_entry_count(name); i++)
1508 		{
1509 		ne=(X509_NAME_ENTRY *)X509_NAME_get_entry(name,i);
1510 		obj=X509_NAME_ENTRY_get_object(ne);
1511 		j=i2a_ASN1_OBJECT(bio_err,obj);
1512 		str=X509_NAME_ENTRY_get_data(ne);
1513 		pbuf=buf;
1514 		for (j=22-j; j>0; j--)
1515 			*(pbuf++)=' ';
1516 		*(pbuf++)=':';
1517 		*(pbuf++)='\0';
1518 		BIO_puts(bio_err,buf);
1519 
1520 		if (msie_hack)
1521 			{
1522 			/* assume all type should be strings */
1523 			nid=OBJ_obj2nid(ne->object);
1524 
1525 			if (str->type == V_ASN1_UNIVERSALSTRING)
1526 				ASN1_UNIVERSALSTRING_to_string(str);
1527 
1528 			if ((str->type == V_ASN1_IA5STRING) &&
1529 				(nid != NID_pkcs9_emailAddress))
1530 				str->type=V_ASN1_T61STRING;
1531 
1532 			if ((nid == NID_pkcs9_emailAddress) &&
1533 				(str->type == V_ASN1_PRINTABLESTRING))
1534 				str->type=V_ASN1_IA5STRING;
1535 			}
1536 
1537 		if (str->type == V_ASN1_PRINTABLESTRING)
1538 			BIO_printf(bio_err,"PRINTABLE:'");
1539 		else if (str->type == V_ASN1_T61STRING)
1540 			BIO_printf(bio_err,"T61STRING:'");
1541 		else if (str->type == V_ASN1_IA5STRING)
1542 			BIO_printf(bio_err,"IA5STRING:'");
1543 		else if (str->type == V_ASN1_UNIVERSALSTRING)
1544 			BIO_printf(bio_err,"UNIVERSALSTRING:'");
1545 		else
1546 			BIO_printf(bio_err,"ASN.1 %2d:'",str->type);
1547 
1548 		/* check some things */
1549 		if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1550 			(str->type != V_ASN1_IA5STRING))
1551 			{
1552 			BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
1553 			goto err;
1554 			}
1555 		j=ASN1_PRINTABLE_type(str->data,str->length);
1556 		if (	((j == V_ASN1_T61STRING) &&
1557 			 (str->type != V_ASN1_T61STRING)) ||
1558 			((j == V_ASN1_IA5STRING) &&
1559 			 (str->type == V_ASN1_PRINTABLESTRING)))
1560 			{
1561 			BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1562 			goto err;
1563 			}
1564 
1565 		p=(char *)str->data;
1566 		for (j=str->length; j>0; j--)
1567 			{
1568 			if ((*p >= ' ') && (*p <= '~'))
1569 				BIO_printf(bio_err,"%c",*p);
1570 			else if (*p & 0x80)
1571 				BIO_printf(bio_err,"\\0x%02X",*p);
1572 			else if ((unsigned char)*p == 0xf7)
1573 				BIO_printf(bio_err,"^?");
1574 			else	BIO_printf(bio_err,"^%c",*p+'@');
1575 			p++;
1576 			}
1577 		BIO_printf(bio_err,"'\n");
1578 		}
1579 
1580 	/* Ok, now we check the 'policy' stuff. */
1581 	if ((subject=X509_NAME_new()) == NULL)
1582 		{
1583 		BIO_printf(bio_err,"Malloc failure\n");
1584 		goto err;
1585 		}
1586 
1587 	/* take a copy of the issuer name before we mess with it. */
1588 	CAname=X509_NAME_dup(x509->cert_info->subject);
1589 	if (CAname == NULL) goto err;
1590 	str=str2=NULL;
1591 
1592 	for (i=0; i<sk_CONF_VALUE_num(policy); i++)
1593 		{
1594 		cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
1595 		if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
1596 			{
1597 			BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
1598 			goto err;
1599 			}
1600 		obj=OBJ_nid2obj(j);
1601 
1602 		last= -1;
1603 		for (;;)
1604 			{
1605 			/* lookup the object in the supplied name list */
1606 			j=X509_NAME_get_index_by_OBJ(name,obj,last);
1607 			if (j < 0)
1608 				{
1609 				if (last != -1) break;
1610 				tne=NULL;
1611 				}
1612 			else
1613 				{
1614 				tne=X509_NAME_get_entry(name,j);
1615 				}
1616 			last=j;
1617 
1618 			/* depending on the 'policy', decide what to do. */
1619 			push=NULL;
1620 			if (strcmp(cv->value,"optional") == 0)
1621 				{
1622 				if (tne != NULL)
1623 					push=tne;
1624 				}
1625 			else if (strcmp(cv->value,"supplied") == 0)
1626 				{
1627 				if (tne == NULL)
1628 					{
1629 					BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
1630 					goto err;
1631 					}
1632 				else
1633 					push=tne;
1634 				}
1635 			else if (strcmp(cv->value,"match") == 0)
1636 				{
1637 				int last2;
1638 
1639 				if (tne == NULL)
1640 					{
1641 					BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
1642 					goto err;
1643 					}
1644 
1645 				last2= -1;
1646 
1647 again2:
1648 				j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
1649 				if ((j < 0) && (last2 == -1))
1650 					{
1651 					BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
1652 					goto err;
1653 					}
1654 				if (j >= 0)
1655 					{
1656 					push=X509_NAME_get_entry(CAname,j);
1657 					str=X509_NAME_ENTRY_get_data(tne);
1658 					str2=X509_NAME_ENTRY_get_data(push);
1659 					last2=j;
1660 					if (ASN1_STRING_cmp(str,str2) != 0)
1661 						goto again2;
1662 					}
1663 				if (j < 0)
1664 					{
1665 					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));
1666 					goto err;
1667 					}
1668 				}
1669 			else
1670 				{
1671 				BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
1672 				goto err;
1673 				}
1674 
1675 			if (push != NULL)
1676 				{
1677 				if (!X509_NAME_add_entry(subject,push, -1, 0))
1678 					{
1679 					if (push != NULL)
1680 						X509_NAME_ENTRY_free(push);
1681 					BIO_printf(bio_err,"Malloc failure\n");
1682 					goto err;
1683 					}
1684 				}
1685 			if (j < 0) break;
1686 			}
1687 		}
1688 
1689 	if (preserve)
1690 		{
1691 		X509_NAME_free(subject);
1692 		subject=X509_NAME_dup(X509_REQ_get_subject_name(req));
1693 		if (subject == NULL) goto err;
1694 		}
1695 
1696 	if (verbose)
1697 		BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
1698 
1699 	row[DB_name]=X509_NAME_oneline(subject,NULL,0);
1700 	row[DB_serial]=BN_bn2hex(serial);
1701 	if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
1702 		{
1703 		BIO_printf(bio_err,"Malloc failure\n");
1704 		goto err;
1705 		}
1706 
1707 	rrow=TXT_DB_get_by_index(db,DB_name,row);
1708 	if (rrow != NULL)
1709 		{
1710 		BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n",
1711 			row[DB_name]);
1712 		}
1713 	else
1714 		{
1715 		rrow=TXT_DB_get_by_index(db,DB_serial,row);
1716 		if (rrow != NULL)
1717 			{
1718 			BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
1719 				row[DB_serial]);
1720 			BIO_printf(bio_err,"      check the database/serial_file for corruption\n");
1721 			}
1722 		}
1723 
1724 	if (rrow != NULL)
1725 		{
1726 		BIO_printf(bio_err,
1727 			"The matching entry has the following details\n");
1728 		if (rrow[DB_type][0] == 'E')
1729 			p="Expired";
1730 		else if (rrow[DB_type][0] == 'R')
1731 			p="Revoked";
1732 		else if (rrow[DB_type][0] == 'V')
1733 			p="Valid";
1734 		else
1735 			p="\ninvalid type, Data base error\n";
1736 		BIO_printf(bio_err,"Type	  :%s\n",p);;
1737 		if (rrow[DB_type][0] == 'R')
1738 			{
1739 			p=rrow[DB_exp_date]; if (p == NULL) p="undef";
1740 			BIO_printf(bio_err,"Was revoked on:%s\n",p);
1741 			}
1742 		p=rrow[DB_exp_date]; if (p == NULL) p="undef";
1743 		BIO_printf(bio_err,"Expires on    :%s\n",p);
1744 		p=rrow[DB_serial]; if (p == NULL) p="undef";
1745 		BIO_printf(bio_err,"Serial Number :%s\n",p);
1746 		p=rrow[DB_file]; if (p == NULL) p="undef";
1747 		BIO_printf(bio_err,"File name     :%s\n",p);
1748 		p=rrow[DB_name]; if (p == NULL) p="undef";
1749 		BIO_printf(bio_err,"Subject Name  :%s\n",p);
1750 		ok= -1; /* This is now a 'bad' error. */
1751 		goto err;
1752 		}
1753 
1754 	/* We are now totally happy, lets make and sign the certificate */
1755 	if (verbose)
1756 		BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
1757 
1758 	if ((ret=X509_new()) == NULL) goto err;
1759 	ci=ret->cert_info;
1760 
1761 #ifdef X509_V3
1762 	/* Make it an X509 v3 certificate. */
1763 	if (!X509_set_version(x509,2)) goto err;
1764 #endif
1765 
1766 	if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
1767 		goto err;
1768 	if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
1769 		goto err;
1770 
1771 	BIO_printf(bio_err,"Certificate is to be certified until ");
1772 	if (strcmp(startdate,"today") == 0)
1773 		X509_gmtime_adj(X509_get_notBefore(ret),0);
1774 	else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
1775 
1776 	if (enddate == NULL)
1777 		X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
1778 	else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
1779 
1780 	ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
1781 	if(days) BIO_printf(bio_err," (%d days)",days);
1782 	BIO_printf(bio_err, "\n");
1783 
1784 	if (!X509_set_subject_name(ret,subject)) goto err;
1785 
1786 	pktmp=X509_REQ_get_pubkey(req);
1787 	i = X509_set_pubkey(ret,pktmp);
1788 	EVP_PKEY_free(pktmp);
1789 	if (!i) goto err;
1790 
1791 	/* Lets add the extensions, if there are any */
1792 	if (ext_sect)
1793 		{
1794 		X509V3_CTX ctx;
1795 		if (ci->version == NULL)
1796 			if ((ci->version=ASN1_INTEGER_new()) == NULL)
1797 				goto err;
1798 		ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
1799 
1800 		/* Free the current entries if any, there should not
1801 		 * be any I believe */
1802 		if (ci->extensions != NULL)
1803 			sk_X509_EXTENSION_pop_free(ci->extensions,
1804 						   X509_EXTENSION_free);
1805 
1806 		ci->extensions = NULL;
1807 
1808 		X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
1809 		X509V3_set_conf_lhash(&ctx, lconf);
1810 
1811 		if(!X509V3_EXT_add_conf(lconf, &ctx, ext_sect, ret)) goto err;
1812 
1813 		}
1814 
1815 
1816 	if (!batch)
1817 		{
1818 		BIO_printf(bio_err,"Sign the certificate? [y/n]:");
1819 		(void)BIO_flush(bio_err);
1820 		buf[0]='\0';
1821 		fgets(buf,sizeof(buf)-1,stdin);
1822 		if (!((buf[0] == 'y') || (buf[0] == 'Y')))
1823 			{
1824 			BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
1825 			ok=0;
1826 			goto err;
1827 			}
1828 		}
1829 
1830 
1831 #ifndef NO_DSA
1832 	if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
1833 	pktmp=X509_get_pubkey(ret);
1834 	if (EVP_PKEY_missing_parameters(pktmp) &&
1835 		!EVP_PKEY_missing_parameters(pkey))
1836 		EVP_PKEY_copy_parameters(pktmp,pkey);
1837 	EVP_PKEY_free(pktmp);
1838 #endif
1839 
1840 	if (!X509_sign(ret,pkey,dgst))
1841 		goto err;
1842 
1843 	/* We now just add it to the database */
1844 	row[DB_type]=(char *)Malloc(2);
1845 
1846 	tm=X509_get_notAfter(ret);
1847 	row[DB_exp_date]=(char *)Malloc(tm->length+1);
1848 	memcpy(row[DB_exp_date],tm->data,tm->length);
1849 	row[DB_exp_date][tm->length]='\0';
1850 
1851 	row[DB_rev_date]=NULL;
1852 
1853 	/* row[DB_serial] done already */
1854 	row[DB_file]=(char *)Malloc(8);
1855 	/* row[DB_name] done already */
1856 
1857 	if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
1858 		(row[DB_file] == NULL))
1859 		{
1860 		BIO_printf(bio_err,"Malloc failure\n");
1861 		goto err;
1862 		}
1863 	strcpy(row[DB_file],"unknown");
1864 	row[DB_type][0]='V';
1865 	row[DB_type][1]='\0';
1866 
1867 	if ((irow=(char **)Malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
1868 		{
1869 		BIO_printf(bio_err,"Malloc failure\n");
1870 		goto err;
1871 		}
1872 
1873 	for (i=0; i<DB_NUMBER; i++)
1874 		{
1875 		irow[i]=row[i];
1876 		row[i]=NULL;
1877 		}
1878 	irow[DB_NUMBER]=NULL;
1879 
1880 	if (!TXT_DB_insert(db,irow))
1881 		{
1882 		BIO_printf(bio_err,"failed to update database\n");
1883 		BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
1884 		goto err;
1885 		}
1886 	ok=1;
1887 err:
1888 	for (i=0; i<DB_NUMBER; i++)
1889 		if (row[i] != NULL) Free(row[i]);
1890 
1891 	if (CAname != NULL)
1892 		X509_NAME_free(CAname);
1893 	if (subject != NULL)
1894 		X509_NAME_free(subject);
1895 	if (tmptm != NULL)
1896 		ASN1_UTCTIME_free(tmptm);
1897 	if (ok <= 0)
1898 		{
1899 		if (ret != NULL) X509_free(ret);
1900 		ret=NULL;
1901 		}
1902 	else
1903 		*xret=ret;
1904 	return(ok);
1905 	}
1906 
1907 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
1908 	{
1909 
1910 	if (output_der)
1911 		{
1912 		(void)i2d_X509_bio(bp,x);
1913 		return;
1914 		}
1915 #if 0
1916 	/* ??? Not needed since X509_print prints all this stuff anyway */
1917 	f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
1918 	BIO_printf(bp,"issuer :%s\n",f);
1919 
1920 	f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
1921 	BIO_printf(bp,"subject:%s\n",f);
1922 
1923 	BIO_puts(bp,"serial :");
1924 	i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
1925 	BIO_puts(bp,"\n\n");
1926 #endif
1927 	if(!notext)X509_print(bp,x);
1928 	PEM_write_bio_X509(bp,x);
1929 	}
1930 
1931 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1932 	     const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1933 	     BIGNUM *serial, char *startdate, char *enddate, int days,
1934 	     char *ext_sect, LHASH *lconf, int verbose)
1935 	{
1936 	STACK_OF(CONF_VALUE) *sk=NULL;
1937 	LHASH *parms=NULL;
1938 	X509_REQ *req=NULL;
1939 	CONF_VALUE *cv=NULL;
1940 	NETSCAPE_SPKI *spki = NULL;
1941 	X509_REQ_INFO *ri;
1942 	char *type,*buf;
1943 	EVP_PKEY *pktmp=NULL;
1944 	X509_NAME *n=NULL;
1945 	X509_NAME_ENTRY *ne=NULL;
1946 	int ok= -1,i,j;
1947 	long errline;
1948 	int nid;
1949 
1950 	/*
1951 	 * Load input file into a hash table.  (This is just an easy
1952 	 * way to read and parse the file, then put it into a convenient
1953 	 * STACK format).
1954 	 */
1955 	parms=CONF_load(NULL,infile,&errline);
1956 	if (parms == NULL)
1957 		{
1958 		BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
1959 		ERR_print_errors(bio_err);
1960 		goto err;
1961 		}
1962 
1963 	sk=CONF_get_section(parms, "default");
1964 	if (sk_CONF_VALUE_num(sk) == 0)
1965 		{
1966 		BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
1967 		CONF_free(parms);
1968 		goto err;
1969 		}
1970 
1971 	/*
1972 	 * Now create a dummy X509 request structure.  We don't actually
1973 	 * have an X509 request, but we have many of the components
1974 	 * (a public key, various DN components).  The idea is that we
1975 	 * put these components into the right X509 request structure
1976 	 * and we can use the same code as if you had a real X509 request.
1977 	 */
1978 	req=X509_REQ_new();
1979 	if (req == NULL)
1980 		{
1981 		ERR_print_errors(bio_err);
1982 		goto err;
1983 		}
1984 
1985 	/*
1986 	 * Build up the subject name set.
1987 	 */
1988 	ri=req->req_info;
1989 	n = ri->subject;
1990 
1991 	for (i = 0; ; i++)
1992 		{
1993 		if (sk_CONF_VALUE_num(sk) <= i) break;
1994 
1995 		cv=sk_CONF_VALUE_value(sk,i);
1996 		type=cv->name;
1997 		/* Skip past any leading X. X: X, etc to allow for
1998 		 * multiple instances
1999 		 */
2000 		for(buf = cv->name; *buf ; buf++)
2001 			if ((*buf == ':') || (*buf == ',') || (*buf == '.')) {
2002 					buf++;
2003 					if(*buf) type = buf;
2004 					break;
2005 		}
2006 
2007 		buf=cv->value;
2008 		if ((nid=OBJ_txt2nid(type)) == NID_undef)
2009 			{
2010 			if (strcmp(type, "SPKAC") == 0)
2011 				{
2012 				spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2013 				if (spki == NULL)
2014 					{
2015 					BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2016 					ERR_print_errors(bio_err);
2017 					goto err;
2018 					}
2019 				}
2020 			continue;
2021 			}
2022 
2023 		j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
2024 		if (fix_data(nid, &j) == 0)
2025 			{
2026 			BIO_printf(bio_err,
2027 				"invalid characters in string %s\n",buf);
2028 			goto err;
2029 			}
2030 
2031 		if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
2032 			(unsigned char *)buf,
2033 			strlen(buf))) == NULL)
2034 			goto err;
2035 
2036 		if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
2037 		}
2038 	if (spki == NULL)
2039 		{
2040 		BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2041 			infile);
2042 		goto err;
2043 		}
2044 
2045 	/*
2046 	 * Now extract the key from the SPKI structure.
2047 	 */
2048 
2049 	BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2050 
2051 	if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
2052 		{
2053 		BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2054 		goto err;
2055 		}
2056 
2057 	j = NETSCAPE_SPKI_verify(spki, pktmp);
2058 	if (j <= 0)
2059 		{
2060 		BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2061 		goto err;
2062 		}
2063 	BIO_printf(bio_err,"Signature ok\n");
2064 
2065 	X509_REQ_set_pubkey(req,pktmp);
2066 	EVP_PKEY_free(pktmp);
2067 	ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,
2068 		   days,1,verbose,req,ext_sect,lconf);
2069 err:
2070 	if (req != NULL) X509_REQ_free(req);
2071 	if (parms != NULL) CONF_free(parms);
2072 	if (spki != NULL) NETSCAPE_SPKI_free(spki);
2073 	if (ne != NULL) X509_NAME_ENTRY_free(ne);
2074 
2075 	return(ok);
2076 	}
2077 
2078 static int fix_data(int nid, int *type)
2079 	{
2080 	if (nid == NID_pkcs9_emailAddress)
2081 		*type=V_ASN1_IA5STRING;
2082 	if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
2083 		*type=V_ASN1_T61STRING;
2084 	if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
2085 		*type=V_ASN1_T61STRING;
2086 	if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
2087 		return(0);
2088 	if (nid == NID_pkcs9_unstructuredName)
2089 		*type=V_ASN1_IA5STRING;
2090 	return(1);
2091 	}
2092 
2093 static int check_time_format(char *str)
2094 	{
2095 	ASN1_UTCTIME tm;
2096 
2097 	tm.data=(unsigned char *)str;
2098 	tm.length=strlen(str);
2099 	tm.type=V_ASN1_UTCTIME;
2100 	return(ASN1_UTCTIME_check(&tm));
2101 	}
2102 
2103 static int add_oid_section(LHASH *hconf)
2104 {
2105 	char *p;
2106 	STACK_OF(CONF_VALUE) *sktmp;
2107 	CONF_VALUE *cnf;
2108 	int i;
2109 	if(!(p=CONF_get_string(hconf,NULL,"oid_section"))) return 1;
2110 	if(!(sktmp = CONF_get_section(hconf, p))) {
2111 		BIO_printf(bio_err, "problem loading oid section %s\n", p);
2112 		return 0;
2113 	}
2114 	for(i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
2115 		cnf = sk_CONF_VALUE_value(sktmp, i);
2116 		if(OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
2117 			BIO_printf(bio_err, "problem creating object %s=%s\n",
2118 							 cnf->name, cnf->value);
2119 			return 0;
2120 		}
2121 	}
2122 	return 1;
2123 }
2124 
2125 static int do_revoke(X509 *x509, TXT_DB *db)
2126 {
2127 	ASN1_UTCTIME *tm=NULL, *revtm=NULL;
2128 	char *row[DB_NUMBER],**rrow,**irow;
2129 	BIGNUM *bn = NULL;
2130 	int ok=-1,i;
2131 
2132 	for (i=0; i<DB_NUMBER; i++)
2133 		row[i]=NULL;
2134 	row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2135 	bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2136 	row[DB_serial]=BN_bn2hex(bn);
2137 	BN_free(bn);
2138 	if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2139 		{
2140 		BIO_printf(bio_err,"Malloc failure\n");
2141 		goto err;
2142 		}
2143 	/* We have to lookup by serial number because name lookup
2144 	 * skips revoked certs
2145  	 */
2146 	rrow=TXT_DB_get_by_index(db,DB_serial,row);
2147 	if (rrow == NULL)
2148 		{
2149 		BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]);
2150 
2151 		/* We now just add it to the database */
2152 		row[DB_type]=(char *)Malloc(2);
2153 
2154 		tm=X509_get_notAfter(x509);
2155 		row[DB_exp_date]=(char *)Malloc(tm->length+1);
2156 		memcpy(row[DB_exp_date],tm->data,tm->length);
2157 		row[DB_exp_date][tm->length]='\0';
2158 
2159 		row[DB_rev_date]=NULL;
2160 
2161 		/* row[DB_serial] done already */
2162 		row[DB_file]=(char *)Malloc(8);
2163 
2164 		/* row[DB_name] done already */
2165 
2166 		if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2167 			(row[DB_file] == NULL))
2168 			{
2169 			BIO_printf(bio_err,"Malloc failure\n");
2170 			goto err;
2171 			}
2172 		strcpy(row[DB_file],"unknown");
2173 		row[DB_type][0]='V';
2174 		row[DB_type][1]='\0';
2175 
2176 		if ((irow=(char **)Malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2177 			{
2178 			BIO_printf(bio_err,"Malloc 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,irow))
2190 			{
2191 			BIO_printf(bio_err,"failed to update database\n");
2192 			BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2193 			goto err;
2194 			}
2195 
2196 		/* Revoke Certificate */
2197 		ok = do_revoke(x509,db);
2198 
2199 		goto err;
2200 
2201 		}
2202 	else if (index_name_cmp(row,rrow))
2203 		{
2204 		BIO_printf(bio_err,"ERROR:name does not match %s\n",
2205 			   row[DB_name]);
2206 		goto err;
2207 		}
2208 	else if (rrow[DB_type][0]=='R')
2209 		{
2210 		BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2211 			   row[DB_serial]);
2212 		goto err;
2213 		}
2214 	else
2215 		{
2216 		BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2217 		revtm = ASN1_UTCTIME_new();
2218 		revtm=X509_gmtime_adj(revtm,0);
2219 		rrow[DB_type][0]='R';
2220 		rrow[DB_type][1]='\0';
2221 		rrow[DB_rev_date]=(char *)Malloc(revtm->length+1);
2222 		memcpy(rrow[DB_rev_date],revtm->data,revtm->length);
2223 		rrow[DB_rev_date][revtm->length]='\0';
2224 		ASN1_UTCTIME_free(revtm);
2225 		}
2226 	ok=1;
2227 err:
2228 	for (i=0; i<DB_NUMBER; i++)
2229 		{
2230 		if (row[i] != NULL)
2231 			Free(row[i]);
2232 		}
2233 	return(ok);
2234 }
2235 
2236