]> git.ipfire.org Git - thirdparty/openssl.git/blame - apps/ca.c
Reverse the change with the following log, it needs further investigation:
[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 }
30b4c272
RL
702 pkey = load_key(bio_err, keyfile, keyform, key, e,
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 {
1457 BIO_printf(bio_err,"cannot lookup how long until the next CRL is issuer\n");
1458 goto err;
1459 }
1460
1461 if (verbose) BIO_printf(bio_err,"making CRL\n");
1462 if ((crl=X509_CRL_new()) == NULL) goto err;
35bf3541 1463 if (!X509_CRL_set_issuer_name(crl, X509_get_issuer_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
1518 if (pkey->type == EVP_PKEY_ECDSA)
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 {
1694 BIO_printf(bio_err,"error converting number from bin to BIGNUM");
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
2097 row[DB_name]=X509_NAME_oneline(dn_subject,NULL,0);
dfeab068 2098 row[DB_serial]=BN_bn2hex(serial);
d02b48c6
RE
2099 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2100 {
26a3a48d 2101 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
2102 goto err;
2103 }
2104
2105 rrow=TXT_DB_get_by_index(db,DB_name,row);
2106 if (rrow != NULL)
2107 {
2108 BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n",
2109 row[DB_name]);
2110 }
2111 else
2112 {
2113 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2114 if (rrow != NULL)
2115 {
2116 BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
2117 row[DB_serial]);
2118 BIO_printf(bio_err," check the database/serial_file for corruption\n");
2119 }
2120 }
2121
2122 if (rrow != NULL)
2123 {
2124 BIO_printf(bio_err,
2125 "The matching entry has the following details\n");
2126 if (rrow[DB_type][0] == 'E')
2127 p="Expired";
2128 else if (rrow[DB_type][0] == 'R')
2129 p="Revoked";
2130 else if (rrow[DB_type][0] == 'V')
2131 p="Valid";
2132 else
2133 p="\ninvalid type, Data base error\n";
b1c4fe36 2134 BIO_printf(bio_err,"Type :%s\n",p);;
d02b48c6
RE
2135 if (rrow[DB_type][0] == 'R')
2136 {
2137 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2138 BIO_printf(bio_err,"Was revoked on:%s\n",p);
2139 }
2140 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2141 BIO_printf(bio_err,"Expires on :%s\n",p);
2142 p=rrow[DB_serial]; if (p == NULL) p="undef";
2143 BIO_printf(bio_err,"Serial Number :%s\n",p);
2144 p=rrow[DB_file]; if (p == NULL) p="undef";
2145 BIO_printf(bio_err,"File name :%s\n",p);
2146 p=rrow[DB_name]; if (p == NULL) p="undef";
2147 BIO_printf(bio_err,"Subject Name :%s\n",p);
2148 ok= -1; /* This is now a 'bad' error. */
2149 goto err;
2150 }
2151
657e60fa 2152 /* We are now totally happy, lets make and sign the certificate */
d02b48c6
RE
2153 if (verbose)
2154 BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
2155
2156 if ((ret=X509_new()) == NULL) goto err;
2157 ci=ret->cert_info;
2158
2159#ifdef X509_V3
2160 /* Make it an X509 v3 certificate. */
2161 if (!X509_set_version(x509,2)) goto err;
2162#endif
2163
2164 if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
2165 goto err;
2166 if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
2167 goto err;
2168
58964a49 2169 if (strcmp(startdate,"today") == 0)
58964a49 2170 X509_gmtime_adj(X509_get_notBefore(ret),0);
ed7f60fb
DSH
2171 else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
2172
2173 if (enddate == NULL)
58964a49 2174 X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
ed7f60fb
DSH
2175 else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
2176
d02b48c6
RE
2177 if (!X509_set_subject_name(ret,subject)) goto err;
2178
2179 pktmp=X509_REQ_get_pubkey(req);
10061c7c
DSH
2180 i = X509_set_pubkey(ret,pktmp);
2181 EVP_PKEY_free(pktmp);
2182 if (!i) goto err;
d02b48c6
RE
2183
2184 /* Lets add the extensions, if there are any */
b2347661 2185 if (ext_sect)
d02b48c6 2186 {
175b0942 2187 X509V3_CTX ctx;
d02b48c6
RE
2188 if (ci->version == NULL)
2189 if ((ci->version=ASN1_INTEGER_new()) == NULL)
2190 goto err;
2191 ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
2192
2193 /* Free the current entries if any, there should not
657e60fa 2194 * be any I believe */
d02b48c6 2195 if (ci->extensions != NULL)
0b3f827c
BL
2196 sk_X509_EXTENSION_pop_free(ci->extensions,
2197 X509_EXTENSION_free);
d02b48c6 2198
b2347661
DSH
2199 ci->extensions = NULL;
2200
dfebac32 2201 /* Initialize the context structure */
1d48dd00 2202 X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
175b0942 2203
dfebac32
BM
2204 if (extconf)
2205 {
2206 if (verbose)
2207 BIO_printf(bio_err, "Extra configuration file found\n");
2208
2209 /* Use the extconf configuration db LHASH */
b7a26e6d 2210 X509V3_set_nconf(&ctx, extconf);
dfebac32
BM
2211
2212 /* Test the structure (needed?) */
2213 /* X509V3_set_ctx_test(&ctx); */
2214
2215 /* Adds exts contained in the configuration file */
b7a26e6d 2216 if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect,ret))
dfebac32
BM
2217 {
2218 BIO_printf(bio_err,
2219 "ERROR: adding extensions in section %s\n",
2220 ext_sect);
2221 ERR_print_errors(bio_err);
2222 goto err;
2223 }
2224 if (verbose)
2225 BIO_printf(bio_err, "Successfully added extensions from file.\n");
2226 }
2227 else if (ext_sect)
2228 {
2229 /* We found extensions to be set from config file */
b7a26e6d 2230 X509V3_set_nconf(&ctx, lconf);
d02b48c6 2231
b7a26e6d 2232 if(!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret))
dfebac32
BM
2233 {
2234 BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2235 ERR_print_errors(bio_err);
2236 goto err;
2237 }
2238
2239 if (verbose)
2240 BIO_printf(bio_err, "Successfully added extensions from config\n");
2241 }
d02b48c6
RE
2242 }
2243
791bd0cd
DSH
2244 /* Copy extensions from request (if any) */
2245
2246 if (!copy_extensions(ret, req, ext_copy))
2247 {
2248 BIO_printf(bio_err, "ERROR: adding extensions from request\n");
2249 ERR_print_errors(bio_err);
2250 goto err;
2251 }
2252
89da653f
BM
2253 /* Set the right value for the noemailDN option */
2254 if( email_dn == 0 )
2255 {
2256 if (!X509_set_subject_name(ret,dn_subject)) goto err;
2257 }
791bd0cd
DSH
2258
2259 if (!default_op)
2260 {
2261 BIO_printf(bio_err, "Certificate Details:\n");
2262 /* Never print signature details because signature not present */
2263 certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
2264 X509_print_ex(bio_err, ret, nameopt, certopt);
2265 }
2266
2267 BIO_printf(bio_err,"Certificate is to be certified until ");
2268 ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
2269 if (days) BIO_printf(bio_err," (%d days)",days);
2270 BIO_printf(bio_err, "\n");
d02b48c6
RE
2271
2272 if (!batch)
2273 {
791bd0cd 2274
d02b48c6 2275 BIO_printf(bio_err,"Sign the certificate? [y/n]:");
d58d092b 2276 (void)BIO_flush(bio_err);
d02b48c6
RE
2277 buf[0]='\0';
2278 fgets(buf,sizeof(buf)-1,stdin);
2279 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
2280 {
2281 BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
2282 ok=0;
2283 goto err;
2284 }
2285 }
2286
dfeab068 2287
cf1b7d96 2288#ifndef OPENSSL_NO_DSA
c35f549e 2289 if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
b1c4fe36
BM
2290 pktmp=X509_get_pubkey(ret);
2291 if (EVP_PKEY_missing_parameters(pktmp) &&
d02b48c6
RE
2292 !EVP_PKEY_missing_parameters(pkey))
2293 EVP_PKEY_copy_parameters(pktmp,pkey);
10061c7c 2294 EVP_PKEY_free(pktmp);
d02b48c6 2295#endif
4d94ae00
BM
2296#ifndef OPENSSL_NO_ECDSA
2297 if (pkey->type == EVP_PKEY_ECDSA)
2298 dgst = EVP_ecdsa();
2299 pktmp = X509_get_pubkey(ret);
2300 if (EVP_PKEY_missing_parameters(pktmp) &&
2301 !EVP_PKEY_missing_parameters(pkey))
2302 EVP_PKEY_copy_parameters(pktmp, pkey);
2303 EVP_PKEY_free(pktmp);
2304#endif
2305
d02b48c6
RE
2306
2307 if (!X509_sign(ret,pkey,dgst))
2308 goto err;
2309
2310 /* We now just add it to the database */
26a3a48d 2311 row[DB_type]=(char *)OPENSSL_malloc(2);
d02b48c6
RE
2312
2313 tm=X509_get_notAfter(ret);
26a3a48d 2314 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
d02b48c6
RE
2315 memcpy(row[DB_exp_date],tm->data,tm->length);
2316 row[DB_exp_date][tm->length]='\0';
2317
2318 row[DB_rev_date]=NULL;
2319
2320 /* row[DB_serial] done already */
26a3a48d 2321 row[DB_file]=(char *)OPENSSL_malloc(8);
d02b48c6
RE
2322 /* row[DB_name] done already */
2323
2324 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2325 (row[DB_file] == NULL))
2326 {
26a3a48d 2327 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
2328 goto err;
2329 }
2330 strcpy(row[DB_file],"unknown");
2331 row[DB_type][0]='V';
2332 row[DB_type][1]='\0';
2333
26a3a48d 2334 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
d02b48c6 2335 {
26a3a48d 2336 BIO_printf(bio_err,"Memory allocation failure\n");
d02b48c6
RE
2337 goto err;
2338 }
2339
2340 for (i=0; i<DB_NUMBER; i++)
2341 {
2342 irow[i]=row[i];
2343 row[i]=NULL;
2344 }
2345 irow[DB_NUMBER]=NULL;
2346
2347 if (!TXT_DB_insert(db,irow))
2348 {
2349 BIO_printf(bio_err,"failed to update database\n");
2350 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2351 goto err;
2352 }
2353 ok=1;
2354err:
2355 for (i=0; i<DB_NUMBER; i++)
26a3a48d 2356 if (row[i] != NULL) OPENSSL_free(row[i]);
d02b48c6
RE
2357
2358 if (CAname != NULL)
2359 X509_NAME_free(CAname);
2360 if (subject != NULL)
2361 X509_NAME_free(subject);
437db75b
DSH
2362 if ((dn_subject != NULL) && !email_dn)
2363 X509_NAME_free(dn_subject);
79875776
BM
2364 if (tmptm != NULL)
2365 ASN1_UTCTIME_free(tmptm);
d02b48c6
RE
2366 if (ok <= 0)
2367 {
2368 if (ret != NULL) X509_free(ret);
2369 ret=NULL;
2370 }
2371 else
2372 *xret=ret;
2373 return(ok);
2374 }
2375
82fc1d9c 2376static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
d02b48c6 2377 {
d02b48c6
RE
2378
2379 if (output_der)
2380 {
2381 (void)i2d_X509_bio(bp,x);
2382 return;
2383 }
82fc1d9c
DSH
2384#if 0
2385 /* ??? Not needed since X509_print prints all this stuff anyway */
d02b48c6
RE
2386 f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
2387 BIO_printf(bp,"issuer :%s\n",f);
2388
2389 f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
2390 BIO_printf(bp,"subject:%s\n",f);
2391
2392 BIO_puts(bp,"serial :");
2393 i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
2394 BIO_puts(bp,"\n\n");
82fc1d9c 2395#endif
c67cdb50 2396 if (!notext)X509_print(bp,x);
d02b48c6 2397 PEM_write_bio_X509(bp,x);
d02b48c6
RE
2398 }
2399
6b691a5c 2400static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
ba404b5e 2401 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
89da653f
BM
2402 BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate,
2403 long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt,
535d79da 2404 unsigned long nameopt, int default_op, int ext_copy)
d02b48c6 2405 {
ba404b5e 2406 STACK_OF(CONF_VALUE) *sk=NULL;
d02b48c6
RE
2407 LHASH *parms=NULL;
2408 X509_REQ *req=NULL;
2409 CONF_VALUE *cv=NULL;
2410 NETSCAPE_SPKI *spki = NULL;
d02b48c6
RE
2411 X509_REQ_INFO *ri;
2412 char *type,*buf;
2413 EVP_PKEY *pktmp=NULL;
2414 X509_NAME *n=NULL;
2415 X509_NAME_ENTRY *ne=NULL;
2416 int ok= -1,i,j;
2417 long errline;
2418 int nid;
2419
2420 /*
2421 * Load input file into a hash table. (This is just an easy
2422 * way to read and parse the file, then put it into a convenient
2423 * STACK format).
2424 */
2425 parms=CONF_load(NULL,infile,&errline);
2426 if (parms == NULL)
2427 {
2428 BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
2429 ERR_print_errors(bio_err);
2430 goto err;
2431 }
2432
2433 sk=CONF_get_section(parms, "default");
ba404b5e 2434 if (sk_CONF_VALUE_num(sk) == 0)
d02b48c6
RE
2435 {
2436 BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2437 CONF_free(parms);
2438 goto err;
2439 }
2440
2441 /*
2442 * Now create a dummy X509 request structure. We don't actually
2443 * have an X509 request, but we have many of the components
2444 * (a public key, various DN components). The idea is that we
2445 * put these components into the right X509 request structure
2446 * and we can use the same code as if you had a real X509 request.
2447 */
2448 req=X509_REQ_new();
2449 if (req == NULL)
2450 {
2451 ERR_print_errors(bio_err);
2452 goto err;
2453 }
2454
2455 /*
2456 * Build up the subject name set.
2457 */
2458 ri=req->req_info;
2459 n = ri->subject;
2460
2461 for (i = 0; ; i++)
2462 {
ba404b5e 2463 if (sk_CONF_VALUE_num(sk) <= i) break;
d02b48c6 2464
ba404b5e 2465 cv=sk_CONF_VALUE_value(sk,i);
d02b48c6 2466 type=cv->name;
f9150e54
DSH
2467 /* Skip past any leading X. X: X, etc to allow for
2468 * multiple instances
2469 */
c67cdb50
BM
2470 for (buf = cv->name; *buf ; buf++)
2471 if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2472 {
2473 buf++;
2474 if (*buf) type = buf;
2475 break;
2476 }
d02b48c6 2477
f9150e54 2478 buf=cv->value;
d02b48c6
RE
2479 if ((nid=OBJ_txt2nid(type)) == NID_undef)
2480 {
2481 if (strcmp(type, "SPKAC") == 0)
2482 {
8ce97163 2483 spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
d02b48c6
RE
2484 if (spki == NULL)
2485 {
2486 BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2487 ERR_print_errors(bio_err);
2488 goto err;
2489 }
2490 }
2491 continue;
2492 }
2493
89da653f
BM
2494 /*
2495 if ((nid == NID_pkcs9_emailAddress) && (email_dn == 0))
2496 continue;
2497 */
2498
d02b48c6
RE
2499 j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
2500 if (fix_data(nid, &j) == 0)
2501 {
2502 BIO_printf(bio_err,
2503 "invalid characters in string %s\n",buf);
2504 goto err;
2505 }
2506
2507 if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
2508 (unsigned char *)buf,
2509 strlen(buf))) == NULL)
2510 goto err;
2511
74400f73 2512 if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
d02b48c6
RE
2513 }
2514 if (spki == NULL)
2515 {
2516 BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2517 infile);
2518 goto err;
2519 }
2520
2521 /*
2522 * Now extract the key from the SPKI structure.
2523 */
2524
2525 BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2526
8ce97163 2527 if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
d02b48c6
RE
2528 {
2529 BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2530 goto err;
2531 }
2532
2533 j = NETSCAPE_SPKI_verify(spki, pktmp);
2534 if (j <= 0)
2535 {
2536 BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2537 goto err;
2538 }
2539 BIO_printf(bio_err,"Signature ok\n");
2540
2541 X509_REQ_set_pubkey(req,pktmp);
10061c7c 2542 EVP_PKEY_free(pktmp);
89da653f 2543 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,email_dn,startdate,enddate,
535d79da
DSH
2544 days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op,
2545 ext_copy);
d02b48c6
RE
2546err:
2547 if (req != NULL) X509_REQ_free(req);
2548 if (parms != NULL) CONF_free(parms);
d02b48c6
RE
2549 if (spki != NULL) NETSCAPE_SPKI_free(spki);
2550 if (ne != NULL) X509_NAME_ENTRY_free(ne);
2551
2552 return(ok);
2553 }
2554
6b691a5c 2555static int fix_data(int nid, int *type)
d02b48c6
RE
2556 {
2557 if (nid == NID_pkcs9_emailAddress)
2558 *type=V_ASN1_IA5STRING;
2559 if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
2560 *type=V_ASN1_T61STRING;
2561 if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
2562 *type=V_ASN1_T61STRING;
2563 if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
2564 return(0);
2565 if (nid == NID_pkcs9_unstructuredName)
2566 *type=V_ASN1_IA5STRING;
2567 return(1);
2568 }
2569
6b691a5c 2570static int check_time_format(char *str)
d02b48c6
RE
2571 {
2572 ASN1_UTCTIME tm;
2573
2574 tm.data=(unsigned char *)str;
2575 tm.length=strlen(str);
2576 tm.type=V_ASN1_UTCTIME;
2577 return(ASN1_UTCTIME_check(&tm));
2578 }
2579
a6b7ffdd 2580static int do_revoke(X509 *x509, TXT_DB *db, int type, char *value)
c67cdb50 2581 {
a6b7ffdd 2582 ASN1_UTCTIME *tm=NULL;
b1c4fe36 2583 char *row[DB_NUMBER],**rrow,**irow;
a6b7ffdd 2584 char *rev_str = NULL;
a0ad17bb 2585 BIGNUM *bn = NULL;
b1c4fe36
BM
2586 int ok=-1,i;
2587
2588 for (i=0; i<DB_NUMBER; i++)
2589 row[i]=NULL;
a0ad17bb
DSH
2590 row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2591 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2592 row[DB_serial]=BN_bn2hex(bn);
2593 BN_free(bn);
b1c4fe36
BM
2594 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2595 {
26a3a48d 2596 BIO_printf(bio_err,"Memory allocation failure\n");
b1c4fe36
BM
2597 goto err;
2598 }
a0ad17bb
DSH
2599 /* We have to lookup by serial number because name lookup
2600 * skips revoked certs
2601 */
2602 rrow=TXT_DB_get_by_index(db,DB_serial,row);
b1c4fe36
BM
2603 if (rrow == NULL)
2604 {
2605 BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]);
2606
2607 /* We now just add it to the database */
26a3a48d 2608 row[DB_type]=(char *)OPENSSL_malloc(2);
b1c4fe36
BM
2609
2610 tm=X509_get_notAfter(x509);
26a3a48d 2611 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
b1c4fe36
BM
2612 memcpy(row[DB_exp_date],tm->data,tm->length);
2613 row[DB_exp_date][tm->length]='\0';
2614
2615 row[DB_rev_date]=NULL;
2616
2617 /* row[DB_serial] done already */
26a3a48d 2618 row[DB_file]=(char *)OPENSSL_malloc(8);
b1c4fe36
BM
2619
2620 /* row[DB_name] done already */
2621
2622 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2623 (row[DB_file] == NULL))
2624 {
26a3a48d 2625 BIO_printf(bio_err,"Memory allocation failure\n");
b1c4fe36
BM
2626 goto err;
2627 }
2628 strcpy(row[DB_file],"unknown");
2629 row[DB_type][0]='V';
2630 row[DB_type][1]='\0';
2631
26a3a48d 2632 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
b1c4fe36 2633 {
26a3a48d 2634 BIO_printf(bio_err,"Memory allocation failure\n");
b1c4fe36
BM
2635 goto err;
2636 }
2637
2638 for (i=0; i<DB_NUMBER; i++)
2639 {
2640 irow[i]=row[i];
2641 row[i]=NULL;
2642 }
2643 irow[DB_NUMBER]=NULL;
2644
2645 if (!TXT_DB_insert(db,irow))
2646 {
2647 BIO_printf(bio_err,"failed to update database\n");
2648 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2649 goto err;
2650 }
2651
2652 /* Revoke Certificate */
a6b7ffdd 2653 ok = do_revoke(x509,db, type, value);
b1c4fe36 2654
b1c4fe36
BM
2655 goto err;
2656
2657 }
35a99b63 2658 else if (index_name_cmp((const char **)row,(const char **)rrow))
b1c4fe36 2659 {
a0ad17bb
DSH
2660 BIO_printf(bio_err,"ERROR:name does not match %s\n",
2661 row[DB_name]);
b1c4fe36
BM
2662 goto err;
2663 }
2664 else if (rrow[DB_type][0]=='R')
2665 {
2666 BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2667 row[DB_serial]);
2668 goto err;
2669 }
2670 else
2671 {
2672 BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
a6b7ffdd
DSH
2673 rev_str = make_revocation_str(type, value);
2674 if (!rev_str)
2675 {
2676 BIO_printf(bio_err, "Error in revocation arguments\n");
2677 goto err;
2678 }
b1c4fe36
BM
2679 rrow[DB_type][0]='R';
2680 rrow[DB_type][1]='\0';
a6b7ffdd 2681 rrow[DB_rev_date] = rev_str;
b1c4fe36
BM
2682 }
2683 ok=1;
f9a25931 2684err:
b1c4fe36
BM
2685 for (i=0; i<DB_NUMBER; i++)
2686 {
2687 if (row[i] != NULL)
26a3a48d 2688 OPENSSL_free(row[i]);
b1c4fe36 2689 }
b1c4fe36 2690 return(ok);
c67cdb50
BM
2691 }
2692
2693static int get_certificate_status(const char *serial, TXT_DB *db)
2694 {
8e5b6314 2695 char *row[DB_NUMBER],**rrow;
c67cdb50
BM
2696 int ok=-1,i;
2697
2698 /* Free Resources */
2699 for (i=0; i<DB_NUMBER; i++)
2700 row[i]=NULL;
2701
2702 /* Malloc needed char spaces */
2703 row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2704 if (row[DB_serial] == NULL)
2705 {
2706 BIO_printf(bio_err,"Malloc failure\n");
2707 goto err;
2708 }
2709
2710 if (strlen(serial) % 2)
2711 {
2712 /* Set the first char to 0 */;
2713 row[DB_serial][0]='0';
2714
2715 /* Copy String from serial to row[DB_serial] */
2716 memcpy(row[DB_serial]+1, serial, strlen(serial));
2717 row[DB_serial][strlen(serial)+1]='\0';
2718 }
2719 else
2720 {
2721 /* Copy String from serial to row[DB_serial] */
2722 memcpy(row[DB_serial], serial, strlen(serial));
2723 row[DB_serial][strlen(serial)]='\0';
2724 }
2725
2726 /* Make it Upper Case */
2727 for (i=0; row[DB_serial][i] != '\0'; i++)
dfebac32
BM
2728 row[DB_serial][i] = toupper(row[DB_serial][i]);
2729
c67cdb50
BM
2730
2731 ok=1;
2732
2733 /* Search for the certificate */
2734 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2735 if (rrow == NULL)
2736 {
2737 BIO_printf(bio_err,"Serial %s not present in db.\n",
2738 row[DB_serial]);
2739 ok=-1;
2740 goto err;
2741 }
2742 else if (rrow[DB_type][0]=='V')
2743 {
2744 BIO_printf(bio_err,"%s=Valid (%c)\n",
2745 row[DB_serial], rrow[DB_type][0]);
2746 goto err;
2747 }
2748 else if (rrow[DB_type][0]=='R')
2749 {
2750 BIO_printf(bio_err,"%s=Revoked (%c)\n",
2751 row[DB_serial], rrow[DB_type][0]);
2752 goto err;
2753 }
2754 else if (rrow[DB_type][0]=='E')
2755 {
2756 BIO_printf(bio_err,"%s=Expired (%c)\n",
2757 row[DB_serial], rrow[DB_type][0]);
2758 goto err;
2759 }
2760 else if (rrow[DB_type][0]=='S')
2761 {
2762 BIO_printf(bio_err,"%s=Suspended (%c)\n",
2763 row[DB_serial], rrow[DB_type][0]);
2764 goto err;
2765 }
2766 else
2767 {
2768 BIO_printf(bio_err,"%s=Unknown (%c).\n",
2769 row[DB_serial], rrow[DB_type][0]);
2770 ok=-1;
2771 }
2772err:
2773 for (i=0; i<DB_NUMBER; i++)
2774 {
2775 if (row[i] != NULL)
2776 OPENSSL_free(row[i]);
2777 }
2778 return(ok);
2779 }
2780
2781static int do_updatedb (TXT_DB *db)
2782 {
2783 ASN1_UTCTIME *a_tm = NULL;
2784 int i, cnt = 0;
2785 int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */
2786 char **rrow, *a_tm_s;
2787
2788 a_tm = ASN1_UTCTIME_new();
2789
2790 /* get actual time and make a string */
2791 a_tm = X509_gmtime_adj(a_tm, 0);
2792 a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2793 if (a_tm_s == NULL)
2794 {
2795 cnt = -1;
2796 goto err;
2797 }
2798
2799 memcpy(a_tm_s, a_tm->data, a_tm->length);
2800 a_tm_s[a_tm->length] = '\0';
2801
2802 if (strncmp(a_tm_s, "49", 2) <= 0)
2803 a_y2k = 1;
2804 else
2805 a_y2k = 0;
f9a25931 2806
c67cdb50
BM
2807 for (i = 0; i < sk_num(db->data); i++)
2808 {
2809 rrow = (char **) sk_value(db->data, i);
2810
2811 if (rrow[DB_type][0] == 'V')
2812 {
2813 /* ignore entries that are not valid */
2814 if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2815 db_y2k = 1;
2816 else
2817 db_y2k = 0;
2818
2819 if (db_y2k == a_y2k)
2820 {
2821 /* all on the same y2k side */
2822 if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2823 {
2824 rrow[DB_type][0] = 'E';
2825 rrow[DB_type][1] = '\0';
2826 cnt++;
2827
2828 BIO_printf(bio_err, "%s=Expired\n",
2829 rrow[DB_serial]);
2830 }
2831 }
2832 else if (db_y2k < a_y2k)
2833 {
2834 rrow[DB_type][0] = 'E';
2835 rrow[DB_type][1] = '\0';
2836 cnt++;
2837
2838 BIO_printf(bio_err, "%s=Expired\n",
2839 rrow[DB_serial]);
2840 }
2841
2842 }
2843 }
2844
2845err:
2846
2847 ASN1_UTCTIME_free(a_tm);
2848 OPENSSL_free(a_tm_s);
2849
2850 return (cnt);
2851 }
a6b7ffdd
DSH
2852
2853static char *crl_reasons[] = {
2854 /* CRL reason strings */
2855 "unspecified",
2856 "keyCompromise",
2857 "CACompromise",
2858 "affiliationChanged",
2859 "superseded",
2860 "cessationOfOperation",
2861 "certificateHold",
2862 "removeFromCRL",
2863 /* Additional pseudo reasons */
2864 "holdInstruction",
2865 "keyTime",
2866 "CAkeyTime"
2867};
2868
2869#define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2870
2871/* Given revocation information convert to a DB string.
2872 * The format of the string is:
2873 * revtime[,reason,extra]. Where 'revtime' is the
2874 * revocation time (the current time). 'reason' is the
2875 * optional CRL reason and 'extra' is any additional
2876 * argument
2877 */
2878
2879char *make_revocation_str(int rev_type, char *rev_arg)
2880 {
2881 char *reason = NULL, *other = NULL, *str;
2882 ASN1_OBJECT *otmp;
2883 ASN1_UTCTIME *revtm = NULL;
2884 int i;
2885 switch (rev_type)
2886 {
2887 case REV_NONE:
2888 break;
2889
2890 case REV_CRL_REASON:
2891 for (i = 0; i < 8; i++)
2892 {
2893 if (!strcasecmp(rev_arg, crl_reasons[i]))
2894 {
2895 reason = crl_reasons[i];
2896 break;
2897 }
2898 }
2899 if (reason == NULL)
2900 {
2901 BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2902 return NULL;
2903 }
2904 break;
2905
2906 case REV_HOLD:
2907 /* Argument is an OID */
2908
2909 otmp = OBJ_txt2obj(rev_arg, 0);
2910 ASN1_OBJECT_free(otmp);
2911
2912 if (otmp == NULL)
2913 {
2914 BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2915 return NULL;
2916 }
2917
2918 reason = "holdInstruction";
2919 other = rev_arg;
2920 break;
2921
2922 case REV_KEY_COMPROMISE:
2923 case REV_CA_COMPROMISE:
2924
2925 /* Argument is the key compromise time */
2926 if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg))
2927 {
2928 BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg);
2929 return NULL;
2930 }
2931 other = rev_arg;
2932 if (rev_type == REV_KEY_COMPROMISE)
2933 reason = "keyTime";
2934 else
2935 reason = "CAkeyTime";
2936
2937 break;
2938
2939 }
2940
2941 revtm = X509_gmtime_adj(NULL, 0);
2942
2943 i = revtm->length + 1;
2944
2945 if (reason) i += strlen(reason) + 1;
2946 if (other) i += strlen(other) + 1;
2947
2948 str = OPENSSL_malloc(i);
2949
2950 if (!str) return NULL;
2951
2952 strcpy(str, (char *)revtm->data);
2953 if (reason)
2954 {
2955 strcat(str, ",");
2956 strcat(str, reason);
2957 }
2958 if (other)
2959 {
2960 strcat(str, ",");
2961 strcat(str, other);
2962 }
2963 ASN1_UTCTIME_free(revtm);
2964 return str;
2965 }
2966
2967/* Convert revocation field to X509_REVOKED entry
2968 * return code:
2969 * 0 error
2970 * 1 OK
2971 * 2 OK and some extensions added (i.e. V2 CRL)
2972 */
2973
ee306a13 2974
a6b7ffdd
DSH
2975int make_revoked(X509_REVOKED *rev, char *str)
2976 {
2977 char *tmp = NULL;
a6b7ffdd
DSH
2978 int reason_code = -1;
2979 int i, ret = 0;
2980 ASN1_OBJECT *hold = NULL;
2981 ASN1_GENERALIZEDTIME *comp_time = NULL;
2982 ASN1_ENUMERATED *rtmp = NULL;
a6b7ffdd 2983
35bf3541 2984 ASN1_TIME *revDate = NULL;
a6b7ffdd 2985
35bf3541 2986 i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str);
a6b7ffdd 2987
ee306a13 2988 if (i == 0)
a6b7ffdd 2989 goto err;
a6b7ffdd 2990
35bf3541
DSH
2991 if (rev && !X509_REVOKED_set_revocationDate(rev, revDate))
2992 goto err;
2993
a6b7ffdd
DSH
2994 if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
2995 {
2996 rtmp = ASN1_ENUMERATED_new();
2997 if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
2998 goto err;
2999 if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
3000 goto err;
3001 }
3002
3003 if (rev && comp_time)
3004 {
3005 if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
3006 goto err;
3007 }
3008 if (rev && hold)
3009 {
3010 if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
3011 goto err;
3012 }
3013
3014 if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
3015 ret = 2;
3016 else ret = 1;
3017
3018 err:
3019
3020 if (tmp) OPENSSL_free(tmp);
3021 ASN1_OBJECT_free(hold);
3022 ASN1_GENERALIZEDTIME_free(comp_time);
3023 ASN1_ENUMERATED_free(rtmp);
35bf3541 3024 ASN1_TIME_free(revDate);
a6b7ffdd
DSH
3025
3026 return ret;
3027 }
bad40585 3028
c0455cbb
LJ
3029/*
3030 * subject is expected to be in the format /type0=value0/type1=value1/type2=...
3031 * where characters may be escaped by \
3032 */
eee6c81a 3033X509_NAME *do_subject(char *subject, long chtype)
bad40585 3034 {
eee6c81a
DSH
3035 size_t buflen = strlen(subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */
3036 char *buf = OPENSSL_malloc(buflen);
c0455cbb 3037 size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
eee6c81a
DSH
3038 char **ne_types = OPENSSL_malloc(max_ne * sizeof (char *));
3039 char **ne_values = OPENSSL_malloc(max_ne * sizeof (char *));
bad40585 3040
c0455cbb
LJ
3041 char *sp = subject, *bp = buf;
3042 int i, ne_num = 0;
bad40585 3043
c0455cbb
LJ
3044 X509_NAME *n = NULL;
3045 int nid;
bad40585 3046
c0455cbb
LJ
3047 if (!buf || !ne_types || !ne_values)
3048 {
3049 BIO_printf(bio_err, "malloc error\n");
eee6c81a 3050 goto error;
c0455cbb 3051 }
bad40585 3052
c0455cbb
LJ
3053 if (*subject != '/')
3054 {
3055 BIO_printf(bio_err, "Subject does not start with '/'.\n");
eee6c81a 3056 goto error;
c0455cbb
LJ
3057 }
3058 sp++; /* skip leading / */
bad40585 3059
c0455cbb
LJ
3060 while (*sp)
3061 {
3062 /* collect type */
3063 ne_types[ne_num] = bp;
3064 while (*sp)
bad40585 3065 {
c0455cbb
LJ
3066 if (*sp == '\\') /* is there anything to escape in the type...? */
3067 if (*++sp)
3068 *bp++ = *sp++;
3069 else
3070 {
3071 BIO_printf(bio_err, "escape character at end of string\n");
eee6c81a 3072 goto error;
c0455cbb
LJ
3073 }
3074 else if (*sp == '=')
3075 {
3076 sp++;
3077 *bp++ = '\0';
3078 break;
3079 }
3080 else
3081 *bp++ = *sp++;
bad40585 3082 }
c0455cbb
LJ
3083 if (!*sp)
3084 {
3085 BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num);
eee6c81a 3086 goto error;
c0455cbb
LJ
3087 }
3088 ne_values[ne_num] = bp;
3089 while (*sp)
3090 {
3091 if (*sp == '\\')
3092 if (*++sp)
3093 *bp++ = *sp++;
3094 else
3095 {
3096 BIO_printf(bio_err, "escape character at end of string\n");
eee6c81a 3097 goto error;
c0455cbb
LJ
3098 }
3099 else if (*sp == '/')
3100 {
3101 sp++;
c0455cbb
LJ
3102 break;
3103 }
3104 else
3105 *bp++ = *sp++;
3106 }
3107 *bp++ = '\0';
3108 ne_num++;
3109 }
3110
3111 if (!(n = X509_NAME_new()))
eee6c81a 3112 goto error;
bad40585
BM
3113
3114 for (i = 0; i < ne_num; i++)
3115 {
c0455cbb 3116 if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef)
bad40585 3117 {
c0455cbb 3118 BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]);
bad40585
BM
3119 continue;
3120 }
3121
c0455cbb 3122 if (!*ne_values[i])
bad40585 3123 {
c0455cbb 3124 BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]);
bad40585
BM
3125 continue;
3126 }
3127
eee6c81a
DSH
3128 if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,0))
3129 goto error;
bad40585
BM
3130 }
3131
eee6c81a
DSH
3132 OPENSSL_free(ne_values);
3133 OPENSSL_free(ne_types);
3134 OPENSSL_free(buf);
bad40585 3135 return n;
c0455cbb 3136
eee6c81a 3137error:
c0455cbb 3138 X509_NAME_free(n);
eee6c81a
DSH
3139 if (ne_values)
3140 OPENSSL_free(ne_values);
3141 if (ne_types)
3142 OPENSSL_free(ne_types);
3143 if (buf)
3144 OPENSSL_free(buf);
c0455cbb
LJ
3145 return NULL;
3146}
535d79da 3147
535d79da
DSH
3148int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
3149 {
3150 char buf[25],*pbuf, *p;
3151 int j;
3152 j=i2a_ASN1_OBJECT(bp,obj);
3153 pbuf=buf;
3154 for (j=22-j; j>0; j--)
3155 *(pbuf++)=' ';
3156 *(pbuf++)=':';
3157 *(pbuf++)='\0';
3158 BIO_puts(bp,buf);
3159
3160 if (str->type == V_ASN1_PRINTABLESTRING)
3161 BIO_printf(bp,"PRINTABLE:'");
3162 else if (str->type == V_ASN1_T61STRING)
3163 BIO_printf(bp,"T61STRING:'");
3164 else if (str->type == V_ASN1_IA5STRING)
3165 BIO_printf(bp,"IA5STRING:'");
3166 else if (str->type == V_ASN1_UNIVERSALSTRING)
3167 BIO_printf(bp,"UNIVERSALSTRING:'");
3168 else
3169 BIO_printf(bp,"ASN.1 %2d:'",str->type);
3170
3171 p=(char *)str->data;
3172 for (j=str->length; j>0; j--)
3173 {
3174 if ((*p >= ' ') && (*p <= '~'))
3175 BIO_printf(bp,"%c",*p);
3176 else if (*p & 0x80)
3177 BIO_printf(bp,"\\0x%02X",*p);
3178 else if ((unsigned char)*p == 0xf7)
3179 BIO_printf(bp,"^?");
3180 else BIO_printf(bp,"^%c",*p+'@');
3181 p++;
3182 }
3183 BIO_printf(bp,"'\n");
3184 return 1;
3185 }
ee306a13
DSH
3186
3187int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, char *str)
3188 {
3189 char *tmp = NULL;
3190 char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
3191 int reason_code = -1;
3192 int i, ret = 0;
3193 ASN1_OBJECT *hold = NULL;
3194 ASN1_GENERALIZEDTIME *comp_time = NULL;
3195 tmp = BUF_strdup(str);
3196
3197 p = strchr(tmp, ',');
3198
3199 rtime_str = tmp;
3200
3201 if (p)
3202 {
3203 *p = '\0';
3204 p++;
3205 reason_str = p;
3206 p = strchr(p, ',');
3207 if (p)
3208 {
3209 *p = '\0';
3210 arg_str = p + 1;
3211 }
3212 }
3213
3214 if (prevtm)
3215 {
3216 *prevtm = ASN1_UTCTIME_new();
3217 if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str))
3218 {
3219 BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
3220 goto err;
3221 }
3222 }
3223 if (reason_str)
3224 {
3225 for (i = 0; i < NUM_REASONS; i++)
3226 {
3227 if(!strcasecmp(reason_str, crl_reasons[i]))
3228 {
3229 reason_code = i;
3230 break;
3231 }
3232 }
3233 if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS)
3234 {
3235 BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
3236 goto err;
3237 }
3238
3239 if (reason_code == 7)
3240 reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
3241 else if (reason_code == 8) /* Hold instruction */
3242 {
3243 if (!arg_str)
3244 {
3245 BIO_printf(bio_err, "missing hold instruction\n");
3246 goto err;
3247 }
3248 reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
3249 hold = OBJ_txt2obj(arg_str, 0);
3250
3251 if (!hold)
3252 {
3253 BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
3254 goto err;
3255 }
3256 if (phold) *phold = hold;
3257 }
3258 else if ((reason_code == 9) || (reason_code == 10))
3259 {
3260 if (!arg_str)
3261 {
3262 BIO_printf(bio_err, "missing compromised time\n");
3263 goto err;
3264 }
3265 comp_time = ASN1_GENERALIZEDTIME_new();
3266 if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str))
3267 {
3268 BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
3269 goto err;
3270 }
3271 if (reason_code == 9)
3272 reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
3273 else
3274 reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
3275 }
3276 }
3277
3278 if (preason) *preason = reason_code;
3279 if (pinvtm) *pinvtm = comp_time;
3280 else ASN1_GENERALIZEDTIME_free(comp_time);
3281
35bf3541
DSH
3282 ret = 1;
3283
ee306a13
DSH
3284 err:
3285
3286 if (tmp) OPENSSL_free(tmp);
3287 if (!phold) ASN1_OBJECT_free(hold);
3288 if (!pinvtm) ASN1_GENERALIZEDTIME_free(comp_time);
3289
3290 return ret;
3291 }
3292
3293int make_serial_index(TXT_DB *db)
3294 {
3295 if (!TXT_DB_create_index(db, DB_serial, NULL,
3296 LHASH_HASH_FN(index_serial_hash),
3297 LHASH_COMP_FN(index_serial_cmp)))
3298 {
3299 BIO_printf(bio_err,
3300 "error creating serial number index:(%ld,%ld,%ld)\n",
3301 db->error,db->arg1,db->arg2);
3302 return 0;
3303 }
3304 return 1;
3305 }