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