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