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