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