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