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