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