]> git.ipfire.org Git - thirdparty/openssl.git/blame - apps/ca.c
There have been a number of complaints from a number of sources that names
[thirdparty/openssl.git] / apps / ca.c
CommitLineData
d02b48c6 1/* apps/ca.c */
58964a49 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
d02b48c6
RE
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"
ec577822
BM
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>
d02b48c6
RE
77
78#ifndef W_OK
7d7d2cbc
UM
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
d02b48c6
RE
95#endif
96
97#undef PROG
98#define PROG ca_main
99
100#define BASE_SECTION "ca"
d5a2ea4b 101#define CONFIG_FILE "openssl.cnf"
d02b48c6
RE
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"
58964a49 116#define ENV_DEFAULT_STARTDATE "default_startdate"
ed7f60fb 117#define ENV_DEFAULT_ENDDATE "default_enddate"
d02b48c6
RE
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"
1756d405 124#define ENV_CRLEXT "crl_extensions"
d02b48c6
RE
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
141static 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",
9a0f732d
BM
150" -startdate YYMMDDHHMMSSZ - certificate validity notBefore\n",
151" -enddate YYMMDDHHMMSSZ - certificate validity notAfter (overrides -days)\n",
d02b48c6
RE
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",
29d28247 157" -cert file - The CA certificate\n",
d02b48c6
RE
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",
58964a49 163" -ss_cert file - File contains a self signed cert to sign\n",
d02b48c6 164" -preserveDN - Don't re-order the DN\n",
7c7c8851
RE
165" -batch - Don't ask questions\n",
166" -msie_hack - msie modifications to handle all those universal strings\n",
f9a25931 167" -revoke file - Revoke a certificate (given in file)\n",
87a25f90
DSH
168" -extensions .. - Extension section (override value in config file)\n",
169" -crlexts .. - CRL extension section (override value in config file)\n",
d02b48c6
RE
170NULL
171};
172
173#ifdef EFENCE
174extern int EF_PROTECT_FREE;
175extern int EF_PROTECT_BELOW;
176extern int EF_ALIGNMENT;
177#endif
178
a43aa73e 179static int add_oid_section(LHASH *conf);
d02b48c6 180static void lookup_fail(char *name,char *tag);
d02b48c6
RE
181static unsigned long index_serial_hash(char **a);
182static int index_serial_cmp(char **a, char **b);
183static unsigned long index_name_hash(char **a);
184static int index_name_qual(char **a);
185static int index_name_cmp(char **a,char **b);
186static BIGNUM *load_serial(char *serialfile);
187static int save_serial(char *serialfile, BIGNUM *serial);
188static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
ba404b5e 189 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,TXT_DB *db,
ed7f60fb
DSH
190 BIGNUM *serial, char *startdate,char *enddate, int days,
191 int batch, char *ext_sect, LHASH *conf,int verbose);
58964a49 192static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
ba404b5e 193 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
ed7f60fb
DSH
194 TXT_DB *db, BIGNUM *serial,char *startdate,
195 char *enddate, int days, int batch, char *ext_sect,
196 LHASH *conf,int verbose);
d02b48c6 197static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
ba404b5e 198 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
ed7f60fb
DSH
199 TXT_DB *db, BIGNUM *serial,char *startdate,
200 char *enddate, int days, char *ext_sect,LHASH *conf,
201 int verbose);
d02b48c6 202static int fix_data(int nid, int *type);
82fc1d9c 203static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
e778802f 204static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
ba404b5e 205 STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
ed7f60fb
DSH
206 char *startdate, char *enddate, int days, int batch, int verbose,
207 X509_REQ *req, char *ext_sect, LHASH *conf);
f9a25931 208static int do_revoke(X509 *x509, TXT_DB *db);
d02b48c6 209static int check_time_format(char *str);
a32640b0 210static LHASH *conf=NULL;
d02b48c6
RE
211static char *section=NULL;
212
213static int preserve=0;
214static int msie_hack=0;
215
667ac4ec
RE
216int MAIN(int, char **);
217
6b691a5c 218int MAIN(int argc, char **argv)
d02b48c6 219 {
53b1899e 220 char *key=NULL;
d02b48c6
RE
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;
a36a1a51 228 int dorevoke=0;
d02b48c6
RE
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;
58964a49 239 char *ss_cert_file=NULL;
d02b48c6
RE
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;
1756d405 246 char *crl_ext=NULL;
d02b48c6 247 BIGNUM *serial=NULL;
58964a49 248 char *startdate=NULL;
ed7f60fb 249 char *enddate=NULL;
d02b48c6
RE
250 int days=0;
251 int batch=0;
82fc1d9c 252 int notext=0;
d02b48c6
RE
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;
e778802f 264 const EVP_MD *dgst=NULL;
ba404b5e 265 STACK_OF(CONF_VALUE) *attribs=NULL;
b4604683 266 STACK_OF(X509) *cert_sk=NULL;
d02b48c6
RE
267 BIO *hex=NULL;
268#undef BSIZE
269#define BSIZE 256
270 MS_STATIC char buf[3][BSIZE];
95fdc5ee 271 char *randfile=NULL;
d02b48c6
RE
272
273#ifdef EFENCE
274EF_PROTECT_FREE=1;
275EF_PROTECT_BELOW=1;
276EF_ALIGNMENT=0;
277#endif
278
279 apps_startup();
280
a32640b0 281 conf = NULL;
b74ba295
BM
282 key = NULL;
283 section = NULL;
284
d02b48c6 285 preserve=0;
b74ba295 286 msie_hack=0;
d02b48c6
RE
287 if (bio_err == NULL)
288 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
58964a49 289 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
d02b48c6
RE
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 }
58964a49
RE
307 else if (strcmp(*argv,"-startdate") == 0)
308 {
309 if (--argc < 1) goto bad;
310 startdate= *(++argv);
311 }
ed7f60fb
DSH
312 else if (strcmp(*argv,"-enddate") == 0)
313 {
314 if (--argc < 1) goto bad;
315 enddate= *(++argv);
316 }
d02b48c6
RE
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 }
82fc1d9c
DSH
363 else if (strcmp(*argv,"-notext") == 0)
364 notext=1;
d02b48c6
RE
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 }
58964a49
RE
390 else if (strcmp(*argv, "-ss_cert") == 0)
391 {
392 if (--argc < 1) goto bad;
393 ss_cert_file = *(++argv);
394 req=1;
395 }
d02b48c6
RE
396 else if (strcmp(*argv, "-spkac") == 0)
397 {
398 if (--argc < 1) goto bad;
399 spkac_file = *(++argv);
400 req=1;
401 }
f9a25931
RE
402 else if (strcmp(*argv,"-revoke") == 0)
403 {
404 if (--argc < 1) goto bad;
405 infile= *(++argv);
a36a1a51 406 dorevoke=1;
f9a25931 407 }
87a25f90
DSH
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 }
d02b48c6
RE
418 else
419 {
420bad:
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 /*****************************************************************/
e40b7abe
DSH
439 if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
440 if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
d02b48c6
RE
441 if (configfile == NULL)
442 {
443 /* We will just use 'buf[0]' as a temporary buffer. */
7d7d2cbc
UM
444#ifdef VMS
445 strncpy(buf[0],X509_get_default_cert_area(),
446 sizeof(buf[0])-1-sizeof(CONFIG_FILE));
447#else
d02b48c6
RE
448 strncpy(buf[0],X509_get_default_cert_area(),
449 sizeof(buf[0])-2-sizeof(CONFIG_FILE));
450 strcat(buf[0],"/");
7d7d2cbc 451#endif
d02b48c6
RE
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
dfeab068
RE
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 */
c106c613 493 ERR_clear_error();
dfeab068
RE
494 }
495 else
496 {
497 OBJ_create_objects(oid_bio);
498 BIO_free(oid_bio);
499 }
500 }
a31011e8
BM
501 if(!add_oid_section(conf))
502 {
a43aa73e
DSH
503 ERR_print_errors(bio_err);
504 goto err;
a31011e8 505 }
a43aa73e 506 }
dfeab068 507
a31011e8
BM
508 randfile = CONF_get_string(conf, BASE_SECTION, "RANDFILE");
509 app_RAND_load_file(randfile, bio_err, 0);
510
d02b48c6
RE
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 /*****************************************************************/
657e60fa 522 /* we definitely need an public key, so lets get it */
d02b48c6
RE
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 }
a3fe382e 536 pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,key);
36217a94 537 if(key) memset(key,0,strlen(key));
d02b48c6
RE
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 }
74678cc2 558 x509=PEM_read_bio_X509(in,NULL,NULL,NULL);
d02b48c6
RE
559 if (x509 == NULL)
560 {
561 BIO_printf(bio_err,"unable to load CA certificate\n");
562 goto err;
563 }
564
dfeab068
RE
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
d02b48c6
RE
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 }
207c7df7
RL
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 */
d02b48c6
RE
600 if (access(outdir,R_OK|W_OK|X_OK) != 0)
601 {
657e60fa 602 BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
d02b48c6
RE
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 }
79875776 613#ifdef S_IFDIR
d02b48c6
RE
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 }
cb464c38 620#endif
79875776 621#endif
d02b48c6
RE
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 }
b1c4fe36 631 if (BIO_read_filename(in,dbfile) <= 0)
d02b48c6
RE
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 {
7c7c8851 647 BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
d02b48c6
RE
648 goto err;
649 }
650 if ((pp[DB_type][0] == DB_TYPE_REV) &&
651 !check_time_format(pp[DB_rev_date]))
652 {
7c7c8851 653 BIO_printf(bio_err,"entry %d: invalid revocation date\n",
d02b48c6
RE
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 {
58964a49 683 BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
d02b48c6
RE
684 TXT_DB_write(out,db);
685 BIO_printf(bio_err,"%d entries loaded from the database\n",
686 db->data->num);
657e60fa 687 BIO_printf(bio_err,"generating index\n");
d02b48c6
RE
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
58964a49 718 BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
d02b48c6
RE
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 }
87a25f90
DSH
752 if(!extensions)
753 extensions=CONF_get_string(conf,section,ENV_EXTENSIONS);
7ec218eb 754 if(extensions) {
b2347661 755 /* Check syntax of file */
41b731f2
DSH
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)) {
b2347661
DSH
760 BIO_printf(bio_err,
761 "Error Loading extension section %s\n",
762 extensions);
aa066b9e 763 ret = 1;
d02b48c6
RE
764 goto err;
765 }
b2347661 766 }
d02b48c6 767
58964a49
RE
768 if (startdate == NULL)
769 {
ed7f60fb 770 startdate=CONF_get_string(conf,section,
58964a49 771 ENV_DEFAULT_STARTDATE);
ed7f60fb
DSH
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;
58964a49
RE
789 }
790
d02b48c6
RE
791 if (days == 0)
792 {
793 days=(int)CONF_get_number(conf,section,
794 ENV_DEFAULT_DAYS);
795 }
ed7f60fb 796 if (!enddate && (days == 0))
d02b48c6
RE
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 {
dfeab068 809 if ((f=BN_bn2hex(serial)) == NULL) goto err;
d02b48c6 810 BIO_printf(bio_err,"next serial number is %s\n",f);
26a3a48d 811 OPENSSL_free(f);
d02b48c6
RE
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
b4604683 820 if ((cert_sk=sk_X509_new_null()) == NULL)
d02b48c6 821 {
26a3a48d 822 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
823 goto err;
824 }
825 if (spkac_file != NULL)
826 {
827 total++;
828 j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
ed7f60fb
DSH
829 serial,startdate,enddate, days,extensions,conf,
830 verbose);
d02b48c6
RE
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;
b4604683 837 if (!sk_X509_push(cert_sk,x))
d02b48c6 838 {
26a3a48d 839 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
840 goto err;
841 }
842 if (outfile)
843 {
844 output_der = 1;
845 batch = 1;
846 }
847 }
848 }
58964a49
RE
849 if (ss_cert_file != NULL)
850 {
851 total++;
852 j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
ed7f60fb 853 db,serial,startdate,enddate,days,batch,
b2347661 854 extensions,conf,verbose);
58964a49
RE
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;
b4604683 861 if (!sk_X509_push(cert_sk,x))
58964a49 862 {
26a3a48d 863 BIO_printf(bio_err,"Memory allocation failure\n");
58964a49
RE
864 goto err;
865 }
866 }
867 }
d02b48c6
RE
868 if (infile != NULL)
869 {
870 total++;
871 j=certify(&x,infile,pkey,x509,dgst,attribs,db,
ed7f60fb 872 serial,startdate,enddate,days,batch,
b2347661 873 extensions,conf,verbose);
d02b48c6
RE
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;
b4604683 880 if (!sk_X509_push(cert_sk,x))
d02b48c6 881 {
26a3a48d 882 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
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,
ed7f60fb 891 serial,startdate,enddate,days,batch,
b2347661 892 extensions,conf,verbose);
d02b48c6
RE
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;
b4604683 899 if (!sk_X509_push(cert_sk,x))
d02b48c6 900 {
26a3a48d 901 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
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
b4604683 910 if (sk_X509_num(cert_sk) > 0)
d02b48c6
RE
911 {
912 if (!batch)
913 {
914 BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
d58d092b 915 (void)BIO_flush(bio_err);
d02b48c6
RE
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
b4604683 926 BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
d02b48c6
RE
927
928 strncpy(buf[0],serialfile,BSIZE-4);
7d7d2cbc
UM
929
930#ifdef VMS
931 strcat(buf[0],"-new");
932#else
d02b48c6 933 strcat(buf[0],".new");
7d7d2cbc 934#endif
d02b48c6
RE
935
936 if (!save_serial(buf[0],serial)) goto err;
937
938 strncpy(buf[1],dbfile,BSIZE-4);
7d7d2cbc
UM
939
940#ifdef VMS
941 strcat(buf[1],"-new");
942#else
d02b48c6 943 strcat(buf[1],".new");
7d7d2cbc
UM
944#endif
945
d02b48c6
RE
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");
b4604683 958 for (i=0; i<sk_X509_num(cert_sk); i++)
d02b48c6
RE
959 {
960 int k;
961 unsigned char *n;
962
b4604683 963 x=sk_X509_value(cert_sk,i);
d02b48c6
RE
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);
7d7d2cbc
UM
969
970#ifndef VMS
d02b48c6 971 strcat(buf[2],"/");
7d7d2cbc
UM
972#endif
973
d02b48c6
RE
974 n=(unsigned char *)&(buf[2][strlen(buf[2])]);
975 if (j > 0)
976 {
977 for (k=0; k<j; k++)
978 {
58964a49 979 sprintf((char *)n,"%02X",(unsigned char)*(p++));
d02b48c6
RE
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 }
82fc1d9c
DSH
998 write_new_certificate(Cout,x, 0, notext);
999 write_new_certificate(Sout,x, output_der, notext);
d02b48c6
RE
1000 }
1001
b4604683 1002 if (sk_X509_num(cert_sk))
d02b48c6
RE
1003 {
1004 /* Rename the database and the serial file */
1005 strncpy(buf[2],serialfile,BSIZE-4);
7d7d2cbc
UM
1006
1007#ifdef VMS
1008 strcat(buf[2],"-old");
1009#else
d02b48c6 1010 strcat(buf[2],".old");
7d7d2cbc
UM
1011#endif
1012
d02b48c6
RE
1013 BIO_free(in);
1014 BIO_free(out);
1015 in=NULL;
1016 out=NULL;
1017 if (rename(serialfile,buf[2]) < 0)
1018 {
657e60fa 1019 BIO_printf(bio_err,"unable to rename %s to %s\n",
d02b48c6
RE
1020 serialfile,buf[2]);
1021 perror("reason");
1022 goto err;
1023 }
1024 if (rename(buf[0],serialfile) < 0)
1025 {
657e60fa 1026 BIO_printf(bio_err,"unable to rename %s to %s\n",
d02b48c6
RE
1027 buf[0],serialfile);
1028 perror("reason");
1029 rename(buf[2],serialfile);
1030 goto err;
1031 }
1032
1033 strncpy(buf[2],dbfile,BSIZE-4);
7d7d2cbc
UM
1034
1035#ifdef VMS
1036 strcat(buf[2],"-old");
1037#else
d02b48c6 1038 strcat(buf[2],".old");
7d7d2cbc
UM
1039#endif
1040
d02b48c6
RE
1041 if (rename(dbfile,buf[2]) < 0)
1042 {
657e60fa 1043 BIO_printf(bio_err,"unable to rename %s to %s\n",
d02b48c6
RE
1044 dbfile,buf[2]);
1045 perror("reason");
1046 goto err;
1047 }
1048 if (rename(buf[1],dbfile) < 0)
1049 {
657e60fa 1050 BIO_printf(bio_err,"unable to rename %s to %s\n",
d02b48c6
RE
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 {
87a25f90 1063 if(!crl_ext) crl_ext=CONF_get_string(conf,section,ENV_CRLEXT);
1756d405
DSH
1064 if(crl_ext) {
1065 /* Check syntax of file */
41b731f2
DSH
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)) {
1756d405
DSH
1070 BIO_printf(bio_err,
1071 "Error Loading CRL extension section %s\n",
1072 crl_ext);
1073 ret = 1;
1074 goto err;
1075 }
1076 }
d02b48c6
RE
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);
58964a49
RE
1100 if (ci->nextUpdate == NULL)
1101 ci->nextUpdate=ASN1_UTCTIME_new();
d02b48c6
RE
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
d58d092b 1116 (void)BIO_reset(hex);
d02b48c6
RE
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
ee8ba0b2 1122 sk_X509_REVOKED_push(ci->revoked,r);
d02b48c6
RE
1123 }
1124 }
1125 /* sort the data so it will be written in serial
1126 * number order */
ee8ba0b2
BL
1127 sk_X509_REVOKED_sort(ci->revoked);
1128 for (i=0; i<sk_X509_REVOKED_num(ci->revoked); i++)
d02b48c6 1129 {
ee8ba0b2 1130 r=sk_X509_REVOKED_value(ci->revoked,i);
d02b48c6
RE
1131 r->sequence=i;
1132 }
1133
13e91dd3 1134 /* we now have a CRL */
d02b48c6
RE
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
512d2228 1145 {
13e91dd3 1146#ifndef NO_DSA
512d2228
BL
1147 if (pkey->type == EVP_PKEY_DSA)
1148 dgst=EVP_dss1();
1149 else
13e91dd3 1150#endif
512d2228
BL
1151 dgst=EVP_md5();
1152 }
1153
1756d405
DSH
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 */
1d48dd00
DSH
1161 X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1162 X509V3_set_conf_lhash(&crlctx, conf);
1756d405
DSH
1163
1164 if(!X509V3_EXT_CRL_add_conf(conf, &crlctx,
1165 crl_ext, crl)) goto err;
1166 }
1167
d02b48c6
RE
1168 if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1169
1170 PEM_write_bio_X509_CRL(Sout,crl);
1171 }
1172 /*****************************************************************/
a36a1a51 1173 if (dorevoke)
f9a25931 1174 {
b1c4fe36
BM
1175 if (infile == NULL)
1176 {
1177 BIO_printf(bio_err,"no input files\n");
1178 goto err;
1179 }
f9a25931
RE
1180 else
1181 {
a0ad17bb 1182 X509 *revcert;
b1c4fe36
BM
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 }
a0ad17bb
DSH
1189 revcert=PEM_read_bio_X509(in,NULL,NULL,NULL);
1190 if (revcert == NULL)
b1c4fe36
BM
1191 {
1192 BIO_printf(bio_err,"unable to load '%s' certificate\n",infile);
f9a25931 1193 goto err;
b1c4fe36 1194 }
a0ad17bb
DSH
1195 j=do_revoke(revcert,db);
1196 if (j <= 0) goto err;
1197 X509_free(revcert);
f9a25931
RE
1198
1199 strncpy(buf[0],dbfile,BSIZE-4);
b1c4fe36
BM
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;
b1c4fe36
BM
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 }
f9a25931
RE
1226 }
1227 /*****************************************************************/
d02b48c6
RE
1228 ret=0;
1229err:
a43aa73e
DSH
1230 BIO_free(hex);
1231 BIO_free(Cout);
1232 BIO_free(Sout);
1233 BIO_free(out);
1234 BIO_free(in);
d02b48c6 1235
b4604683 1236 sk_X509_pop_free(cert_sk,X509_free);
d02b48c6
RE
1237
1238 if (ret) ERR_print_errors(bio_err);
a31011e8 1239 app_RAND_write_file(randfile, bio_err);
a43aa73e
DSH
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);
a43aa73e 1246 OBJ_cleanup();
d02b48c6
RE
1247 EXIT(ret);
1248 }
1249
6b691a5c 1250static void lookup_fail(char *name, char *tag)
d02b48c6
RE
1251 {
1252 BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1253 }
1254
6b691a5c 1255static unsigned long index_serial_hash(char **a)
d02b48c6
RE
1256 {
1257 char *n;
1258
1259 n=a[DB_serial];
1260 while (*n == '0') n++;
1261 return(lh_strhash(n));
1262 }
1263
6b691a5c 1264static int index_serial_cmp(char **a, char **b)
d02b48c6
RE
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
6b691a5c 1273static unsigned long index_name_hash(char **a)
d02b48c6
RE
1274 { return(lh_strhash(a[DB_name])); }
1275
6b691a5c 1276static int index_name_qual(char **a)
d02b48c6
RE
1277 { return(a[0][0] == 'V'); }
1278
6b691a5c
UM
1279static int index_name_cmp(char **a, char **b)
1280 { return(strcmp(a[DB_name],
1281 b[DB_name])); }
d02b48c6 1282
6b691a5c 1283static BIGNUM *load_serial(char *serialfile)
d02b48c6
RE
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 }
1315err:
1316 if (in != NULL) BIO_free(in);
1317 if (ai != NULL) ASN1_INTEGER_free(ai);
1318 return(ret);
1319 }
1320
6b691a5c 1321static int save_serial(char *serialfile, BIGNUM *serial)
d02b48c6
RE
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;
1347err:
1348 if (out != NULL) BIO_free(out);
1349 if (ai != NULL) ASN1_INTEGER_free(ai);
1350 return(ret);
1351 }
1352
6b691a5c 1353static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
ba404b5e 1354 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
ed7f60fb
DSH
1355 BIGNUM *serial, char *startdate, char *enddate, int days,
1356 int batch, char *ext_sect, LHASH *lconf, int verbose)
d02b48c6
RE
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 }
74678cc2 1370 if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
d02b48c6
RE
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
d02b48c6
RE
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);
10061c7c 1387 EVP_PKEY_free(pktmp);
d02b48c6
RE
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
ed7f60fb 1403 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate, enddate,
08853ba8 1404 days,batch,verbose,req,ext_sect,lconf);
d02b48c6
RE
1405
1406err:
1407 if (req != NULL) X509_REQ_free(req);
1408 if (in != NULL) BIO_free(in);
1409 return(ok);
1410 }
1411
6b691a5c 1412static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
ba404b5e 1413 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
ed7f60fb
DSH
1414 BIGNUM *serial, char *startdate, char *enddate, int days,
1415 int batch, char *ext_sect, LHASH *lconf, int verbose)
58964a49
RE
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 }
74678cc2 1430 if ((req=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
58964a49
RE
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);
10061c7c 1446 EVP_PKEY_free(pktmp);
58964a49
RE
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;
dfeab068 1456 BIO_printf(bio_err,"Signature did not match the certificate\n");
58964a49
RE
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
ed7f60fb 1465 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,days,
08853ba8 1466 batch,verbose,rreq,ext_sect,lconf);
58964a49
RE
1467
1468err:
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
6b691a5c 1475static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
ba404b5e 1476 STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
ed7f60fb
DSH
1477 char *startdate, char *enddate, int days, int batch, int verbose,
1478 X509_REQ *req, char *ext_sect, LHASH *lconf)
d02b48c6
RE
1479 {
1480 X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
58964a49 1481 ASN1_UTCTIME *tm,*tmptm;
d02b48c6
RE
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;
d02b48c6
RE
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
58964a49
RE
1495 tmptm=ASN1_UTCTIME_new();
1496 if (tmptm == NULL)
1497 {
1498 BIO_printf(bio_err,"malloc error\n");
1499 return(0);
1500 }
1501
d02b48c6
RE
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 {
26a3a48d 1583 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
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
ba404b5e 1592 for (i=0; i<sk_CONF_VALUE_num(policy); i++)
d02b48c6 1593 {
ba404b5e 1594 cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
d02b48c6
RE
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
1647again2:
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 {
c6125200 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));
d02b48c6
RE
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 {
74400f73 1677 if (!X509_NAME_add_entry(subject,push, -1, 0))
d02b48c6
RE
1678 {
1679 if (push != NULL)
1680 X509_NAME_ENTRY_free(push);
26a3a48d 1681 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
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)
657e60fa 1697 BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
d02b48c6
RE
1698
1699 row[DB_name]=X509_NAME_oneline(subject,NULL,0);
dfeab068 1700 row[DB_serial]=BN_bn2hex(serial);
d02b48c6
RE
1701 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
1702 {
26a3a48d 1703 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
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";
b1c4fe36 1736 BIO_printf(bio_err,"Type :%s\n",p);;
d02b48c6
RE
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
657e60fa 1754 /* We are now totally happy, lets make and sign the certificate */
d02b48c6
RE
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 ");
58964a49 1772 if (strcmp(startdate,"today") == 0)
58964a49 1773 X509_gmtime_adj(X509_get_notBefore(ret),0);
ed7f60fb
DSH
1774 else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
1775
1776 if (enddate == NULL)
58964a49 1777 X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
ed7f60fb
DSH
1778 else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
1779
d02b48c6 1780 ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
ed7f60fb
DSH
1781 if(days) BIO_printf(bio_err," (%d days)",days);
1782 BIO_printf(bio_err, "\n");
d02b48c6
RE
1783
1784 if (!X509_set_subject_name(ret,subject)) goto err;
1785
1786 pktmp=X509_REQ_get_pubkey(req);
10061c7c
DSH
1787 i = X509_set_pubkey(ret,pktmp);
1788 EVP_PKEY_free(pktmp);
1789 if (!i) goto err;
d02b48c6
RE
1790
1791 /* Lets add the extensions, if there are any */
b2347661 1792 if (ext_sect)
d02b48c6 1793 {
175b0942 1794 X509V3_CTX ctx;
d02b48c6
RE
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
657e60fa 1801 * be any I believe */
d02b48c6 1802 if (ci->extensions != NULL)
0b3f827c
BL
1803 sk_X509_EXTENSION_pop_free(ci->extensions,
1804 X509_EXTENSION_free);
d02b48c6 1805
b2347661
DSH
1806 ci->extensions = NULL;
1807
1d48dd00
DSH
1808 X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
1809 X509V3_set_conf_lhash(&ctx, lconf);
175b0942 1810
08853ba8 1811 if(!X509V3_EXT_add_conf(lconf, &ctx, ext_sect, ret)) goto err;
d02b48c6 1812
d02b48c6
RE
1813 }
1814
1815
1816 if (!batch)
1817 {
1818 BIO_printf(bio_err,"Sign the certificate? [y/n]:");
d58d092b 1819 (void)BIO_flush(bio_err);
d02b48c6
RE
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
dfeab068 1830
d02b48c6 1831#ifndef NO_DSA
c35f549e 1832 if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
b1c4fe36
BM
1833 pktmp=X509_get_pubkey(ret);
1834 if (EVP_PKEY_missing_parameters(pktmp) &&
d02b48c6
RE
1835 !EVP_PKEY_missing_parameters(pkey))
1836 EVP_PKEY_copy_parameters(pktmp,pkey);
10061c7c 1837 EVP_PKEY_free(pktmp);
d02b48c6
RE
1838#endif
1839
1840 if (!X509_sign(ret,pkey,dgst))
1841 goto err;
1842
1843 /* We now just add it to the database */
26a3a48d 1844 row[DB_type]=(char *)OPENSSL_malloc(2);
d02b48c6
RE
1845
1846 tm=X509_get_notAfter(ret);
26a3a48d 1847 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
d02b48c6
RE
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 */
26a3a48d 1854 row[DB_file]=(char *)OPENSSL_malloc(8);
d02b48c6
RE
1855 /* row[DB_name] done already */
1856
1857 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
1858 (row[DB_file] == NULL))
1859 {
26a3a48d 1860 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
1861 goto err;
1862 }
1863 strcpy(row[DB_file],"unknown");
1864 row[DB_type][0]='V';
1865 row[DB_type][1]='\0';
1866
26a3a48d 1867 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
d02b48c6 1868 {
26a3a48d 1869 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
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;
1887err:
1888 for (i=0; i<DB_NUMBER; i++)
26a3a48d 1889 if (row[i] != NULL) OPENSSL_free(row[i]);
d02b48c6
RE
1890
1891 if (CAname != NULL)
1892 X509_NAME_free(CAname);
1893 if (subject != NULL)
1894 X509_NAME_free(subject);
79875776
BM
1895 if (tmptm != NULL)
1896 ASN1_UTCTIME_free(tmptm);
d02b48c6
RE
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
82fc1d9c 1907static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
d02b48c6 1908 {
d02b48c6
RE
1909
1910 if (output_der)
1911 {
1912 (void)i2d_X509_bio(bp,x);
1913 return;
1914 }
82fc1d9c
DSH
1915#if 0
1916 /* ??? Not needed since X509_print prints all this stuff anyway */
d02b48c6
RE
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");
82fc1d9c
DSH
1926#endif
1927 if(!notext)X509_print(bp,x);
d02b48c6 1928 PEM_write_bio_X509(bp,x);
d02b48c6
RE
1929 }
1930
6b691a5c 1931static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
ba404b5e 1932 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
ed7f60fb
DSH
1933 BIGNUM *serial, char *startdate, char *enddate, int days,
1934 char *ext_sect, LHASH *lconf, int verbose)
d02b48c6 1935 {
ba404b5e 1936 STACK_OF(CONF_VALUE) *sk=NULL;
d02b48c6
RE
1937 LHASH *parms=NULL;
1938 X509_REQ *req=NULL;
1939 CONF_VALUE *cv=NULL;
1940 NETSCAPE_SPKI *spki = NULL;
d02b48c6
RE
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");
ba404b5e 1964 if (sk_CONF_VALUE_num(sk) == 0)
d02b48c6
RE
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 {
ba404b5e 1993 if (sk_CONF_VALUE_num(sk) <= i) break;
d02b48c6 1994
ba404b5e 1995 cv=sk_CONF_VALUE_value(sk,i);
d02b48c6 1996 type=cv->name;
f9150e54
DSH
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 }
d02b48c6 2006
f9150e54 2007 buf=cv->value;
d02b48c6
RE
2008 if ((nid=OBJ_txt2nid(type)) == NID_undef)
2009 {
2010 if (strcmp(type, "SPKAC") == 0)
2011 {
8ce97163 2012 spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
d02b48c6
RE
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
74400f73 2036 if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
d02b48c6
RE
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
8ce97163 2051 if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
d02b48c6
RE
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);
10061c7c 2066 EVP_PKEY_free(pktmp);
ed7f60fb 2067 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,
08853ba8 2068 days,1,verbose,req,ext_sect,lconf);
d02b48c6
RE
2069err:
2070 if (req != NULL) X509_REQ_free(req);
2071 if (parms != NULL) CONF_free(parms);
d02b48c6
RE
2072 if (spki != NULL) NETSCAPE_SPKI_free(spki);
2073 if (ne != NULL) X509_NAME_ENTRY_free(ne);
2074
2075 return(ok);
2076 }
2077
6b691a5c 2078static int fix_data(int nid, int *type)
d02b48c6
RE
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
6b691a5c 2093static int check_time_format(char *str)
d02b48c6
RE
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
6b691a5c 2103static int add_oid_section(LHASH *hconf)
a43aa73e
DSH
2104{
2105 char *p;
ba404b5e 2106 STACK_OF(CONF_VALUE) *sktmp;
a43aa73e
DSH
2107 CONF_VALUE *cnf;
2108 int i;
15799403
BL
2109 if(!(p=CONF_get_string(hconf,NULL,"oid_section"))) return 1;
2110 if(!(sktmp = CONF_get_section(hconf, p))) {
a43aa73e
DSH
2111 BIO_printf(bio_err, "problem loading oid section %s\n", p);
2112 return 0;
2113 }
ba404b5e
DSH
2114 for(i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
2115 cnf = sk_CONF_VALUE_value(sktmp, i);
a43aa73e
DSH
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}
f9a25931 2124
6b691a5c 2125static int do_revoke(X509 *x509, TXT_DB *db)
f9a25931 2126{
a0ad17bb 2127 ASN1_UTCTIME *tm=NULL, *revtm=NULL;
b1c4fe36 2128 char *row[DB_NUMBER],**rrow,**irow;
a0ad17bb 2129 BIGNUM *bn = NULL;
b1c4fe36
BM
2130 int ok=-1,i;
2131
2132 for (i=0; i<DB_NUMBER; i++)
2133 row[i]=NULL;
a0ad17bb
DSH
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);
b1c4fe36
BM
2138 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2139 {
26a3a48d 2140 BIO_printf(bio_err,"Memory allocation failure\n");
b1c4fe36
BM
2141 goto err;
2142 }
a0ad17bb
DSH
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);
b1c4fe36
BM
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 */
26a3a48d 2152 row[DB_type]=(char *)OPENSSL_malloc(2);
b1c4fe36
BM
2153
2154 tm=X509_get_notAfter(x509);
26a3a48d 2155 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
b1c4fe36
BM
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 */
26a3a48d 2162 row[DB_file]=(char *)OPENSSL_malloc(8);
b1c4fe36
BM
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 {
26a3a48d 2169 BIO_printf(bio_err,"Memory allocation failure\n");
b1c4fe36
BM
2170 goto err;
2171 }
2172 strcpy(row[DB_file],"unknown");
2173 row[DB_type][0]='V';
2174 row[DB_type][1]='\0';
2175
26a3a48d 2176 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
b1c4fe36 2177 {
26a3a48d 2178 BIO_printf(bio_err,"Memory allocation failure\n");
b1c4fe36
BM
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 */
a0ad17bb 2197 ok = do_revoke(x509,db);
b1c4fe36 2198
b1c4fe36
BM
2199 goto err;
2200
2201 }
a0ad17bb 2202 else if (index_name_cmp(row,rrow))
b1c4fe36 2203 {
a0ad17bb
DSH
2204 BIO_printf(bio_err,"ERROR:name does not match %s\n",
2205 row[DB_name]);
b1c4fe36
BM
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]);
a0ad17bb
DSH
2217 revtm = ASN1_UTCTIME_new();
2218 revtm=X509_gmtime_adj(revtm,0);
b1c4fe36
BM
2219 rrow[DB_type][0]='R';
2220 rrow[DB_type][1]='\0';
26a3a48d 2221 rrow[DB_rev_date]=(char *)OPENSSL_malloc(revtm->length+1);
a0ad17bb
DSH
2222 memcpy(rrow[DB_rev_date],revtm->data,revtm->length);
2223 rrow[DB_rev_date][revtm->length]='\0';
2224 ASN1_UTCTIME_free(revtm);
b1c4fe36
BM
2225 }
2226 ok=1;
f9a25931 2227err:
b1c4fe36
BM
2228 for (i=0; i<DB_NUMBER; i++)
2229 {
2230 if (row[i] != NULL)
26a3a48d 2231 OPENSSL_free(row[i]);
b1c4fe36 2232 }
b1c4fe36 2233 return(ok);
f9a25931
RE
2234}
2235