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