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