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