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