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