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