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