Annotation of src/usr.bin/openssl/apps.c, Revision 1.38
1.38 ! deraadt 1: /* $OpenBSD: apps.c,v 1.37 2015/11/14 14:53:14 miod Exp $ */
1.2 jsing 2: /*
3: * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
1.1 jsing 17: /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
18: * All rights reserved.
19: *
20: * This package is an SSL implementation written
21: * by Eric Young (eay@cryptsoft.com).
22: * The implementation was written so as to conform with Netscapes SSL.
23: *
24: * This library is free for commercial and non-commercial use as long as
25: * the following conditions are aheared to. The following conditions
26: * apply to all code found in this distribution, be it the RC4, RSA,
27: * lhash, DES, etc., code; not just the SSL code. The SSL documentation
28: * included with this distribution is covered by the same copyright terms
29: * except that the holder is Tim Hudson (tjh@cryptsoft.com).
30: *
31: * Copyright remains Eric Young's, and as such any Copyright notices in
32: * the code are not to be removed.
33: * If this package is used in a product, Eric Young should be given attribution
34: * as the author of the parts of the library used.
35: * This can be in the form of a textual message at program startup or
36: * in documentation (online or textual) provided with the package.
37: *
38: * Redistribution and use in source and binary forms, with or without
39: * modification, are permitted provided that the following conditions
40: * are met:
41: * 1. Redistributions of source code must retain the copyright
42: * notice, this list of conditions and the following disclaimer.
43: * 2. Redistributions in binary form must reproduce the above copyright
44: * notice, this list of conditions and the following disclaimer in the
45: * documentation and/or other materials provided with the distribution.
46: * 3. All advertising materials mentioning features or use of this software
47: * must display the following acknowledgement:
48: * "This product includes cryptographic software written by
49: * Eric Young (eay@cryptsoft.com)"
50: * The word 'cryptographic' can be left out if the rouines from the library
51: * being used are not cryptographic related :-).
52: * 4. If you include any Windows specific code (or a derivative thereof) from
53: * the apps directory (application code) you must include an acknowledgement:
54: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
55: *
56: * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
57: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
60: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66: * SUCH DAMAGE.
67: *
68: * The licence and distribution terms for any publically available version or
69: * derivative of this code cannot be changed. i.e. this code cannot simply be
70: * copied and put under another distribution licence
71: * [including the GNU Public Licence.]
72: */
73: /* ====================================================================
74: * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
75: *
76: * Redistribution and use in source and binary forms, with or without
77: * modification, are permitted provided that the following conditions
78: * are met:
79: *
80: * 1. Redistributions of source code must retain the above copyright
81: * notice, this list of conditions and the following disclaimer.
82: *
83: * 2. Redistributions in binary form must reproduce the above copyright
84: * notice, this list of conditions and the following disclaimer in
85: * the documentation and/or other materials provided with the
86: * distribution.
87: *
88: * 3. All advertising materials mentioning features or use of this
89: * software must display the following acknowledgment:
90: * "This product includes software developed by the OpenSSL Project
91: * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
92: *
93: * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
94: * endorse or promote products derived from this software without
95: * prior written permission. For written permission, please contact
96: * openssl-core@openssl.org.
97: *
98: * 5. Products derived from this software may not be called "OpenSSL"
99: * nor may "OpenSSL" appear in their names without prior written
100: * permission of the OpenSSL Project.
101: *
102: * 6. Redistributions of any form whatsoever must retain the following
103: * acknowledgment:
104: * "This product includes software developed by the OpenSSL Project
105: * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
106: *
107: * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
108: * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
109: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
110: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
111: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
112: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
113: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
114: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
115: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
116: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
117: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
118: * OF THE POSSIBILITY OF SUCH DAMAGE.
119: * ====================================================================
120: *
121: * This product includes cryptographic software written by Eric Young
122: * (eay@cryptsoft.com). This product includes software written by Tim
123: * Hudson (tjh@cryptsoft.com).
124: *
125: */
126:
127: #include <sys/types.h>
128: #include <sys/stat.h>
129:
130: #include <ctype.h>
131: #include <errno.h>
132: #include <stdio.h>
133: #include <stdlib.h>
134: #include <limits.h>
135: #include <string.h>
136: #include <unistd.h>
137:
138: #include "apps.h"
139:
140: #include <openssl/bn.h>
141: #include <openssl/err.h>
142: #include <openssl/pem.h>
143: #include <openssl/pkcs12.h>
144: #include <openssl/safestack.h>
145: #include <openssl/x509.h>
146: #include <openssl/x509v3.h>
147:
148: #include <openssl/rsa.h>
149:
150: typedef struct {
151: const char *name;
152: unsigned long flag;
153: unsigned long mask;
154: } NAME_EX_TBL;
155:
1.36 bcook 156: UI_METHOD *ui_method = NULL;
1.1 jsing 157:
158: static int set_table_opts(unsigned long *flags, const char *arg,
159: const NAME_EX_TBL *in_tbl);
160: static int set_multi_opts(unsigned long *flags, const char *arg,
161: const NAME_EX_TBL *in_tbl);
162:
163: #if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
164: /* Looks like this stuff is worth moving into separate function */
165: static EVP_PKEY *load_netscape_key(BIO *err, BIO *key, const char *file,
166: const char *key_descrip, int format);
167: #endif
168:
169: int
170: str2fmt(char *s)
171: {
172: if (s == NULL)
173: return FORMAT_UNDEF;
174: if ((*s == 'D') || (*s == 'd'))
175: return (FORMAT_ASN1);
176: else if ((*s == 'T') || (*s == 't'))
177: return (FORMAT_TEXT);
178: else if ((*s == 'N') || (*s == 'n'))
179: return (FORMAT_NETSCAPE);
180: else if ((*s == 'S') || (*s == 's'))
181: return (FORMAT_SMIME);
182: else if ((*s == 'M') || (*s == 'm'))
183: return (FORMAT_MSBLOB);
184: else if ((*s == '1') ||
185: (strcmp(s, "PKCS12") == 0) || (strcmp(s, "pkcs12") == 0) ||
186: (strcmp(s, "P12") == 0) || (strcmp(s, "p12") == 0))
187: return (FORMAT_PKCS12);
188: else if ((*s == 'P') || (*s == 'p')) {
189: if (s[1] == 'V' || s[1] == 'v')
190: return FORMAT_PVK;
191: else
192: return (FORMAT_PEM);
193: } else
194: return (FORMAT_UNDEF);
195: }
196:
197: void
198: program_name(char *in, char *out, int size)
199: {
200: char *p;
201:
202: p = strrchr(in, '/');
203: if (p != NULL)
204: p++;
205: else
206: p = in;
207: strlcpy(out, p, size);
208: }
209:
210: int
211: chopup_args(ARGS *arg, char *buf, int *argc, char **argv[])
212: {
213: int num, i;
214: char *p;
215:
216: *argc = 0;
217: *argv = NULL;
218:
219: i = 0;
220: if (arg->count == 0) {
221: arg->count = 20;
222: arg->data = reallocarray(NULL, arg->count, sizeof(char *));
1.24 lteo 223: if (arg->data == NULL)
224: return 0;
1.1 jsing 225: }
226: for (i = 0; i < arg->count; i++)
227: arg->data[i] = NULL;
228:
229: num = 0;
230: p = buf;
231: for (;;) {
232: /* first scan over white space */
233: if (!*p)
234: break;
235: while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n')))
236: p++;
237: if (!*p)
238: break;
239:
240: /* The start of something good :-) */
241: if (num >= arg->count) {
242: char **tmp_p;
243: int tlen = arg->count + 20;
244: tmp_p = reallocarray(arg->data, tlen, sizeof(char *));
245: if (tmp_p == NULL)
246: return 0;
247: arg->data = tmp_p;
248: arg->count = tlen;
249: /* initialize newly allocated data */
250: for (i = num; i < arg->count; i++)
251: arg->data[i] = NULL;
252: }
253: arg->data[num++] = p;
254:
255: /* now look for the end of this */
256: if ((*p == '\'') || (*p == '\"')) { /* scan for closing
257: * quote */
258: i = *(p++);
259: arg->data[num - 1]++; /* jump over quote */
260: while (*p && (*p != i))
261: p++;
262: *p = '\0';
263: } else {
264: while (*p && ((*p != ' ') &&
265: (*p != '\t') && (*p != '\n')))
266: p++;
267:
268: if (*p == '\0')
269: p--;
270: else
271: *p = '\0';
272: }
273: p++;
274: }
275: *argc = num;
276: *argv = arg->data;
277: return (1);
278: }
279:
280: int
281: dump_cert_text(BIO *out, X509 *x)
282: {
283: char *p;
284:
285: p = X509_NAME_oneline(X509_get_subject_name(x), NULL, 0);
286: BIO_puts(out, "subject=");
287: BIO_puts(out, p);
288: free(p);
289:
290: p = X509_NAME_oneline(X509_get_issuer_name(x), NULL, 0);
291: BIO_puts(out, "\nissuer=");
292: BIO_puts(out, p);
293: BIO_puts(out, "\n");
294: free(p);
295:
296: return 0;
297: }
298:
1.36 bcook 299: int
1.1 jsing 300: ui_open(UI *ui)
301: {
302: return UI_method_get_opener(UI_OpenSSL()) (ui);
303: }
304:
1.36 bcook 305: int
1.1 jsing 306: ui_read(UI *ui, UI_STRING *uis)
307: {
1.36 bcook 308: const char *password;
309: int string_type;
310:
1.1 jsing 311: if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD &&
312: UI_get0_user_data(ui)) {
1.36 bcook 313: string_type = UI_get_string_type(uis);
314: if (string_type == UIT_PROMPT || string_type == UIT_VERIFY) {
315: password =
316: ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
317: if (password && password[0] != '\0') {
318: UI_set_result(ui, uis, password);
319: return 1;
1.1 jsing 320: }
321: }
322: }
323: return UI_method_get_reader(UI_OpenSSL()) (ui, uis);
324: }
325:
1.36 bcook 326: int
1.1 jsing 327: ui_write(UI *ui, UI_STRING *uis)
328: {
1.36 bcook 329: const char *password;
330: int string_type;
331:
1.1 jsing 332: if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD &&
333: UI_get0_user_data(ui)) {
1.36 bcook 334: string_type = UI_get_string_type(uis);
335: if (string_type == UIT_PROMPT || string_type == UIT_VERIFY) {
336: password =
337: ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
338: if (password && password[0] != '\0')
339: return 1;
1.1 jsing 340: }
341: }
342: return UI_method_get_writer(UI_OpenSSL()) (ui, uis);
343: }
344:
1.36 bcook 345: int
1.1 jsing 346: ui_close(UI *ui)
347: {
348: return UI_method_get_closer(UI_OpenSSL()) (ui);
349: }
350:
351: int
352: password_callback(char *buf, int bufsiz, int verify, void *arg)
353: {
354: PW_CB_DATA *cb_tmp = arg;
355: UI *ui = NULL;
356: int res = 0;
357: const char *prompt_info = NULL;
358: const char *password = NULL;
359: PW_CB_DATA *cb_data = (PW_CB_DATA *) cb_tmp;
360:
361: if (cb_data) {
362: if (cb_data->password)
363: password = cb_data->password;
364: if (cb_data->prompt_info)
365: prompt_info = cb_data->prompt_info;
366: }
367: if (password) {
368: res = strlen(password);
369: if (res > bufsiz)
370: res = bufsiz;
371: memcpy(buf, password, res);
372: return res;
373: }
374: ui = UI_new_method(ui_method);
375: if (ui) {
376: int ok = 0;
377: char *buff = NULL;
378: int ui_flags = 0;
379: char *prompt = NULL;
380:
381: prompt = UI_construct_prompt(ui, "pass phrase", prompt_info);
382:
383: ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
384: UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
385:
386: if (ok >= 0)
387: ok = UI_add_input_string(ui, prompt, ui_flags, buf,
388: PW_MIN_LENGTH, bufsiz - 1);
389: if (ok >= 0 && verify) {
390: buff = malloc(bufsiz);
391: ok = UI_add_verify_string(ui, prompt, ui_flags, buff,
392: PW_MIN_LENGTH, bufsiz - 1, buf);
393: }
394: if (ok >= 0)
395: do {
396: ok = UI_process(ui);
397: } while (ok < 0 &&
398: UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
399:
400: if (buff) {
1.34 jsing 401: explicit_bzero(buff, (unsigned int) bufsiz);
1.1 jsing 402: free(buff);
403: }
404: if (ok >= 0)
405: res = strlen(buf);
406: if (ok == -1) {
407: BIO_printf(bio_err, "User interface error\n");
408: ERR_print_errors(bio_err);
1.34 jsing 409: explicit_bzero(buf, (unsigned int) bufsiz);
1.1 jsing 410: res = 0;
411: }
412: if (ok == -2) {
413: BIO_printf(bio_err, "aborted!\n");
1.34 jsing 414: explicit_bzero(buf, (unsigned int) bufsiz);
1.1 jsing 415: res = 0;
416: }
417: UI_free(ui);
418: free(prompt);
419: }
420: return res;
421: }
422:
423: static char *app_get_pass(BIO *err, char *arg, int keepbio);
424:
425: int
426: app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2)
427: {
428: int same;
429:
430: if (!arg2 || !arg1 || strcmp(arg1, arg2))
431: same = 0;
432: else
433: same = 1;
434: if (arg1) {
435: *pass1 = app_get_pass(err, arg1, same);
436: if (!*pass1)
437: return 0;
438: } else if (pass1)
439: *pass1 = NULL;
440: if (arg2) {
441: *pass2 = app_get_pass(err, arg2, same ? 2 : 0);
442: if (!*pass2)
443: return 0;
444: } else if (pass2)
445: *pass2 = NULL;
446: return 1;
447: }
448:
449: static char *
450: app_get_pass(BIO *err, char *arg, int keepbio)
451: {
452: char *tmp, tpass[APP_PASS_LEN];
453: static BIO *pwdbio = NULL;
454: const char *errstr = NULL;
455: int i;
456:
457: if (!strncmp(arg, "pass:", 5))
458: return strdup(arg + 5);
459: if (!strncmp(arg, "env:", 4)) {
460: tmp = getenv(arg + 4);
461: if (!tmp) {
462: BIO_printf(err, "Can't read environment variable %s\n",
463: arg + 4);
464: return NULL;
465: }
466: return strdup(tmp);
467: }
468: if (!keepbio || !pwdbio) {
469: if (!strncmp(arg, "file:", 5)) {
470: pwdbio = BIO_new_file(arg + 5, "r");
471: if (!pwdbio) {
472: BIO_printf(err, "Can't open file %s\n",
473: arg + 5);
474: return NULL;
475: }
476: } else if (!strncmp(arg, "fd:", 3)) {
477: BIO *btmp;
478: i = strtonum(arg + 3, 0, INT_MAX, &errstr);
479: if (errstr) {
480: BIO_printf(err,
481: "Invalid file descriptor %s: %s\n",
482: arg, errstr);
483: return NULL;
484: }
485: pwdbio = BIO_new_fd(i, BIO_NOCLOSE);
486: if (!pwdbio) {
487: BIO_printf(err,
488: "Can't access file descriptor %s\n",
489: arg + 3);
490: return NULL;
491: }
492: /*
493: * Can't do BIO_gets on an fd BIO so add a buffering
494: * BIO
495: */
496: btmp = BIO_new(BIO_f_buffer());
497: pwdbio = BIO_push(btmp, pwdbio);
498: } else if (!strcmp(arg, "stdin")) {
499: pwdbio = BIO_new_fp(stdin, BIO_NOCLOSE);
500: if (!pwdbio) {
501: BIO_printf(err, "Can't open BIO for stdin\n");
502: return NULL;
503: }
504: } else {
505: BIO_printf(err, "Invalid password argument \"%s\"\n",
506: arg);
507: return NULL;
508: }
509: }
510: i = BIO_gets(pwdbio, tpass, APP_PASS_LEN);
511: if (keepbio != 1) {
512: BIO_free_all(pwdbio);
513: pwdbio = NULL;
514: }
515: if (i <= 0) {
516: BIO_printf(err, "Error reading password from BIO\n");
517: return NULL;
518: }
519: tmp = strchr(tpass, '\n');
520: if (tmp)
521: *tmp = 0;
522: return strdup(tpass);
523: }
524:
525: int
526: add_oid_section(BIO *err, CONF *conf)
527: {
528: char *p;
529: STACK_OF(CONF_VALUE) *sktmp;
530: CONF_VALUE *cnf;
531: int i;
532:
533: if (!(p = NCONF_get_string(conf, NULL, "oid_section"))) {
534: ERR_clear_error();
535: return 1;
536: }
537: if (!(sktmp = NCONF_get_section(conf, p))) {
538: BIO_printf(err, "problem loading oid section %s\n", p);
539: return 0;
540: }
541: for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
542: cnf = sk_CONF_VALUE_value(sktmp, i);
543: if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
544: BIO_printf(err, "problem creating object %s=%s\n",
545: cnf->name, cnf->value);
546: return 0;
547: }
548: }
549: return 1;
550: }
551:
552: static int
553: load_pkcs12(BIO *err, BIO *in, const char *desc, pem_password_cb *pem_cb,
554: void *cb_data, EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
555: {
556: const char *pass;
557: char tpass[PEM_BUFSIZE];
558: int len, ret = 0;
559: PKCS12 *p12;
560:
561: p12 = d2i_PKCS12_bio(in, NULL);
562: if (p12 == NULL) {
563: BIO_printf(err, "Error loading PKCS12 file for %s\n", desc);
564: goto die;
565: }
566: /* See if an empty password will do */
567: if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0))
568: pass = "";
569: else {
570: if (!pem_cb)
571: pem_cb = password_callback;
572: len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data);
573: if (len < 0) {
574: BIO_printf(err, "Passpharse callback error for %s\n",
575: desc);
576: goto die;
577: }
578: if (len < PEM_BUFSIZE)
579: tpass[len] = 0;
580: if (!PKCS12_verify_mac(p12, tpass, len)) {
581: BIO_printf(err,
582: "Mac verify error (wrong password?) in PKCS12 file for %s\n", desc);
583: goto die;
584: }
585: pass = tpass;
586: }
587: ret = PKCS12_parse(p12, pass, pkey, cert, ca);
588:
589: die:
590: if (p12)
591: PKCS12_free(p12);
592: return ret;
593: }
594:
595: X509 *
1.35 bcook 596: load_cert(BIO *err, const char *file, int format, const char *pass,
1.1 jsing 597: const char *cert_descrip)
598: {
599: X509 *x = NULL;
600: BIO *cert;
601:
602: if ((cert = BIO_new(BIO_s_file())) == NULL) {
603: ERR_print_errors(err);
604: goto end;
605: }
606: if (file == NULL) {
607: setvbuf(stdin, NULL, _IONBF, 0);
608: BIO_set_fp(cert, stdin, BIO_NOCLOSE);
609: } else {
610: if (BIO_read_filename(cert, file) <= 0) {
611: BIO_printf(err, "Error opening %s %s\n",
612: cert_descrip, file);
613: ERR_print_errors(err);
614: goto end;
615: }
616: }
617:
618: if (format == FORMAT_ASN1)
619: x = d2i_X509_bio(cert, NULL);
620: else if (format == FORMAT_NETSCAPE) {
621: NETSCAPE_X509 *nx;
622: nx = ASN1_item_d2i_bio(ASN1_ITEM_rptr(NETSCAPE_X509),
623: cert, NULL);
624: if (nx == NULL)
625: goto end;
626:
627: if ((strncmp(NETSCAPE_CERT_HDR, (char *) nx->header->data,
628: nx->header->length) != 0)) {
629: NETSCAPE_X509_free(nx);
630: BIO_printf(err,
631: "Error reading header on certificate\n");
632: goto end;
633: }
634: x = nx->cert;
635: nx->cert = NULL;
636: NETSCAPE_X509_free(nx);
637: } else if (format == FORMAT_PEM)
638: x = PEM_read_bio_X509_AUX(cert, NULL, password_callback, NULL);
639: else if (format == FORMAT_PKCS12) {
640: if (!load_pkcs12(err, cert, cert_descrip, NULL, NULL,
641: NULL, &x, NULL))
642: goto end;
643: } else {
644: BIO_printf(err, "bad input format specified for %s\n",
645: cert_descrip);
646: goto end;
647: }
648:
649: end:
650: if (x == NULL) {
651: BIO_printf(err, "unable to load certificate\n");
652: ERR_print_errors(err);
653: }
654: BIO_free(cert);
655: return (x);
656: }
657:
658: EVP_PKEY *
659: load_key(BIO *err, const char *file, int format, int maybe_stdin,
1.35 bcook 660: const char *pass, const char *key_descrip)
1.1 jsing 661: {
662: BIO *key = NULL;
663: EVP_PKEY *pkey = NULL;
664: PW_CB_DATA cb_data;
665:
666: cb_data.password = pass;
667: cb_data.prompt_info = file;
668:
1.35 bcook 669: if (file == NULL && (!maybe_stdin)) {
1.1 jsing 670: BIO_printf(err, "no keyfile specified\n");
671: goto end;
672: }
673: key = BIO_new(BIO_s_file());
674: if (key == NULL) {
675: ERR_print_errors(err);
676: goto end;
677: }
678: if (file == NULL && maybe_stdin) {
679: setvbuf(stdin, NULL, _IONBF, 0);
680: BIO_set_fp(key, stdin, BIO_NOCLOSE);
681: } else if (BIO_read_filename(key, file) <= 0) {
682: BIO_printf(err, "Error opening %s %s\n",
683: key_descrip, file);
684: ERR_print_errors(err);
685: goto end;
686: }
687: if (format == FORMAT_ASN1) {
688: pkey = d2i_PrivateKey_bio(key, NULL);
689: } else if (format == FORMAT_PEM) {
690: pkey = PEM_read_bio_PrivateKey(key, NULL, password_callback, &cb_data);
691: }
692: #if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
693: else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC)
694: pkey = load_netscape_key(err, key, file, key_descrip, format);
695: #endif
696: else if (format == FORMAT_PKCS12) {
697: if (!load_pkcs12(err, key, key_descrip, password_callback, &cb_data,
698: &pkey, NULL, NULL))
699: goto end;
700: }
701: #if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4)
702: else if (format == FORMAT_MSBLOB)
703: pkey = b2i_PrivateKey_bio(key);
704: else if (format == FORMAT_PVK)
705: pkey = b2i_PVK_bio(key, password_callback,
706: &cb_data);
707: #endif
708: else {
709: BIO_printf(err, "bad input format specified for key file\n");
710: goto end;
711: }
712: end:
713: BIO_free(key);
714: if (pkey == NULL) {
715: BIO_printf(err, "unable to load %s\n", key_descrip);
716: ERR_print_errors(err);
717: }
718: return (pkey);
719: }
720:
721: EVP_PKEY *
722: load_pubkey(BIO *err, const char *file, int format, int maybe_stdin,
1.35 bcook 723: const char *pass, const char *key_descrip)
1.1 jsing 724: {
725: BIO *key = NULL;
726: EVP_PKEY *pkey = NULL;
727: PW_CB_DATA cb_data;
728:
729: cb_data.password = pass;
730: cb_data.prompt_info = file;
731:
1.35 bcook 732: if (file == NULL && !maybe_stdin) {
1.1 jsing 733: BIO_printf(err, "no keyfile specified\n");
734: goto end;
735: }
736: key = BIO_new(BIO_s_file());
737: if (key == NULL) {
738: ERR_print_errors(err);
739: goto end;
740: }
741: if (file == NULL && maybe_stdin) {
742: setvbuf(stdin, NULL, _IONBF, 0);
743: BIO_set_fp(key, stdin, BIO_NOCLOSE);
744: } else if (BIO_read_filename(key, file) <= 0) {
745: BIO_printf(err, "Error opening %s %s\n", key_descrip, file);
746: ERR_print_errors(err);
747: goto end;
748: }
749: if (format == FORMAT_ASN1) {
750: pkey = d2i_PUBKEY_bio(key, NULL);
751: }
752: else if (format == FORMAT_ASN1RSA) {
753: RSA *rsa;
754: rsa = d2i_RSAPublicKey_bio(key, NULL);
755: if (rsa) {
756: pkey = EVP_PKEY_new();
757: if (pkey)
758: EVP_PKEY_set1_RSA(pkey, rsa);
759: RSA_free(rsa);
760: } else
761: pkey = NULL;
762: } else if (format == FORMAT_PEMRSA) {
763: RSA *rsa;
764: rsa = PEM_read_bio_RSAPublicKey(key, NULL, password_callback, &cb_data);
765: if (rsa) {
766: pkey = EVP_PKEY_new();
767: if (pkey)
768: EVP_PKEY_set1_RSA(pkey, rsa);
769: RSA_free(rsa);
770: } else
771: pkey = NULL;
772: }
773: else if (format == FORMAT_PEM) {
774: pkey = PEM_read_bio_PUBKEY(key, NULL, password_callback, &cb_data);
775: }
776: #if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
777: else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC)
778: pkey = load_netscape_key(err, key, file, key_descrip, format);
779: #endif
780: #if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
781: else if (format == FORMAT_MSBLOB)
782: pkey = b2i_PublicKey_bio(key);
783: #endif
784: else {
785: BIO_printf(err, "bad input format specified for key file\n");
786: goto end;
787: }
788:
789: end:
790: BIO_free(key);
791: if (pkey == NULL)
792: BIO_printf(err, "unable to load %s\n", key_descrip);
793: return (pkey);
794: }
795:
796: #if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
797: static EVP_PKEY *
798: load_netscape_key(BIO *err, BIO *key, const char *file,
799: const char *key_descrip, int format)
800: {
801: EVP_PKEY *pkey;
802: BUF_MEM *buf;
803: RSA *rsa;
804: const unsigned char *p;
805: int size, i;
806:
807: buf = BUF_MEM_new();
808: pkey = EVP_PKEY_new();
809: size = 0;
810: if (buf == NULL || pkey == NULL)
811: goto error;
812: for (;;) {
813: if (!BUF_MEM_grow_clean(buf, size + 1024 * 10))
814: goto error;
815: i = BIO_read(key, &(buf->data[size]), 1024 * 10);
816: size += i;
817: if (i == 0)
818: break;
819: if (i < 0) {
820: BIO_printf(err, "Error reading %s %s",
821: key_descrip, file);
822: goto error;
823: }
824: }
825: p = (unsigned char *) buf->data;
826: rsa = d2i_RSA_NET(NULL, &p, (long) size, NULL,
827: (format == FORMAT_IISSGC ? 1 : 0));
828: if (rsa == NULL)
829: goto error;
830: BUF_MEM_free(buf);
831: EVP_PKEY_set1_RSA(pkey, rsa);
832: return pkey;
833:
834: error:
835: BUF_MEM_free(buf);
836: EVP_PKEY_free(pkey);
837: return NULL;
838: }
839: #endif /* ndef OPENSSL_NO_RC4 */
840:
841: static int
842: load_certs_crls(BIO *err, const char *file, int format, const char *pass,
1.35 bcook 843: const char *desc, STACK_OF(X509) **pcerts,
1.1 jsing 844: STACK_OF(X509_CRL) **pcrls)
845: {
846: int i;
847: BIO *bio;
848: STACK_OF(X509_INFO) *xis = NULL;
849: X509_INFO *xi;
850: PW_CB_DATA cb_data;
851: int rv = 0;
852:
853: cb_data.password = pass;
854: cb_data.prompt_info = file;
855:
856: if (format != FORMAT_PEM) {
857: BIO_printf(err, "bad input format specified for %s\n", desc);
858: return 0;
859: }
860: if (file == NULL)
861: bio = BIO_new_fp(stdin, BIO_NOCLOSE);
862: else
863: bio = BIO_new_file(file, "r");
864:
865: if (bio == NULL) {
866: BIO_printf(err, "Error opening %s %s\n",
867: desc, file ? file : "stdin");
868: ERR_print_errors(err);
869: return 0;
870: }
871: xis = PEM_X509_INFO_read_bio(bio, NULL, password_callback, &cb_data);
872:
873: BIO_free(bio);
874:
875: if (pcerts) {
876: *pcerts = sk_X509_new_null();
877: if (!*pcerts)
878: goto end;
879: }
880: if (pcrls) {
881: *pcrls = sk_X509_CRL_new_null();
882: if (!*pcrls)
883: goto end;
884: }
885: for (i = 0; i < sk_X509_INFO_num(xis); i++) {
886: xi = sk_X509_INFO_value(xis, i);
887: if (xi->x509 && pcerts) {
888: if (!sk_X509_push(*pcerts, xi->x509))
889: goto end;
890: xi->x509 = NULL;
891: }
892: if (xi->crl && pcrls) {
893: if (!sk_X509_CRL_push(*pcrls, xi->crl))
894: goto end;
895: xi->crl = NULL;
896: }
897: }
898:
899: if (pcerts && sk_X509_num(*pcerts) > 0)
900: rv = 1;
901:
902: if (pcrls && sk_X509_CRL_num(*pcrls) > 0)
903: rv = 1;
904:
905: end:
906: if (xis)
907: sk_X509_INFO_pop_free(xis, X509_INFO_free);
908:
909: if (rv == 0) {
910: if (pcerts) {
911: sk_X509_pop_free(*pcerts, X509_free);
912: *pcerts = NULL;
913: }
914: if (pcrls) {
915: sk_X509_CRL_pop_free(*pcrls, X509_CRL_free);
916: *pcrls = NULL;
917: }
918: BIO_printf(err, "unable to load %s\n",
919: pcerts ? "certificates" : "CRLs");
920: ERR_print_errors(err);
921: }
922: return rv;
923: }
924:
925: STACK_OF(X509) *
926: load_certs(BIO *err, const char *file, int format, const char *pass,
1.35 bcook 927: const char *desc)
1.1 jsing 928: {
929: STACK_OF(X509) *certs;
930:
1.35 bcook 931: if (!load_certs_crls(err, file, format, pass, desc, &certs, NULL))
1.1 jsing 932: return NULL;
933: return certs;
934: }
935:
936: STACK_OF(X509_CRL) *
1.35 bcook 937: load_crls(BIO *err, const char *file, int format, const char *pass,
1.1 jsing 938: const char *desc)
939: {
940: STACK_OF(X509_CRL) *crls;
941:
1.35 bcook 942: if (!load_certs_crls(err, file, format, pass, desc, NULL, &crls))
1.1 jsing 943: return NULL;
944: return crls;
945: }
946:
947: #define X509V3_EXT_UNKNOWN_MASK (0xfL << 16)
948: /* Return error for unknown extensions */
949: #define X509V3_EXT_DEFAULT 0
950: /* Print error for unknown extensions */
951: #define X509V3_EXT_ERROR_UNKNOWN (1L << 16)
952: /* ASN1 parse unknown extensions */
953: #define X509V3_EXT_PARSE_UNKNOWN (2L << 16)
954: /* BIO_dump unknown extensions */
955: #define X509V3_EXT_DUMP_UNKNOWN (3L << 16)
956:
957: #define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \
958: X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION)
959:
960: int
961: set_cert_ex(unsigned long *flags, const char *arg)
962: {
963: static const NAME_EX_TBL cert_tbl[] = {
964: {"compatible", X509_FLAG_COMPAT, 0xffffffffl},
965: {"ca_default", X509_FLAG_CA, 0xffffffffl},
966: {"no_header", X509_FLAG_NO_HEADER, 0},
967: {"no_version", X509_FLAG_NO_VERSION, 0},
968: {"no_serial", X509_FLAG_NO_SERIAL, 0},
969: {"no_signame", X509_FLAG_NO_SIGNAME, 0},
970: {"no_validity", X509_FLAG_NO_VALIDITY, 0},
971: {"no_subject", X509_FLAG_NO_SUBJECT, 0},
972: {"no_issuer", X509_FLAG_NO_ISSUER, 0},
973: {"no_pubkey", X509_FLAG_NO_PUBKEY, 0},
974: {"no_extensions", X509_FLAG_NO_EXTENSIONS, 0},
975: {"no_sigdump", X509_FLAG_NO_SIGDUMP, 0},
976: {"no_aux", X509_FLAG_NO_AUX, 0},
977: {"no_attributes", X509_FLAG_NO_ATTRIBUTES, 0},
978: {"ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK},
979: {"ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
980: {"ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
981: {"ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
982: {NULL, 0, 0}
983: };
984: return set_multi_opts(flags, arg, cert_tbl);
985: }
986:
987: int
988: set_name_ex(unsigned long *flags, const char *arg)
989: {
990: static const NAME_EX_TBL ex_tbl[] = {
991: {"esc_2253", ASN1_STRFLGS_ESC_2253, 0},
992: {"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0},
993: {"esc_msb", ASN1_STRFLGS_ESC_MSB, 0},
994: {"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0},
995: {"utf8", ASN1_STRFLGS_UTF8_CONVERT, 0},
996: {"ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0},
997: {"show_type", ASN1_STRFLGS_SHOW_TYPE, 0},
998: {"dump_all", ASN1_STRFLGS_DUMP_ALL, 0},
999: {"dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0},
1000: {"dump_der", ASN1_STRFLGS_DUMP_DER, 0},
1001: {"compat", XN_FLAG_COMPAT, 0xffffffffL},
1002: {"sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK},
1003: {"sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK},
1004: {"sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK},
1005: {"sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK},
1006: {"dn_rev", XN_FLAG_DN_REV, 0},
1007: {"nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK},
1008: {"sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK},
1009: {"lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK},
1010: {"align", XN_FLAG_FN_ALIGN, 0},
1011: {"oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK},
1012: {"space_eq", XN_FLAG_SPC_EQ, 0},
1013: {"dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0},
1014: {"RFC2253", XN_FLAG_RFC2253, 0xffffffffL},
1015: {"oneline", XN_FLAG_ONELINE, 0xffffffffL},
1016: {"multiline", XN_FLAG_MULTILINE, 0xffffffffL},
1017: {"ca_default", XN_FLAG_MULTILINE, 0xffffffffL},
1018: {NULL, 0, 0}
1019: };
1020: return set_multi_opts(flags, arg, ex_tbl);
1021: }
1022:
1023: int
1024: set_ext_copy(int *copy_type, const char *arg)
1025: {
1026: if (!strcasecmp(arg, "none"))
1027: *copy_type = EXT_COPY_NONE;
1028: else if (!strcasecmp(arg, "copy"))
1029: *copy_type = EXT_COPY_ADD;
1030: else if (!strcasecmp(arg, "copyall"))
1031: *copy_type = EXT_COPY_ALL;
1032: else
1033: return 0;
1034: return 1;
1035: }
1036:
1037: int
1038: copy_extensions(X509 *x, X509_REQ *req, int copy_type)
1039: {
1040: STACK_OF(X509_EXTENSION) *exts = NULL;
1041: X509_EXTENSION *ext, *tmpext;
1042: ASN1_OBJECT *obj;
1043: int i, idx, ret = 0;
1044:
1045: if (!x || !req || (copy_type == EXT_COPY_NONE))
1046: return 1;
1047: exts = X509_REQ_get_extensions(req);
1048:
1049: for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
1050: ext = sk_X509_EXTENSION_value(exts, i);
1051: obj = X509_EXTENSION_get_object(ext);
1052: idx = X509_get_ext_by_OBJ(x, obj, -1);
1053: /* Does extension exist? */
1054: if (idx != -1) {
1055: /* If normal copy don't override existing extension */
1056: if (copy_type == EXT_COPY_ADD)
1057: continue;
1058: /* Delete all extensions of same type */
1059: do {
1060: tmpext = X509_get_ext(x, idx);
1061: X509_delete_ext(x, idx);
1062: X509_EXTENSION_free(tmpext);
1063: idx = X509_get_ext_by_OBJ(x, obj, -1);
1064: } while (idx != -1);
1065: }
1066: if (!X509_add_ext(x, ext, -1))
1067: goto end;
1068: }
1069:
1070: ret = 1;
1071:
1072: end:
1073: sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
1074:
1075: return ret;
1076: }
1077:
1078: static int
1079: set_multi_opts(unsigned long *flags, const char *arg,
1080: const NAME_EX_TBL *in_tbl)
1081: {
1082: STACK_OF(CONF_VALUE) *vals;
1083: CONF_VALUE *val;
1084: int i, ret = 1;
1085:
1086: if (!arg)
1087: return 0;
1088: vals = X509V3_parse_list(arg);
1089: for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
1090: val = sk_CONF_VALUE_value(vals, i);
1091: if (!set_table_opts(flags, val->name, in_tbl))
1092: ret = 0;
1093: }
1094: sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
1095: return ret;
1096: }
1097:
1098: static int
1099: set_table_opts(unsigned long *flags, const char *arg,
1100: const NAME_EX_TBL *in_tbl)
1101: {
1102: char c;
1103: const NAME_EX_TBL *ptbl;
1104:
1105: c = arg[0];
1106: if (c == '-') {
1107: c = 0;
1108: arg++;
1109: } else if (c == '+') {
1110: c = 1;
1111: arg++;
1112: } else
1113: c = 1;
1114:
1115: for (ptbl = in_tbl; ptbl->name; ptbl++) {
1116: if (!strcasecmp(arg, ptbl->name)) {
1117: *flags &= ~ptbl->mask;
1118: if (c)
1119: *flags |= ptbl->flag;
1120: else
1121: *flags &= ~ptbl->flag;
1122: return 1;
1123: }
1124: }
1125: return 0;
1126: }
1127:
1128: void
1129: print_name(BIO *out, const char *title, X509_NAME *nm, unsigned long lflags)
1130: {
1131: char *buf;
1132: char mline = 0;
1133: int indent = 0;
1134:
1135: if (title)
1136: BIO_puts(out, title);
1137: if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
1138: mline = 1;
1139: indent = 4;
1140: }
1141: if (lflags == XN_FLAG_COMPAT) {
1142: buf = X509_NAME_oneline(nm, 0, 0);
1143: BIO_puts(out, buf);
1144: BIO_puts(out, "\n");
1145: free(buf);
1146: } else {
1147: if (mline)
1148: BIO_puts(out, "\n");
1149: X509_NAME_print_ex(out, nm, indent, lflags);
1150: BIO_puts(out, "\n");
1151: }
1152: }
1153:
1154: X509_STORE *
1155: setup_verify(BIO *bp, char *CAfile, char *CApath)
1156: {
1157: X509_STORE *store;
1158: X509_LOOKUP *lookup;
1159:
1160: if (!(store = X509_STORE_new()))
1161: goto end;
1162: lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
1163: if (lookup == NULL)
1164: goto end;
1165: if (CAfile) {
1166: if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) {
1167: BIO_printf(bp, "Error loading file %s\n", CAfile);
1168: goto end;
1169: }
1170: } else
1171: X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
1172:
1173: lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
1174: if (lookup == NULL)
1175: goto end;
1176: if (CApath) {
1177: if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) {
1178: BIO_printf(bp, "Error loading directory %s\n", CApath);
1179: goto end;
1180: }
1181: } else
1182: X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
1183:
1184: ERR_clear_error();
1185: return store;
1186:
1187: end:
1188: X509_STORE_free(store);
1189: return NULL;
1190: }
1191:
1192: int
1193: load_config(BIO *err, CONF *cnf)
1194: {
1195: static int load_config_called = 0;
1196:
1197: if (load_config_called)
1198: return 1;
1199: load_config_called = 1;
1200: if (cnf == NULL)
1201: cnf = config;
1202: if (cnf == NULL)
1203: return 1;
1204:
1205: OPENSSL_load_builtin_modules();
1206:
1207: if (CONF_modules_load(cnf, NULL, 0) <= 0) {
1208: BIO_printf(err, "Error configuring OpenSSL\n");
1209: ERR_print_errors(err);
1210: return 0;
1211: }
1212: return 1;
1213: }
1214:
1215: char *
1216: make_config_name()
1217: {
1218: const char *t = X509_get_default_cert_area();
1219: char *p;
1220:
1221: if (asprintf(&p, "%s/openssl.cnf", t) == -1)
1222: return NULL;
1223: return p;
1224: }
1225:
1226: static unsigned long
1227: index_serial_hash(const OPENSSL_CSTRING *a)
1228: {
1229: const char *n;
1230:
1231: n = a[DB_serial];
1232: while (*n == '0')
1233: n++;
1234: return (lh_strhash(n));
1235: }
1236:
1237: static int
1238: index_serial_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b)
1239: {
1240: const char *aa, *bb;
1241:
1242: for (aa = a[DB_serial]; *aa == '0'; aa++)
1243: ;
1244: for (bb = b[DB_serial]; *bb == '0'; bb++)
1245: ;
1246: return (strcmp(aa, bb));
1247: }
1248:
1249: static int
1250: index_name_qual(char **a)
1251: {
1252: return (a[0][0] == 'V');
1253: }
1254:
1255: static unsigned long
1256: index_name_hash(const OPENSSL_CSTRING *a)
1257: {
1258: return (lh_strhash(a[DB_name]));
1259: }
1260:
1261: int
1262: index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b)
1263: {
1264: return (strcmp(a[DB_name], b[DB_name]));
1265: }
1266:
1267: static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING)
1268: static IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING)
1269: static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING)
1270: static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING)
1271:
1272: BIGNUM *
1273: load_serial(char *serialfile, int create, ASN1_INTEGER **retai)
1274: {
1275: BIO *in = NULL;
1276: BIGNUM *ret = NULL;
1277: char buf[1024];
1278: ASN1_INTEGER *ai = NULL;
1279:
1280: ai = ASN1_INTEGER_new();
1281: if (ai == NULL)
1282: goto err;
1283:
1284: if ((in = BIO_new(BIO_s_file())) == NULL) {
1285: ERR_print_errors(bio_err);
1286: goto err;
1287: }
1288: if (BIO_read_filename(in, serialfile) <= 0) {
1289: if (!create) {
1290: perror(serialfile);
1291: goto err;
1292: } else {
1293: ret = BN_new();
1294: if (ret == NULL || !rand_serial(ret, ai))
1295: BIO_printf(bio_err, "Out of memory\n");
1296: }
1297: } else {
1.38 ! deraadt 1298: if (!a2i_ASN1_INTEGER(in, ai, buf, sizeof buf)) {
1.1 jsing 1299: BIO_printf(bio_err, "unable to load number from %s\n",
1300: serialfile);
1301: goto err;
1302: }
1303: ret = ASN1_INTEGER_to_BN(ai, NULL);
1304: if (ret == NULL) {
1305: BIO_printf(bio_err,
1306: "error converting number from bin to BIGNUM\n");
1307: goto err;
1308: }
1309: }
1310:
1311: if (ret && retai) {
1312: *retai = ai;
1313: ai = NULL;
1314: }
1315:
1316: err:
1317: if (in != NULL)
1318: BIO_free(in);
1319: if (ai != NULL)
1320: ASN1_INTEGER_free(ai);
1321: return (ret);
1322: }
1323:
1324: int
1325: save_serial(char *serialfile, char *suffix, BIGNUM *serial,
1326: ASN1_INTEGER **retai)
1327: {
1.38 ! deraadt 1328: char serialpath[PATH_MAX];
1.1 jsing 1329: BIO *out = NULL;
1330: int ret = 0, n;
1331: ASN1_INTEGER *ai = NULL;
1332:
1333: if (suffix == NULL)
1.38 ! deraadt 1334: n = strlcpy(serialpath, serialfile, sizeof serialpath);
1.1 jsing 1335: else
1.38 ! deraadt 1336: n = snprintf(serialpath, sizeof serialpath, "%s.%s",
1.1 jsing 1337: serialfile, suffix);
1.38 ! deraadt 1338: if (n == -1 || n >= sizeof(serialpath)) {
1.1 jsing 1339: BIO_printf(bio_err, "serial too long\n");
1340: goto err;
1341: }
1342: out = BIO_new(BIO_s_file());
1343: if (out == NULL) {
1344: ERR_print_errors(bio_err);
1345: goto err;
1346: }
1.38 ! deraadt 1347: if (BIO_write_filename(out, serialpath) <= 0) {
1.1 jsing 1348: perror(serialfile);
1349: goto err;
1350: }
1351: if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) {
1352: BIO_printf(bio_err,
1353: "error converting serial to ASN.1 format\n");
1354: goto err;
1355: }
1356: i2a_ASN1_INTEGER(out, ai);
1357: BIO_puts(out, "\n");
1358: ret = 1;
1359: if (retai) {
1360: *retai = ai;
1361: ai = NULL;
1362: }
1363:
1364: err:
1365: if (out != NULL)
1366: BIO_free_all(out);
1367: if (ai != NULL)
1368: ASN1_INTEGER_free(ai);
1369: return (ret);
1370: }
1371:
1372: int
1373: rotate_serial(char *serialfile, char *new_suffix, char *old_suffix)
1374: {
1.38 ! deraadt 1375: char opath[PATH_MAX], npath[PATH_MAX];
1.1 jsing 1376:
1.38 ! deraadt 1377: if (snprintf(npath, sizeof npath, "%s.%s", serialfile,
! 1378: new_suffix) >= sizeof npath) {
1.1 jsing 1379: BIO_printf(bio_err, "file name too long\n");
1380: goto err;
1381: }
1382:
1.38 ! deraadt 1383: if (snprintf(opath, sizeof opath, "%s.%s", serialfile,
! 1384: old_suffix) >= sizeof opath) {
! 1385: BIO_printf(bio_err, "file name too long\n");
! 1386: goto err;
! 1387: }
1.1 jsing 1388:
1.38 ! deraadt 1389: if (rename(serialfile, opath) < 0 &&
1.1 jsing 1390: errno != ENOENT && errno != ENOTDIR) {
1391: BIO_printf(bio_err, "unable to rename %s to %s\n",
1.38 ! deraadt 1392: serialfile, opath);
1.1 jsing 1393: perror("reason");
1394: goto err;
1395: }
1396:
1397:
1.38 ! deraadt 1398: if (rename(npath, serialfile) < 0) {
1.1 jsing 1399: BIO_printf(bio_err, "unable to rename %s to %s\n",
1.38 ! deraadt 1400: npath, serialfile);
1.1 jsing 1401: perror("reason");
1.38 ! deraadt 1402: if (rename(opath, serialfile) < 0) {
1.30 doug 1403: BIO_printf(bio_err, "unable to rename %s to %s\n",
1.38 ! deraadt 1404: opath, serialfile);
1.30 doug 1405: perror("reason");
1406: }
1.1 jsing 1407: goto err;
1408: }
1409: return 1;
1410:
1411: err:
1412: return 0;
1413: }
1414:
1415: int
1416: rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
1417: {
1418: BIGNUM *btmp;
1419: int ret = 0;
1420:
1421: if (b)
1422: btmp = b;
1423: else
1424: btmp = BN_new();
1425:
1426: if (!btmp)
1427: return 0;
1428:
1429: if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
1430: goto error;
1431: if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
1432: goto error;
1433:
1434: ret = 1;
1435:
1436: error:
1437: if (!b)
1438: BN_free(btmp);
1439:
1440: return ret;
1441: }
1442:
1443: CA_DB *
1444: load_index(char *dbfile, DB_ATTR *db_attr)
1445: {
1446: CA_DB *retdb = NULL;
1447: TXT_DB *tmpdb = NULL;
1448: BIO *in = BIO_new(BIO_s_file());
1449: CONF *dbattr_conf = NULL;
1.38 ! deraadt 1450: char attrpath[PATH_MAX];
1.1 jsing 1451: long errorline = -1;
1452:
1453: if (in == NULL) {
1454: ERR_print_errors(bio_err);
1455: goto err;
1456: }
1457: if (BIO_read_filename(in, dbfile) <= 0) {
1458: perror(dbfile);
1459: BIO_printf(bio_err, "unable to open '%s'\n", dbfile);
1460: goto err;
1461: }
1462: if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL)
1463: goto err;
1464:
1.38 ! deraadt 1465: if (snprintf(attrpath, sizeof attrpath, "%s.attr", dbfile)
! 1466: >= sizeof attrpath) {
! 1467: BIO_printf(bio_err, "attr filename too long\n");
! 1468: goto err;
! 1469: }
! 1470:
1.1 jsing 1471: dbattr_conf = NCONF_new(NULL);
1.38 ! deraadt 1472: if (NCONF_load(dbattr_conf, attrpath, &errorline) <= 0) {
1.1 jsing 1473: if (errorline > 0) {
1474: BIO_printf(bio_err,
1475: "error on line %ld of db attribute file '%s'\n",
1.38 ! deraadt 1476: errorline, attrpath);
1.1 jsing 1477: goto err;
1478: } else {
1479: NCONF_free(dbattr_conf);
1480: dbattr_conf = NULL;
1481: }
1482: }
1483: if ((retdb = malloc(sizeof(CA_DB))) == NULL) {
1484: fprintf(stderr, "Out of memory\n");
1485: goto err;
1486: }
1487: retdb->db = tmpdb;
1488: tmpdb = NULL;
1489: if (db_attr)
1490: retdb->attributes = *db_attr;
1491: else {
1492: retdb->attributes.unique_subject = 1;
1493: }
1494:
1495: if (dbattr_conf) {
1496: char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject");
1497: if (p) {
1498: retdb->attributes.unique_subject = parse_yesno(p, 1);
1499: }
1500: }
1501:
1502: err:
1503: if (dbattr_conf)
1504: NCONF_free(dbattr_conf);
1505: if (tmpdb)
1506: TXT_DB_free(tmpdb);
1507: if (in)
1508: BIO_free_all(in);
1509: return retdb;
1510: }
1511:
1512: int
1513: index_index(CA_DB *db)
1514: {
1515: if (!TXT_DB_create_index(db->db, DB_serial, NULL,
1516: LHASH_HASH_FN(index_serial), LHASH_COMP_FN(index_serial))) {
1517: BIO_printf(bio_err,
1518: "error creating serial number index:(%ld,%ld,%ld)\n",
1519: db->db->error, db->db->arg1, db->db->arg2);
1520: return 0;
1521: }
1522: if (db->attributes.unique_subject &&
1523: !TXT_DB_create_index(db->db, DB_name, index_name_qual,
1524: LHASH_HASH_FN(index_name), LHASH_COMP_FN(index_name))) {
1525: BIO_printf(bio_err, "error creating name index:(%ld,%ld,%ld)\n",
1526: db->db->error, db->db->arg1, db->db->arg2);
1527: return 0;
1528: }
1529: return 1;
1530: }
1531:
1532: int
1.38 ! deraadt 1533: save_index(const char *file, const char *suffix, CA_DB *db)
1.1 jsing 1534: {
1.38 ! deraadt 1535: char attrpath[PATH_MAX], dbfile[PATH_MAX];
1.1 jsing 1536: BIO *out = BIO_new(BIO_s_file());
1537: int j;
1538:
1539: if (out == NULL) {
1540: ERR_print_errors(bio_err);
1541: goto err;
1542: }
1.38 ! deraadt 1543: if (snprintf(attrpath, sizeof attrpath, "%s.attr.%s",
! 1544: file, suffix) >= sizeof attrpath) {
! 1545: BIO_printf(bio_err, "file name too long\n");
! 1546: goto err;
! 1547: }
! 1548: if (snprintf(dbfile, sizeof dbfile, "%s.%s",
! 1549: file, suffix) >= sizeof dbfile) {
1.1 jsing 1550: BIO_printf(bio_err, "file name too long\n");
1551: goto err;
1552: }
1553:
1.38 ! deraadt 1554: if (BIO_write_filename(out, dbfile) <= 0) {
1.1 jsing 1555: perror(dbfile);
1556: BIO_printf(bio_err, "unable to open '%s'\n", dbfile);
1557: goto err;
1558: }
1559: j = TXT_DB_write(out, db->db);
1560: if (j <= 0)
1561: goto err;
1562:
1563: BIO_free(out);
1564:
1565: out = BIO_new(BIO_s_file());
1566:
1.38 ! deraadt 1567: if (BIO_write_filename(out, attrpath) <= 0) {
! 1568: perror(attrpath);
! 1569: BIO_printf(bio_err, "unable to open '%s'\n", attrpath);
1.1 jsing 1570: goto err;
1571: }
1572: BIO_printf(out, "unique_subject = %s\n",
1573: db->attributes.unique_subject ? "yes" : "no");
1574: BIO_free(out);
1575:
1576: return 1;
1577:
1578: err:
1579: return 0;
1580: }
1581:
1582: int
1583: rotate_index(const char *dbfile, const char *new_suffix, const char *old_suffix)
1584: {
1.38 ! deraadt 1585: char attrpath[PATH_MAX], nattrpath[PATH_MAX], oattrpath[PATH_MAX];
! 1586: char dbpath[PATH_MAX], odbpath[PATH_MAX];
1.1 jsing 1587:
1.38 ! deraadt 1588: if (snprintf(attrpath, sizeof attrpath, "%s.attr",
! 1589: dbfile) >= sizeof attrpath) {
! 1590: BIO_printf(bio_err, "file name too long\n");
! 1591: goto err;
! 1592: }
! 1593: if (snprintf(nattrpath, sizeof nattrpath, "%s.attr.%s",
! 1594: dbfile, new_suffix) >= sizeof nattrpath) {
! 1595: BIO_printf(bio_err, "file name too long\n");
! 1596: goto err;
! 1597: }
! 1598: if (snprintf(oattrpath, sizeof oattrpath, "%s.attr.%s",
! 1599: dbfile, old_suffix) >= sizeof oattrpath) {
! 1600: BIO_printf(bio_err, "file name too long\n");
! 1601: goto err;
! 1602: }
! 1603: if (snprintf(dbpath, sizeof dbpath, "%s.%s",
! 1604: dbfile, new_suffix) >= sizeof dbpath) {
! 1605: BIO_printf(bio_err, "file name too long\n");
! 1606: goto err;
! 1607: }
! 1608: if (snprintf(odbpath, sizeof odbpath, "%s.%s",
! 1609: dbfile, old_suffix) >= sizeof odbpath) {
1.1 jsing 1610: BIO_printf(bio_err, "file name too long\n");
1611: goto err;
1612: }
1613:
1.38 ! deraadt 1614: if (rename(dbfile, odbpath) < 0 && errno != ENOENT && errno != ENOTDIR) {
1.1 jsing 1615: BIO_printf(bio_err, "unable to rename %s to %s\n",
1.38 ! deraadt 1616: dbfile, odbpath);
1.1 jsing 1617: perror("reason");
1618: goto err;
1619: }
1620:
1.38 ! deraadt 1621: if (rename(dbpath, dbfile) < 0) {
1.1 jsing 1622: BIO_printf(bio_err, "unable to rename %s to %s\n",
1.38 ! deraadt 1623: dbpath, dbfile);
1.1 jsing 1624: perror("reason");
1.38 ! deraadt 1625: if (rename(odbpath, dbfile) < 0) {
1.30 doug 1626: BIO_printf(bio_err, "unable to rename %s to %s\n",
1.38 ! deraadt 1627: odbpath, dbfile);
1.30 doug 1628: perror("reason");
1629: }
1.1 jsing 1630: goto err;
1631: }
1632:
1.38 ! deraadt 1633: if (rename(attrpath, oattrpath) < 0 && errno != ENOENT && errno != ENOTDIR) {
1.1 jsing 1634: BIO_printf(bio_err, "unable to rename %s to %s\n",
1.38 ! deraadt 1635: attrpath, oattrpath);
1.1 jsing 1636: perror("reason");
1.38 ! deraadt 1637: if (rename(dbfile, dbpath) < 0) {
1.30 doug 1638: BIO_printf(bio_err, "unable to rename %s to %s\n",
1.38 ! deraadt 1639: dbfile, dbpath);
1.30 doug 1640: perror("reason");
1641: }
1.38 ! deraadt 1642: if (rename(odbpath, dbfile) < 0) {
1.30 doug 1643: BIO_printf(bio_err, "unable to rename %s to %s\n",
1.38 ! deraadt 1644: odbpath, dbfile);
1.30 doug 1645: perror("reason");
1646: }
1.1 jsing 1647: goto err;
1648: }
1649:
1.38 ! deraadt 1650: if (rename(nattrpath, attrpath) < 0) {
1.1 jsing 1651: BIO_printf(bio_err, "unable to rename %s to %s\n",
1.38 ! deraadt 1652: nattrpath, attrpath);
1.1 jsing 1653: perror("reason");
1.38 ! deraadt 1654: if (rename(oattrpath, attrpath) < 0) {
1.30 doug 1655: BIO_printf(bio_err, "unable to rename %s to %s\n",
1.38 ! deraadt 1656: oattrpath, attrpath);
1.30 doug 1657: perror("reason");
1658: }
1.38 ! deraadt 1659: if (rename(dbfile, dbpath) < 0) {
1.30 doug 1660: BIO_printf(bio_err, "unable to rename %s to %s\n",
1.38 ! deraadt 1661: dbfile, dbpath);
1.30 doug 1662: perror("reason");
1663: }
1.38 ! deraadt 1664: if (rename(odbpath, dbfile) < 0) {
1.30 doug 1665: BIO_printf(bio_err, "unable to rename %s to %s\n",
1.38 ! deraadt 1666: odbpath, dbfile);
1.30 doug 1667: perror("reason");
1668: }
1.1 jsing 1669: goto err;
1670: }
1671: return 1;
1672:
1673: err:
1674: return 0;
1675: }
1676:
1677: void
1678: free_index(CA_DB *db)
1679: {
1680: if (db) {
1681: if (db->db)
1682: TXT_DB_free(db->db);
1683: free(db);
1684: }
1685: }
1686:
1687: int
1688: parse_yesno(const char *str, int def)
1689: {
1690: int ret = def;
1691:
1692: if (str) {
1693: switch (*str) {
1694: case 'f': /* false */
1695: case 'F': /* FALSE */
1696: case 'n': /* no */
1697: case 'N': /* NO */
1698: case '0': /* 0 */
1699: ret = 0;
1700: break;
1701: case 't': /* true */
1702: case 'T': /* TRUE */
1703: case 'y': /* yes */
1704: case 'Y': /* YES */
1705: case '1': /* 1 */
1706: ret = 1;
1707: break;
1708: default:
1709: ret = def;
1710: break;
1711: }
1712: }
1713: return ret;
1714: }
1715:
1716: /*
1717: * subject is expected to be in the format /type0=value0/type1=value1/type2=...
1718: * where characters may be escaped by \
1719: */
1720: X509_NAME *
1721: parse_name(char *subject, long chtype, int multirdn)
1722: {
1723: X509_NAME *name = NULL;
1724: size_t buflen, max_ne;
1725: char **ne_types, **ne_values;
1726: char *buf, *bp, *sp;
1727: int i, nid, ne_num = 0;
1728: int *mval;
1729:
1730: /*
1731: * Buffer to copy the types and values into. Due to escaping the
1732: * copy can only become shorter.
1733: */
1734: buflen = strlen(subject) + 1;
1735: buf = malloc(buflen);
1736:
1737: /* Maximum number of name elements. */
1738: max_ne = buflen / 2 + 1;
1739: ne_types = reallocarray(NULL, max_ne, sizeof(char *));
1740: ne_values = reallocarray(NULL, max_ne, sizeof(char *));
1741: mval = reallocarray(NULL, max_ne, sizeof(int));
1742:
1743: if (buf == NULL || ne_types == NULL || ne_values == NULL ||
1744: mval == NULL) {
1745: BIO_printf(bio_err, "malloc error\n");
1746: goto error;
1747: }
1748:
1749: bp = buf;
1750: sp = subject;
1751:
1752: if (*subject != '/') {
1753: BIO_printf(bio_err, "Subject does not start with '/'.\n");
1754: goto error;
1755: }
1756:
1757: /* Skip leading '/'. */
1758: sp++;
1759:
1760: /* No multivalued RDN by default. */
1761: mval[ne_num] = 0;
1762:
1763: while (*sp) {
1764: /* Collect type. */
1765: ne_types[ne_num] = bp;
1766: while (*sp) {
1767: /* is there anything to escape in the type...? */
1768: if (*sp == '\\') {
1769: if (*++sp)
1770: *bp++ = *sp++;
1771: else {
1772: BIO_printf(bio_err, "escape character "
1773: "at end of string\n");
1774: goto error;
1775: }
1776: } else if (*sp == '=') {
1777: sp++;
1778: *bp++ = '\0';
1779: break;
1780: } else
1781: *bp++ = *sp++;
1782: }
1783: if (!*sp) {
1784: BIO_printf(bio_err, "end of string encountered while "
1785: "processing type of subject name element #%d\n",
1786: ne_num);
1787: goto error;
1788: }
1789: ne_values[ne_num] = bp;
1790: while (*sp) {
1791: if (*sp == '\\') {
1792: if (*++sp)
1793: *bp++ = *sp++;
1794: else {
1795: BIO_printf(bio_err, "escape character "
1796: "at end of string\n");
1797: goto error;
1798: }
1799: } else if (*sp == '/') {
1800: sp++;
1801: /* no multivalued RDN by default */
1802: mval[ne_num + 1] = 0;
1803: break;
1804: } else if (*sp == '+' && multirdn) {
1.37 miod 1805: /* a not escaped + signals a multivalued RDN */
1.1 jsing 1806: sp++;
1807: mval[ne_num + 1] = -1;
1808: break;
1809: } else
1810: *bp++ = *sp++;
1811: }
1812: *bp++ = '\0';
1813: ne_num++;
1814: }
1815:
1816: if ((name = X509_NAME_new()) == NULL)
1817: goto error;
1818:
1819: for (i = 0; i < ne_num; i++) {
1820: if ((nid = OBJ_txt2nid(ne_types[i])) == NID_undef) {
1821: BIO_printf(bio_err,
1822: "Subject Attribute %s has no known NID, skipped\n",
1823: ne_types[i]);
1824: continue;
1825: }
1826: if (!*ne_values[i]) {
1827: BIO_printf(bio_err, "No value provided for Subject "
1828: "Attribute %s, skipped\n", ne_types[i]);
1829: continue;
1830: }
1831: if (!X509_NAME_add_entry_by_NID(name, nid, chtype,
1832: (unsigned char *) ne_values[i], -1, -1, mval[i]))
1833: goto error;
1834: }
1835: goto done;
1836:
1837: error:
1838: X509_NAME_free(name);
1839: name = NULL;
1840:
1841: done:
1842: free(ne_values);
1843: free(ne_types);
1844: free(mval);
1845: free(buf);
1846:
1847: return name;
1848: }
1849:
1850: int
1851: args_verify(char ***pargs, int *pargc, int *badarg, BIO *err,
1852: X509_VERIFY_PARAM **pm)
1853: {
1854: ASN1_OBJECT *otmp = NULL;
1855: unsigned long flags = 0;
1856: int i;
1857: int purpose = 0, depth = -1;
1858: char **oldargs = *pargs;
1859: char *arg = **pargs, *argn = (*pargs)[1];
1860: time_t at_time = 0;
1861: const char *errstr = NULL;
1862:
1863: if (!strcmp(arg, "-policy")) {
1864: if (!argn)
1865: *badarg = 1;
1866: else {
1867: otmp = OBJ_txt2obj(argn, 0);
1868: if (!otmp) {
1869: BIO_printf(err, "Invalid Policy \"%s\"\n",
1870: argn);
1871: *badarg = 1;
1872: }
1873: }
1874: (*pargs)++;
1875: } else if (strcmp(arg, "-purpose") == 0) {
1876: X509_PURPOSE *xptmp;
1877: if (!argn)
1878: *badarg = 1;
1879: else {
1880: i = X509_PURPOSE_get_by_sname(argn);
1881: if (i < 0) {
1882: BIO_printf(err, "unrecognized purpose\n");
1883: *badarg = 1;
1884: } else {
1885: xptmp = X509_PURPOSE_get0(i);
1886: purpose = X509_PURPOSE_get_id(xptmp);
1887: }
1888: }
1889: (*pargs)++;
1890: } else if (strcmp(arg, "-verify_depth") == 0) {
1891: if (!argn)
1892: *badarg = 1;
1893: else {
1894: depth = strtonum(argn, 1, INT_MAX, &errstr);
1895: if (errstr) {
1896: BIO_printf(err, "invalid depth %s: %s\n",
1897: argn, errstr);
1898: *badarg = 1;
1899: }
1900: }
1901: (*pargs)++;
1902: } else if (strcmp(arg, "-attime") == 0) {
1903: if (!argn)
1904: *badarg = 1;
1905: else {
1906: long long timestamp;
1907: /*
1908: * interpret the -attime argument as seconds since
1909: * Epoch
1910: */
1911: if (sscanf(argn, "%lli", ×tamp) != 1) {
1912: BIO_printf(bio_err,
1913: "Error parsing timestamp %s\n",
1914: argn);
1915: *badarg = 1;
1916: }
1917: /* XXX 2038 truncation */
1918: at_time = (time_t) timestamp;
1919: }
1920: (*pargs)++;
1921: } else if (!strcmp(arg, "-ignore_critical"))
1922: flags |= X509_V_FLAG_IGNORE_CRITICAL;
1923: else if (!strcmp(arg, "-issuer_checks"))
1924: flags |= X509_V_FLAG_CB_ISSUER_CHECK;
1925: else if (!strcmp(arg, "-crl_check"))
1926: flags |= X509_V_FLAG_CRL_CHECK;
1927: else if (!strcmp(arg, "-crl_check_all"))
1928: flags |= X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL;
1929: else if (!strcmp(arg, "-policy_check"))
1930: flags |= X509_V_FLAG_POLICY_CHECK;
1931: else if (!strcmp(arg, "-explicit_policy"))
1932: flags |= X509_V_FLAG_EXPLICIT_POLICY;
1933: else if (!strcmp(arg, "-inhibit_any"))
1934: flags |= X509_V_FLAG_INHIBIT_ANY;
1935: else if (!strcmp(arg, "-inhibit_map"))
1936: flags |= X509_V_FLAG_INHIBIT_MAP;
1937: else if (!strcmp(arg, "-x509_strict"))
1938: flags |= X509_V_FLAG_X509_STRICT;
1939: else if (!strcmp(arg, "-extended_crl"))
1940: flags |= X509_V_FLAG_EXTENDED_CRL_SUPPORT;
1941: else if (!strcmp(arg, "-use_deltas"))
1942: flags |= X509_V_FLAG_USE_DELTAS;
1943: else if (!strcmp(arg, "-policy_print"))
1944: flags |= X509_V_FLAG_NOTIFY_POLICY;
1945: else if (!strcmp(arg, "-check_ss_sig"))
1946: flags |= X509_V_FLAG_CHECK_SS_SIGNATURE;
1947: else
1948: return 0;
1949:
1950: if (*badarg) {
1951: if (*pm)
1952: X509_VERIFY_PARAM_free(*pm);
1953: *pm = NULL;
1954: goto end;
1955: }
1956: if (!*pm && !(*pm = X509_VERIFY_PARAM_new())) {
1957: *badarg = 1;
1958: goto end;
1959: }
1.29 beck 1960: if (otmp) {
1.1 jsing 1961: X509_VERIFY_PARAM_add0_policy(*pm, otmp);
1.29 beck 1962: otmp = NULL;
1963: }
1.1 jsing 1964: if (flags)
1965: X509_VERIFY_PARAM_set_flags(*pm, flags);
1966:
1967: if (purpose)
1968: X509_VERIFY_PARAM_set_purpose(*pm, purpose);
1969:
1970: if (depth >= 0)
1971: X509_VERIFY_PARAM_set_depth(*pm, depth);
1972:
1973: if (at_time)
1974: X509_VERIFY_PARAM_set_time(*pm, at_time);
1975:
1976: end:
1977: (*pargs)++;
1978:
1979: if (pargc)
1980: *pargc -= *pargs - oldargs;
1981:
1.29 beck 1982: ASN1_OBJECT_free(otmp);
1.1 jsing 1983: return 1;
1984: }
1985:
1986: /* Read whole contents of a BIO into an allocated memory buffer and
1987: * return it.
1988: */
1989:
1990: int
1991: bio_to_mem(unsigned char **out, int maxlen, BIO *in)
1992: {
1993: BIO *mem;
1994: int len, ret;
1995: unsigned char tbuf[1024];
1996:
1997: mem = BIO_new(BIO_s_mem());
1998: if (!mem)
1999: return -1;
2000: for (;;) {
2001: if ((maxlen != -1) && maxlen < 1024)
2002: len = maxlen;
2003: else
2004: len = 1024;
2005: len = BIO_read(in, tbuf, len);
2006: if (len <= 0)
2007: break;
2008: if (BIO_write(mem, tbuf, len) != len) {
2009: BIO_free(mem);
2010: return -1;
2011: }
2012: maxlen -= len;
2013:
2014: if (maxlen == 0)
2015: break;
2016: }
2017: ret = BIO_get_mem_data(mem, (char **) out);
2018: BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY);
2019: BIO_free(mem);
2020: return ret;
2021: }
2022:
2023: int
2024: pkey_ctrl_string(EVP_PKEY_CTX *ctx, char *value)
2025: {
2026: int rv;
2027: char *stmp, *vtmp = NULL;
2028:
1.11 jsing 2029: if (value == NULL)
2030: return -1;
2031: stmp = strdup(value);
1.1 jsing 2032: if (!stmp)
2033: return -1;
2034: vtmp = strchr(stmp, ':');
2035: if (vtmp) {
2036: *vtmp = 0;
2037: vtmp++;
2038: }
2039: rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp);
2040: free(stmp);
2041:
2042: return rv;
2043: }
2044:
2045: static void
2046: nodes_print(BIO *out, const char *name, STACK_OF(X509_POLICY_NODE) *nodes)
2047: {
2048: X509_POLICY_NODE *node;
2049: int i;
2050:
2051: BIO_printf(out, "%s Policies:", name);
2052: if (nodes) {
2053: BIO_puts(out, "\n");
2054: for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) {
2055: node = sk_X509_POLICY_NODE_value(nodes, i);
2056: X509_POLICY_NODE_print(out, node, 2);
2057: }
2058: } else
2059: BIO_puts(out, " <empty>\n");
2060: }
2061:
2062: void
2063: policies_print(BIO *out, X509_STORE_CTX *ctx)
2064: {
2065: X509_POLICY_TREE *tree;
2066: int explicit_policy;
2067: int free_out = 0;
2068:
2069: if (out == NULL) {
2070: out = BIO_new_fp(stderr, BIO_NOCLOSE);
2071: free_out = 1;
2072: }
2073: tree = X509_STORE_CTX_get0_policy_tree(ctx);
2074: explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx);
2075:
2076: BIO_printf(out, "Require explicit Policy: %s\n",
2077: explicit_policy ? "True" : "False");
2078:
2079: nodes_print(out, "Authority", X509_policy_tree_get0_policies(tree));
2080: nodes_print(out, "User", X509_policy_tree_get0_user_policies(tree));
2081: if (free_out)
2082: BIO_free(out);
2083: }
2084:
2085: /* next_protos_parse parses a comma separated list of strings into a string
2086: * in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
2087: * outlen: (output) set to the length of the resulting buffer on success.
2088: * err: (maybe NULL) on failure, an error message line is written to this BIO.
2089: * in: a NUL termianted string like "abc,def,ghi"
2090: *
2091: * returns: a malloced buffer or NULL on failure.
2092: */
2093: unsigned char *
2094: next_protos_parse(unsigned short *outlen, const char *in)
2095: {
2096: size_t len;
2097: unsigned char *out;
2098: size_t i, start = 0;
2099:
2100: len = strlen(in);
2101: if (len >= 65535)
2102: return NULL;
2103:
2104: out = malloc(strlen(in) + 1);
2105: if (!out)
2106: return NULL;
2107:
2108: for (i = 0; i <= len; ++i) {
2109: if (i == len || in[i] == ',') {
2110: if (i - start > 255) {
2111: free(out);
2112: return NULL;
2113: }
2114: out[start] = i - start;
2115: start = i + 1;
2116: } else
2117: out[i + 1] = in[i];
2118: }
2119:
2120: *outlen = len + 1;
2121: return out;
2122: }
2123:
2124: int
2125: app_isdir(const char *name)
2126: {
2127: struct stat st;
2128:
2129: if (stat(name, &st) == 0)
2130: return S_ISDIR(st.st_mode);
2131: return -1;
1.2 jsing 2132: }
2133:
1.10 jsing 2134: #define OPTION_WIDTH 18
2135:
1.2 jsing 2136: void
2137: options_usage(struct option *opts)
2138: {
1.10 jsing 2139: const char *p, *q;
2140: char optstr[32];
1.2 jsing 2141: int i;
2142:
2143: for (i = 0; opts[i].name != NULL; i++) {
2144: if (opts[i].desc == NULL)
2145: continue;
1.10 jsing 2146:
2147: snprintf(optstr, sizeof(optstr), "-%s %s", opts[i].name,
2148: (opts[i].argname != NULL) ? opts[i].argname : "");
2149: fprintf(stderr, " %-*s", OPTION_WIDTH, optstr);
2150: if (strlen(optstr) > OPTION_WIDTH)
2151: fprintf(stderr, "\n %-*s", OPTION_WIDTH, "");
2152:
2153: p = opts[i].desc;
2154: while ((q = strchr(p, '\n')) != NULL) {
2155: fprintf(stderr, " %.*s", (int)(q - p), p);
2156: fprintf(stderr, "\n %-*s", OPTION_WIDTH, "");
2157: p = q + 1;
2158: }
2159: fprintf(stderr, " %s\n", p);
1.2 jsing 2160: }
2161: }
2162:
2163: int
1.18 jsing 2164: options_parse(int argc, char **argv, struct option *opts, char **unnamed,
2165: int *argsused)
1.2 jsing 2166: {
1.3 jsing 2167: const char *errstr;
1.2 jsing 2168: struct option *opt;
1.3 jsing 2169: long long val;
1.2 jsing 2170: char *arg, *p;
1.20 jsing 2171: int fmt, used;
1.5 jsing 2172: int ord = 0;
1.2 jsing 2173: int i, j;
2174:
1.17 jsing 2175: if (unnamed != NULL)
2176: *unnamed = NULL;
2177:
1.2 jsing 2178: for (i = 1; i < argc; i++) {
2179: p = arg = argv[i];
2180:
1.17 jsing 2181: /* Single unnamed argument (without leading hyphen). */
1.2 jsing 2182: if (*p++ != '-') {
1.18 jsing 2183: if (argsused != NULL)
2184: goto done;
1.2 jsing 2185: if (unnamed == NULL)
2186: goto unknown;
1.17 jsing 2187: if (*unnamed != NULL)
2188: goto toomany;
1.2 jsing 2189: *unnamed = arg;
2190: continue;
2191: }
1.17 jsing 2192:
1.19 jsing 2193: /* End of named options (single hyphen). */
2194: if (*p == '\0') {
2195: if (++i >= argc)
2196: goto done;
2197: if (argsused != NULL)
2198: goto done;
2199: if (unnamed != NULL && i == argc - 1) {
2200: if (*unnamed != NULL)
2201: goto toomany;
2202: *unnamed = argv[i];
2203: continue;
2204: }
1.2 jsing 2205: goto unknown;
1.19 jsing 2206: }
1.2 jsing 2207:
1.20 jsing 2208: /* See if there is a matching option... */
1.2 jsing 2209: for (j = 0; opts[j].name != NULL; j++) {
1.21 jsing 2210: if (strcmp(p, opts[j].name) == 0)
1.16 jsing 2211: break;
2212: }
1.21 jsing 2213: opt = &opts[j];
1.22 jsing 2214: if (opt->name == NULL && opt->type == 0)
1.16 jsing 2215: goto unknown;
1.2 jsing 2216:
1.16 jsing 2217: if (opt->type == OPTION_ARG ||
2218: opt->type == OPTION_ARG_FORMAT ||
2219: opt->type == OPTION_ARG_FUNC ||
1.28 jsing 2220: opt->type == OPTION_ARG_INT ||
2221: opt->type == OPTION_ARG_LONG) {
1.16 jsing 2222: if (++i >= argc) {
2223: fprintf(stderr, "missing %s argument for -%s\n",
2224: opt->argname, opt->name);
2225: return (1);
1.3 jsing 2226: }
1.16 jsing 2227: }
1.3 jsing 2228:
1.16 jsing 2229: switch (opt->type) {
2230: case OPTION_ARG:
2231: *opt->opt.arg = argv[i];
1.20 jsing 2232: break;
2233:
2234: case OPTION_ARGV_FUNC:
2235: if (opt->opt.argvfunc(argc - i, &argv[i], &used) != 0)
2236: return (1);
2237: i += used - 1;
1.16 jsing 2238: break;
1.4 jsing 2239:
1.16 jsing 2240: case OPTION_ARG_FORMAT:
2241: fmt = str2fmt(argv[i]);
2242: if (fmt == FORMAT_UNDEF) {
2243: fprintf(stderr, "unknown %s '%s' for -%s\n",
2244: opt->argname, argv[i], opt->name);
2245: return (1);
2246: }
2247: *opt->opt.value = fmt;
2248: break;
1.8 jsing 2249:
1.16 jsing 2250: case OPTION_ARG_FUNC:
2251: if (opt->opt.argfunc(argv[i]) != 0)
2252: return (1);
2253: break;
1.3 jsing 2254:
1.16 jsing 2255: case OPTION_ARG_INT:
2256: val = strtonum(argv[i], 0, INT_MAX, &errstr);
2257: if (errstr != NULL) {
2258: fprintf(stderr, "%s %s argument for -%s\n",
2259: errstr, opt->argname, opt->name);
2260: return (1);
2261: }
2262: *opt->opt.value = (int)val;
1.28 jsing 2263: break;
2264:
2265: case OPTION_ARG_LONG:
2266: val = strtonum(argv[i], 0, LONG_MAX, &errstr);
2267: if (errstr != NULL) {
2268: fprintf(stderr, "%s %s argument for -%s\n",
2269: errstr, opt->argname, opt->name);
2270: return (1);
2271: }
2272: *opt->opt.lvalue = (long)val;
1.26 doug 2273: break;
2274:
2275: case OPTION_DISCARD:
1.16 jsing 2276: break;
1.2 jsing 2277:
1.16 jsing 2278: case OPTION_FUNC:
2279: if (opt->opt.func() != 0)
2280: return (1);
2281: break;
1.13 bcook 2282:
1.16 jsing 2283: case OPTION_FLAG:
2284: *opt->opt.flag = 1;
2285: break;
1.5 jsing 2286:
1.16 jsing 2287: case OPTION_FLAG_ORD:
2288: *opt->opt.flag = ++ord;
2289: break;
1.2 jsing 2290:
1.16 jsing 2291: case OPTION_VALUE:
2292: *opt->opt.value = opt->value;
1.23 jsing 2293: break;
2294:
2295: case OPTION_VALUE_AND:
2296: *opt->opt.value &= opt->value;
2297: break;
2298:
2299: case OPTION_VALUE_OR:
2300: *opt->opt.value |= opt->value;
1.16 jsing 2301: break;
1.2 jsing 2302:
1.16 jsing 2303: default:
2304: fprintf(stderr, "option %s - unknown type %i\n",
2305: opt->name, opt->type);
2306: return (1);
1.2 jsing 2307: }
2308: }
1.18 jsing 2309:
2310: done:
2311: if (argsused != NULL)
2312: *argsused = i;
1.2 jsing 2313:
2314: return (0);
1.17 jsing 2315:
2316: toomany:
2317: fprintf(stderr, "too many arguments\n");
2318: return (1);
1.2 jsing 2319:
2320: unknown:
2321: fprintf(stderr, "unknown option '%s'\n", arg);
2322: return (1);
1.1 jsing 2323: }