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