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