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