]> git.ipfire.org Git - thirdparty/openssl.git/blame - apps/ca.c
Fix inconsistencies in the Darwin targets.
[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 {
dfeab068 1161 if ((f=BN_bn2hex(serial)) == NULL) goto err;
d02b48c6 1162 BIO_printf(bio_err,"next serial number is %s\n",f);
26a3a48d 1163 OPENSSL_free(f);
d02b48c6
RE
1164 }
1165
b7a26e6d 1166 if ((attribs=NCONF_get_section(conf,policy)) == NULL)
d02b48c6
RE
1167 {
1168 BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
1169 goto err;
1170 }
1171
b4604683 1172 if ((cert_sk=sk_X509_new_null()) == NULL)
d02b48c6 1173 {
26a3a48d 1174 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
1175 goto err;
1176 }
1177 if (spkac_file != NULL)
1178 {
1179 total++;
1180 j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
89da653f
BM
1181 serial,subj,email_dn,startdate,enddate,days,extensions,
1182 conf,verbose,certopt,nameopt,default_op,ext_copy);
d02b48c6
RE
1183 if (j < 0) goto err;
1184 if (j > 0)
1185 {
1186 total_done++;
1187 BIO_printf(bio_err,"\n");
1188 if (!BN_add_word(serial,1)) goto err;
b4604683 1189 if (!sk_X509_push(cert_sk,x))
d02b48c6 1190 {
26a3a48d 1191 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
1192 goto err;
1193 }
1194 if (outfile)
1195 {
1196 output_der = 1;
1197 batch = 1;
1198 }
1199 }
1200 }
58964a49
RE
1201 if (ss_cert_file != NULL)
1202 {
1203 total++;
1204 j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
89da653f 1205 db,serial,subj,email_dn,startdate,enddate,days,batch,
535d79da 1206 extensions,conf,verbose, certopt, nameopt,
ce16450a 1207 default_op, ext_copy, e);
58964a49
RE
1208 if (j < 0) goto err;
1209 if (j > 0)
1210 {
1211 total_done++;
1212 BIO_printf(bio_err,"\n");
1213 if (!BN_add_word(serial,1)) goto err;
b4604683 1214 if (!sk_X509_push(cert_sk,x))
58964a49 1215 {
26a3a48d 1216 BIO_printf(bio_err,"Memory allocation failure\n");
58964a49
RE
1217 goto err;
1218 }
1219 }
1220 }
d02b48c6
RE
1221 if (infile != NULL)
1222 {
1223 total++;
1224 j=certify(&x,infile,pkey,x509,dgst,attribs,db,
89da653f 1225 serial,subj,email_dn,startdate,enddate,days,batch,
535d79da
DSH
1226 extensions,conf,verbose, certopt, nameopt,
1227 default_op, ext_copy);
d02b48c6
RE
1228 if (j < 0) goto err;
1229 if (j > 0)
1230 {
1231 total_done++;
1232 BIO_printf(bio_err,"\n");
1233 if (!BN_add_word(serial,1)) goto err;
b4604683 1234 if (!sk_X509_push(cert_sk,x))
d02b48c6 1235 {
26a3a48d 1236 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
1237 goto err;
1238 }
1239 }
1240 }
1241 for (i=0; i<argc; i++)
1242 {
1243 total++;
1244 j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
89da653f 1245 serial,subj,email_dn,startdate,enddate,days,batch,
535d79da
DSH
1246 extensions,conf,verbose, certopt, nameopt,
1247 default_op, ext_copy);
d02b48c6
RE
1248 if (j < 0) goto err;
1249 if (j > 0)
1250 {
1251 total_done++;
1252 BIO_printf(bio_err,"\n");
1253 if (!BN_add_word(serial,1)) goto err;
b4604683 1254 if (!sk_X509_push(cert_sk,x))
d02b48c6 1255 {
26a3a48d 1256 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
1257 goto err;
1258 }
1259 }
1260 }
1261 /* we have a stack of newly certified certificates
1262 * and a data base and serial number that need
1263 * updating */
1264
b4604683 1265 if (sk_X509_num(cert_sk) > 0)
d02b48c6
RE
1266 {
1267 if (!batch)
1268 {
1269 BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
d58d092b 1270 (void)BIO_flush(bio_err);
d02b48c6
RE
1271 buf[0][0]='\0';
1272 fgets(buf[0],10,stdin);
1273 if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
1274 {
1275 BIO_printf(bio_err,"CERTIFICATION CANCELED\n");
1276 ret=0;
1277 goto err;
1278 }
1279 }
1280
b4604683 1281 BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
d02b48c6
RE
1282
1283 strncpy(buf[0],serialfile,BSIZE-4);
26414ee0 1284 buf[0][BSIZE-4]='\0';
7d7d2cbc 1285
bc36ee62 1286#ifdef OPENSSL_SYS_VMS
7d7d2cbc
UM
1287 strcat(buf[0],"-new");
1288#else
d02b48c6 1289 strcat(buf[0],".new");
7d7d2cbc 1290#endif
d02b48c6
RE
1291
1292 if (!save_serial(buf[0],serial)) goto err;
1293
1294 strncpy(buf[1],dbfile,BSIZE-4);
26414ee0 1295 buf[1][BSIZE-4]='\0';
7d7d2cbc 1296
bc36ee62 1297#ifdef OPENSSL_SYS_VMS
7d7d2cbc
UM
1298 strcat(buf[1],"-new");
1299#else
d02b48c6 1300 strcat(buf[1],".new");
7d7d2cbc
UM
1301#endif
1302
d02b48c6
RE
1303 if (BIO_write_filename(out,buf[1]) <= 0)
1304 {
1305 perror(dbfile);
1306 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1307 goto err;
1308 }
1309 l=TXT_DB_write(out,db);
1310 if (l <= 0) goto err;
1311 }
1312
1313 if (verbose)
1314 BIO_printf(bio_err,"writing new certificates\n");
b4604683 1315 for (i=0; i<sk_X509_num(cert_sk); i++)
d02b48c6
RE
1316 {
1317 int k;
1318 unsigned char *n;
1319
b4604683 1320 x=sk_X509_value(cert_sk,i);
d02b48c6
RE
1321
1322 j=x->cert_info->serialNumber->length;
1323 p=(char *)x->cert_info->serialNumber->data;
1324
1325 strncpy(buf[2],outdir,BSIZE-(j*2)-6);
26414ee0 1326 buf[2][BSIZE-(j*2)-6]='\0';
7d7d2cbc 1327
bc36ee62 1328#ifndef OPENSSL_SYS_VMS
d02b48c6 1329 strcat(buf[2],"/");
7d7d2cbc
UM
1330#endif
1331
d02b48c6
RE
1332 n=(unsigned char *)&(buf[2][strlen(buf[2])]);
1333 if (j > 0)
1334 {
1335 for (k=0; k<j; k++)
1336 {
58964a49 1337 sprintf((char *)n,"%02X",(unsigned char)*(p++));
d02b48c6
RE
1338 n+=2;
1339 }
1340 }
1341 else
1342 {
1343 *(n++)='0';
1344 *(n++)='0';
1345 }
1346 *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
1347 *n='\0';
1348 if (verbose)
1349 BIO_printf(bio_err,"writing %s\n",buf[2]);
1350
1351 if (BIO_write_filename(Cout,buf[2]) <= 0)
1352 {
1353 perror(buf[2]);
1354 goto err;
1355 }
82fc1d9c
DSH
1356 write_new_certificate(Cout,x, 0, notext);
1357 write_new_certificate(Sout,x, output_der, notext);
d02b48c6
RE
1358 }
1359
b4604683 1360 if (sk_X509_num(cert_sk))
d02b48c6
RE
1361 {
1362 /* Rename the database and the serial file */
1363 strncpy(buf[2],serialfile,BSIZE-4);
26414ee0 1364 buf[2][BSIZE-4]='\0';
7d7d2cbc 1365
bc36ee62 1366#ifdef OPENSSL_SYS_VMS
7d7d2cbc
UM
1367 strcat(buf[2],"-old");
1368#else
d02b48c6 1369 strcat(buf[2],".old");
7d7d2cbc
UM
1370#endif
1371
d02b48c6 1372 BIO_free(in);
645749ef 1373 BIO_free_all(out);
d02b48c6
RE
1374 in=NULL;
1375 out=NULL;
1376 if (rename(serialfile,buf[2]) < 0)
1377 {
657e60fa 1378 BIO_printf(bio_err,"unable to rename %s to %s\n",
d02b48c6
RE
1379 serialfile,buf[2]);
1380 perror("reason");
1381 goto err;
1382 }
1383 if (rename(buf[0],serialfile) < 0)
1384 {
657e60fa 1385 BIO_printf(bio_err,"unable to rename %s to %s\n",
d02b48c6
RE
1386 buf[0],serialfile);
1387 perror("reason");
1388 rename(buf[2],serialfile);
1389 goto err;
1390 }
1391
1392 strncpy(buf[2],dbfile,BSIZE-4);
26414ee0 1393 buf[2][BSIZE-4]='\0';
7d7d2cbc 1394
bc36ee62 1395#ifdef OPENSSL_SYS_VMS
7d7d2cbc
UM
1396 strcat(buf[2],"-old");
1397#else
d02b48c6 1398 strcat(buf[2],".old");
7d7d2cbc
UM
1399#endif
1400
d02b48c6
RE
1401 if (rename(dbfile,buf[2]) < 0)
1402 {
657e60fa 1403 BIO_printf(bio_err,"unable to rename %s to %s\n",
d02b48c6
RE
1404 dbfile,buf[2]);
1405 perror("reason");
1406 goto err;
1407 }
1408 if (rename(buf[1],dbfile) < 0)
1409 {
657e60fa 1410 BIO_printf(bio_err,"unable to rename %s to %s\n",
d02b48c6
RE
1411 buf[1],dbfile);
1412 perror("reason");
1413 rename(buf[2],dbfile);
1414 goto err;
1415 }
1416 BIO_printf(bio_err,"Data Base Updated\n");
1417 }
1418 }
1419
1420 /*****************************************************************/
1421 if (gencrl)
1422 {
a6b7ffdd 1423 int crl_v2 = 0;
2c0d1012
BM
1424 if (!crl_ext)
1425 {
b7a26e6d 1426 crl_ext=NCONF_get_string(conf,section,ENV_CRLEXT);
2c0d1012
BM
1427 if (!crl_ext)
1428 ERR_clear_error();
1429 }
1430 if (crl_ext)
1431 {
1756d405 1432 /* Check syntax of file */
41b731f2
DSH
1433 X509V3_CTX ctx;
1434 X509V3_set_ctx_test(&ctx);
b7a26e6d
DSH
1435 X509V3_set_nconf(&ctx, conf);
1436 if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL))
2c0d1012 1437 {
1756d405
DSH
1438 BIO_printf(bio_err,
1439 "Error Loading CRL extension section %s\n",
1440 crl_ext);
1441 ret = 1;
1442 goto err;
2c0d1012 1443 }
1756d405 1444 }
d02b48c6
RE
1445
1446 if (!crldays && !crlhours)
1447 {
b7a26e6d
DSH
1448 if (!NCONF_get_number(conf,section,
1449 ENV_DEFAULT_CRL_DAYS, &crldays))
1450 crldays = 0;
1451 if (!NCONF_get_number(conf,section,
1452 ENV_DEFAULT_CRL_HOURS, &crlhours))
1453 crlhours = 0;
d02b48c6
RE
1454 }
1455 if ((crldays == 0) && (crlhours == 0))
1456 {
7e661761 1457 BIO_printf(bio_err,"cannot lookup how long until the next CRL is issued\n");
d02b48c6
RE
1458 goto err;
1459 }
1460
1461 if (verbose) BIO_printf(bio_err,"making CRL\n");
1462 if ((crl=X509_CRL_new()) == NULL) goto err;
7e661761 1463 if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) goto err;
d02b48c6 1464
35bf3541
DSH
1465 tmptm = ASN1_TIME_new();
1466 if (!tmptm) goto err;
1467 X509_gmtime_adj(tmptm,0);
1468 X509_CRL_set_lastUpdate(crl, tmptm);
1469 X509_gmtime_adj(tmptm,(crldays*24+crlhours)*60*60);
1470 X509_CRL_set_nextUpdate(crl, tmptm);
1471
1472 ASN1_TIME_free(tmptm);
d02b48c6
RE
1473
1474 for (i=0; i<sk_num(db->data); i++)
1475 {
1476 pp=(char **)sk_value(db->data,i);
1477 if (pp[DB_type][0] == DB_TYPE_REV)
1478 {
1479 if ((r=X509_REVOKED_new()) == NULL) goto err;
a6b7ffdd
DSH
1480 j = make_revoked(r, pp[DB_rev_date]);
1481 if (!j) goto err;
1482 if (j == 2) crl_v2 = 1;
acba75c5
DSH
1483 if (!BN_hex2bn(&serial, pp[DB_serial]))
1484 goto err;
35bf3541 1485 tmpser = BN_to_ASN1_INTEGER(serial, NULL);
acba75c5
DSH
1486 BN_free(serial);
1487 serial = NULL;
35bf3541 1488 if (!tmpser)
d02b48c6 1489 goto err;
35bf3541
DSH
1490 X509_REVOKED_set_serialNumber(r, tmpser);
1491 ASN1_INTEGER_free(tmpser);
9d6b1ce6 1492 X509_CRL_add0_revoked(crl,r);
d02b48c6
RE
1493 }
1494 }
35bf3541 1495
d02b48c6
RE
1496 /* sort the data so it will be written in serial
1497 * number order */
35bf3541 1498 X509_CRL_sort(crl);
d02b48c6 1499
13e91dd3 1500 /* we now have a CRL */
d02b48c6
RE
1501 if (verbose) BIO_printf(bio_err,"signing CRL\n");
1502 if (md != NULL)
1503 {
1504 if ((dgst=EVP_get_digestbyname(md)) == NULL)
1505 {
1506 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1507 goto err;
1508 }
1509 }
1510 else
c67cdb50 1511 {
cf1b7d96 1512#ifndef OPENSSL_NO_DSA
c67cdb50
BM
1513 if (pkey->type == EVP_PKEY_DSA)
1514 dgst=EVP_dss1();
1515 else
4d94ae00
BM
1516#endif
1517#ifndef OPENSSL_NO_ECDSA
5488bb61 1518 if (pkey->type == EVP_PKEY_EC)
4d94ae00
BM
1519 dgst=EVP_ecdsa();
1520 else
13e91dd3 1521#endif
c67cdb50
BM
1522 dgst=EVP_md5();
1523 }
512d2228 1524
1756d405
DSH
1525 /* Add any extensions asked for */
1526
c67cdb50
BM
1527 if (crl_ext)
1528 {
1529 X509V3_CTX crlctx;
c67cdb50 1530 X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
b7a26e6d 1531 X509V3_set_nconf(&crlctx, conf);
1756d405 1532
b7a26e6d 1533 if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx,
c67cdb50
BM
1534 crl_ext, crl)) goto err;
1535 }
a6b7ffdd
DSH
1536 if (crl_ext || crl_v2)
1537 {
35bf3541
DSH
1538 if (!X509_CRL_set_version(crl, 1))
1539 goto err; /* version 2 CRL */
a6b7ffdd 1540 }
1756d405 1541
d02b48c6
RE
1542 if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1543
1544 PEM_write_bio_X509_CRL(Sout,crl);
1545 }
1546 /*****************************************************************/
a36a1a51 1547 if (dorevoke)
f9a25931 1548 {
b1c4fe36
BM
1549 if (infile == NULL)
1550 {
1551 BIO_printf(bio_err,"no input files\n");
1552 goto err;
1553 }
f9a25931
RE
1554 else
1555 {
a0ad17bb 1556 X509 *revcert;
ce16450a
RL
1557 revcert=load_cert(bio_err, infile, FORMAT_PEM,
1558 NULL, e, infile);
a0ad17bb 1559 if (revcert == NULL)
f9a25931 1560 goto err;
a6b7ffdd 1561 j=do_revoke(revcert,db, rev_type, rev_arg);
a0ad17bb
DSH
1562 if (j <= 0) goto err;
1563 X509_free(revcert);
f9a25931
RE
1564
1565 strncpy(buf[0],dbfile,BSIZE-4);
26414ee0 1566 buf[0][BSIZE-4]='\0';
98405f24 1567#ifndef OPENSSL_SYS_VMS
b1c4fe36 1568 strcat(buf[0],".new");
98405f24
RL
1569#else
1570 strcat(buf[0],"-new");
1571#endif
b1c4fe36
BM
1572 if (BIO_write_filename(out,buf[0]) <= 0)
1573 {
1574 perror(dbfile);
1575 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1576 goto err;
1577 }
1578 j=TXT_DB_write(out,db);
1579 if (j <= 0) goto err;
b1c4fe36 1580 strncpy(buf[1],dbfile,BSIZE-4);
26414ee0 1581 buf[1][BSIZE-4]='\0';
98405f24 1582#ifndef OPENSSL_SYS_VMS
b1c4fe36 1583 strcat(buf[1],".old");
98405f24
RL
1584#else
1585 strcat(buf[1],"-old");
1586#endif
26e12373
DSH
1587 BIO_free(in);
1588 in = NULL;
1589 BIO_free(out);
1590 out = NULL;
b1c4fe36
BM
1591 if (rename(dbfile,buf[1]) < 0)
1592 {
1593 BIO_printf(bio_err,"unable to rename %s to %s\n", dbfile, buf[1]);
1594 perror("reason");
1595 goto err;
1596 }
1597 if (rename(buf[0],dbfile) < 0)
1598 {
1599 BIO_printf(bio_err,"unable to rename %s to %s\n", buf[0],dbfile);
1600 perror("reason");
1601 rename(buf[1],dbfile);
1602 goto err;
1603 }
1604 BIO_printf(bio_err,"Data Base Updated\n");
1605 }
f9a25931
RE
1606 }
1607 /*****************************************************************/
d02b48c6
RE
1608 ret=0;
1609err:
645749ef
RL
1610 BIO_free_all(Cout);
1611 BIO_free_all(Sout);
1612 BIO_free_all(out);
ce16450a 1613 BIO_free_all(in);
d02b48c6 1614
b4604683 1615 sk_X509_pop_free(cert_sk,X509_free);
d02b48c6
RE
1616
1617 if (ret) ERR_print_errors(bio_err);
a31011e8 1618 app_RAND_write_file(randfile, bio_err);
b65f8513
DSH
1619 if (free_key)
1620 OPENSSL_free(key);
a43aa73e
DSH
1621 BN_free(serial);
1622 TXT_DB_free(db);
1623 EVP_PKEY_free(pkey);
1624 X509_free(x509);
1625 X509_CRL_free(crl);
b7a26e6d 1626 NCONF_free(conf);
a43aa73e 1627 OBJ_cleanup();
ce16450a 1628 apps_shutdown();
d02b48c6
RE
1629 EXIT(ret);
1630 }
1631
6b691a5c 1632static void lookup_fail(char *name, char *tag)
d02b48c6
RE
1633 {
1634 BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1635 }
1636
35a99b63 1637static unsigned long index_serial_hash(const char **a)
d02b48c6 1638 {
35a99b63 1639 const char *n;
d02b48c6
RE
1640
1641 n=a[DB_serial];
1642 while (*n == '0') n++;
1643 return(lh_strhash(n));
1644 }
1645
35a99b63 1646static int index_serial_cmp(const char **a, const char **b)
d02b48c6 1647 {
35a99b63 1648 const char *aa,*bb;
d02b48c6
RE
1649
1650 for (aa=a[DB_serial]; *aa == '0'; aa++);
1651 for (bb=b[DB_serial]; *bb == '0'; bb++);
1652 return(strcmp(aa,bb));
1653 }
1654
35a99b63 1655static unsigned long index_name_hash(const char **a)
d02b48c6
RE
1656 { return(lh_strhash(a[DB_name])); }
1657
6b691a5c 1658static int index_name_qual(char **a)
d02b48c6
RE
1659 { return(a[0][0] == 'V'); }
1660
35a99b63 1661static int index_name_cmp(const char **a, const char **b)
6b691a5c
UM
1662 { return(strcmp(a[DB_name],
1663 b[DB_name])); }
d02b48c6 1664
6b691a5c 1665static BIGNUM *load_serial(char *serialfile)
d02b48c6
RE
1666 {
1667 BIO *in=NULL;
1668 BIGNUM *ret=NULL;
1669 MS_STATIC char buf[1024];
1670 ASN1_INTEGER *ai=NULL;
1671
1672 if ((in=BIO_new(BIO_s_file())) == NULL)
1673 {
1674 ERR_print_errors(bio_err);
1675 goto err;
1676 }
1677
1678 if (BIO_read_filename(in,serialfile) <= 0)
1679 {
1680 perror(serialfile);
1681 goto err;
1682 }
1683 ai=ASN1_INTEGER_new();
1684 if (ai == NULL) goto err;
1685 if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
1686 {
1687 BIO_printf(bio_err,"unable to load number from %s\n",
1688 serialfile);
1689 goto err;
1690 }
1691 ret=ASN1_INTEGER_to_BN(ai,NULL);
1692 if (ret == NULL)
1693 {
d7b2342a 1694 BIO_printf(bio_err,"error converting number from bin to BIGNUM\n");
d02b48c6
RE
1695 goto err;
1696 }
1697err:
1698 if (in != NULL) BIO_free(in);
1699 if (ai != NULL) ASN1_INTEGER_free(ai);
1700 return(ret);
1701 }
1702
6b691a5c 1703static int save_serial(char *serialfile, BIGNUM *serial)
d02b48c6
RE
1704 {
1705 BIO *out;
1706 int ret=0;
1707 ASN1_INTEGER *ai=NULL;
1708
1709 out=BIO_new(BIO_s_file());
1710 if (out == NULL)
1711 {
1712 ERR_print_errors(bio_err);
1713 goto err;
1714 }
1715 if (BIO_write_filename(out,serialfile) <= 0)
1716 {
1717 perror(serialfile);
1718 goto err;
1719 }
1720
1721 if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
1722 {
1723 BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
1724 goto err;
1725 }
1726 i2a_ASN1_INTEGER(out,ai);
1727 BIO_puts(out,"\n");
1728 ret=1;
1729err:
645749ef 1730 if (out != NULL) BIO_free_all(out);
d02b48c6
RE
1731 if (ai != NULL) ASN1_INTEGER_free(ai);
1732 return(ret);
1733 }
1734
6b691a5c 1735static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
ba404b5e 1736 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
89da653f
BM
1737 BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate,
1738 long days, int batch, char *ext_sect, CONF *lconf, int verbose,
535d79da
DSH
1739 unsigned long certopt, unsigned long nameopt, int default_op,
1740 int ext_copy)
d02b48c6
RE
1741 {
1742 X509_REQ *req=NULL;
1743 BIO *in=NULL;
1744 EVP_PKEY *pktmp=NULL;
1745 int ok= -1,i;
1746
1747 in=BIO_new(BIO_s_file());
1748
1749 if (BIO_read_filename(in,infile) <= 0)
1750 {
1751 perror(infile);
1752 goto err;
1753 }
74678cc2 1754 if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
d02b48c6
RE
1755 {
1756 BIO_printf(bio_err,"Error reading certificate request in %s\n",
1757 infile);
1758 goto err;
1759 }
1760 if (verbose)
1761 X509_REQ_print(bio_err,req);
1762
1763 BIO_printf(bio_err,"Check that the request matches the signature\n");
1764
d02b48c6
RE
1765 if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
1766 {
1767 BIO_printf(bio_err,"error unpacking public key\n");
1768 goto err;
1769 }
1770 i=X509_REQ_verify(req,pktmp);
10061c7c 1771 EVP_PKEY_free(pktmp);
d02b48c6
RE
1772 if (i < 0)
1773 {
1774 ok=0;
1775 BIO_printf(bio_err,"Signature verification problems....\n");
1776 goto err;
1777 }
1778 if (i == 0)
1779 {
1780 ok=0;
1781 BIO_printf(bio_err,"Signature did not match the certificate request\n");
1782 goto err;
1783 }
1784 else
1785 BIO_printf(bio_err,"Signature ok\n");
1786
89da653f
BM
1787 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj, email_dn,
1788 startdate,enddate,days,batch,verbose,req,ext_sect,lconf,
535d79da 1789 certopt, nameopt, default_op, ext_copy);
d02b48c6
RE
1790
1791err:
1792 if (req != NULL) X509_REQ_free(req);
1793 if (in != NULL) BIO_free(in);
1794 return(ok);
1795 }
1796
6b691a5c 1797static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
ba404b5e 1798 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
89da653f
BM
1799 BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate,
1800 long days, int batch, char *ext_sect, CONF *lconf, int verbose,
535d79da 1801 unsigned long certopt, unsigned long nameopt, int default_op,
ce16450a 1802 int ext_copy, ENGINE *e)
58964a49
RE
1803 {
1804 X509 *req=NULL;
1805 X509_REQ *rreq=NULL;
58964a49
RE
1806 EVP_PKEY *pktmp=NULL;
1807 int ok= -1,i;
1808
ce16450a 1809 if ((req=load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL)
58964a49 1810 goto err;
58964a49
RE
1811 if (verbose)
1812 X509_print(bio_err,req);
1813
1814 BIO_printf(bio_err,"Check that the request matches the signature\n");
1815
1816 if ((pktmp=X509_get_pubkey(req)) == NULL)
1817 {
1818 BIO_printf(bio_err,"error unpacking public key\n");
1819 goto err;
1820 }
1821 i=X509_verify(req,pktmp);
10061c7c 1822 EVP_PKEY_free(pktmp);
58964a49
RE
1823 if (i < 0)
1824 {
1825 ok=0;
1826 BIO_printf(bio_err,"Signature verification problems....\n");
1827 goto err;
1828 }
1829 if (i == 0)
1830 {
1831 ok=0;
dfeab068 1832 BIO_printf(bio_err,"Signature did not match the certificate\n");
58964a49
RE
1833 goto err;
1834 }
1835 else
1836 BIO_printf(bio_err,"Signature ok\n");
1837
1838 if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
1839 goto err;
1840
89da653f
BM
1841 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,email_dn,startdate,enddate,
1842 days,batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op,
1843 ext_copy);
58964a49
RE
1844
1845err:
1846 if (rreq != NULL) X509_REQ_free(rreq);
1847 if (req != NULL) X509_free(req);
58964a49
RE
1848 return(ok);
1849 }
1850
6b691a5c 1851static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
bad40585 1852 STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial, char *subj,
89da653f
BM
1853 int email_dn, char *startdate, char *enddate, long days, int batch,
1854 int verbose, X509_REQ *req, char *ext_sect, CONF *lconf,
535d79da
DSH
1855 unsigned long certopt, unsigned long nameopt, int default_op,
1856 int ext_copy)
d02b48c6 1857 {
89da653f 1858 X509_NAME *name=NULL,*CAname=NULL,*subject=NULL, *dn_subject=NULL;
58964a49 1859 ASN1_UTCTIME *tm,*tmptm;
d02b48c6
RE
1860 ASN1_STRING *str,*str2;
1861 ASN1_OBJECT *obj;
1862 X509 *ret=NULL;
1863 X509_CINF *ci;
1864 X509_NAME_ENTRY *ne;
1865 X509_NAME_ENTRY *tne,*push;
d02b48c6
RE
1866 EVP_PKEY *pktmp;
1867 int ok= -1,i,j,last,nid;
1868 char *p;
1869 CONF_VALUE *cv;
1870 char *row[DB_NUMBER],**rrow,**irow=NULL;
535d79da 1871 char buf[25];
d02b48c6 1872
58964a49
RE
1873 tmptm=ASN1_UTCTIME_new();
1874 if (tmptm == NULL)
1875 {
1876 BIO_printf(bio_err,"malloc error\n");
1877 return(0);
1878 }
1879
d02b48c6
RE
1880 for (i=0; i<DB_NUMBER; i++)
1881 row[i]=NULL;
1882
bad40585
BM
1883 if (subj)
1884 {
eee6c81a 1885 X509_NAME *n = do_subject(subj, MBSTRING_ASC);
bad40585
BM
1886
1887 if (!n)
1888 {
1889 ERR_print_errors(bio_err);
1890 goto err;
1891 }
1892 X509_REQ_set_subject_name(req,n);
1893 req->req_info->enc.modified = 1;
1894 X509_NAME_free(n);
1895 }
1896
535d79da
DSH
1897 if (default_op)
1898 BIO_printf(bio_err,"The Subject's Distinguished Name is as follows\n");
89da653f 1899
d02b48c6
RE
1900 name=X509_REQ_get_subject_name(req);
1901 for (i=0; i<X509_NAME_entry_count(name); i++)
1902 {
535d79da 1903 ne= X509_NAME_get_entry(name,i);
d02b48c6 1904 str=X509_NAME_ENTRY_get_data(ne);
535d79da 1905 obj=X509_NAME_ENTRY_get_object(ne);
d02b48c6
RE
1906
1907 if (msie_hack)
1908 {
1909 /* assume all type should be strings */
1910 nid=OBJ_obj2nid(ne->object);
1911
1912 if (str->type == V_ASN1_UNIVERSALSTRING)
1913 ASN1_UNIVERSALSTRING_to_string(str);
1914
1915 if ((str->type == V_ASN1_IA5STRING) &&
1916 (nid != NID_pkcs9_emailAddress))
1917 str->type=V_ASN1_T61STRING;
1918
1919 if ((nid == NID_pkcs9_emailAddress) &&
1920 (str->type == V_ASN1_PRINTABLESTRING))
1921 str->type=V_ASN1_IA5STRING;
1922 }
1923
89da653f
BM
1924 /* If no EMAIL is wanted in the subject */
1925 if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn))
1926 continue;
1927
d02b48c6
RE
1928 /* check some things */
1929 if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1930 (str->type != V_ASN1_IA5STRING))
1931 {
1932 BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
1933 goto err;
1934 }
e7156ff2 1935 if ((str->type != V_ASN1_BMPSTRING) && (str->type != V_ASN1_UTF8STRING))
d02b48c6 1936 {
e7156ff2
DSH
1937 j=ASN1_PRINTABLE_type(str->data,str->length);
1938 if ( ((j == V_ASN1_T61STRING) &&
1939 (str->type != V_ASN1_T61STRING)) ||
1940 ((j == V_ASN1_IA5STRING) &&
1941 (str->type == V_ASN1_PRINTABLESTRING)))
1942 {
1943 BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1944 goto err;
1945 }
d02b48c6 1946 }
535d79da
DSH
1947
1948 if (default_op)
1949 old_entry_print(bio_err, obj, str);
d02b48c6
RE
1950 }
1951
1952 /* Ok, now we check the 'policy' stuff. */
1953 if ((subject=X509_NAME_new()) == NULL)
1954 {
26a3a48d 1955 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
1956 goto err;
1957 }
1958
1959 /* take a copy of the issuer name before we mess with it. */
1960 CAname=X509_NAME_dup(x509->cert_info->subject);
1961 if (CAname == NULL) goto err;
1962 str=str2=NULL;
1963
ba404b5e 1964 for (i=0; i<sk_CONF_VALUE_num(policy); i++)
d02b48c6 1965 {
ba404b5e 1966 cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
d02b48c6
RE
1967 if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
1968 {
1969 BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
1970 goto err;
1971 }
1972 obj=OBJ_nid2obj(j);
1973
1974 last= -1;
1975 for (;;)
1976 {
1977 /* lookup the object in the supplied name list */
1978 j=X509_NAME_get_index_by_OBJ(name,obj,last);
1979 if (j < 0)
1980 {
1981 if (last != -1) break;
1982 tne=NULL;
1983 }
1984 else
1985 {
1986 tne=X509_NAME_get_entry(name,j);
1987 }
1988 last=j;
1989
1990 /* depending on the 'policy', decide what to do. */
1991 push=NULL;
1992 if (strcmp(cv->value,"optional") == 0)
1993 {
1994 if (tne != NULL)
1995 push=tne;
1996 }
1997 else if (strcmp(cv->value,"supplied") == 0)
1998 {
1999 if (tne == NULL)
2000 {
2001 BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
2002 goto err;
2003 }
2004 else
2005 push=tne;
2006 }
2007 else if (strcmp(cv->value,"match") == 0)
2008 {
2009 int last2;
2010
2011 if (tne == NULL)
2012 {
2013 BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
2014 goto err;
2015 }
2016
2017 last2= -1;
2018
2019again2:
2020 j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
2021 if ((j < 0) && (last2 == -1))
2022 {
2023 BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
2024 goto err;
2025 }
2026 if (j >= 0)
2027 {
2028 push=X509_NAME_get_entry(CAname,j);
2029 str=X509_NAME_ENTRY_get_data(tne);
2030 str2=X509_NAME_ENTRY_get_data(push);
2031 last2=j;
2032 if (ASN1_STRING_cmp(str,str2) != 0)
2033 goto again2;
2034 }
2035 if (j < 0)
2036 {
c6125200 2037 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
2038 goto err;
2039 }
2040 }
2041 else
2042 {
2043 BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
2044 goto err;
2045 }
2046
2047 if (push != NULL)
2048 {
74400f73 2049 if (!X509_NAME_add_entry(subject,push, -1, 0))
d02b48c6
RE
2050 {
2051 if (push != NULL)
2052 X509_NAME_ENTRY_free(push);
26a3a48d 2053 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
2054 goto err;
2055 }
2056 }
2057 if (j < 0) break;
2058 }
2059 }
2060
2061 if (preserve)
2062 {
2063 X509_NAME_free(subject);
89da653f
BM
2064 /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */
2065 subject=X509_NAME_dup(name);
d02b48c6
RE
2066 if (subject == NULL) goto err;
2067 }
2068
2069 if (verbose)
657e60fa 2070 BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
d02b48c6 2071
89da653f
BM
2072 /* Build the correct Subject if no e-mail is wanted in the subject */
2073 /* and add it later on because of the method extensions are added (altName) */
2074
437db75b
DSH
2075 if (email_dn)
2076 dn_subject = subject;
2077 else
89da653f 2078 {
437db75b
DSH
2079 X509_NAME_ENTRY *tmpne;
2080 /* Its best to dup the subject DN and then delete any email
2081 * addresses because this retains its structure.
2082 */
2083 if (!(dn_subject = X509_NAME_dup(subject)))
89da653f
BM
2084 {
2085 BIO_printf(bio_err,"Memory allocation failure\n");
2086 goto err;
2087 }
437db75b 2088 while((i = X509_NAME_get_index_by_NID(dn_subject,
6229a560 2089 NID_pkcs9_emailAddress, -1)) >= 0)
89da653f 2090 {
437db75b
DSH
2091 tmpne = X509_NAME_get_entry(dn_subject, i);
2092 X509_NAME_delete_entry(dn_subject, i);
2093 X509_NAME_ENTRY_free(tmpne);
89da653f
BM
2094 }
2095 }
2096
dfeab068 2097 row[DB_serial]=BN_bn2hex(serial);
87e8feca 2098 if (row[DB_serial] == NULL)
d02b48c6 2099 {
26a3a48d 2100 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
2101 goto err;
2102 }
2103
2104 rrow=TXT_DB_get_by_index(db,DB_name,row);
2105 if (rrow != NULL)
2106 {
2107 BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n",
2108 row[DB_name]);
2109 }
2110 else
2111 {
2112 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2113 if (rrow != NULL)
2114 {
2115 BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
2116 row[DB_serial]);
2117 BIO_printf(bio_err," check the database/serial_file for corruption\n");
2118 }
2119 }
2120
2121 if (rrow != NULL)
2122 {
2123 BIO_printf(bio_err,
2124 "The matching entry has the following details\n");
2125 if (rrow[DB_type][0] == 'E')
2126 p="Expired";
2127 else if (rrow[DB_type][0] == 'R')
2128 p="Revoked";
2129 else if (rrow[DB_type][0] == 'V')
2130 p="Valid";
2131 else
2132 p="\ninvalid type, Data base error\n";
b1c4fe36 2133 BIO_printf(bio_err,"Type :%s\n",p);;
d02b48c6
RE
2134 if (rrow[DB_type][0] == 'R')
2135 {
2136 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2137 BIO_printf(bio_err,"Was revoked on:%s\n",p);
2138 }
2139 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2140 BIO_printf(bio_err,"Expires on :%s\n",p);
2141 p=rrow[DB_serial]; if (p == NULL) p="undef";
2142 BIO_printf(bio_err,"Serial Number :%s\n",p);
2143 p=rrow[DB_file]; if (p == NULL) p="undef";
2144 BIO_printf(bio_err,"File name :%s\n",p);
2145 p=rrow[DB_name]; if (p == NULL) p="undef";
2146 BIO_printf(bio_err,"Subject Name :%s\n",p);
2147 ok= -1; /* This is now a 'bad' error. */
2148 goto err;
2149 }
2150
657e60fa 2151 /* We are now totally happy, lets make and sign the certificate */
d02b48c6
RE
2152 if (verbose)
2153 BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
2154
2155 if ((ret=X509_new()) == NULL) goto err;
2156 ci=ret->cert_info;
2157
2158#ifdef X509_V3
2159 /* Make it an X509 v3 certificate. */
2160 if (!X509_set_version(x509,2)) goto err;
2161#endif
2162
2163 if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
2164 goto err;
2165 if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
2166 goto err;
2167
58964a49 2168 if (strcmp(startdate,"today") == 0)
58964a49 2169 X509_gmtime_adj(X509_get_notBefore(ret),0);
ed7f60fb
DSH
2170 else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
2171
2172 if (enddate == NULL)
58964a49 2173 X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
ed7f60fb
DSH
2174 else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
2175
d02b48c6
RE
2176 if (!X509_set_subject_name(ret,subject)) goto err;
2177
2178 pktmp=X509_REQ_get_pubkey(req);
10061c7c
DSH
2179 i = X509_set_pubkey(ret,pktmp);
2180 EVP_PKEY_free(pktmp);
2181 if (!i) goto err;
d02b48c6
RE
2182
2183 /* Lets add the extensions, if there are any */
b2347661 2184 if (ext_sect)
d02b48c6 2185 {
175b0942 2186 X509V3_CTX ctx;
d02b48c6
RE
2187 if (ci->version == NULL)
2188 if ((ci->version=ASN1_INTEGER_new()) == NULL)
2189 goto err;
2190 ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
2191
2192 /* Free the current entries if any, there should not
657e60fa 2193 * be any I believe */
d02b48c6 2194 if (ci->extensions != NULL)
0b3f827c
BL
2195 sk_X509_EXTENSION_pop_free(ci->extensions,
2196 X509_EXTENSION_free);
d02b48c6 2197
b2347661
DSH
2198 ci->extensions = NULL;
2199
dfebac32 2200 /* Initialize the context structure */
1d48dd00 2201 X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
175b0942 2202
dfebac32
BM
2203 if (extconf)
2204 {
2205 if (verbose)
2206 BIO_printf(bio_err, "Extra configuration file found\n");
2207
2208 /* Use the extconf configuration db LHASH */
b7a26e6d 2209 X509V3_set_nconf(&ctx, extconf);
dfebac32
BM
2210
2211 /* Test the structure (needed?) */
2212 /* X509V3_set_ctx_test(&ctx); */
2213
2214 /* Adds exts contained in the configuration file */
b7a26e6d 2215 if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect,ret))
dfebac32
BM
2216 {
2217 BIO_printf(bio_err,
2218 "ERROR: adding extensions in section %s\n",
2219 ext_sect);
2220 ERR_print_errors(bio_err);
2221 goto err;
2222 }
2223 if (verbose)
2224 BIO_printf(bio_err, "Successfully added extensions from file.\n");
2225 }
2226 else if (ext_sect)
2227 {
2228 /* We found extensions to be set from config file */
b7a26e6d 2229 X509V3_set_nconf(&ctx, lconf);
d02b48c6 2230
b7a26e6d 2231 if(!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret))
dfebac32
BM
2232 {
2233 BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2234 ERR_print_errors(bio_err);
2235 goto err;
2236 }
2237
2238 if (verbose)
2239 BIO_printf(bio_err, "Successfully added extensions from config\n");
2240 }
d02b48c6
RE
2241 }
2242
791bd0cd
DSH
2243 /* Copy extensions from request (if any) */
2244
2245 if (!copy_extensions(ret, req, ext_copy))
2246 {
2247 BIO_printf(bio_err, "ERROR: adding extensions from request\n");
2248 ERR_print_errors(bio_err);
2249 goto err;
2250 }
2251
89da653f
BM
2252 /* Set the right value for the noemailDN option */
2253 if( email_dn == 0 )
2254 {
2255 if (!X509_set_subject_name(ret,dn_subject)) goto err;
2256 }
791bd0cd
DSH
2257
2258 if (!default_op)
2259 {
2260 BIO_printf(bio_err, "Certificate Details:\n");
2261 /* Never print signature details because signature not present */
2262 certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
2263 X509_print_ex(bio_err, ret, nameopt, certopt);
2264 }
2265
2266 BIO_printf(bio_err,"Certificate is to be certified until ");
2267 ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
2268 if (days) BIO_printf(bio_err," (%d days)",days);
2269 BIO_printf(bio_err, "\n");
d02b48c6
RE
2270
2271 if (!batch)
2272 {
791bd0cd 2273
d02b48c6 2274 BIO_printf(bio_err,"Sign the certificate? [y/n]:");
d58d092b 2275 (void)BIO_flush(bio_err);
d02b48c6
RE
2276 buf[0]='\0';
2277 fgets(buf,sizeof(buf)-1,stdin);
2278 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
2279 {
2280 BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
2281 ok=0;
2282 goto err;
2283 }
2284 }
2285
dfeab068 2286
cf1b7d96 2287#ifndef OPENSSL_NO_DSA
c35f549e 2288 if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
b1c4fe36
BM
2289 pktmp=X509_get_pubkey(ret);
2290 if (EVP_PKEY_missing_parameters(pktmp) &&
d02b48c6
RE
2291 !EVP_PKEY_missing_parameters(pkey))
2292 EVP_PKEY_copy_parameters(pktmp,pkey);
10061c7c 2293 EVP_PKEY_free(pktmp);
d02b48c6 2294#endif
4d94ae00 2295#ifndef OPENSSL_NO_ECDSA
5488bb61 2296 if (pkey->type == EVP_PKEY_EC)
4d94ae00
BM
2297 dgst = EVP_ecdsa();
2298 pktmp = X509_get_pubkey(ret);
2299 if (EVP_PKEY_missing_parameters(pktmp) &&
2300 !EVP_PKEY_missing_parameters(pkey))
2301 EVP_PKEY_copy_parameters(pktmp, pkey);
2302 EVP_PKEY_free(pktmp);
2303#endif
2304
d02b48c6
RE
2305
2306 if (!X509_sign(ret,pkey,dgst))
2307 goto err;
2308
2309 /* We now just add it to the database */
26a3a48d 2310 row[DB_type]=(char *)OPENSSL_malloc(2);
d02b48c6
RE
2311
2312 tm=X509_get_notAfter(ret);
26a3a48d 2313 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
d02b48c6
RE
2314 memcpy(row[DB_exp_date],tm->data,tm->length);
2315 row[DB_exp_date][tm->length]='\0';
2316
2317 row[DB_rev_date]=NULL;
2318
2319 /* row[DB_serial] done already */
26a3a48d 2320 row[DB_file]=(char *)OPENSSL_malloc(8);
87e8feca 2321 row[DB_name]=X509_NAME_oneline(X509_get_subject_name(ret),NULL,0);
d02b48c6
RE
2322
2323 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
87e8feca 2324 (row[DB_file] == NULL) || (row[DB_name] == NULL))
d02b48c6 2325 {
26a3a48d 2326 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
2327 goto err;
2328 }
2329 strcpy(row[DB_file],"unknown");
2330 row[DB_type][0]='V';
2331 row[DB_type][1]='\0';
2332
26a3a48d 2333 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
d02b48c6 2334 {
26a3a48d 2335 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
2336 goto err;
2337 }
2338
2339 for (i=0; i<DB_NUMBER; i++)
2340 {
2341 irow[i]=row[i];
2342 row[i]=NULL;
2343 }
2344 irow[DB_NUMBER]=NULL;
2345
2346 if (!TXT_DB_insert(db,irow))
2347 {
2348 BIO_printf(bio_err,"failed to update database\n");
2349 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2350 goto err;
2351 }
2352 ok=1;
2353err:
2354 for (i=0; i<DB_NUMBER; i++)
26a3a48d 2355 if (row[i] != NULL) OPENSSL_free(row[i]);
d02b48c6
RE
2356
2357 if (CAname != NULL)
2358 X509_NAME_free(CAname);
2359 if (subject != NULL)
2360 X509_NAME_free(subject);
437db75b
DSH
2361 if ((dn_subject != NULL) && !email_dn)
2362 X509_NAME_free(dn_subject);
79875776
BM
2363 if (tmptm != NULL)
2364 ASN1_UTCTIME_free(tmptm);
d02b48c6
RE
2365 if (ok <= 0)
2366 {
2367 if (ret != NULL) X509_free(ret);
2368 ret=NULL;
2369 }
2370 else
2371 *xret=ret;
2372 return(ok);
2373 }
2374
82fc1d9c 2375static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
d02b48c6 2376 {
d02b48c6
RE
2377
2378 if (output_der)
2379 {
2380 (void)i2d_X509_bio(bp,x);
2381 return;
2382 }
82fc1d9c
DSH
2383#if 0
2384 /* ??? Not needed since X509_print prints all this stuff anyway */
d02b48c6
RE
2385 f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
2386 BIO_printf(bp,"issuer :%s\n",f);
2387
2388 f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
2389 BIO_printf(bp,"subject:%s\n",f);
2390
2391 BIO_puts(bp,"serial :");
2392 i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
2393 BIO_puts(bp,"\n\n");
82fc1d9c 2394#endif
c67cdb50 2395 if (!notext)X509_print(bp,x);
d02b48c6 2396 PEM_write_bio_X509(bp,x);
d02b48c6
RE
2397 }
2398
6b691a5c 2399static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
ba404b5e 2400 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
89da653f
BM
2401 BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate,
2402 long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt,
535d79da 2403 unsigned long nameopt, int default_op, int ext_copy)
d02b48c6 2404 {
ba404b5e 2405 STACK_OF(CONF_VALUE) *sk=NULL;
d02b48c6
RE
2406 LHASH *parms=NULL;
2407 X509_REQ *req=NULL;
2408 CONF_VALUE *cv=NULL;
2409 NETSCAPE_SPKI *spki = NULL;
d02b48c6
RE
2410 X509_REQ_INFO *ri;
2411 char *type,*buf;
2412 EVP_PKEY *pktmp=NULL;
2413 X509_NAME *n=NULL;
2414 X509_NAME_ENTRY *ne=NULL;
2415 int ok= -1,i,j;
2416 long errline;
2417 int nid;
2418
2419 /*
2420 * Load input file into a hash table. (This is just an easy
2421 * way to read and parse the file, then put it into a convenient
2422 * STACK format).
2423 */
2424 parms=CONF_load(NULL,infile,&errline);
2425 if (parms == NULL)
2426 {
2427 BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
2428 ERR_print_errors(bio_err);
2429 goto err;
2430 }
2431
2432 sk=CONF_get_section(parms, "default");
ba404b5e 2433 if (sk_CONF_VALUE_num(sk) == 0)
d02b48c6
RE
2434 {
2435 BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2436 CONF_free(parms);
2437 goto err;
2438 }
2439
2440 /*
2441 * Now create a dummy X509 request structure. We don't actually
2442 * have an X509 request, but we have many of the components
2443 * (a public key, various DN components). The idea is that we
2444 * put these components into the right X509 request structure
2445 * and we can use the same code as if you had a real X509 request.
2446 */
2447 req=X509_REQ_new();
2448 if (req == NULL)
2449 {
2450 ERR_print_errors(bio_err);
2451 goto err;
2452 }
2453
2454 /*
2455 * Build up the subject name set.
2456 */
2457 ri=req->req_info;
2458 n = ri->subject;
2459
2460 for (i = 0; ; i++)
2461 {
ba404b5e 2462 if (sk_CONF_VALUE_num(sk) <= i) break;
d02b48c6 2463
ba404b5e 2464 cv=sk_CONF_VALUE_value(sk,i);
d02b48c6 2465 type=cv->name;
f9150e54
DSH
2466 /* Skip past any leading X. X: X, etc to allow for
2467 * multiple instances
2468 */
c67cdb50
BM
2469 for (buf = cv->name; *buf ; buf++)
2470 if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2471 {
2472 buf++;
2473 if (*buf) type = buf;
2474 break;
2475 }
d02b48c6 2476
f9150e54 2477 buf=cv->value;
d02b48c6
RE
2478 if ((nid=OBJ_txt2nid(type)) == NID_undef)
2479 {
2480 if (strcmp(type, "SPKAC") == 0)
2481 {
8ce97163 2482 spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
d02b48c6
RE
2483 if (spki == NULL)
2484 {
2485 BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2486 ERR_print_errors(bio_err);
2487 goto err;
2488 }
2489 }
2490 continue;
2491 }
2492
89da653f
BM
2493 /*
2494 if ((nid == NID_pkcs9_emailAddress) && (email_dn == 0))
2495 continue;
2496 */
2497
d02b48c6
RE
2498 j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
2499 if (fix_data(nid, &j) == 0)
2500 {
2501 BIO_printf(bio_err,
2502 "invalid characters in string %s\n",buf);
2503 goto err;
2504 }
2505
2506 if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
2507 (unsigned char *)buf,
2508 strlen(buf))) == NULL)
2509 goto err;
2510
74400f73 2511 if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
d02b48c6
RE
2512 }
2513 if (spki == NULL)
2514 {
2515 BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2516 infile);
2517 goto err;
2518 }
2519
2520 /*
2521 * Now extract the key from the SPKI structure.
2522 */
2523
2524 BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2525
8ce97163 2526 if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
d02b48c6
RE
2527 {
2528 BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2529 goto err;
2530 }
2531
2532 j = NETSCAPE_SPKI_verify(spki, pktmp);
2533 if (j <= 0)
2534 {
2535 BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2536 goto err;
2537 }
2538 BIO_printf(bio_err,"Signature ok\n");
2539
2540 X509_REQ_set_pubkey(req,pktmp);
10061c7c 2541 EVP_PKEY_free(pktmp);
89da653f 2542 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,email_dn,startdate,enddate,
535d79da
DSH
2543 days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op,
2544 ext_copy);
d02b48c6
RE
2545err:
2546 if (req != NULL) X509_REQ_free(req);
2547 if (parms != NULL) CONF_free(parms);
d02b48c6
RE
2548 if (spki != NULL) NETSCAPE_SPKI_free(spki);
2549 if (ne != NULL) X509_NAME_ENTRY_free(ne);
2550
2551 return(ok);
2552 }
2553
6b691a5c 2554static int fix_data(int nid, int *type)
d02b48c6
RE
2555 {
2556 if (nid == NID_pkcs9_emailAddress)
2557 *type=V_ASN1_IA5STRING;
2558 if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
2559 *type=V_ASN1_T61STRING;
2560 if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
2561 *type=V_ASN1_T61STRING;
2562 if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
2563 return(0);
2564 if (nid == NID_pkcs9_unstructuredName)
2565 *type=V_ASN1_IA5STRING;
2566 return(1);
2567 }
2568
6b691a5c 2569static int check_time_format(char *str)
d02b48c6
RE
2570 {
2571 ASN1_UTCTIME tm;
2572
2573 tm.data=(unsigned char *)str;
2574 tm.length=strlen(str);
2575 tm.type=V_ASN1_UTCTIME;
2576 return(ASN1_UTCTIME_check(&tm));
2577 }
2578
a6b7ffdd 2579static int do_revoke(X509 *x509, TXT_DB *db, int type, char *value)
c67cdb50 2580 {
a6b7ffdd 2581 ASN1_UTCTIME *tm=NULL;
b1c4fe36 2582 char *row[DB_NUMBER],**rrow,**irow;
a6b7ffdd 2583 char *rev_str = NULL;
a0ad17bb 2584 BIGNUM *bn = NULL;
b1c4fe36
BM
2585 int ok=-1,i;
2586
2587 for (i=0; i<DB_NUMBER; i++)
2588 row[i]=NULL;
a0ad17bb
DSH
2589 row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2590 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2591 row[DB_serial]=BN_bn2hex(bn);
2592 BN_free(bn);
b1c4fe36
BM
2593 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2594 {
26a3a48d 2595 BIO_printf(bio_err,"Memory allocation failure\n");
b1c4fe36
BM
2596 goto err;
2597 }
a0ad17bb
DSH
2598 /* We have to lookup by serial number because name lookup
2599 * skips revoked certs
2600 */
2601 rrow=TXT_DB_get_by_index(db,DB_serial,row);
b1c4fe36
BM
2602 if (rrow == NULL)
2603 {
2604 BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]);
2605
2606 /* We now just add it to the database */
26a3a48d 2607 row[DB_type]=(char *)OPENSSL_malloc(2);
b1c4fe36
BM
2608
2609 tm=X509_get_notAfter(x509);
26a3a48d 2610 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
b1c4fe36
BM
2611 memcpy(row[DB_exp_date],tm->data,tm->length);
2612 row[DB_exp_date][tm->length]='\0';
2613
2614 row[DB_rev_date]=NULL;
2615
2616 /* row[DB_serial] done already */
26a3a48d 2617 row[DB_file]=(char *)OPENSSL_malloc(8);
b1c4fe36
BM
2618
2619 /* row[DB_name] done already */
2620
2621 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2622 (row[DB_file] == NULL))
2623 {
26a3a48d 2624 BIO_printf(bio_err,"Memory allocation failure\n");
b1c4fe36
BM
2625 goto err;
2626 }
2627 strcpy(row[DB_file],"unknown");
2628 row[DB_type][0]='V';
2629 row[DB_type][1]='\0';
2630
26a3a48d 2631 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
b1c4fe36 2632 {
26a3a48d 2633 BIO_printf(bio_err,"Memory allocation failure\n");
b1c4fe36
BM
2634 goto err;
2635 }
2636
2637 for (i=0; i<DB_NUMBER; i++)
2638 {
2639 irow[i]=row[i];
2640 row[i]=NULL;
2641 }
2642 irow[DB_NUMBER]=NULL;
2643
2644 if (!TXT_DB_insert(db,irow))
2645 {
2646 BIO_printf(bio_err,"failed to update database\n");
2647 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2648 goto err;
2649 }
2650
2651 /* Revoke Certificate */
a6b7ffdd 2652 ok = do_revoke(x509,db, type, value);
b1c4fe36 2653
b1c4fe36
BM
2654 goto err;
2655
2656 }
35a99b63 2657 else if (index_name_cmp((const char **)row,(const char **)rrow))
b1c4fe36 2658 {
a0ad17bb
DSH
2659 BIO_printf(bio_err,"ERROR:name does not match %s\n",
2660 row[DB_name]);
b1c4fe36
BM
2661 goto err;
2662 }
2663 else if (rrow[DB_type][0]=='R')
2664 {
2665 BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2666 row[DB_serial]);
2667 goto err;
2668 }
2669 else
2670 {
2671 BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
a6b7ffdd
DSH
2672 rev_str = make_revocation_str(type, value);
2673 if (!rev_str)
2674 {
2675 BIO_printf(bio_err, "Error in revocation arguments\n");
2676 goto err;
2677 }
b1c4fe36
BM
2678 rrow[DB_type][0]='R';
2679 rrow[DB_type][1]='\0';
a6b7ffdd 2680 rrow[DB_rev_date] = rev_str;
b1c4fe36
BM
2681 }
2682 ok=1;
f9a25931 2683err:
b1c4fe36
BM
2684 for (i=0; i<DB_NUMBER; i++)
2685 {
2686 if (row[i] != NULL)
26a3a48d 2687 OPENSSL_free(row[i]);
b1c4fe36 2688 }
b1c4fe36 2689 return(ok);
c67cdb50
BM
2690 }
2691
2692static int get_certificate_status(const char *serial, TXT_DB *db)
2693 {
8e5b6314 2694 char *row[DB_NUMBER],**rrow;
c67cdb50
BM
2695 int ok=-1,i;
2696
2697 /* Free Resources */
2698 for (i=0; i<DB_NUMBER; i++)
2699 row[i]=NULL;
2700
2701 /* Malloc needed char spaces */
2702 row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2703 if (row[DB_serial] == NULL)
2704 {
2705 BIO_printf(bio_err,"Malloc failure\n");
2706 goto err;
2707 }
2708
2709 if (strlen(serial) % 2)
2710 {
2711 /* Set the first char to 0 */;
2712 row[DB_serial][0]='0';
2713
2714 /* Copy String from serial to row[DB_serial] */
2715 memcpy(row[DB_serial]+1, serial, strlen(serial));
2716 row[DB_serial][strlen(serial)+1]='\0';
2717 }
2718 else
2719 {
2720 /* Copy String from serial to row[DB_serial] */
2721 memcpy(row[DB_serial], serial, strlen(serial));
2722 row[DB_serial][strlen(serial)]='\0';
2723 }
2724
2725 /* Make it Upper Case */
2726 for (i=0; row[DB_serial][i] != '\0'; i++)
dfebac32
BM
2727 row[DB_serial][i] = toupper(row[DB_serial][i]);
2728
c67cdb50
BM
2729
2730 ok=1;
2731
2732 /* Search for the certificate */
2733 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2734 if (rrow == NULL)
2735 {
2736 BIO_printf(bio_err,"Serial %s not present in db.\n",
2737 row[DB_serial]);
2738 ok=-1;
2739 goto err;
2740 }
2741 else if (rrow[DB_type][0]=='V')
2742 {
2743 BIO_printf(bio_err,"%s=Valid (%c)\n",
2744 row[DB_serial], rrow[DB_type][0]);
2745 goto err;
2746 }
2747 else if (rrow[DB_type][0]=='R')
2748 {
2749 BIO_printf(bio_err,"%s=Revoked (%c)\n",
2750 row[DB_serial], rrow[DB_type][0]);
2751 goto err;
2752 }
2753 else if (rrow[DB_type][0]=='E')
2754 {
2755 BIO_printf(bio_err,"%s=Expired (%c)\n",
2756 row[DB_serial], rrow[DB_type][0]);
2757 goto err;
2758 }
2759 else if (rrow[DB_type][0]=='S')
2760 {
2761 BIO_printf(bio_err,"%s=Suspended (%c)\n",
2762 row[DB_serial], rrow[DB_type][0]);
2763 goto err;
2764 }
2765 else
2766 {
2767 BIO_printf(bio_err,"%s=Unknown (%c).\n",
2768 row[DB_serial], rrow[DB_type][0]);
2769 ok=-1;
2770 }
2771err:
2772 for (i=0; i<DB_NUMBER; i++)
2773 {
2774 if (row[i] != NULL)
2775 OPENSSL_free(row[i]);
2776 }
2777 return(ok);
2778 }
2779
2780static int do_updatedb (TXT_DB *db)
2781 {
2782 ASN1_UTCTIME *a_tm = NULL;
2783 int i, cnt = 0;
2784 int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */
2785 char **rrow, *a_tm_s;
2786
2787 a_tm = ASN1_UTCTIME_new();
2788
2789 /* get actual time and make a string */
2790 a_tm = X509_gmtime_adj(a_tm, 0);
2791 a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2792 if (a_tm_s == NULL)
2793 {
2794 cnt = -1;
2795 goto err;
2796 }
2797
2798 memcpy(a_tm_s, a_tm->data, a_tm->length);
2799 a_tm_s[a_tm->length] = '\0';
2800
2801 if (strncmp(a_tm_s, "49", 2) <= 0)
2802 a_y2k = 1;
2803 else
2804 a_y2k = 0;
f9a25931 2805
c67cdb50
BM
2806 for (i = 0; i < sk_num(db->data); i++)
2807 {
2808 rrow = (char **) sk_value(db->data, i);
2809
2810 if (rrow[DB_type][0] == 'V')
2811 {
2812 /* ignore entries that are not valid */
2813 if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2814 db_y2k = 1;
2815 else
2816 db_y2k = 0;
2817
2818 if (db_y2k == a_y2k)
2819 {
2820 /* all on the same y2k side */
2821 if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2822 {
2823 rrow[DB_type][0] = 'E';
2824 rrow[DB_type][1] = '\0';
2825 cnt++;
2826
2827 BIO_printf(bio_err, "%s=Expired\n",
2828 rrow[DB_serial]);
2829 }
2830 }
2831 else if (db_y2k < a_y2k)
2832 {
2833 rrow[DB_type][0] = 'E';
2834 rrow[DB_type][1] = '\0';
2835 cnt++;
2836
2837 BIO_printf(bio_err, "%s=Expired\n",
2838 rrow[DB_serial]);
2839 }
2840
2841 }
2842 }
2843
2844err:
2845
2846 ASN1_UTCTIME_free(a_tm);
2847 OPENSSL_free(a_tm_s);
2848
2849 return (cnt);
2850 }
a6b7ffdd
DSH
2851
2852static char *crl_reasons[] = {
2853 /* CRL reason strings */
2854 "unspecified",
2855 "keyCompromise",
2856 "CACompromise",
2857 "affiliationChanged",
2858 "superseded",
2859 "cessationOfOperation",
2860 "certificateHold",
2861 "removeFromCRL",
2862 /* Additional pseudo reasons */
2863 "holdInstruction",
2864 "keyTime",
2865 "CAkeyTime"
2866};
2867
2868#define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2869
2870/* Given revocation information convert to a DB string.
2871 * The format of the string is:
2872 * revtime[,reason,extra]. Where 'revtime' is the
2873 * revocation time (the current time). 'reason' is the
2874 * optional CRL reason and 'extra' is any additional
2875 * argument
2876 */
2877
2878char *make_revocation_str(int rev_type, char *rev_arg)
2879 {
2880 char *reason = NULL, *other = NULL, *str;
2881 ASN1_OBJECT *otmp;
2882 ASN1_UTCTIME *revtm = NULL;
2883 int i;
2884 switch (rev_type)
2885 {
2886 case REV_NONE:
2887 break;
2888
2889 case REV_CRL_REASON:
2890 for (i = 0; i < 8; i++)
2891 {
2892 if (!strcasecmp(rev_arg, crl_reasons[i]))
2893 {
2894 reason = crl_reasons[i];
2895 break;
2896 }
2897 }
2898 if (reason == NULL)
2899 {
2900 BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2901 return NULL;
2902 }
2903 break;
2904
2905 case REV_HOLD:
2906 /* Argument is an OID */
2907
2908 otmp = OBJ_txt2obj(rev_arg, 0);
2909 ASN1_OBJECT_free(otmp);
2910
2911 if (otmp == NULL)
2912 {
2913 BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2914 return NULL;
2915 }
2916
2917 reason = "holdInstruction";
2918 other = rev_arg;
2919 break;
2920
2921 case REV_KEY_COMPROMISE:
2922 case REV_CA_COMPROMISE:
2923
2924 /* Argument is the key compromise time */
2925 if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg))
2926 {
2927 BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg);
2928 return NULL;
2929 }
2930 other = rev_arg;
2931 if (rev_type == REV_KEY_COMPROMISE)
2932 reason = "keyTime";
2933 else
2934 reason = "CAkeyTime";
2935
2936 break;
2937
2938 }
2939
2940 revtm = X509_gmtime_adj(NULL, 0);
2941
2942 i = revtm->length + 1;
2943
2944 if (reason) i += strlen(reason) + 1;
2945 if (other) i += strlen(other) + 1;
2946
2947 str = OPENSSL_malloc(i);
2948
2949 if (!str) return NULL;
2950
2951 strcpy(str, (char *)revtm->data);
2952 if (reason)
2953 {
2954 strcat(str, ",");
2955 strcat(str, reason);
2956 }
2957 if (other)
2958 {
2959 strcat(str, ",");
2960 strcat(str, other);
2961 }
2962 ASN1_UTCTIME_free(revtm);
2963 return str;
2964 }
2965
2966/* Convert revocation field to X509_REVOKED entry
2967 * return code:
2968 * 0 error
2969 * 1 OK
2970 * 2 OK and some extensions added (i.e. V2 CRL)
2971 */
2972
ee306a13 2973
a6b7ffdd
DSH
2974int make_revoked(X509_REVOKED *rev, char *str)
2975 {
2976 char *tmp = NULL;
a6b7ffdd
DSH
2977 int reason_code = -1;
2978 int i, ret = 0;
2979 ASN1_OBJECT *hold = NULL;
2980 ASN1_GENERALIZEDTIME *comp_time = NULL;
2981 ASN1_ENUMERATED *rtmp = NULL;
a6b7ffdd 2982
35bf3541 2983 ASN1_TIME *revDate = NULL;
a6b7ffdd 2984
35bf3541 2985 i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str);
a6b7ffdd 2986
ee306a13 2987 if (i == 0)
a6b7ffdd 2988 goto err;
a6b7ffdd 2989
35bf3541
DSH
2990 if (rev && !X509_REVOKED_set_revocationDate(rev, revDate))
2991 goto err;
2992
a6b7ffdd
DSH
2993 if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
2994 {
2995 rtmp = ASN1_ENUMERATED_new();
2996 if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
2997 goto err;
2998 if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
2999 goto err;
3000 }
3001
3002 if (rev && comp_time)
3003 {
3004 if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
3005 goto err;
3006 }
3007 if (rev && hold)
3008 {
3009 if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
3010 goto err;
3011 }
3012
3013 if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
3014 ret = 2;
3015 else ret = 1;
3016
3017 err:
3018
3019 if (tmp) OPENSSL_free(tmp);
3020 ASN1_OBJECT_free(hold);
3021 ASN1_GENERALIZEDTIME_free(comp_time);
3022 ASN1_ENUMERATED_free(rtmp);
35bf3541 3023 ASN1_TIME_free(revDate);
a6b7ffdd
DSH
3024
3025 return ret;
3026 }
bad40585 3027
c0455cbb
LJ
3028/*
3029 * subject is expected to be in the format /type0=value0/type1=value1/type2=...
3030 * where characters may be escaped by \
3031 */
eee6c81a 3032X509_NAME *do_subject(char *subject, long chtype)
bad40585 3033 {
eee6c81a
DSH
3034 size_t buflen = strlen(subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */
3035 char *buf = OPENSSL_malloc(buflen);
c0455cbb 3036 size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
eee6c81a
DSH
3037 char **ne_types = OPENSSL_malloc(max_ne * sizeof (char *));
3038 char **ne_values = OPENSSL_malloc(max_ne * sizeof (char *));
bad40585 3039
c0455cbb
LJ
3040 char *sp = subject, *bp = buf;
3041 int i, ne_num = 0;
bad40585 3042
c0455cbb
LJ
3043 X509_NAME *n = NULL;
3044 int nid;
bad40585 3045
c0455cbb
LJ
3046 if (!buf || !ne_types || !ne_values)
3047 {
3048 BIO_printf(bio_err, "malloc error\n");
eee6c81a 3049 goto error;
c0455cbb 3050 }
bad40585 3051
c0455cbb
LJ
3052 if (*subject != '/')
3053 {
3054 BIO_printf(bio_err, "Subject does not start with '/'.\n");
eee6c81a 3055 goto error;
c0455cbb
LJ
3056 }
3057 sp++; /* skip leading / */
bad40585 3058
c0455cbb
LJ
3059 while (*sp)
3060 {
3061 /* collect type */
3062 ne_types[ne_num] = bp;
3063 while (*sp)
bad40585 3064 {
c0455cbb
LJ
3065 if (*sp == '\\') /* is there anything to escape in the type...? */
3066 if (*++sp)
3067 *bp++ = *sp++;
3068 else
3069 {
3070 BIO_printf(bio_err, "escape character at end of string\n");
eee6c81a 3071 goto error;
c0455cbb
LJ
3072 }
3073 else if (*sp == '=')
3074 {
3075 sp++;
3076 *bp++ = '\0';
3077 break;
3078 }
3079 else
3080 *bp++ = *sp++;
bad40585 3081 }
c0455cbb
LJ
3082 if (!*sp)
3083 {
3084 BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num);
eee6c81a 3085 goto error;
c0455cbb
LJ
3086 }
3087 ne_values[ne_num] = bp;
3088 while (*sp)
3089 {
3090 if (*sp == '\\')
3091 if (*++sp)
3092 *bp++ = *sp++;
3093 else
3094 {
3095 BIO_printf(bio_err, "escape character at end of string\n");
eee6c81a 3096 goto error;
c0455cbb
LJ
3097 }
3098 else if (*sp == '/')
3099 {
3100 sp++;
c0455cbb
LJ
3101 break;
3102 }
3103 else
3104 *bp++ = *sp++;
3105 }
3106 *bp++ = '\0';
3107 ne_num++;
3108 }
3109
3110 if (!(n = X509_NAME_new()))
eee6c81a 3111 goto error;
bad40585
BM
3112
3113 for (i = 0; i < ne_num; i++)
3114 {
c0455cbb 3115 if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef)
bad40585 3116 {
c0455cbb 3117 BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]);
bad40585
BM
3118 continue;
3119 }
3120
c0455cbb 3121 if (!*ne_values[i])
bad40585 3122 {
c0455cbb 3123 BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]);
bad40585
BM
3124 continue;
3125 }
3126
eee6c81a
DSH
3127 if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,0))
3128 goto error;
bad40585
BM
3129 }
3130
eee6c81a
DSH
3131 OPENSSL_free(ne_values);
3132 OPENSSL_free(ne_types);
3133 OPENSSL_free(buf);
bad40585 3134 return n;
c0455cbb 3135
eee6c81a 3136error:
c0455cbb 3137 X509_NAME_free(n);
eee6c81a
DSH
3138 if (ne_values)
3139 OPENSSL_free(ne_values);
3140 if (ne_types)
3141 OPENSSL_free(ne_types);
3142 if (buf)
3143 OPENSSL_free(buf);
c0455cbb
LJ
3144 return NULL;
3145}
535d79da 3146
535d79da
DSH
3147int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
3148 {
3149 char buf[25],*pbuf, *p;
3150 int j;
3151 j=i2a_ASN1_OBJECT(bp,obj);
3152 pbuf=buf;
3153 for (j=22-j; j>0; j--)
3154 *(pbuf++)=' ';
3155 *(pbuf++)=':';
3156 *(pbuf++)='\0';
3157 BIO_puts(bp,buf);
3158
3159 if (str->type == V_ASN1_PRINTABLESTRING)
3160 BIO_printf(bp,"PRINTABLE:'");
3161 else if (str->type == V_ASN1_T61STRING)
3162 BIO_printf(bp,"T61STRING:'");
3163 else if (str->type == V_ASN1_IA5STRING)
3164 BIO_printf(bp,"IA5STRING:'");
3165 else if (str->type == V_ASN1_UNIVERSALSTRING)
3166 BIO_printf(bp,"UNIVERSALSTRING:'");
3167 else
3168 BIO_printf(bp,"ASN.1 %2d:'",str->type);
3169
3170 p=(char *)str->data;
3171 for (j=str->length; j>0; j--)
3172 {
3173 if ((*p >= ' ') && (*p <= '~'))
3174 BIO_printf(bp,"%c",*p);
3175 else if (*p & 0x80)
3176 BIO_printf(bp,"\\0x%02X",*p);
3177 else if ((unsigned char)*p == 0xf7)
3178 BIO_printf(bp,"^?");
3179 else BIO_printf(bp,"^%c",*p+'@');
3180 p++;
3181 }
3182 BIO_printf(bp,"'\n");
3183 return 1;
3184 }
ee306a13
DSH
3185
3186int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, char *str)
3187 {
3188 char *tmp = NULL;
3189 char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
3190 int reason_code = -1;
3191 int i, ret = 0;
3192 ASN1_OBJECT *hold = NULL;
3193 ASN1_GENERALIZEDTIME *comp_time = NULL;
3194 tmp = BUF_strdup(str);
3195
3196 p = strchr(tmp, ',');
3197
3198 rtime_str = tmp;
3199
3200 if (p)
3201 {
3202 *p = '\0';
3203 p++;
3204 reason_str = p;
3205 p = strchr(p, ',');
3206 if (p)
3207 {
3208 *p = '\0';
3209 arg_str = p + 1;
3210 }
3211 }
3212
3213 if (prevtm)
3214 {
3215 *prevtm = ASN1_UTCTIME_new();
3216 if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str))
3217 {
3218 BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
3219 goto err;
3220 }
3221 }
3222 if (reason_str)
3223 {
3224 for (i = 0; i < NUM_REASONS; i++)
3225 {
3226 if(!strcasecmp(reason_str, crl_reasons[i]))
3227 {
3228 reason_code = i;
3229 break;
3230 }
3231 }
3232 if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS)
3233 {
3234 BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
3235 goto err;
3236 }
3237
3238 if (reason_code == 7)
3239 reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
3240 else if (reason_code == 8) /* Hold instruction */
3241 {
3242 if (!arg_str)
3243 {
3244 BIO_printf(bio_err, "missing hold instruction\n");
3245 goto err;
3246 }
3247 reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
3248 hold = OBJ_txt2obj(arg_str, 0);
3249
3250 if (!hold)
3251 {
3252 BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
3253 goto err;
3254 }
3255 if (phold) *phold = hold;
3256 }
3257 else if ((reason_code == 9) || (reason_code == 10))
3258 {
3259 if (!arg_str)
3260 {
3261 BIO_printf(bio_err, "missing compromised time\n");
3262 goto err;
3263 }
3264 comp_time = ASN1_GENERALIZEDTIME_new();
3265 if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str))
3266 {
3267 BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
3268 goto err;
3269 }
3270 if (reason_code == 9)
3271 reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
3272 else
3273 reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
3274 }
3275 }
3276
3277 if (preason) *preason = reason_code;
3278 if (pinvtm) *pinvtm = comp_time;
3279 else ASN1_GENERALIZEDTIME_free(comp_time);
3280
35bf3541
DSH
3281 ret = 1;
3282
ee306a13
DSH
3283 err:
3284
3285 if (tmp) OPENSSL_free(tmp);
3286 if (!phold) ASN1_OBJECT_free(hold);
3287 if (!pinvtm) ASN1_GENERALIZEDTIME_free(comp_time);
3288
3289 return ret;
3290 }
3291
3292int make_serial_index(TXT_DB *db)
3293 {
3294 if (!TXT_DB_create_index(db, DB_serial, NULL,
3295 LHASH_HASH_FN(index_serial_hash),
3296 LHASH_COMP_FN(index_serial_cmp)))
3297 {
3298 BIO_printf(bio_err,
3299 "error creating serial number index:(%ld,%ld,%ld)\n",
3300 db->error,db->arg1,db->arg2);
3301 return 0;
3302 }
3303 return 1;
3304 }