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