155714Skris/* apps/apps.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 8296341Sdelphij * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15296341Sdelphij * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 22296341Sdelphij * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 37296341Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40296341Sdelphij * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 52296341Sdelphij * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 58109998Smarkm/* ==================================================================== 59109998Smarkm * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. 60109998Smarkm * 61109998Smarkm * Redistribution and use in source and binary forms, with or without 62109998Smarkm * modification, are permitted provided that the following conditions 63109998Smarkm * are met: 64109998Smarkm * 65109998Smarkm * 1. Redistributions of source code must retain the above copyright 66296341Sdelphij * notice, this list of conditions and the following disclaimer. 67109998Smarkm * 68109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 69109998Smarkm * notice, this list of conditions and the following disclaimer in 70109998Smarkm * the documentation and/or other materials provided with the 71109998Smarkm * distribution. 72109998Smarkm * 73109998Smarkm * 3. All advertising materials mentioning features or use of this 74109998Smarkm * software must display the following acknowledgment: 75109998Smarkm * "This product includes software developed by the OpenSSL Project 76109998Smarkm * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 77109998Smarkm * 78109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 79109998Smarkm * endorse or promote products derived from this software without 80109998Smarkm * prior written permission. For written permission, please contact 81109998Smarkm * openssl-core@openssl.org. 82109998Smarkm * 83109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 84109998Smarkm * nor may "OpenSSL" appear in their names without prior written 85109998Smarkm * permission of the OpenSSL Project. 86109998Smarkm * 87109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 88109998Smarkm * acknowledgment: 89109998Smarkm * "This product includes software developed by the OpenSSL Project 90109998Smarkm * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 91109998Smarkm * 92109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 93109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 94109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 95109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 96109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 97109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 98109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 99109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 100109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 101109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 102109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 103109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 104109998Smarkm * ==================================================================== 105109998Smarkm * 106109998Smarkm * This product includes cryptographic software written by Eric Young 107109998Smarkm * (eay@cryptsoft.com). This product includes software written by Tim 108109998Smarkm * Hudson (tjh@cryptsoft.com). 109109998Smarkm * 110109998Smarkm */ 11155714Skris 112238405Sjkim#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS) 113296341Sdelphij/* 114296341Sdelphij * On VMS, you need to define this to get the declaration of fileno(). The 115296341Sdelphij * value 2 is to make sure no function defined in POSIX-2 is left undefined. 116296341Sdelphij */ 117296341Sdelphij# define _POSIX_C_SOURCE 2 118238405Sjkim#endif 11955714Skris#include <stdio.h> 12055714Skris#include <stdlib.h> 12155714Skris#include <string.h> 122238405Sjkim#if !defined(OPENSSL_SYSNAME_WIN32) && !defined(NETWARE_CLIB) 123296341Sdelphij# include <strings.h> 124238405Sjkim#endif 12555714Skris#include <sys/types.h> 126109998Smarkm#include <ctype.h> 127238405Sjkim#include <errno.h> 128194206Ssimon#include <assert.h> 12968651Skris#include <openssl/err.h> 13068651Skris#include <openssl/x509.h> 131109998Smarkm#include <openssl/x509v3.h> 13268651Skris#include <openssl/pem.h> 13368651Skris#include <openssl/pkcs12.h> 134109998Smarkm#include <openssl/ui.h> 13568651Skris#include <openssl/safestack.h> 136111147Snectar#ifndef OPENSSL_NO_ENGINE 137296341Sdelphij# include <openssl/engine.h> 138111147Snectar#endif 139160814Ssimon#ifndef OPENSSL_NO_RSA 140296341Sdelphij# include <openssl/rsa.h> 141160814Ssimon#endif 142160814Ssimon#include <openssl/bn.h> 143194206Ssimon#ifndef OPENSSL_NO_JPAKE 144296341Sdelphij# include <openssl/jpake.h> 145194206Ssimon#endif 14655714Skris 147109998Smarkm#define NON_MAIN 148109998Smarkm#include "apps.h" 149109998Smarkm#undef NON_MAIN 150109998Smarkm 151238405Sjkim#ifdef _WIN32 152238405Sjkimstatic int WIN32_rename(const char *from, const char *to); 153296341Sdelphij# define rename(from,to) WIN32_rename((from),(to)) 154238405Sjkim#endif 155238405Sjkim 156109998Smarkmtypedef struct { 157296341Sdelphij const char *name; 158296341Sdelphij unsigned long flag; 159296341Sdelphij unsigned long mask; 160109998Smarkm} NAME_EX_TBL; 161109998Smarkm 162109998Smarkmstatic UI_METHOD *ui_method = NULL; 163109998Smarkm 164296341Sdelphijstatic int set_table_opts(unsigned long *flags, const char *arg, 165296341Sdelphij const NAME_EX_TBL * in_tbl); 166296341Sdelphijstatic int set_multi_opts(unsigned long *flags, const char *arg, 167296341Sdelphij const NAME_EX_TBL * in_tbl); 168109998Smarkm 169109998Smarkm#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA) 170109998Smarkm/* Looks like this stuff is worth moving into separate function */ 171296341Sdelphijstatic EVP_PKEY *load_netscape_key(BIO *err, BIO *key, const char *file, 172296341Sdelphij const char *key_descrip, int format); 173109998Smarkm#endif 174109998Smarkm 17555714Skrisint app_init(long mesgwin); 176296341Sdelphij#ifdef undef /* never finished - probably never will be 177296341Sdelphij * :-) */ 17855714Skrisint args_from_file(char *file, int *argc, char **argv[]) 179296341Sdelphij{ 180296341Sdelphij FILE *fp; 181296341Sdelphij int num, i; 182296341Sdelphij unsigned int len; 183296341Sdelphij static char *buf = NULL; 184296341Sdelphij static char **arg = NULL; 185296341Sdelphij char *p; 18655714Skris 187296341Sdelphij fp = fopen(file, "r"); 188296341Sdelphij if (fp == NULL) 189296341Sdelphij return (0); 19055714Skris 191296341Sdelphij if (fseek(fp, 0, SEEK_END) == 0) 192296341Sdelphij len = ftell(fp), rewind(fp); 193296341Sdelphij else 194296341Sdelphij len = -1; 195296341Sdelphij if (len <= 0) { 196296341Sdelphij fclose(fp); 197296341Sdelphij return (0); 198296341Sdelphij } 199238405Sjkim 200296341Sdelphij *argc = 0; 201296341Sdelphij *argv = NULL; 20255714Skris 203296341Sdelphij if (buf != NULL) 204296341Sdelphij OPENSSL_free(buf); 205296341Sdelphij buf = (char *)OPENSSL_malloc(len + 1); 206296341Sdelphij if (buf == NULL) 207296341Sdelphij return (0); 20855714Skris 209296341Sdelphij len = fread(buf, 1, len, fp); 210296341Sdelphij if (len <= 1) 211296341Sdelphij return (0); 212296341Sdelphij buf[len] = '\0'; 21355714Skris 214296341Sdelphij i = 0; 215296341Sdelphij for (p = buf; *p; p++) 216296341Sdelphij if (*p == '\n') 217296341Sdelphij i++; 218296341Sdelphij if (arg != NULL) 219296341Sdelphij OPENSSL_free(arg); 220296341Sdelphij arg = (char **)OPENSSL_malloc(sizeof(char *) * (i * 2)); 22155714Skris 222296341Sdelphij *argv = arg; 223296341Sdelphij num = 0; 224296341Sdelphij p = buf; 225296341Sdelphij for (;;) { 226296341Sdelphij if (!*p) 227296341Sdelphij break; 228296341Sdelphij if (*p == '#') { /* comment line */ 229296341Sdelphij while (*p && (*p != '\n')) 230296341Sdelphij p++; 231296341Sdelphij continue; 232296341Sdelphij } 233296341Sdelphij /* else we have a line */ 234296341Sdelphij *(arg++) = p; 235296341Sdelphij num++; 236296341Sdelphij while (*p && ((*p != ' ') && (*p != '\t') && (*p != '\n'))) 237296341Sdelphij p++; 238296341Sdelphij if (!*p) 239296341Sdelphij break; 240296341Sdelphij if (*p == '\n') { 241296341Sdelphij *(p++) = '\0'; 242296341Sdelphij continue; 243296341Sdelphij } 244296341Sdelphij /* else it is a tab or space */ 245296341Sdelphij p++; 246296341Sdelphij while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n'))) 247296341Sdelphij p++; 248296341Sdelphij if (!*p) 249296341Sdelphij break; 250296341Sdelphij if (*p == '\n') { 251296341Sdelphij p++; 252296341Sdelphij continue; 253296341Sdelphij } 254296341Sdelphij *(arg++) = p++; 255296341Sdelphij num++; 256296341Sdelphij while (*p && (*p != '\n')) 257296341Sdelphij p++; 258296341Sdelphij if (!*p) 259296341Sdelphij break; 260296341Sdelphij /* else *p == '\n' */ 261296341Sdelphij *(p++) = '\0'; 262296341Sdelphij } 263296341Sdelphij *argc = num; 264296341Sdelphij return (1); 265296341Sdelphij} 26655714Skris#endif 26755714Skris 26855714Skrisint str2fmt(char *s) 269296341Sdelphij{ 270296341Sdelphij if (s == NULL) 271296341Sdelphij return FORMAT_UNDEF; 272296341Sdelphij if ((*s == 'D') || (*s == 'd')) 273296341Sdelphij return (FORMAT_ASN1); 274296341Sdelphij else if ((*s == 'T') || (*s == 't')) 275296341Sdelphij return (FORMAT_TEXT); 276296341Sdelphij else if ((*s == 'N') || (*s == 'n')) 277296341Sdelphij return (FORMAT_NETSCAPE); 278296341Sdelphij else if ((*s == 'S') || (*s == 's')) 279296341Sdelphij return (FORMAT_SMIME); 280296341Sdelphij else if ((*s == 'M') || (*s == 'm')) 281296341Sdelphij return (FORMAT_MSBLOB); 282296341Sdelphij else if ((*s == '1') 283296341Sdelphij || (strcmp(s, "PKCS12") == 0) || (strcmp(s, "pkcs12") == 0) 284296341Sdelphij || (strcmp(s, "P12") == 0) || (strcmp(s, "p12") == 0)) 285296341Sdelphij return (FORMAT_PKCS12); 286296341Sdelphij else if ((*s == 'E') || (*s == 'e')) 287296341Sdelphij return (FORMAT_ENGINE); 288296341Sdelphij else if ((*s == 'P') || (*s == 'p')) { 289296341Sdelphij if (s[1] == 'V' || s[1] == 'v') 290296341Sdelphij return FORMAT_PVK; 291296341Sdelphij else 292296341Sdelphij return (FORMAT_PEM); 293296341Sdelphij } else 294296341Sdelphij return (FORMAT_UNDEF); 295296341Sdelphij} 29655714Skris 297160814Ssimon#if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) || defined(OPENSSL_SYS_NETWARE) 29855714Skrisvoid program_name(char *in, char *out, int size) 299296341Sdelphij{ 300296341Sdelphij int i, n; 301296341Sdelphij char *p = NULL; 30255714Skris 303296341Sdelphij n = strlen(in); 304296341Sdelphij /* find the last '/', '\' or ':' */ 305296341Sdelphij for (i = n - 1; i > 0; i--) { 306296341Sdelphij if ((in[i] == '/') || (in[i] == '\\') || (in[i] == ':')) { 307296341Sdelphij p = &(in[i + 1]); 308296341Sdelphij break; 309296341Sdelphij } 310296341Sdelphij } 311296341Sdelphij if (p == NULL) 312296341Sdelphij p = in; 313296341Sdelphij n = strlen(p); 314160814Ssimon 315296341Sdelphij# if defined(OPENSSL_SYS_NETWARE) 316296341Sdelphij /* strip off trailing .nlm if present. */ 317296341Sdelphij if ((n > 4) && (p[n - 4] == '.') && 318296341Sdelphij ((p[n - 3] == 'n') || (p[n - 3] == 'N')) && 319296341Sdelphij ((p[n - 2] == 'l') || (p[n - 2] == 'L')) && 320296341Sdelphij ((p[n - 1] == 'm') || (p[n - 1] == 'M'))) 321296341Sdelphij n -= 4; 322296341Sdelphij# else 323296341Sdelphij /* strip off trailing .exe if present. */ 324296341Sdelphij if ((n > 4) && (p[n - 4] == '.') && 325296341Sdelphij ((p[n - 3] == 'e') || (p[n - 3] == 'E')) && 326296341Sdelphij ((p[n - 2] == 'x') || (p[n - 2] == 'X')) && 327296341Sdelphij ((p[n - 1] == 'e') || (p[n - 1] == 'E'))) 328296341Sdelphij n -= 4; 329296341Sdelphij# endif 330160814Ssimon 331296341Sdelphij if (n > size - 1) 332296341Sdelphij n = size - 1; 33355714Skris 334296341Sdelphij for (i = 0; i < n; i++) { 335296341Sdelphij if ((p[i] >= 'A') && (p[i] <= 'Z')) 336296341Sdelphij out[i] = p[i] - 'A' + 'a'; 337296341Sdelphij else 338296341Sdelphij out[i] = p[i]; 339296341Sdelphij } 340296341Sdelphij out[n] = '\0'; 341296341Sdelphij} 34255714Skris#else 343296341Sdelphij# ifdef OPENSSL_SYS_VMS 34455714Skrisvoid program_name(char *in, char *out, int size) 345296341Sdelphij{ 346296341Sdelphij char *p = in, *q; 347296341Sdelphij char *chars = ":]>"; 34855714Skris 349296341Sdelphij while (*chars != '\0') { 350296341Sdelphij q = strrchr(p, *chars); 351296341Sdelphij if (q > p) 352296341Sdelphij p = q + 1; 353296341Sdelphij chars++; 354296341Sdelphij } 35555714Skris 356296341Sdelphij q = strrchr(p, '.'); 357296341Sdelphij if (q == NULL) 358296341Sdelphij q = p + strlen(p); 359296341Sdelphij strncpy(out, p, size - 1); 360296341Sdelphij if (q - p >= size) { 361296341Sdelphij out[size - 1] = '\0'; 362296341Sdelphij } else { 363296341Sdelphij out[q - p] = '\0'; 364296341Sdelphij } 365296341Sdelphij} 366296341Sdelphij# else 36755714Skrisvoid program_name(char *in, char *out, int size) 368296341Sdelphij{ 369296341Sdelphij char *p; 37055714Skris 371296341Sdelphij p = strrchr(in, '/'); 372296341Sdelphij if (p != NULL) 373296341Sdelphij p++; 374296341Sdelphij else 375296341Sdelphij p = in; 376296341Sdelphij BUF_strlcpy(out, p, size); 377296341Sdelphij} 378296341Sdelphij# endif 37955714Skris#endif 38055714Skris 38155714Skrisint chopup_args(ARGS *arg, char *buf, int *argc, char **argv[]) 382296341Sdelphij{ 383296341Sdelphij int num, i; 384296341Sdelphij char *p; 38555714Skris 386296341Sdelphij *argc = 0; 387296341Sdelphij *argv = NULL; 38855714Skris 389296341Sdelphij i = 0; 390296341Sdelphij if (arg->count == 0) { 391296341Sdelphij arg->count = 20; 392296341Sdelphij arg->data = (char **)OPENSSL_malloc(sizeof(char *) * arg->count); 393296341Sdelphij if (arg->data == NULL) 394296341Sdelphij return 0; 395296341Sdelphij } 396296341Sdelphij for (i = 0; i < arg->count; i++) 397296341Sdelphij arg->data[i] = NULL; 39855714Skris 399296341Sdelphij num = 0; 400296341Sdelphij p = buf; 401296341Sdelphij for (;;) { 402296341Sdelphij /* first scan over white space */ 403296341Sdelphij if (!*p) 404296341Sdelphij break; 405296341Sdelphij while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n'))) 406296341Sdelphij p++; 407296341Sdelphij if (!*p) 408296341Sdelphij break; 40955714Skris 410296341Sdelphij /* The start of something good :-) */ 411296341Sdelphij if (num >= arg->count) { 412296341Sdelphij char **tmp_p; 413296341Sdelphij int tlen = arg->count + 20; 414296341Sdelphij tmp_p = (char **)OPENSSL_realloc(arg->data, 415296341Sdelphij sizeof(char *) * tlen); 416296341Sdelphij if (tmp_p == NULL) 417296341Sdelphij return 0; 418296341Sdelphij arg->data = tmp_p; 419296341Sdelphij arg->count = tlen; 420296341Sdelphij /* initialize newly allocated data */ 421296341Sdelphij for (i = num; i < arg->count; i++) 422296341Sdelphij arg->data[i] = NULL; 423296341Sdelphij } 424296341Sdelphij arg->data[num++] = p; 42555714Skris 426296341Sdelphij /* now look for the end of this */ 427296341Sdelphij if ((*p == '\'') || (*p == '\"')) { /* scan for closing quote */ 428296341Sdelphij i = *(p++); 429296341Sdelphij arg->data[num - 1]++; /* jump over quote */ 430296341Sdelphij while (*p && (*p != i)) 431296341Sdelphij p++; 432296341Sdelphij *p = '\0'; 433296341Sdelphij } else { 434296341Sdelphij while (*p && ((*p != ' ') && (*p != '\t') && (*p != '\n'))) 435296341Sdelphij p++; 43655714Skris 437296341Sdelphij if (*p == '\0') 438296341Sdelphij p--; 439296341Sdelphij else 440296341Sdelphij *p = '\0'; 441296341Sdelphij } 442296341Sdelphij p++; 443296341Sdelphij } 444296341Sdelphij *argc = num; 445296341Sdelphij *argv = arg->data; 446296341Sdelphij return (1); 447296341Sdelphij} 44855714Skris 44955714Skris#ifndef APP_INIT 45055714Skrisint app_init(long mesgwin) 451296341Sdelphij{ 452296341Sdelphij return (1); 453296341Sdelphij} 45455714Skris#endif 45559191Skris 456296341Sdelphijint dump_cert_text(BIO *out, X509 *x) 45759191Skris{ 458296341Sdelphij char *p; 459109998Smarkm 460296341Sdelphij p = X509_NAME_oneline(X509_get_subject_name(x), NULL, 0); 461296341Sdelphij BIO_puts(out, "subject="); 462296341Sdelphij BIO_puts(out, p); 463296341Sdelphij OPENSSL_free(p); 46459191Skris 465296341Sdelphij p = X509_NAME_oneline(X509_get_issuer_name(x), NULL, 0); 466296341Sdelphij BIO_puts(out, "\nissuer="); 467296341Sdelphij BIO_puts(out, p); 468296341Sdelphij BIO_puts(out, "\n"); 469296341Sdelphij OPENSSL_free(p); 470109998Smarkm 471296341Sdelphij return 0; 47259191Skris} 47359191Skris 474109998Smarkmstatic int ui_open(UI *ui) 475296341Sdelphij{ 476296341Sdelphij return UI_method_get_opener(UI_OpenSSL())(ui); 477296341Sdelphij} 478296341Sdelphij 479109998Smarkmstatic int ui_read(UI *ui, UI_STRING *uis) 480296341Sdelphij{ 481296341Sdelphij if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD 482296341Sdelphij && UI_get0_user_data(ui)) { 483296341Sdelphij switch (UI_get_string_type(uis)) { 484296341Sdelphij case UIT_PROMPT: 485296341Sdelphij case UIT_VERIFY: 486296341Sdelphij { 487296341Sdelphij const char *password = 488296341Sdelphij ((PW_CB_DATA *)UI_get0_user_data(ui))->password; 489296341Sdelphij if (password && password[0] != '\0') { 490296341Sdelphij UI_set_result(ui, uis, password); 491296341Sdelphij return 1; 492296341Sdelphij } 493296341Sdelphij } 494296341Sdelphij default: 495296341Sdelphij break; 496296341Sdelphij } 497296341Sdelphij } 498296341Sdelphij return UI_method_get_reader(UI_OpenSSL())(ui, uis); 499296341Sdelphij} 500296341Sdelphij 501109998Smarkmstatic int ui_write(UI *ui, UI_STRING *uis) 502296341Sdelphij{ 503296341Sdelphij if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD 504296341Sdelphij && UI_get0_user_data(ui)) { 505296341Sdelphij switch (UI_get_string_type(uis)) { 506296341Sdelphij case UIT_PROMPT: 507296341Sdelphij case UIT_VERIFY: 508296341Sdelphij { 509296341Sdelphij const char *password = 510296341Sdelphij ((PW_CB_DATA *)UI_get0_user_data(ui))->password; 511296341Sdelphij if (password && password[0] != '\0') 512296341Sdelphij return 1; 513296341Sdelphij } 514296341Sdelphij default: 515296341Sdelphij break; 516296341Sdelphij } 517296341Sdelphij } 518296341Sdelphij return UI_method_get_writer(UI_OpenSSL())(ui, uis); 519296341Sdelphij} 520296341Sdelphij 521109998Smarkmstatic int ui_close(UI *ui) 522296341Sdelphij{ 523296341Sdelphij return UI_method_get_closer(UI_OpenSSL())(ui); 524296341Sdelphij} 525296341Sdelphij 526109998Smarkmint setup_ui_method(void) 527296341Sdelphij{ 528296341Sdelphij ui_method = UI_create_method("OpenSSL application user interface"); 529296341Sdelphij UI_method_set_opener(ui_method, ui_open); 530296341Sdelphij UI_method_set_reader(ui_method, ui_read); 531296341Sdelphij UI_method_set_writer(ui_method, ui_write); 532296341Sdelphij UI_method_set_closer(ui_method, ui_close); 533296341Sdelphij return 0; 534296341Sdelphij} 535296341Sdelphij 536109998Smarkmvoid destroy_ui_method(void) 537296341Sdelphij{ 538296341Sdelphij if (ui_method) { 539296341Sdelphij UI_destroy_method(ui_method); 540296341Sdelphij ui_method = NULL; 541296341Sdelphij } 542296341Sdelphij} 543109998Smarkm 544296341Sdelphijint password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_tmp) 545296341Sdelphij{ 546296341Sdelphij UI *ui = NULL; 547296341Sdelphij int res = 0; 548296341Sdelphij const char *prompt_info = NULL; 549296341Sdelphij const char *password = NULL; 550296341Sdelphij PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp; 551109998Smarkm 552296341Sdelphij if (cb_data) { 553296341Sdelphij if (cb_data->password) 554296341Sdelphij password = cb_data->password; 555296341Sdelphij if (cb_data->prompt_info) 556296341Sdelphij prompt_info = cb_data->prompt_info; 557296341Sdelphij } 558109998Smarkm 559296341Sdelphij if (password) { 560296341Sdelphij res = strlen(password); 561296341Sdelphij if (res > bufsiz) 562296341Sdelphij res = bufsiz; 563296341Sdelphij memcpy(buf, password, res); 564296341Sdelphij return res; 565296341Sdelphij } 566109998Smarkm 567296341Sdelphij ui = UI_new_method(ui_method); 568296341Sdelphij if (ui) { 569296341Sdelphij int ok = 0; 570296341Sdelphij char *buff = NULL; 571296341Sdelphij int ui_flags = 0; 572296341Sdelphij char *prompt = NULL; 573109998Smarkm 574296341Sdelphij prompt = UI_construct_prompt(ui, "pass phrase", prompt_info); 575296341Sdelphij if (!prompt) { 576296341Sdelphij BIO_printf(bio_err, "Out of memory\n"); 577296341Sdelphij UI_free(ui); 578296341Sdelphij return 0; 579296341Sdelphij } 580109998Smarkm 581296341Sdelphij ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD; 582296341Sdelphij UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); 583109998Smarkm 584296341Sdelphij if (ok >= 0) 585296341Sdelphij ok = UI_add_input_string(ui, prompt, ui_flags, buf, 586296341Sdelphij PW_MIN_LENGTH, bufsiz - 1); 587296341Sdelphij if (ok >= 0 && verify) { 588296341Sdelphij buff = (char *)OPENSSL_malloc(bufsiz); 589296341Sdelphij if (!buff) { 590296341Sdelphij BIO_printf(bio_err, "Out of memory\n"); 591296341Sdelphij UI_free(ui); 592296341Sdelphij OPENSSL_free(prompt); 593296341Sdelphij return 0; 594296341Sdelphij } 595296341Sdelphij ok = UI_add_verify_string(ui, prompt, ui_flags, buff, 596296341Sdelphij PW_MIN_LENGTH, bufsiz - 1, buf); 597296341Sdelphij } 598296341Sdelphij if (ok >= 0) 599296341Sdelphij do { 600296341Sdelphij ok = UI_process(ui); 601296341Sdelphij } 602296341Sdelphij while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); 603109998Smarkm 604296341Sdelphij if (buff) { 605296341Sdelphij OPENSSL_cleanse(buff, (unsigned int)bufsiz); 606296341Sdelphij OPENSSL_free(buff); 607296341Sdelphij } 608109998Smarkm 609296341Sdelphij if (ok >= 0) 610296341Sdelphij res = strlen(buf); 611296341Sdelphij if (ok == -1) { 612296341Sdelphij BIO_printf(bio_err, "User interface error\n"); 613296341Sdelphij ERR_print_errors(bio_err); 614296341Sdelphij OPENSSL_cleanse(buf, (unsigned int)bufsiz); 615296341Sdelphij res = 0; 616296341Sdelphij } 617296341Sdelphij if (ok == -2) { 618296341Sdelphij BIO_printf(bio_err, "aborted!\n"); 619296341Sdelphij OPENSSL_cleanse(buf, (unsigned int)bufsiz); 620296341Sdelphij res = 0; 621296341Sdelphij } 622296341Sdelphij UI_free(ui); 623296341Sdelphij OPENSSL_free(prompt); 624296341Sdelphij } 625296341Sdelphij return res; 626296341Sdelphij} 627296341Sdelphij 62859191Skrisstatic char *app_get_pass(BIO *err, char *arg, int keepbio); 62959191Skris 63059191Skrisint app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2) 63159191Skris{ 632296341Sdelphij int same; 633296341Sdelphij if (!arg2 || !arg1 || strcmp(arg1, arg2)) 634296341Sdelphij same = 0; 635296341Sdelphij else 636296341Sdelphij same = 1; 637296341Sdelphij if (arg1) { 638296341Sdelphij *pass1 = app_get_pass(err, arg1, same); 639296341Sdelphij if (!*pass1) 640296341Sdelphij return 0; 641296341Sdelphij } else if (pass1) 642296341Sdelphij *pass1 = NULL; 643296341Sdelphij if (arg2) { 644296341Sdelphij *pass2 = app_get_pass(err, arg2, same ? 2 : 0); 645296341Sdelphij if (!*pass2) 646296341Sdelphij return 0; 647296341Sdelphij } else if (pass2) 648296341Sdelphij *pass2 = NULL; 649296341Sdelphij return 1; 65059191Skris} 65159191Skris 65259191Skrisstatic char *app_get_pass(BIO *err, char *arg, int keepbio) 65359191Skris{ 654296341Sdelphij char *tmp, tpass[APP_PASS_LEN]; 655296341Sdelphij static BIO *pwdbio = NULL; 656296341Sdelphij int i; 657296341Sdelphij if (!strncmp(arg, "pass:", 5)) 658296341Sdelphij return BUF_strdup(arg + 5); 659296341Sdelphij if (!strncmp(arg, "env:", 4)) { 660296341Sdelphij tmp = getenv(arg + 4); 661296341Sdelphij if (!tmp) { 662296341Sdelphij BIO_printf(err, "Can't read environment variable %s\n", arg + 4); 663296341Sdelphij return NULL; 664296341Sdelphij } 665296341Sdelphij return BUF_strdup(tmp); 666296341Sdelphij } 667296341Sdelphij if (!keepbio || !pwdbio) { 668296341Sdelphij if (!strncmp(arg, "file:", 5)) { 669296341Sdelphij pwdbio = BIO_new_file(arg + 5, "r"); 670296341Sdelphij if (!pwdbio) { 671296341Sdelphij BIO_printf(err, "Can't open file %s\n", arg + 5); 672296341Sdelphij return NULL; 673296341Sdelphij } 674238405Sjkim#if !defined(_WIN32) 675296341Sdelphij /* 676296341Sdelphij * Under _WIN32, which covers even Win64 and CE, file 677296341Sdelphij * descriptors referenced by BIO_s_fd are not inherited 678296341Sdelphij * by child process and therefore below is not an option. 679296341Sdelphij * It could have been an option if bss_fd.c was operating 680296341Sdelphij * on real Windows descriptors, such as those obtained 681296341Sdelphij * with CreateFile. 682296341Sdelphij */ 683296341Sdelphij } else if (!strncmp(arg, "fd:", 3)) { 684296341Sdelphij BIO *btmp; 685296341Sdelphij i = atoi(arg + 3); 686296341Sdelphij if (i >= 0) 687296341Sdelphij pwdbio = BIO_new_fd(i, BIO_NOCLOSE); 688296341Sdelphij if ((i < 0) || !pwdbio) { 689296341Sdelphij BIO_printf(err, "Can't access file descriptor %s\n", arg + 3); 690296341Sdelphij return NULL; 691296341Sdelphij } 692296341Sdelphij /* 693296341Sdelphij * Can't do BIO_gets on an fd BIO so add a buffering BIO 694296341Sdelphij */ 695296341Sdelphij btmp = BIO_new(BIO_f_buffer()); 696296341Sdelphij pwdbio = BIO_push(btmp, pwdbio); 697238405Sjkim#endif 698296341Sdelphij } else if (!strcmp(arg, "stdin")) { 699296341Sdelphij pwdbio = BIO_new_fp(stdin, BIO_NOCLOSE); 700296341Sdelphij if (!pwdbio) { 701296341Sdelphij BIO_printf(err, "Can't open BIO for stdin\n"); 702296341Sdelphij return NULL; 703296341Sdelphij } 704296341Sdelphij } else { 705296341Sdelphij BIO_printf(err, "Invalid password argument \"%s\"\n", arg); 706296341Sdelphij return NULL; 707296341Sdelphij } 708296341Sdelphij } 709296341Sdelphij i = BIO_gets(pwdbio, tpass, APP_PASS_LEN); 710296341Sdelphij if (keepbio != 1) { 711296341Sdelphij BIO_free_all(pwdbio); 712296341Sdelphij pwdbio = NULL; 713296341Sdelphij } 714296341Sdelphij if (i <= 0) { 715296341Sdelphij BIO_printf(err, "Error reading password from BIO\n"); 716296341Sdelphij return NULL; 717296341Sdelphij } 718296341Sdelphij tmp = strchr(tpass, '\n'); 719296341Sdelphij if (tmp) 720296341Sdelphij *tmp = 0; 721296341Sdelphij return BUF_strdup(tpass); 72259191Skris} 72368651Skris 724109998Smarkmint add_oid_section(BIO *err, CONF *conf) 725296341Sdelphij{ 726296341Sdelphij char *p; 727296341Sdelphij STACK_OF(CONF_VALUE) *sktmp; 728296341Sdelphij CONF_VALUE *cnf; 729296341Sdelphij int i; 730296341Sdelphij if (!(p = NCONF_get_string(conf, NULL, "oid_section"))) { 731296341Sdelphij ERR_clear_error(); 732296341Sdelphij return 1; 733296341Sdelphij } 734296341Sdelphij if (!(sktmp = NCONF_get_section(conf, p))) { 735296341Sdelphij BIO_printf(err, "problem loading oid section %s\n", p); 736296341Sdelphij return 0; 737296341Sdelphij } 738296341Sdelphij for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { 739296341Sdelphij cnf = sk_CONF_VALUE_value(sktmp, i); 740296341Sdelphij if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) { 741296341Sdelphij BIO_printf(err, "problem creating object %s=%s\n", 742296341Sdelphij cnf->name, cnf->value); 743296341Sdelphij return 0; 744296341Sdelphij } 745296341Sdelphij } 746296341Sdelphij return 1; 74768651Skris} 74868651Skris 749160814Ssimonstatic int load_pkcs12(BIO *err, BIO *in, const char *desc, 750296341Sdelphij pem_password_cb *pem_cb, void *cb_data, 751296341Sdelphij EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca) 752296341Sdelphij{ 753296341Sdelphij const char *pass; 754296341Sdelphij char tpass[PEM_BUFSIZE]; 755296341Sdelphij int len, ret = 0; 756296341Sdelphij PKCS12 *p12; 757296341Sdelphij p12 = d2i_PKCS12_bio(in, NULL); 758296341Sdelphij if (p12 == NULL) { 759296341Sdelphij BIO_printf(err, "Error loading PKCS12 file for %s\n", desc); 760296341Sdelphij goto die; 761296341Sdelphij } 762296341Sdelphij /* See if an empty password will do */ 763296341Sdelphij if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0)) 764296341Sdelphij pass = ""; 765296341Sdelphij else { 766296341Sdelphij if (!pem_cb) 767296341Sdelphij pem_cb = (pem_password_cb *)password_callback; 768296341Sdelphij len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data); 769296341Sdelphij if (len < 0) { 770296341Sdelphij BIO_printf(err, "Passpharse callback error for %s\n", desc); 771296341Sdelphij goto die; 772296341Sdelphij } 773296341Sdelphij if (len < PEM_BUFSIZE) 774296341Sdelphij tpass[len] = 0; 775296341Sdelphij if (!PKCS12_verify_mac(p12, tpass, len)) { 776296341Sdelphij BIO_printf(err, 777296341Sdelphij "Mac verify error (wrong password?) in PKCS12 file for %s\n", 778296341Sdelphij desc); 779296341Sdelphij goto die; 780296341Sdelphij } 781296341Sdelphij pass = tpass; 782296341Sdelphij } 783296341Sdelphij ret = PKCS12_parse(p12, pass, pkey, cert, ca); 784296341Sdelphij die: 785296341Sdelphij if (p12) 786296341Sdelphij PKCS12_free(p12); 787296341Sdelphij return ret; 788296341Sdelphij} 789160814Ssimon 790109998SmarkmX509 *load_cert(BIO *err, const char *file, int format, 791296341Sdelphij const char *pass, ENGINE *e, const char *cert_descrip) 792296341Sdelphij{ 793296341Sdelphij X509 *x = NULL; 794296341Sdelphij BIO *cert; 79568651Skris 796296341Sdelphij if ((cert = BIO_new(BIO_s_file())) == NULL) { 797296341Sdelphij ERR_print_errors(err); 798296341Sdelphij goto end; 799296341Sdelphij } 80068651Skris 801296341Sdelphij if (file == NULL) { 802238405Sjkim#ifdef _IONBF 803238405Sjkim# ifndef OPENSSL_NO_SETVBUF_IONBF 804296341Sdelphij setvbuf(stdin, NULL, _IONBF, 0); 805296341Sdelphij# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ 806238405Sjkim#endif 807296341Sdelphij BIO_set_fp(cert, stdin, BIO_NOCLOSE); 808296341Sdelphij } else { 809296341Sdelphij if (BIO_read_filename(cert, file) <= 0) { 810296341Sdelphij BIO_printf(err, "Error opening %s %s\n", cert_descrip, file); 811296341Sdelphij ERR_print_errors(err); 812296341Sdelphij goto end; 813296341Sdelphij } 814296341Sdelphij } 81568651Skris 816296341Sdelphij if (format == FORMAT_ASN1) 817296341Sdelphij x = d2i_X509_bio(cert, NULL); 818296341Sdelphij else if (format == FORMAT_NETSCAPE) { 819296341Sdelphij NETSCAPE_X509 *nx; 820296341Sdelphij nx = ASN1_item_d2i_bio(ASN1_ITEM_rptr(NETSCAPE_X509), cert, NULL); 821296341Sdelphij if (nx == NULL) 822296341Sdelphij goto end; 82368651Skris 824296341Sdelphij if ((strncmp(NETSCAPE_CERT_HDR, (char *)nx->header->data, 825296341Sdelphij nx->header->length) != 0)) { 826296341Sdelphij NETSCAPE_X509_free(nx); 827296341Sdelphij BIO_printf(err, "Error reading header on certificate\n"); 828296341Sdelphij goto end; 829296341Sdelphij } 830296341Sdelphij x = nx->cert; 831296341Sdelphij nx->cert = NULL; 832296341Sdelphij NETSCAPE_X509_free(nx); 833296341Sdelphij } else if (format == FORMAT_PEM) 834296341Sdelphij x = PEM_read_bio_X509_AUX(cert, NULL, 835296341Sdelphij (pem_password_cb *)password_callback, NULL); 836296341Sdelphij else if (format == FORMAT_PKCS12) { 837296341Sdelphij if (!load_pkcs12(err, cert, cert_descrip, NULL, NULL, NULL, &x, NULL)) 838296341Sdelphij goto end; 839296341Sdelphij } else { 840296341Sdelphij BIO_printf(err, "bad input format specified for %s\n", cert_descrip); 841296341Sdelphij goto end; 842296341Sdelphij } 843296341Sdelphij end: 844296341Sdelphij if (x == NULL) { 845296341Sdelphij BIO_printf(err, "unable to load certificate\n"); 846296341Sdelphij ERR_print_errors(err); 847296341Sdelphij } 848296341Sdelphij if (cert != NULL) 849296341Sdelphij BIO_free(cert); 850296341Sdelphij return (x); 851296341Sdelphij} 85268651Skris 853109998SmarkmEVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin, 854296341Sdelphij const char *pass, ENGINE *e, const char *key_descrip) 855296341Sdelphij{ 856296341Sdelphij BIO *key = NULL; 857296341Sdelphij EVP_PKEY *pkey = NULL; 858296341Sdelphij PW_CB_DATA cb_data; 85968651Skris 860296341Sdelphij cb_data.password = pass; 861296341Sdelphij cb_data.prompt_info = file; 862109998Smarkm 863296341Sdelphij if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) { 864296341Sdelphij BIO_printf(err, "no keyfile specified\n"); 865296341Sdelphij goto end; 866296341Sdelphij } 867111147Snectar#ifndef OPENSSL_NO_ENGINE 868296341Sdelphij if (format == FORMAT_ENGINE) { 869296341Sdelphij if (!e) 870296341Sdelphij BIO_printf(err, "no engine specified\n"); 871296341Sdelphij else { 872296341Sdelphij pkey = ENGINE_load_private_key(e, file, ui_method, &cb_data); 873296341Sdelphij if (!pkey) { 874296341Sdelphij BIO_printf(err, "cannot load %s from engine\n", key_descrip); 875296341Sdelphij ERR_print_errors(err); 876296341Sdelphij } 877296341Sdelphij } 878296341Sdelphij goto end; 879296341Sdelphij } 880111147Snectar#endif 881296341Sdelphij key = BIO_new(BIO_s_file()); 882296341Sdelphij if (key == NULL) { 883296341Sdelphij ERR_print_errors(err); 884296341Sdelphij goto end; 885296341Sdelphij } 886296341Sdelphij if (file == NULL && maybe_stdin) { 887238405Sjkim#ifdef _IONBF 888238405Sjkim# ifndef OPENSSL_NO_SETVBUF_IONBF 889296341Sdelphij setvbuf(stdin, NULL, _IONBF, 0); 890296341Sdelphij# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ 891238405Sjkim#endif 892296341Sdelphij BIO_set_fp(key, stdin, BIO_NOCLOSE); 893296341Sdelphij } else if (BIO_read_filename(key, file) <= 0) { 894296341Sdelphij BIO_printf(err, "Error opening %s %s\n", key_descrip, file); 895296341Sdelphij ERR_print_errors(err); 896296341Sdelphij goto end; 897296341Sdelphij } 898296341Sdelphij if (format == FORMAT_ASN1) { 899296341Sdelphij pkey = d2i_PrivateKey_bio(key, NULL); 900296341Sdelphij } else if (format == FORMAT_PEM) { 901296341Sdelphij pkey = PEM_read_bio_PrivateKey(key, NULL, 902296341Sdelphij (pem_password_cb *)password_callback, 903296341Sdelphij &cb_data); 904296341Sdelphij } 905109998Smarkm#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA) 906296341Sdelphij else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC) 907296341Sdelphij pkey = load_netscape_key(err, key, file, key_descrip, format); 908109998Smarkm#endif 909296341Sdelphij else if (format == FORMAT_PKCS12) { 910296341Sdelphij if (!load_pkcs12(err, key, key_descrip, 911296341Sdelphij (pem_password_cb *)password_callback, &cb_data, 912296341Sdelphij &pkey, NULL, NULL)) 913296341Sdelphij goto end; 914296341Sdelphij } 915238405Sjkim#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4) 916296341Sdelphij else if (format == FORMAT_MSBLOB) 917296341Sdelphij pkey = b2i_PrivateKey_bio(key); 918296341Sdelphij else if (format == FORMAT_PVK) 919296341Sdelphij pkey = b2i_PVK_bio(key, (pem_password_cb *)password_callback, 920296341Sdelphij &cb_data); 921238405Sjkim#endif 922296341Sdelphij else { 923296341Sdelphij BIO_printf(err, "bad input format specified for key file\n"); 924296341Sdelphij goto end; 925296341Sdelphij } 92668651Skris end: 927296341Sdelphij if (key != NULL) 928296341Sdelphij BIO_free(key); 929296341Sdelphij if (pkey == NULL) { 930296341Sdelphij BIO_printf(err, "unable to load %s\n", key_descrip); 931296341Sdelphij ERR_print_errors(err); 932296341Sdelphij } 933296341Sdelphij return (pkey); 934296341Sdelphij} 93568651Skris 936109998SmarkmEVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin, 937296341Sdelphij const char *pass, ENGINE *e, const char *key_descrip) 938296341Sdelphij{ 939296341Sdelphij BIO *key = NULL; 940296341Sdelphij EVP_PKEY *pkey = NULL; 941296341Sdelphij PW_CB_DATA cb_data; 94268651Skris 943296341Sdelphij cb_data.password = pass; 944296341Sdelphij cb_data.prompt_info = file; 945109998Smarkm 946296341Sdelphij if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) { 947296341Sdelphij BIO_printf(err, "no keyfile specified\n"); 948296341Sdelphij goto end; 949296341Sdelphij } 950111147Snectar#ifndef OPENSSL_NO_ENGINE 951296341Sdelphij if (format == FORMAT_ENGINE) { 952296341Sdelphij if (!e) 953296341Sdelphij BIO_printf(bio_err, "no engine specified\n"); 954296341Sdelphij else 955296341Sdelphij pkey = ENGINE_load_public_key(e, file, ui_method, &cb_data); 956296341Sdelphij goto end; 957296341Sdelphij } 958111147Snectar#endif 959296341Sdelphij key = BIO_new(BIO_s_file()); 960296341Sdelphij if (key == NULL) { 961296341Sdelphij ERR_print_errors(err); 962296341Sdelphij goto end; 963296341Sdelphij } 964296341Sdelphij if (file == NULL && maybe_stdin) { 965238405Sjkim#ifdef _IONBF 966238405Sjkim# ifndef OPENSSL_NO_SETVBUF_IONBF 967296341Sdelphij setvbuf(stdin, NULL, _IONBF, 0); 968296341Sdelphij# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ 969238405Sjkim#endif 970296341Sdelphij BIO_set_fp(key, stdin, BIO_NOCLOSE); 971296341Sdelphij } else if (BIO_read_filename(key, file) <= 0) { 972296341Sdelphij BIO_printf(err, "Error opening %s %s\n", key_descrip, file); 973296341Sdelphij ERR_print_errors(err); 974296341Sdelphij goto end; 975296341Sdelphij } 976296341Sdelphij if (format == FORMAT_ASN1) { 977296341Sdelphij pkey = d2i_PUBKEY_bio(key, NULL); 978296341Sdelphij } 979238405Sjkim#ifndef OPENSSL_NO_RSA 980296341Sdelphij else if (format == FORMAT_ASN1RSA) { 981296341Sdelphij RSA *rsa; 982296341Sdelphij rsa = d2i_RSAPublicKey_bio(key, NULL); 983296341Sdelphij if (rsa) { 984296341Sdelphij pkey = EVP_PKEY_new(); 985296341Sdelphij if (pkey) 986296341Sdelphij EVP_PKEY_set1_RSA(pkey, rsa); 987296341Sdelphij RSA_free(rsa); 988296341Sdelphij } else 989296341Sdelphij pkey = NULL; 990296341Sdelphij } else if (format == FORMAT_PEMRSA) { 991296341Sdelphij RSA *rsa; 992296341Sdelphij rsa = PEM_read_bio_RSAPublicKey(key, NULL, 993296341Sdelphij (pem_password_cb *)password_callback, 994296341Sdelphij &cb_data); 995296341Sdelphij if (rsa) { 996296341Sdelphij pkey = EVP_PKEY_new(); 997296341Sdelphij if (pkey) 998296341Sdelphij EVP_PKEY_set1_RSA(pkey, rsa); 999296341Sdelphij RSA_free(rsa); 1000296341Sdelphij } else 1001296341Sdelphij pkey = NULL; 1002296341Sdelphij } 1003238405Sjkim#endif 1004296341Sdelphij else if (format == FORMAT_PEM) { 1005296341Sdelphij pkey = PEM_read_bio_PUBKEY(key, NULL, 1006296341Sdelphij (pem_password_cb *)password_callback, 1007296341Sdelphij &cb_data); 1008296341Sdelphij } 1009109998Smarkm#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA) 1010296341Sdelphij else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC) 1011296341Sdelphij pkey = load_netscape_key(err, key, file, key_descrip, format); 1012109998Smarkm#endif 1013238405Sjkim#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) 1014296341Sdelphij else if (format == FORMAT_MSBLOB) 1015296341Sdelphij pkey = b2i_PublicKey_bio(key); 1016238405Sjkim#endif 1017296341Sdelphij else { 1018296341Sdelphij BIO_printf(err, "bad input format specified for key file\n"); 1019296341Sdelphij goto end; 1020296341Sdelphij } 102168651Skris end: 1022296341Sdelphij if (key != NULL) 1023296341Sdelphij BIO_free(key); 1024296341Sdelphij if (pkey == NULL) 1025296341Sdelphij BIO_printf(err, "unable to load %s\n", key_descrip); 1026296341Sdelphij return (pkey); 1027296341Sdelphij} 102868651Skris 1029109998Smarkm#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA) 1030296341Sdelphijstatic EVP_PKEY *load_netscape_key(BIO *err, BIO *key, const char *file, 1031296341Sdelphij const char *key_descrip, int format) 1032296341Sdelphij{ 1033296341Sdelphij EVP_PKEY *pkey; 1034296341Sdelphij BUF_MEM *buf; 1035296341Sdelphij RSA *rsa; 1036296341Sdelphij const unsigned char *p; 1037296341Sdelphij int size, i; 1038109998Smarkm 1039296341Sdelphij buf = BUF_MEM_new(); 1040296341Sdelphij pkey = EVP_PKEY_new(); 1041296341Sdelphij size = 0; 1042296341Sdelphij if (buf == NULL || pkey == NULL) 1043296341Sdelphij goto error; 1044296341Sdelphij for (;;) { 1045296341Sdelphij if (!BUF_MEM_grow_clean(buf, size + 1024 * 10)) 1046296341Sdelphij goto error; 1047296341Sdelphij i = BIO_read(key, &(buf->data[size]), 1024 * 10); 1048296341Sdelphij size += i; 1049296341Sdelphij if (i == 0) 1050296341Sdelphij break; 1051296341Sdelphij if (i < 0) { 1052296341Sdelphij BIO_printf(err, "Error reading %s %s", key_descrip, file); 1053296341Sdelphij goto error; 1054296341Sdelphij } 1055296341Sdelphij } 1056296341Sdelphij p = (unsigned char *)buf->data; 1057296341Sdelphij rsa = d2i_RSA_NET(NULL, &p, (long)size, NULL, 1058296341Sdelphij (format == FORMAT_IISSGC ? 1 : 0)); 1059296341Sdelphij if (rsa == NULL) 1060296341Sdelphij goto error; 1061296341Sdelphij BUF_MEM_free(buf); 1062296341Sdelphij EVP_PKEY_set1_RSA(pkey, rsa); 1063296341Sdelphij return pkey; 1064296341Sdelphij error: 1065296341Sdelphij BUF_MEM_free(buf); 1066296341Sdelphij EVP_PKEY_free(pkey); 1067296341Sdelphij return NULL; 1068296341Sdelphij} 1069296341Sdelphij#endif /* ndef OPENSSL_NO_RC4 */ 1070109998Smarkm 1071238405Sjkimstatic int load_certs_crls(BIO *err, const char *file, int format, 1072296341Sdelphij const char *pass, ENGINE *e, const char *desc, 1073296341Sdelphij STACK_OF(X509) **pcerts, 1074296341Sdelphij STACK_OF(X509_CRL) **pcrls) 1075296341Sdelphij{ 1076296341Sdelphij int i; 1077296341Sdelphij BIO *bio; 1078296341Sdelphij STACK_OF(X509_INFO) *xis = NULL; 1079296341Sdelphij X509_INFO *xi; 1080296341Sdelphij PW_CB_DATA cb_data; 1081296341Sdelphij int rv = 0; 108268651Skris 1083296341Sdelphij cb_data.password = pass; 1084296341Sdelphij cb_data.prompt_info = file; 1085109998Smarkm 1086296341Sdelphij if (format != FORMAT_PEM) { 1087296341Sdelphij BIO_printf(err, "bad input format specified for %s\n", desc); 1088296341Sdelphij return 0; 1089296341Sdelphij } 109068651Skris 1091296341Sdelphij if (file == NULL) 1092296341Sdelphij bio = BIO_new_fp(stdin, BIO_NOCLOSE); 1093296341Sdelphij else 1094296341Sdelphij bio = BIO_new_file(file, "r"); 1095238405Sjkim 1096296341Sdelphij if (bio == NULL) { 1097296341Sdelphij BIO_printf(err, "Error opening %s %s\n", desc, file ? file : "stdin"); 1098296341Sdelphij ERR_print_errors(err); 1099296341Sdelphij return 0; 1100296341Sdelphij } 1101238405Sjkim 1102296341Sdelphij xis = PEM_X509_INFO_read_bio(bio, NULL, 1103296341Sdelphij (pem_password_cb *)password_callback, 1104296341Sdelphij &cb_data); 1105238405Sjkim 1106296341Sdelphij BIO_free(bio); 1107238405Sjkim 1108296341Sdelphij if (pcerts) { 1109296341Sdelphij *pcerts = sk_X509_new_null(); 1110296341Sdelphij if (!*pcerts) 1111296341Sdelphij goto end; 1112296341Sdelphij } 111368651Skris 1114296341Sdelphij if (pcrls) { 1115296341Sdelphij *pcrls = sk_X509_CRL_new_null(); 1116296341Sdelphij if (!*pcrls) 1117296341Sdelphij goto end; 1118296341Sdelphij } 1119238405Sjkim 1120296341Sdelphij for (i = 0; i < sk_X509_INFO_num(xis); i++) { 1121296341Sdelphij xi = sk_X509_INFO_value(xis, i); 1122296341Sdelphij if (xi->x509 && pcerts) { 1123296341Sdelphij if (!sk_X509_push(*pcerts, xi->x509)) 1124296341Sdelphij goto end; 1125296341Sdelphij xi->x509 = NULL; 1126296341Sdelphij } 1127296341Sdelphij if (xi->crl && pcrls) { 1128296341Sdelphij if (!sk_X509_CRL_push(*pcrls, xi->crl)) 1129296341Sdelphij goto end; 1130296341Sdelphij xi->crl = NULL; 1131296341Sdelphij } 1132296341Sdelphij } 1133238405Sjkim 1134296341Sdelphij if (pcerts && sk_X509_num(*pcerts) > 0) 1135296341Sdelphij rv = 1; 1136238405Sjkim 1137296341Sdelphij if (pcrls && sk_X509_CRL_num(*pcrls) > 0) 1138296341Sdelphij rv = 1; 1139238405Sjkim 1140296341Sdelphij end: 1141238405Sjkim 1142296341Sdelphij if (xis) 1143296341Sdelphij sk_X509_INFO_pop_free(xis, X509_INFO_free); 1144238405Sjkim 1145296341Sdelphij if (rv == 0) { 1146296341Sdelphij if (pcerts) { 1147296341Sdelphij sk_X509_pop_free(*pcerts, X509_free); 1148296341Sdelphij *pcerts = NULL; 1149296341Sdelphij } 1150296341Sdelphij if (pcrls) { 1151296341Sdelphij sk_X509_CRL_pop_free(*pcrls, X509_CRL_free); 1152296341Sdelphij *pcrls = NULL; 1153296341Sdelphij } 1154296341Sdelphij BIO_printf(err, "unable to load %s\n", 1155296341Sdelphij pcerts ? "certificates" : "CRLs"); 1156296341Sdelphij ERR_print_errors(err); 1157296341Sdelphij } 1158296341Sdelphij return rv; 1159296341Sdelphij} 116068651Skris 1161238405SjkimSTACK_OF(X509) *load_certs(BIO *err, const char *file, int format, 1162296341Sdelphij const char *pass, ENGINE *e, const char *desc) 1163296341Sdelphij{ 1164296341Sdelphij STACK_OF(X509) *certs; 1165296341Sdelphij if (!load_certs_crls(err, file, format, pass, e, desc, &certs, NULL)) 1166296341Sdelphij return NULL; 1167296341Sdelphij return certs; 1168296341Sdelphij} 116968651Skris 1170238405SjkimSTACK_OF(X509_CRL) *load_crls(BIO *err, const char *file, int format, 1171296341Sdelphij const char *pass, ENGINE *e, const char *desc) 1172296341Sdelphij{ 1173296341Sdelphij STACK_OF(X509_CRL) *crls; 1174296341Sdelphij if (!load_certs_crls(err, file, format, pass, e, desc, NULL, &crls)) 1175296341Sdelphij return NULL; 1176296341Sdelphij return crls; 1177296341Sdelphij} 1178238405Sjkim 1179296341Sdelphij#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16) 1180109998Smarkm/* Return error for unknown extensions */ 1181296341Sdelphij#define X509V3_EXT_DEFAULT 0 1182109998Smarkm/* Print error for unknown extensions */ 1183296341Sdelphij#define X509V3_EXT_ERROR_UNKNOWN (1L << 16) 1184109998Smarkm/* ASN1 parse unknown extensions */ 1185296341Sdelphij#define X509V3_EXT_PARSE_UNKNOWN (2L << 16) 1186109998Smarkm/* BIO_dump unknown extensions */ 1187296341Sdelphij#define X509V3_EXT_DUMP_UNKNOWN (3L << 16) 1188109998Smarkm 1189109998Smarkm#define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \ 1190296341Sdelphij X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION) 1191109998Smarkm 1192109998Smarkmint set_cert_ex(unsigned long *flags, const char *arg) 1193109998Smarkm{ 1194296341Sdelphij static const NAME_EX_TBL cert_tbl[] = { 1195296341Sdelphij {"compatible", X509_FLAG_COMPAT, 0xffffffffl}, 1196296341Sdelphij {"ca_default", X509_FLAG_CA, 0xffffffffl}, 1197296341Sdelphij {"no_header", X509_FLAG_NO_HEADER, 0}, 1198296341Sdelphij {"no_version", X509_FLAG_NO_VERSION, 0}, 1199296341Sdelphij {"no_serial", X509_FLAG_NO_SERIAL, 0}, 1200296341Sdelphij {"no_signame", X509_FLAG_NO_SIGNAME, 0}, 1201296341Sdelphij {"no_validity", X509_FLAG_NO_VALIDITY, 0}, 1202296341Sdelphij {"no_subject", X509_FLAG_NO_SUBJECT, 0}, 1203296341Sdelphij {"no_issuer", X509_FLAG_NO_ISSUER, 0}, 1204296341Sdelphij {"no_pubkey", X509_FLAG_NO_PUBKEY, 0}, 1205296341Sdelphij {"no_extensions", X509_FLAG_NO_EXTENSIONS, 0}, 1206296341Sdelphij {"no_sigdump", X509_FLAG_NO_SIGDUMP, 0}, 1207296341Sdelphij {"no_aux", X509_FLAG_NO_AUX, 0}, 1208296341Sdelphij {"no_attributes", X509_FLAG_NO_ATTRIBUTES, 0}, 1209296341Sdelphij {"ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK}, 1210296341Sdelphij {"ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, 1211296341Sdelphij {"ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, 1212296341Sdelphij {"ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, 1213296341Sdelphij {NULL, 0, 0} 1214296341Sdelphij }; 1215296341Sdelphij return set_multi_opts(flags, arg, cert_tbl); 1216109998Smarkm} 1217109998Smarkm 121868651Skrisint set_name_ex(unsigned long *flags, const char *arg) 121968651Skris{ 1220296341Sdelphij static const NAME_EX_TBL ex_tbl[] = { 1221296341Sdelphij {"esc_2253", ASN1_STRFLGS_ESC_2253, 0}, 1222296341Sdelphij {"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0}, 1223296341Sdelphij {"esc_msb", ASN1_STRFLGS_ESC_MSB, 0}, 1224296341Sdelphij {"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0}, 1225296341Sdelphij {"utf8", ASN1_STRFLGS_UTF8_CONVERT, 0}, 1226296341Sdelphij {"ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0}, 1227296341Sdelphij {"show_type", ASN1_STRFLGS_SHOW_TYPE, 0}, 1228296341Sdelphij {"dump_all", ASN1_STRFLGS_DUMP_ALL, 0}, 1229296341Sdelphij {"dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0}, 1230296341Sdelphij {"dump_der", ASN1_STRFLGS_DUMP_DER, 0}, 1231296341Sdelphij {"compat", XN_FLAG_COMPAT, 0xffffffffL}, 1232296341Sdelphij {"sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK}, 1233296341Sdelphij {"sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK}, 1234296341Sdelphij {"sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK}, 1235296341Sdelphij {"sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK}, 1236296341Sdelphij {"dn_rev", XN_FLAG_DN_REV, 0}, 1237296341Sdelphij {"nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK}, 1238296341Sdelphij {"sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK}, 1239296341Sdelphij {"lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK}, 1240296341Sdelphij {"align", XN_FLAG_FN_ALIGN, 0}, 1241296341Sdelphij {"oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK}, 1242296341Sdelphij {"space_eq", XN_FLAG_SPC_EQ, 0}, 1243296341Sdelphij {"dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0}, 1244296341Sdelphij {"RFC2253", XN_FLAG_RFC2253, 0xffffffffL}, 1245296341Sdelphij {"oneline", XN_FLAG_ONELINE, 0xffffffffL}, 1246296341Sdelphij {"multiline", XN_FLAG_MULTILINE, 0xffffffffL}, 1247296341Sdelphij {"ca_default", XN_FLAG_MULTILINE, 0xffffffffL}, 1248296341Sdelphij {NULL, 0, 0} 1249296341Sdelphij }; 1250296341Sdelphij return set_multi_opts(flags, arg, ex_tbl); 1251109998Smarkm} 125268651Skris 1253109998Smarkmint set_ext_copy(int *copy_type, const char *arg) 1254109998Smarkm{ 1255296341Sdelphij if (!strcasecmp(arg, "none")) 1256296341Sdelphij *copy_type = EXT_COPY_NONE; 1257296341Sdelphij else if (!strcasecmp(arg, "copy")) 1258296341Sdelphij *copy_type = EXT_COPY_ADD; 1259296341Sdelphij else if (!strcasecmp(arg, "copyall")) 1260296341Sdelphij *copy_type = EXT_COPY_ALL; 1261296341Sdelphij else 1262296341Sdelphij return 0; 1263296341Sdelphij return 1; 1264109998Smarkm} 1265109998Smarkm 1266109998Smarkmint copy_extensions(X509 *x, X509_REQ *req, int copy_type) 1267109998Smarkm{ 1268296341Sdelphij STACK_OF(X509_EXTENSION) *exts = NULL; 1269296341Sdelphij X509_EXTENSION *ext, *tmpext; 1270296341Sdelphij ASN1_OBJECT *obj; 1271296341Sdelphij int i, idx, ret = 0; 1272296341Sdelphij if (!x || !req || (copy_type == EXT_COPY_NONE)) 1273296341Sdelphij return 1; 1274296341Sdelphij exts = X509_REQ_get_extensions(req); 1275109998Smarkm 1276296341Sdelphij for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { 1277296341Sdelphij ext = sk_X509_EXTENSION_value(exts, i); 1278296341Sdelphij obj = X509_EXTENSION_get_object(ext); 1279296341Sdelphij idx = X509_get_ext_by_OBJ(x, obj, -1); 1280296341Sdelphij /* Does extension exist? */ 1281296341Sdelphij if (idx != -1) { 1282296341Sdelphij /* If normal copy don't override existing extension */ 1283296341Sdelphij if (copy_type == EXT_COPY_ADD) 1284296341Sdelphij continue; 1285296341Sdelphij /* Delete all extensions of same type */ 1286296341Sdelphij do { 1287296341Sdelphij tmpext = X509_get_ext(x, idx); 1288296341Sdelphij X509_delete_ext(x, idx); 1289296341Sdelphij X509_EXTENSION_free(tmpext); 1290296341Sdelphij idx = X509_get_ext_by_OBJ(x, obj, -1); 1291296341Sdelphij } while (idx != -1); 1292296341Sdelphij } 1293296341Sdelphij if (!X509_add_ext(x, ext, -1)) 1294296341Sdelphij goto end; 1295296341Sdelphij } 1296109998Smarkm 1297296341Sdelphij ret = 1; 1298109998Smarkm 1299296341Sdelphij end: 1300109998Smarkm 1301296341Sdelphij sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); 1302109998Smarkm 1303296341Sdelphij return ret; 1304109998Smarkm} 1305109998Smarkm 1306296341Sdelphijstatic int set_multi_opts(unsigned long *flags, const char *arg, 1307296341Sdelphij const NAME_EX_TBL * in_tbl) 1308109998Smarkm{ 1309296341Sdelphij STACK_OF(CONF_VALUE) *vals; 1310296341Sdelphij CONF_VALUE *val; 1311296341Sdelphij int i, ret = 1; 1312296341Sdelphij if (!arg) 1313296341Sdelphij return 0; 1314296341Sdelphij vals = X509V3_parse_list(arg); 1315296341Sdelphij for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { 1316296341Sdelphij val = sk_CONF_VALUE_value(vals, i); 1317296341Sdelphij if (!set_table_opts(flags, val->name, in_tbl)) 1318296341Sdelphij ret = 0; 1319296341Sdelphij } 1320296341Sdelphij sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); 1321296341Sdelphij return ret; 1322109998Smarkm} 1323109998Smarkm 1324296341Sdelphijstatic int set_table_opts(unsigned long *flags, const char *arg, 1325296341Sdelphij const NAME_EX_TBL * in_tbl) 1326109998Smarkm{ 1327296341Sdelphij char c; 1328296341Sdelphij const NAME_EX_TBL *ptbl; 1329296341Sdelphij c = arg[0]; 133068651Skris 1331296341Sdelphij if (c == '-') { 1332296341Sdelphij c = 0; 1333296341Sdelphij arg++; 1334296341Sdelphij } else if (c == '+') { 1335296341Sdelphij c = 1; 1336296341Sdelphij arg++; 1337296341Sdelphij } else 1338296341Sdelphij c = 1; 133968651Skris 1340296341Sdelphij for (ptbl = in_tbl; ptbl->name; ptbl++) { 1341296341Sdelphij if (!strcasecmp(arg, ptbl->name)) { 1342296341Sdelphij *flags &= ~ptbl->mask; 1343296341Sdelphij if (c) 1344296341Sdelphij *flags |= ptbl->flag; 1345296341Sdelphij else 1346296341Sdelphij *flags &= ~ptbl->flag; 1347296341Sdelphij return 1; 1348296341Sdelphij } 1349296341Sdelphij } 1350296341Sdelphij return 0; 135168651Skris} 135268651Skris 1353296341Sdelphijvoid print_name(BIO *out, const char *title, X509_NAME *nm, 1354296341Sdelphij unsigned long lflags) 135568651Skris{ 1356296341Sdelphij char *buf; 1357296341Sdelphij char mline = 0; 1358296341Sdelphij int indent = 0; 1359109998Smarkm 1360296341Sdelphij if (title) 1361296341Sdelphij BIO_puts(out, title); 1362296341Sdelphij if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { 1363296341Sdelphij mline = 1; 1364296341Sdelphij indent = 4; 1365296341Sdelphij } 1366296341Sdelphij if (lflags == XN_FLAG_COMPAT) { 1367296341Sdelphij buf = X509_NAME_oneline(nm, 0, 0); 1368296341Sdelphij BIO_puts(out, buf); 1369296341Sdelphij BIO_puts(out, "\n"); 1370296341Sdelphij OPENSSL_free(buf); 1371296341Sdelphij } else { 1372296341Sdelphij if (mline) 1373296341Sdelphij BIO_puts(out, "\n"); 1374296341Sdelphij X509_NAME_print_ex(out, nm, indent, lflags); 1375296341Sdelphij BIO_puts(out, "\n"); 1376296341Sdelphij } 137768651Skris} 137868651Skris 1379109998SmarkmX509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath) 1380109998Smarkm{ 1381296341Sdelphij X509_STORE *store; 1382296341Sdelphij X509_LOOKUP *lookup; 1383296341Sdelphij if (!(store = X509_STORE_new())) 1384296341Sdelphij goto end; 1385296341Sdelphij lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); 1386296341Sdelphij if (lookup == NULL) 1387296341Sdelphij goto end; 1388296341Sdelphij if (CAfile) { 1389296341Sdelphij if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) { 1390296341Sdelphij BIO_printf(bp, "Error loading file %s\n", CAfile); 1391296341Sdelphij goto end; 1392296341Sdelphij } 1393296341Sdelphij } else 1394296341Sdelphij X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); 1395109998Smarkm 1396296341Sdelphij lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); 1397296341Sdelphij if (lookup == NULL) 1398296341Sdelphij goto end; 1399296341Sdelphij if (CApath) { 1400296341Sdelphij if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) { 1401296341Sdelphij BIO_printf(bp, "Error loading directory %s\n", CApath); 1402296341Sdelphij goto end; 1403296341Sdelphij } 1404296341Sdelphij } else 1405296341Sdelphij X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); 1406296341Sdelphij 1407296341Sdelphij ERR_clear_error(); 1408296341Sdelphij return store; 1409296341Sdelphij end: 1410296341Sdelphij X509_STORE_free(store); 1411296341Sdelphij return NULL; 1412109998Smarkm} 1413109998Smarkm 1414111147Snectar#ifndef OPENSSL_NO_ENGINE 1415109998Smarkm/* Try to load an engine in a shareable library */ 1416109998Smarkmstatic ENGINE *try_load_engine(BIO *err, const char *engine, int debug) 1417296341Sdelphij{ 1418296341Sdelphij ENGINE *e = ENGINE_by_id("dynamic"); 1419296341Sdelphij if (e) { 1420296341Sdelphij if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0) 1421296341Sdelphij || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) { 1422296341Sdelphij ENGINE_free(e); 1423296341Sdelphij e = NULL; 1424296341Sdelphij } 1425296341Sdelphij } 1426296341Sdelphij return e; 1427296341Sdelphij} 1428109998Smarkm 1429109998SmarkmENGINE *setup_engine(BIO *err, const char *engine, int debug) 1430296341Sdelphij{ 1431296341Sdelphij ENGINE *e = NULL; 1432109998Smarkm 1433296341Sdelphij if (engine) { 1434296341Sdelphij if (strcmp(engine, "auto") == 0) { 1435296341Sdelphij BIO_printf(err, "enabling auto ENGINE support\n"); 1436296341Sdelphij ENGINE_register_all_complete(); 1437296341Sdelphij return NULL; 1438296341Sdelphij } 1439296341Sdelphij if ((e = ENGINE_by_id(engine)) == NULL 1440296341Sdelphij && (e = try_load_engine(err, engine, debug)) == NULL) { 1441296341Sdelphij BIO_printf(err, "invalid engine \"%s\"\n", engine); 1442296341Sdelphij ERR_print_errors(err); 1443296341Sdelphij return NULL; 1444296341Sdelphij } 1445296341Sdelphij if (debug) { 1446296341Sdelphij ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, err, 0); 1447296341Sdelphij } 1448296341Sdelphij ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, ui_method, 0, 1); 1449296341Sdelphij if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { 1450296341Sdelphij BIO_printf(err, "can't use that engine\n"); 1451296341Sdelphij ERR_print_errors(err); 1452296341Sdelphij ENGINE_free(e); 1453296341Sdelphij return NULL; 1454296341Sdelphij } 1455109998Smarkm 1456296341Sdelphij BIO_printf(err, "engine \"%s\" set.\n", ENGINE_get_id(e)); 1457109998Smarkm 1458296341Sdelphij /* Free our "structural" reference. */ 1459296341Sdelphij ENGINE_free(e); 1460296341Sdelphij } 1461296341Sdelphij return e; 1462296341Sdelphij} 1463111147Snectar#endif 1464109998Smarkm 1465109998Smarkmint load_config(BIO *err, CONF *cnf) 1466296341Sdelphij{ 1467296341Sdelphij static int load_config_called = 0; 1468296341Sdelphij if (load_config_called) 1469296341Sdelphij return 1; 1470296341Sdelphij load_config_called = 1; 1471296341Sdelphij if (!cnf) 1472296341Sdelphij cnf = config; 1473296341Sdelphij if (!cnf) 1474296341Sdelphij return 1; 1475109998Smarkm 1476296341Sdelphij OPENSSL_load_builtin_modules(); 1477109998Smarkm 1478296341Sdelphij if (CONF_modules_load(cnf, NULL, 0) <= 0) { 1479296341Sdelphij BIO_printf(err, "Error configuring OpenSSL\n"); 1480296341Sdelphij ERR_print_errors(err); 1481296341Sdelphij return 0; 1482296341Sdelphij } 1483296341Sdelphij return 1; 1484296341Sdelphij} 1485109998Smarkm 1486109998Smarkmchar *make_config_name() 1487296341Sdelphij{ 1488296341Sdelphij const char *t = X509_get_default_cert_area(); 1489296341Sdelphij size_t len; 1490296341Sdelphij char *p; 1491109998Smarkm 1492296341Sdelphij len = strlen(t) + strlen(OPENSSL_CONF) + 2; 1493296341Sdelphij p = OPENSSL_malloc(len); 1494296341Sdelphij if (p == NULL) 1495296341Sdelphij return NULL; 1496296341Sdelphij BUF_strlcpy(p, t, len); 1497109998Smarkm#ifndef OPENSSL_SYS_VMS 1498296341Sdelphij BUF_strlcat(p, "/", len); 1499109998Smarkm#endif 1500296341Sdelphij BUF_strlcat(p, OPENSSL_CONF, len); 1501109998Smarkm 1502296341Sdelphij return p; 1503296341Sdelphij} 1504127128Snectar 1505238405Sjkimstatic unsigned long index_serial_hash(const OPENSSL_CSTRING *a) 1506296341Sdelphij{ 1507296341Sdelphij const char *n; 1508127128Snectar 1509296341Sdelphij n = a[DB_serial]; 1510296341Sdelphij while (*n == '0') 1511296341Sdelphij n++; 1512296341Sdelphij return (lh_strhash(n)); 1513296341Sdelphij} 1514127128Snectar 1515296341Sdelphijstatic int index_serial_cmp(const OPENSSL_CSTRING *a, 1516296341Sdelphij const OPENSSL_CSTRING *b) 1517296341Sdelphij{ 1518296341Sdelphij const char *aa, *bb; 1519127128Snectar 1520296341Sdelphij for (aa = a[DB_serial]; *aa == '0'; aa++) ; 1521296341Sdelphij for (bb = b[DB_serial]; *bb == '0'; bb++) ; 1522296341Sdelphij return (strcmp(aa, bb)); 1523296341Sdelphij} 1524127128Snectar 1525127128Snectarstatic int index_name_qual(char **a) 1526296341Sdelphij{ 1527296341Sdelphij return (a[0][0] == 'V'); 1528296341Sdelphij} 1529127128Snectar 1530238405Sjkimstatic unsigned long index_name_hash(const OPENSSL_CSTRING *a) 1531296341Sdelphij{ 1532296341Sdelphij return (lh_strhash(a[DB_name])); 1533296341Sdelphij} 1534127128Snectar 1535238405Sjkimint index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b) 1536296341Sdelphij{ 1537296341Sdelphij return (strcmp(a[DB_name], b[DB_name])); 1538296341Sdelphij} 1539127128Snectar 1540238405Sjkimstatic IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING) 1541238405Sjkimstatic IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING) 1542238405Sjkimstatic IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING) 1543238405Sjkimstatic IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING) 1544127128Snectar#undef BSIZE 1545127128Snectar#define BSIZE 256 1546127128SnectarBIGNUM *load_serial(char *serialfile, int create, ASN1_INTEGER **retai) 1547296341Sdelphij{ 1548296341Sdelphij BIO *in = NULL; 1549296341Sdelphij BIGNUM *ret = NULL; 1550296341Sdelphij MS_STATIC char buf[1024]; 1551296341Sdelphij ASN1_INTEGER *ai = NULL; 1552127128Snectar 1553296341Sdelphij ai = ASN1_INTEGER_new(); 1554296341Sdelphij if (ai == NULL) 1555296341Sdelphij goto err; 1556127128Snectar 1557296341Sdelphij if ((in = BIO_new(BIO_s_file())) == NULL) { 1558296341Sdelphij ERR_print_errors(bio_err); 1559296341Sdelphij goto err; 1560296341Sdelphij } 1561127128Snectar 1562296341Sdelphij if (BIO_read_filename(in, serialfile) <= 0) { 1563296341Sdelphij if (!create) { 1564296341Sdelphij perror(serialfile); 1565296341Sdelphij goto err; 1566296341Sdelphij } else { 1567296341Sdelphij ret = BN_new(); 1568296341Sdelphij if (ret == NULL || !rand_serial(ret, ai)) 1569296341Sdelphij BIO_printf(bio_err, "Out of memory\n"); 1570296341Sdelphij } 1571296341Sdelphij } else { 1572296341Sdelphij if (!a2i_ASN1_INTEGER(in, ai, buf, 1024)) { 1573296341Sdelphij BIO_printf(bio_err, "unable to load number from %s\n", 1574296341Sdelphij serialfile); 1575296341Sdelphij goto err; 1576296341Sdelphij } 1577296341Sdelphij ret = ASN1_INTEGER_to_BN(ai, NULL); 1578296341Sdelphij if (ret == NULL) { 1579296341Sdelphij BIO_printf(bio_err, 1580296341Sdelphij "error converting number from bin to BIGNUM\n"); 1581296341Sdelphij goto err; 1582296341Sdelphij } 1583296341Sdelphij } 1584127128Snectar 1585296341Sdelphij if (ret && retai) { 1586296341Sdelphij *retai = ai; 1587296341Sdelphij ai = NULL; 1588296341Sdelphij } 1589127128Snectar err: 1590296341Sdelphij if (in != NULL) 1591296341Sdelphij BIO_free(in); 1592296341Sdelphij if (ai != NULL) 1593296341Sdelphij ASN1_INTEGER_free(ai); 1594296341Sdelphij return (ret); 1595296341Sdelphij} 1596127128Snectar 1597296341Sdelphijint save_serial(char *serialfile, char *suffix, BIGNUM *serial, 1598296341Sdelphij ASN1_INTEGER **retai) 1599296341Sdelphij{ 1600296341Sdelphij char buf[1][BSIZE]; 1601296341Sdelphij BIO *out = NULL; 1602296341Sdelphij int ret = 0; 1603296341Sdelphij ASN1_INTEGER *ai = NULL; 1604296341Sdelphij int j; 1605127128Snectar 1606296341Sdelphij if (suffix == NULL) 1607296341Sdelphij j = strlen(serialfile); 1608296341Sdelphij else 1609296341Sdelphij j = strlen(serialfile) + strlen(suffix) + 1; 1610296341Sdelphij if (j >= BSIZE) { 1611296341Sdelphij BIO_printf(bio_err, "file name too long\n"); 1612296341Sdelphij goto err; 1613296341Sdelphij } 1614127128Snectar 1615296341Sdelphij if (suffix == NULL) 1616296341Sdelphij BUF_strlcpy(buf[0], serialfile, BSIZE); 1617296341Sdelphij else { 1618127128Snectar#ifndef OPENSSL_SYS_VMS 1619296341Sdelphij j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", serialfile, suffix); 1620127128Snectar#else 1621296341Sdelphij j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", serialfile, suffix); 1622127128Snectar#endif 1623296341Sdelphij } 1624127128Snectar#ifdef RL_DEBUG 1625296341Sdelphij BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[0]); 1626127128Snectar#endif 1627296341Sdelphij out = BIO_new(BIO_s_file()); 1628296341Sdelphij if (out == NULL) { 1629296341Sdelphij ERR_print_errors(bio_err); 1630296341Sdelphij goto err; 1631296341Sdelphij } 1632296341Sdelphij if (BIO_write_filename(out, buf[0]) <= 0) { 1633296341Sdelphij perror(serialfile); 1634296341Sdelphij goto err; 1635296341Sdelphij } 1636127128Snectar 1637296341Sdelphij if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) { 1638296341Sdelphij BIO_printf(bio_err, "error converting serial to ASN.1 format\n"); 1639296341Sdelphij goto err; 1640296341Sdelphij } 1641296341Sdelphij i2a_ASN1_INTEGER(out, ai); 1642296341Sdelphij BIO_puts(out, "\n"); 1643296341Sdelphij ret = 1; 1644296341Sdelphij if (retai) { 1645296341Sdelphij *retai = ai; 1646296341Sdelphij ai = NULL; 1647296341Sdelphij } 1648296341Sdelphij err: 1649296341Sdelphij if (out != NULL) 1650296341Sdelphij BIO_free_all(out); 1651296341Sdelphij if (ai != NULL) 1652296341Sdelphij ASN1_INTEGER_free(ai); 1653296341Sdelphij return (ret); 1654296341Sdelphij} 1655127128Snectar 1656127128Snectarint rotate_serial(char *serialfile, char *new_suffix, char *old_suffix) 1657296341Sdelphij{ 1658296341Sdelphij char buf[5][BSIZE]; 1659296341Sdelphij int i, j; 1660127128Snectar 1661296341Sdelphij i = strlen(serialfile) + strlen(old_suffix); 1662296341Sdelphij j = strlen(serialfile) + strlen(new_suffix); 1663296341Sdelphij if (i > j) 1664296341Sdelphij j = i; 1665296341Sdelphij if (j + 1 >= BSIZE) { 1666296341Sdelphij BIO_printf(bio_err, "file name too long\n"); 1667296341Sdelphij goto err; 1668296341Sdelphij } 1669127128Snectar#ifndef OPENSSL_SYS_VMS 1670296341Sdelphij j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", serialfile, new_suffix); 1671127128Snectar#else 1672296341Sdelphij j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", serialfile, new_suffix); 1673127128Snectar#endif 1674127128Snectar#ifndef OPENSSL_SYS_VMS 1675296341Sdelphij j = BIO_snprintf(buf[1], sizeof buf[1], "%s.%s", serialfile, old_suffix); 1676127128Snectar#else 1677296341Sdelphij j = BIO_snprintf(buf[1], sizeof buf[1], "%s-%s", serialfile, old_suffix); 1678127128Snectar#endif 1679238405Sjkim#ifdef RL_DEBUG 1680296341Sdelphij BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", 1681296341Sdelphij serialfile, buf[1]); 1682238405Sjkim#endif 1683296341Sdelphij if (rename(serialfile, buf[1]) < 0 && errno != ENOENT 1684127128Snectar#ifdef ENOTDIR 1685296341Sdelphij && errno != ENOTDIR 1686127128Snectar#endif 1687296341Sdelphij ) { 1688296341Sdelphij BIO_printf(bio_err, 1689296341Sdelphij "unable to rename %s to %s\n", serialfile, buf[1]); 1690296341Sdelphij perror("reason"); 1691296341Sdelphij goto err; 1692296341Sdelphij } 1693127128Snectar#ifdef RL_DEBUG 1694296341Sdelphij BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", 1695296341Sdelphij buf[0], serialfile); 1696127128Snectar#endif 1697296341Sdelphij if (rename(buf[0], serialfile) < 0) { 1698296341Sdelphij BIO_printf(bio_err, 1699296341Sdelphij "unable to rename %s to %s\n", buf[0], serialfile); 1700296341Sdelphij perror("reason"); 1701296341Sdelphij rename(buf[1], serialfile); 1702296341Sdelphij goto err; 1703296341Sdelphij } 1704296341Sdelphij return 1; 1705127128Snectar err: 1706296341Sdelphij return 0; 1707296341Sdelphij} 1708127128Snectar 1709142425Snectarint rand_serial(BIGNUM *b, ASN1_INTEGER *ai) 1710296341Sdelphij{ 1711296341Sdelphij BIGNUM *btmp; 1712296341Sdelphij int ret = 0; 1713296341Sdelphij if (b) 1714296341Sdelphij btmp = b; 1715296341Sdelphij else 1716296341Sdelphij btmp = BN_new(); 1717142425Snectar 1718296341Sdelphij if (!btmp) 1719296341Sdelphij return 0; 1720142425Snectar 1721296341Sdelphij if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) 1722296341Sdelphij goto error; 1723296341Sdelphij if (ai && !BN_to_ASN1_INTEGER(btmp, ai)) 1724296341Sdelphij goto error; 1725142425Snectar 1726296341Sdelphij ret = 1; 1727142425Snectar 1728296341Sdelphij error: 1729142425Snectar 1730296341Sdelphij if (!b) 1731296341Sdelphij BN_free(btmp); 1732296341Sdelphij 1733296341Sdelphij return ret; 1734296341Sdelphij} 1735296341Sdelphij 1736127128SnectarCA_DB *load_index(char *dbfile, DB_ATTR *db_attr) 1737296341Sdelphij{ 1738296341Sdelphij CA_DB *retdb = NULL; 1739296341Sdelphij TXT_DB *tmpdb = NULL; 1740296341Sdelphij BIO *in = BIO_new(BIO_s_file()); 1741296341Sdelphij CONF *dbattr_conf = NULL; 1742296341Sdelphij char buf[1][BSIZE]; 1743296341Sdelphij long errorline = -1; 1744127128Snectar 1745296341Sdelphij if (in == NULL) { 1746296341Sdelphij ERR_print_errors(bio_err); 1747296341Sdelphij goto err; 1748296341Sdelphij } 1749296341Sdelphij if (BIO_read_filename(in, dbfile) <= 0) { 1750296341Sdelphij perror(dbfile); 1751296341Sdelphij BIO_printf(bio_err, "unable to open '%s'\n", dbfile); 1752296341Sdelphij goto err; 1753296341Sdelphij } 1754296341Sdelphij if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL) 1755296341Sdelphij goto err; 1756127128Snectar 1757127128Snectar#ifndef OPENSSL_SYS_VMS 1758296341Sdelphij BIO_snprintf(buf[0], sizeof buf[0], "%s.attr", dbfile); 1759127128Snectar#else 1760296341Sdelphij BIO_snprintf(buf[0], sizeof buf[0], "%s-attr", dbfile); 1761127128Snectar#endif 1762296341Sdelphij dbattr_conf = NCONF_new(NULL); 1763296341Sdelphij if (NCONF_load(dbattr_conf, buf[0], &errorline) <= 0) { 1764296341Sdelphij if (errorline > 0) { 1765296341Sdelphij BIO_printf(bio_err, 1766296341Sdelphij "error on line %ld of db attribute file '%s'\n", 1767296341Sdelphij errorline, buf[0]); 1768296341Sdelphij goto err; 1769296341Sdelphij } else { 1770296341Sdelphij NCONF_free(dbattr_conf); 1771296341Sdelphij dbattr_conf = NULL; 1772296341Sdelphij } 1773296341Sdelphij } 1774127128Snectar 1775296341Sdelphij if ((retdb = OPENSSL_malloc(sizeof(CA_DB))) == NULL) { 1776296341Sdelphij fprintf(stderr, "Out of memory\n"); 1777296341Sdelphij goto err; 1778296341Sdelphij } 1779127128Snectar 1780296341Sdelphij retdb->db = tmpdb; 1781296341Sdelphij tmpdb = NULL; 1782296341Sdelphij if (db_attr) 1783296341Sdelphij retdb->attributes = *db_attr; 1784296341Sdelphij else { 1785296341Sdelphij retdb->attributes.unique_subject = 1; 1786296341Sdelphij } 1787127128Snectar 1788296341Sdelphij if (dbattr_conf) { 1789296341Sdelphij char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject"); 1790296341Sdelphij if (p) { 1791160814Ssimon#ifdef RL_DEBUG 1792296341Sdelphij BIO_printf(bio_err, 1793296341Sdelphij "DEBUG[load_index]: unique_subject = \"%s\"\n", p); 1794160814Ssimon#endif 1795296341Sdelphij retdb->attributes.unique_subject = parse_yesno(p, 1); 1796296341Sdelphij } 1797296341Sdelphij } 1798127128Snectar 1799127128Snectar err: 1800296341Sdelphij if (dbattr_conf) 1801296341Sdelphij NCONF_free(dbattr_conf); 1802296341Sdelphij if (tmpdb) 1803296341Sdelphij TXT_DB_free(tmpdb); 1804296341Sdelphij if (in) 1805296341Sdelphij BIO_free_all(in); 1806296341Sdelphij return retdb; 1807296341Sdelphij} 1808127128Snectar 1809127128Snectarint index_index(CA_DB *db) 1810296341Sdelphij{ 1811296341Sdelphij if (!TXT_DB_create_index(db->db, DB_serial, NULL, 1812296341Sdelphij LHASH_HASH_FN(index_serial), 1813296341Sdelphij LHASH_COMP_FN(index_serial))) { 1814296341Sdelphij BIO_printf(bio_err, 1815296341Sdelphij "error creating serial number index:(%ld,%ld,%ld)\n", 1816296341Sdelphij db->db->error, db->db->arg1, db->db->arg2); 1817296341Sdelphij return 0; 1818296341Sdelphij } 1819127128Snectar 1820296341Sdelphij if (db->attributes.unique_subject 1821296341Sdelphij && !TXT_DB_create_index(db->db, DB_name, index_name_qual, 1822296341Sdelphij LHASH_HASH_FN(index_name), 1823296341Sdelphij LHASH_COMP_FN(index_name))) { 1824296341Sdelphij BIO_printf(bio_err, "error creating name index:(%ld,%ld,%ld)\n", 1825296341Sdelphij db->db->error, db->db->arg1, db->db->arg2); 1826296341Sdelphij return 0; 1827296341Sdelphij } 1828296341Sdelphij return 1; 1829296341Sdelphij} 1830127128Snectar 1831160814Ssimonint save_index(const char *dbfile, const char *suffix, CA_DB *db) 1832296341Sdelphij{ 1833296341Sdelphij char buf[3][BSIZE]; 1834296341Sdelphij BIO *out = BIO_new(BIO_s_file()); 1835296341Sdelphij int j; 1836127128Snectar 1837296341Sdelphij if (out == NULL) { 1838296341Sdelphij ERR_print_errors(bio_err); 1839296341Sdelphij goto err; 1840296341Sdelphij } 1841127128Snectar 1842296341Sdelphij j = strlen(dbfile) + strlen(suffix); 1843296341Sdelphij if (j + 6 >= BSIZE) { 1844296341Sdelphij BIO_printf(bio_err, "file name too long\n"); 1845296341Sdelphij goto err; 1846296341Sdelphij } 1847127128Snectar#ifndef OPENSSL_SYS_VMS 1848296341Sdelphij j = BIO_snprintf(buf[2], sizeof buf[2], "%s.attr", dbfile); 1849127128Snectar#else 1850296341Sdelphij j = BIO_snprintf(buf[2], sizeof buf[2], "%s-attr", dbfile); 1851127128Snectar#endif 1852127128Snectar#ifndef OPENSSL_SYS_VMS 1853296341Sdelphij j = BIO_snprintf(buf[1], sizeof buf[1], "%s.attr.%s", dbfile, suffix); 1854127128Snectar#else 1855296341Sdelphij j = BIO_snprintf(buf[1], sizeof buf[1], "%s-attr-%s", dbfile, suffix); 1856127128Snectar#endif 1857127128Snectar#ifndef OPENSSL_SYS_VMS 1858296341Sdelphij j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", dbfile, suffix); 1859127128Snectar#else 1860296341Sdelphij j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", dbfile, suffix); 1861127128Snectar#endif 1862127128Snectar#ifdef RL_DEBUG 1863296341Sdelphij BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[0]); 1864127128Snectar#endif 1865296341Sdelphij if (BIO_write_filename(out, buf[0]) <= 0) { 1866296341Sdelphij perror(dbfile); 1867296341Sdelphij BIO_printf(bio_err, "unable to open '%s'\n", dbfile); 1868296341Sdelphij goto err; 1869296341Sdelphij } 1870296341Sdelphij j = TXT_DB_write(out, db->db); 1871296341Sdelphij if (j <= 0) 1872296341Sdelphij goto err; 1873127128Snectar 1874296341Sdelphij BIO_free(out); 1875296341Sdelphij 1876296341Sdelphij out = BIO_new(BIO_s_file()); 1877127128Snectar#ifdef RL_DEBUG 1878296341Sdelphij BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[1]); 1879127128Snectar#endif 1880296341Sdelphij if (BIO_write_filename(out, buf[1]) <= 0) { 1881296341Sdelphij perror(buf[2]); 1882296341Sdelphij BIO_printf(bio_err, "unable to open '%s'\n", buf[2]); 1883296341Sdelphij goto err; 1884296341Sdelphij } 1885296341Sdelphij BIO_printf(out, "unique_subject = %s\n", 1886296341Sdelphij db->attributes.unique_subject ? "yes" : "no"); 1887296341Sdelphij BIO_free(out); 1888127128Snectar 1889296341Sdelphij return 1; 1890127128Snectar err: 1891296341Sdelphij return 0; 1892296341Sdelphij} 1893127128Snectar 1894296341Sdelphijint rotate_index(const char *dbfile, const char *new_suffix, 1895296341Sdelphij const char *old_suffix) 1896296341Sdelphij{ 1897296341Sdelphij char buf[5][BSIZE]; 1898296341Sdelphij int i, j; 1899127128Snectar 1900296341Sdelphij i = strlen(dbfile) + strlen(old_suffix); 1901296341Sdelphij j = strlen(dbfile) + strlen(new_suffix); 1902296341Sdelphij if (i > j) 1903296341Sdelphij j = i; 1904296341Sdelphij if (j + 6 >= BSIZE) { 1905296341Sdelphij BIO_printf(bio_err, "file name too long\n"); 1906296341Sdelphij goto err; 1907296341Sdelphij } 1908127128Snectar#ifndef OPENSSL_SYS_VMS 1909296341Sdelphij j = BIO_snprintf(buf[4], sizeof buf[4], "%s.attr", dbfile); 1910127128Snectar#else 1911296341Sdelphij j = BIO_snprintf(buf[4], sizeof buf[4], "%s-attr", dbfile); 1912127128Snectar#endif 1913127128Snectar#ifndef OPENSSL_SYS_VMS 1914296341Sdelphij j = BIO_snprintf(buf[2], sizeof buf[2], "%s.attr.%s", dbfile, new_suffix); 1915127128Snectar#else 1916296341Sdelphij j = BIO_snprintf(buf[2], sizeof buf[2], "%s-attr-%s", dbfile, new_suffix); 1917127128Snectar#endif 1918127128Snectar#ifndef OPENSSL_SYS_VMS 1919296341Sdelphij j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", dbfile, new_suffix); 1920127128Snectar#else 1921296341Sdelphij j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", dbfile, new_suffix); 1922127128Snectar#endif 1923127128Snectar#ifndef OPENSSL_SYS_VMS 1924296341Sdelphij j = BIO_snprintf(buf[1], sizeof buf[1], "%s.%s", dbfile, old_suffix); 1925127128Snectar#else 1926296341Sdelphij j = BIO_snprintf(buf[1], sizeof buf[1], "%s-%s", dbfile, old_suffix); 1927127128Snectar#endif 1928127128Snectar#ifndef OPENSSL_SYS_VMS 1929296341Sdelphij j = BIO_snprintf(buf[3], sizeof buf[3], "%s.attr.%s", dbfile, old_suffix); 1930127128Snectar#else 1931296341Sdelphij j = BIO_snprintf(buf[3], sizeof buf[3], "%s-attr-%s", dbfile, old_suffix); 1932127128Snectar#endif 1933238405Sjkim#ifdef RL_DEBUG 1934296341Sdelphij BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", dbfile, buf[1]); 1935238405Sjkim#endif 1936296341Sdelphij if (rename(dbfile, buf[1]) < 0 && errno != ENOENT 1937127128Snectar#ifdef ENOTDIR 1938296341Sdelphij && errno != ENOTDIR 1939127128Snectar#endif 1940296341Sdelphij ) { 1941296341Sdelphij BIO_printf(bio_err, "unable to rename %s to %s\n", dbfile, buf[1]); 1942296341Sdelphij perror("reason"); 1943296341Sdelphij goto err; 1944296341Sdelphij } 1945127128Snectar#ifdef RL_DEBUG 1946296341Sdelphij BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", buf[0], dbfile); 1947127128Snectar#endif 1948296341Sdelphij if (rename(buf[0], dbfile) < 0) { 1949296341Sdelphij BIO_printf(bio_err, "unable to rename %s to %s\n", buf[0], dbfile); 1950296341Sdelphij perror("reason"); 1951296341Sdelphij rename(buf[1], dbfile); 1952296341Sdelphij goto err; 1953296341Sdelphij } 1954238405Sjkim#ifdef RL_DEBUG 1955296341Sdelphij BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", buf[4], buf[3]); 1956238405Sjkim#endif 1957296341Sdelphij if (rename(buf[4], buf[3]) < 0 && errno != ENOENT 1958127128Snectar#ifdef ENOTDIR 1959296341Sdelphij && errno != ENOTDIR 1960127128Snectar#endif 1961296341Sdelphij ) { 1962296341Sdelphij BIO_printf(bio_err, "unable to rename %s to %s\n", buf[4], buf[3]); 1963296341Sdelphij perror("reason"); 1964296341Sdelphij rename(dbfile, buf[0]); 1965296341Sdelphij rename(buf[1], dbfile); 1966296341Sdelphij goto err; 1967296341Sdelphij } 1968127128Snectar#ifdef RL_DEBUG 1969296341Sdelphij BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", buf[2], buf[4]); 1970127128Snectar#endif 1971296341Sdelphij if (rename(buf[2], buf[4]) < 0) { 1972296341Sdelphij BIO_printf(bio_err, "unable to rename %s to %s\n", buf[2], buf[4]); 1973296341Sdelphij perror("reason"); 1974296341Sdelphij rename(buf[3], buf[4]); 1975296341Sdelphij rename(dbfile, buf[0]); 1976296341Sdelphij rename(buf[1], dbfile); 1977296341Sdelphij goto err; 1978296341Sdelphij } 1979296341Sdelphij return 1; 1980127128Snectar err: 1981296341Sdelphij return 0; 1982296341Sdelphij} 1983127128Snectar 1984127128Snectarvoid free_index(CA_DB *db) 1985296341Sdelphij{ 1986296341Sdelphij if (db) { 1987296341Sdelphij if (db->db) 1988296341Sdelphij TXT_DB_free(db->db); 1989296341Sdelphij OPENSSL_free(db); 1990296341Sdelphij } 1991296341Sdelphij} 1992142425Snectar 1993160814Ssimonint parse_yesno(const char *str, int def) 1994296341Sdelphij{ 1995296341Sdelphij int ret = def; 1996296341Sdelphij if (str) { 1997296341Sdelphij switch (*str) { 1998296341Sdelphij case 'f': /* false */ 1999296341Sdelphij case 'F': /* FALSE */ 2000296341Sdelphij case 'n': /* no */ 2001296341Sdelphij case 'N': /* NO */ 2002296341Sdelphij case '0': /* 0 */ 2003296341Sdelphij ret = 0; 2004296341Sdelphij break; 2005296341Sdelphij case 't': /* true */ 2006296341Sdelphij case 'T': /* TRUE */ 2007296341Sdelphij case 'y': /* yes */ 2008296341Sdelphij case 'Y': /* YES */ 2009296341Sdelphij case '1': /* 1 */ 2010296341Sdelphij ret = 1; 2011296341Sdelphij break; 2012296341Sdelphij default: 2013296341Sdelphij ret = def; 2014296341Sdelphij break; 2015296341Sdelphij } 2016296341Sdelphij } 2017296341Sdelphij return ret; 2018296341Sdelphij} 2019160814Ssimon 2020160814Ssimon/* 2021160814Ssimon * subject is expected to be in the format /type0=value0/type1=value1/type2=... 2022160814Ssimon * where characters may be escaped by \ 2023160814Ssimon */ 2024160814SsimonX509_NAME *parse_name(char *subject, long chtype, int multirdn) 2025296341Sdelphij{ 2026296341Sdelphij size_t buflen = strlen(subject) + 1; /* to copy the types and values 2027296341Sdelphij * into. due to escaping, the copy 2028296341Sdelphij * can only become shorter */ 2029296341Sdelphij char *buf = OPENSSL_malloc(buflen); 2030296341Sdelphij size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */ 2031296341Sdelphij char **ne_types = OPENSSL_malloc(max_ne * sizeof(char *)); 2032296341Sdelphij char **ne_values = OPENSSL_malloc(max_ne * sizeof(char *)); 2033296341Sdelphij int *mval = OPENSSL_malloc(max_ne * sizeof(int)); 2034160814Ssimon 2035296341Sdelphij char *sp = subject, *bp = buf; 2036296341Sdelphij int i, ne_num = 0; 2037160814Ssimon 2038296341Sdelphij X509_NAME *n = NULL; 2039296341Sdelphij int nid; 2040160814Ssimon 2041296341Sdelphij if (!buf || !ne_types || !ne_values || !mval) { 2042296341Sdelphij BIO_printf(bio_err, "malloc error\n"); 2043296341Sdelphij goto error; 2044296341Sdelphij } 2045160814Ssimon 2046296341Sdelphij if (*subject != '/') { 2047296341Sdelphij BIO_printf(bio_err, "Subject does not start with '/'.\n"); 2048296341Sdelphij goto error; 2049296341Sdelphij } 2050296341Sdelphij sp++; /* skip leading / */ 2051160814Ssimon 2052296341Sdelphij /* no multivalued RDN by default */ 2053296341Sdelphij mval[ne_num] = 0; 2054160814Ssimon 2055296341Sdelphij while (*sp) { 2056296341Sdelphij /* collect type */ 2057296341Sdelphij ne_types[ne_num] = bp; 2058296341Sdelphij while (*sp) { 2059296341Sdelphij if (*sp == '\\') { /* is there anything to escape in the 2060296341Sdelphij * type...? */ 2061296341Sdelphij if (*++sp) 2062296341Sdelphij *bp++ = *sp++; 2063296341Sdelphij else { 2064296341Sdelphij BIO_printf(bio_err, 2065296341Sdelphij "escape character at end of string\n"); 2066296341Sdelphij goto error; 2067296341Sdelphij } 2068296341Sdelphij } else if (*sp == '=') { 2069296341Sdelphij sp++; 2070296341Sdelphij *bp++ = '\0'; 2071296341Sdelphij break; 2072296341Sdelphij } else 2073296341Sdelphij *bp++ = *sp++; 2074296341Sdelphij } 2075296341Sdelphij if (!*sp) { 2076296341Sdelphij BIO_printf(bio_err, 2077296341Sdelphij "end of string encountered while processing type of subject name element #%d\n", 2078296341Sdelphij ne_num); 2079296341Sdelphij goto error; 2080296341Sdelphij } 2081296341Sdelphij ne_values[ne_num] = bp; 2082296341Sdelphij while (*sp) { 2083296341Sdelphij if (*sp == '\\') { 2084296341Sdelphij if (*++sp) 2085296341Sdelphij *bp++ = *sp++; 2086296341Sdelphij else { 2087296341Sdelphij BIO_printf(bio_err, 2088296341Sdelphij "escape character at end of string\n"); 2089296341Sdelphij goto error; 2090296341Sdelphij } 2091296341Sdelphij } else if (*sp == '/') { 2092296341Sdelphij sp++; 2093296341Sdelphij /* no multivalued RDN by default */ 2094296341Sdelphij mval[ne_num + 1] = 0; 2095296341Sdelphij break; 2096296341Sdelphij } else if (*sp == '+' && multirdn) { 2097296341Sdelphij /* 2098296341Sdelphij * a not escaped + signals a mutlivalued RDN 2099296341Sdelphij */ 2100296341Sdelphij sp++; 2101296341Sdelphij mval[ne_num + 1] = -1; 2102296341Sdelphij break; 2103296341Sdelphij } else 2104296341Sdelphij *bp++ = *sp++; 2105296341Sdelphij } 2106296341Sdelphij *bp++ = '\0'; 2107296341Sdelphij ne_num++; 2108296341Sdelphij } 2109160814Ssimon 2110296341Sdelphij if (!(n = X509_NAME_new())) 2111296341Sdelphij goto error; 2112160814Ssimon 2113296341Sdelphij for (i = 0; i < ne_num; i++) { 2114296341Sdelphij if ((nid = OBJ_txt2nid(ne_types[i])) == NID_undef) { 2115296341Sdelphij BIO_printf(bio_err, 2116296341Sdelphij "Subject Attribute %s has no known NID, skipped\n", 2117296341Sdelphij ne_types[i]); 2118296341Sdelphij continue; 2119296341Sdelphij } 2120160814Ssimon 2121296341Sdelphij if (!*ne_values[i]) { 2122296341Sdelphij BIO_printf(bio_err, 2123296341Sdelphij "No value provided for Subject Attribute %s, skipped\n", 2124296341Sdelphij ne_types[i]); 2125296341Sdelphij continue; 2126296341Sdelphij } 2127160814Ssimon 2128296341Sdelphij if (!X509_NAME_add_entry_by_NID 2129296341Sdelphij (n, nid, chtype, (unsigned char *)ne_values[i], -1, -1, mval[i])) 2130296341Sdelphij goto error; 2131296341Sdelphij } 2132160814Ssimon 2133296341Sdelphij OPENSSL_free(ne_values); 2134296341Sdelphij OPENSSL_free(ne_types); 2135296341Sdelphij OPENSSL_free(buf); 2136296341Sdelphij OPENSSL_free(mval); 2137296341Sdelphij return n; 2138160814Ssimon 2139296341Sdelphij error: 2140296341Sdelphij X509_NAME_free(n); 2141296341Sdelphij if (ne_values) 2142296341Sdelphij OPENSSL_free(ne_values); 2143296341Sdelphij if (ne_types) 2144296341Sdelphij OPENSSL_free(ne_types); 2145296341Sdelphij if (mval) 2146296341Sdelphij OPENSSL_free(mval); 2147296341Sdelphij if (buf) 2148296341Sdelphij OPENSSL_free(buf); 2149296341Sdelphij return NULL; 2150160814Ssimon} 2151160814Ssimon 2152160814Ssimonint args_verify(char ***pargs, int *pargc, 2153296341Sdelphij int *badarg, BIO *err, X509_VERIFY_PARAM **pm) 2154296341Sdelphij{ 2155296341Sdelphij ASN1_OBJECT *otmp = NULL; 2156296341Sdelphij unsigned long flags = 0; 2157296341Sdelphij int i; 2158296341Sdelphij int purpose = 0, depth = -1; 2159296341Sdelphij char **oldargs = *pargs; 2160296341Sdelphij char *arg = **pargs, *argn = (*pargs)[1]; 2161296341Sdelphij time_t at_time = 0; 2162296341Sdelphij if (!strcmp(arg, "-policy")) { 2163296341Sdelphij if (!argn) 2164296341Sdelphij *badarg = 1; 2165296341Sdelphij else { 2166296341Sdelphij otmp = OBJ_txt2obj(argn, 0); 2167296341Sdelphij if (!otmp) { 2168296341Sdelphij BIO_printf(err, "Invalid Policy \"%s\"\n", argn); 2169296341Sdelphij *badarg = 1; 2170296341Sdelphij } 2171296341Sdelphij } 2172296341Sdelphij (*pargs)++; 2173296341Sdelphij } else if (strcmp(arg, "-purpose") == 0) { 2174296341Sdelphij X509_PURPOSE *xptmp; 2175296341Sdelphij if (!argn) 2176296341Sdelphij *badarg = 1; 2177296341Sdelphij else { 2178296341Sdelphij i = X509_PURPOSE_get_by_sname(argn); 2179296341Sdelphij if (i < 0) { 2180296341Sdelphij BIO_printf(err, "unrecognized purpose\n"); 2181296341Sdelphij *badarg = 1; 2182296341Sdelphij } else { 2183296341Sdelphij xptmp = X509_PURPOSE_get0(i); 2184296341Sdelphij purpose = X509_PURPOSE_get_id(xptmp); 2185296341Sdelphij } 2186296341Sdelphij } 2187296341Sdelphij (*pargs)++; 2188296341Sdelphij } else if (strcmp(arg, "-verify_depth") == 0) { 2189296341Sdelphij if (!argn) 2190296341Sdelphij *badarg = 1; 2191296341Sdelphij else { 2192296341Sdelphij depth = atoi(argn); 2193296341Sdelphij if (depth < 0) { 2194296341Sdelphij BIO_printf(err, "invalid depth\n"); 2195296341Sdelphij *badarg = 1; 2196296341Sdelphij } 2197296341Sdelphij } 2198296341Sdelphij (*pargs)++; 2199296341Sdelphij } else if (strcmp(arg, "-attime") == 0) { 2200296341Sdelphij if (!argn) 2201296341Sdelphij *badarg = 1; 2202296341Sdelphij else { 2203296341Sdelphij long timestamp; 2204296341Sdelphij /* 2205296341Sdelphij * interpret the -attime argument as seconds since Epoch 2206296341Sdelphij */ 2207296341Sdelphij if (sscanf(argn, "%li", ×tamp) != 1) { 2208296341Sdelphij BIO_printf(bio_err, "Error parsing timestamp %s\n", argn); 2209296341Sdelphij *badarg = 1; 2210296341Sdelphij } 2211296341Sdelphij /* on some platforms time_t may be a float */ 2212296341Sdelphij at_time = (time_t)timestamp; 2213296341Sdelphij } 2214296341Sdelphij (*pargs)++; 2215296341Sdelphij } else if (!strcmp(arg, "-ignore_critical")) 2216296341Sdelphij flags |= X509_V_FLAG_IGNORE_CRITICAL; 2217296341Sdelphij else if (!strcmp(arg, "-issuer_checks")) 2218296341Sdelphij flags |= X509_V_FLAG_CB_ISSUER_CHECK; 2219296341Sdelphij else if (!strcmp(arg, "-crl_check")) 2220296341Sdelphij flags |= X509_V_FLAG_CRL_CHECK; 2221296341Sdelphij else if (!strcmp(arg, "-crl_check_all")) 2222296341Sdelphij flags |= X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL; 2223296341Sdelphij else if (!strcmp(arg, "-policy_check")) 2224296341Sdelphij flags |= X509_V_FLAG_POLICY_CHECK; 2225296341Sdelphij else if (!strcmp(arg, "-explicit_policy")) 2226296341Sdelphij flags |= X509_V_FLAG_EXPLICIT_POLICY; 2227296341Sdelphij else if (!strcmp(arg, "-inhibit_any")) 2228296341Sdelphij flags |= X509_V_FLAG_INHIBIT_ANY; 2229296341Sdelphij else if (!strcmp(arg, "-inhibit_map")) 2230296341Sdelphij flags |= X509_V_FLAG_INHIBIT_MAP; 2231296341Sdelphij else if (!strcmp(arg, "-x509_strict")) 2232296341Sdelphij flags |= X509_V_FLAG_X509_STRICT; 2233296341Sdelphij else if (!strcmp(arg, "-extended_crl")) 2234296341Sdelphij flags |= X509_V_FLAG_EXTENDED_CRL_SUPPORT; 2235296341Sdelphij else if (!strcmp(arg, "-use_deltas")) 2236296341Sdelphij flags |= X509_V_FLAG_USE_DELTAS; 2237296341Sdelphij else if (!strcmp(arg, "-policy_print")) 2238296341Sdelphij flags |= X509_V_FLAG_NOTIFY_POLICY; 2239296341Sdelphij else if (!strcmp(arg, "-check_ss_sig")) 2240296341Sdelphij flags |= X509_V_FLAG_CHECK_SS_SIGNATURE; 2241296341Sdelphij else if (!strcmp(arg, "-no_alt_chains")) 2242296341Sdelphij flags |= X509_V_FLAG_NO_ALT_CHAINS; 2243296341Sdelphij else 2244296341Sdelphij return 0; 2245160814Ssimon 2246296341Sdelphij if (*badarg) { 2247296341Sdelphij if (*pm) 2248296341Sdelphij X509_VERIFY_PARAM_free(*pm); 2249296341Sdelphij *pm = NULL; 2250296341Sdelphij goto end; 2251296341Sdelphij } 2252160814Ssimon 2253296341Sdelphij if (!*pm && !(*pm = X509_VERIFY_PARAM_new())) { 2254296341Sdelphij *badarg = 1; 2255296341Sdelphij goto end; 2256296341Sdelphij } 2257160814Ssimon 2258296341Sdelphij if (otmp) 2259296341Sdelphij X509_VERIFY_PARAM_add0_policy(*pm, otmp); 2260296341Sdelphij if (flags) 2261296341Sdelphij X509_VERIFY_PARAM_set_flags(*pm, flags); 2262160814Ssimon 2263296341Sdelphij if (purpose) 2264296341Sdelphij X509_VERIFY_PARAM_set_purpose(*pm, purpose); 2265160814Ssimon 2266296341Sdelphij if (depth >= 0) 2267296341Sdelphij X509_VERIFY_PARAM_set_depth(*pm, depth); 2268238405Sjkim 2269296341Sdelphij if (at_time) 2270296341Sdelphij X509_VERIFY_PARAM_set_time(*pm, at_time); 2271238405Sjkim 2272296341Sdelphij end: 2273160814Ssimon 2274296341Sdelphij (*pargs)++; 2275160814Ssimon 2276296341Sdelphij if (pargc) 2277296341Sdelphij *pargc -= *pargs - oldargs; 2278160814Ssimon 2279296341Sdelphij return 1; 2280160814Ssimon 2281296341Sdelphij} 2282160814Ssimon 2283296341Sdelphij/* 2284296341Sdelphij * Read whole contents of a BIO into an allocated memory buffer and return 2285296341Sdelphij * it. 2286238405Sjkim */ 2287238405Sjkim 2288238405Sjkimint bio_to_mem(unsigned char **out, int maxlen, BIO *in) 2289296341Sdelphij{ 2290296341Sdelphij BIO *mem; 2291296341Sdelphij int len, ret; 2292296341Sdelphij unsigned char tbuf[1024]; 2293296341Sdelphij mem = BIO_new(BIO_s_mem()); 2294296341Sdelphij if (!mem) 2295296341Sdelphij return -1; 2296296341Sdelphij for (;;) { 2297296341Sdelphij if ((maxlen != -1) && maxlen < 1024) 2298296341Sdelphij len = maxlen; 2299296341Sdelphij else 2300296341Sdelphij len = 1024; 2301296341Sdelphij len = BIO_read(in, tbuf, len); 2302296341Sdelphij if (len <= 0) 2303296341Sdelphij break; 2304296341Sdelphij if (BIO_write(mem, tbuf, len) != len) { 2305296341Sdelphij BIO_free(mem); 2306296341Sdelphij return -1; 2307296341Sdelphij } 2308296341Sdelphij maxlen -= len; 2309238405Sjkim 2310296341Sdelphij if (maxlen == 0) 2311296341Sdelphij break; 2312296341Sdelphij } 2313296341Sdelphij ret = BIO_get_mem_data(mem, (char **)out); 2314296341Sdelphij BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY); 2315296341Sdelphij BIO_free(mem); 2316296341Sdelphij return ret; 2317296341Sdelphij} 2318238405Sjkim 2319238405Sjkimint pkey_ctrl_string(EVP_PKEY_CTX *ctx, char *value) 2320296341Sdelphij{ 2321296341Sdelphij int rv; 2322296341Sdelphij char *stmp, *vtmp = NULL; 2323296341Sdelphij stmp = BUF_strdup(value); 2324296341Sdelphij if (!stmp) 2325296341Sdelphij return -1; 2326296341Sdelphij vtmp = strchr(stmp, ':'); 2327296341Sdelphij if (vtmp) { 2328296341Sdelphij *vtmp = 0; 2329296341Sdelphij vtmp++; 2330296341Sdelphij } 2331296341Sdelphij rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp); 2332296341Sdelphij OPENSSL_free(stmp); 2333296341Sdelphij return rv; 2334296341Sdelphij} 2335238405Sjkim 2336160814Ssimonstatic void nodes_print(BIO *out, const char *name, 2337296341Sdelphij STACK_OF(X509_POLICY_NODE) *nodes) 2338296341Sdelphij{ 2339296341Sdelphij X509_POLICY_NODE *node; 2340296341Sdelphij int i; 2341296341Sdelphij BIO_printf(out, "%s Policies:", name); 2342296341Sdelphij if (nodes) { 2343296341Sdelphij BIO_puts(out, "\n"); 2344296341Sdelphij for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) { 2345296341Sdelphij node = sk_X509_POLICY_NODE_value(nodes, i); 2346296341Sdelphij X509_POLICY_NODE_print(out, node, 2); 2347296341Sdelphij } 2348296341Sdelphij } else 2349296341Sdelphij BIO_puts(out, " <empty>\n"); 2350296341Sdelphij} 2351160814Ssimon 2352160814Ssimonvoid policies_print(BIO *out, X509_STORE_CTX *ctx) 2353296341Sdelphij{ 2354296341Sdelphij X509_POLICY_TREE *tree; 2355296341Sdelphij int explicit_policy; 2356296341Sdelphij int free_out = 0; 2357296341Sdelphij if (out == NULL) { 2358296341Sdelphij out = BIO_new_fp(stderr, BIO_NOCLOSE); 2359296341Sdelphij free_out = 1; 2360296341Sdelphij } 2361296341Sdelphij tree = X509_STORE_CTX_get0_policy_tree(ctx); 2362296341Sdelphij explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx); 2363160814Ssimon 2364296341Sdelphij BIO_printf(out, "Require explicit Policy: %s\n", 2365296341Sdelphij explicit_policy ? "True" : "False"); 2366160814Ssimon 2367296341Sdelphij nodes_print(out, "Authority", X509_policy_tree_get0_policies(tree)); 2368296341Sdelphij nodes_print(out, "User", X509_policy_tree_get0_user_policies(tree)); 2369296341Sdelphij if (free_out) 2370296341Sdelphij BIO_free(out); 2371296341Sdelphij} 2372194206Ssimon 2373238405Sjkim#if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK) 2374194206Ssimon 2375194206Ssimonstatic JPAKE_CTX *jpake_init(const char *us, const char *them, 2376296341Sdelphij const char *secret) 2377296341Sdelphij{ 2378296341Sdelphij BIGNUM *p = NULL; 2379296341Sdelphij BIGNUM *g = NULL; 2380296341Sdelphij BIGNUM *q = NULL; 2381296341Sdelphij BIGNUM *bnsecret = BN_new(); 2382296341Sdelphij JPAKE_CTX *ctx; 2383194206Ssimon 2384296341Sdelphij /* Use a safe prime for p (that we found earlier) */ 2385296341Sdelphij BN_hex2bn(&p, 2386296341Sdelphij "F9E5B365665EA7A05A9C534502780FEE6F1AB5BD4F49947FD036DBD7E905269AF46EF28B0FC07487EE4F5D20FB3C0AF8E700F3A2FA3414970CBED44FEDFF80CE78D800F184BB82435D137AADA2C6C16523247930A63B85661D1FC817A51ACD96168E95898A1F83A79FFB529368AA7833ABD1B0C3AEDDB14D2E1A2F71D99F763F"); 2387296341Sdelphij g = BN_new(); 2388296341Sdelphij BN_set_word(g, 2); 2389296341Sdelphij q = BN_new(); 2390296341Sdelphij BN_rshift1(q, p); 2391194206Ssimon 2392296341Sdelphij BN_bin2bn((const unsigned char *)secret, strlen(secret), bnsecret); 2393194206Ssimon 2394296341Sdelphij ctx = JPAKE_CTX_new(us, them, p, g, q, bnsecret); 2395296341Sdelphij BN_free(bnsecret); 2396296341Sdelphij BN_free(q); 2397296341Sdelphij BN_free(g); 2398296341Sdelphij BN_free(p); 2399194206Ssimon 2400296341Sdelphij return ctx; 2401296341Sdelphij} 2402194206Ssimon 2403194206Ssimonstatic void jpake_send_part(BIO *conn, const JPAKE_STEP_PART *p) 2404296341Sdelphij{ 2405296341Sdelphij BN_print(conn, p->gx); 2406296341Sdelphij BIO_puts(conn, "\n"); 2407296341Sdelphij BN_print(conn, p->zkpx.gr); 2408296341Sdelphij BIO_puts(conn, "\n"); 2409296341Sdelphij BN_print(conn, p->zkpx.b); 2410296341Sdelphij BIO_puts(conn, "\n"); 2411296341Sdelphij} 2412194206Ssimon 2413194206Ssimonstatic void jpake_send_step1(BIO *bconn, JPAKE_CTX *ctx) 2414296341Sdelphij{ 2415296341Sdelphij JPAKE_STEP1 s1; 2416194206Ssimon 2417296341Sdelphij JPAKE_STEP1_init(&s1); 2418296341Sdelphij JPAKE_STEP1_generate(&s1, ctx); 2419296341Sdelphij jpake_send_part(bconn, &s1.p1); 2420296341Sdelphij jpake_send_part(bconn, &s1.p2); 2421296341Sdelphij (void)BIO_flush(bconn); 2422296341Sdelphij JPAKE_STEP1_release(&s1); 2423296341Sdelphij} 2424194206Ssimon 2425194206Ssimonstatic void jpake_send_step2(BIO *bconn, JPAKE_CTX *ctx) 2426296341Sdelphij{ 2427296341Sdelphij JPAKE_STEP2 s2; 2428194206Ssimon 2429296341Sdelphij JPAKE_STEP2_init(&s2); 2430296341Sdelphij JPAKE_STEP2_generate(&s2, ctx); 2431296341Sdelphij jpake_send_part(bconn, &s2); 2432296341Sdelphij (void)BIO_flush(bconn); 2433296341Sdelphij JPAKE_STEP2_release(&s2); 2434296341Sdelphij} 2435194206Ssimon 2436194206Ssimonstatic void jpake_send_step3a(BIO *bconn, JPAKE_CTX *ctx) 2437296341Sdelphij{ 2438296341Sdelphij JPAKE_STEP3A s3a; 2439194206Ssimon 2440296341Sdelphij JPAKE_STEP3A_init(&s3a); 2441296341Sdelphij JPAKE_STEP3A_generate(&s3a, ctx); 2442296341Sdelphij BIO_write(bconn, s3a.hhk, sizeof s3a.hhk); 2443296341Sdelphij (void)BIO_flush(bconn); 2444296341Sdelphij JPAKE_STEP3A_release(&s3a); 2445296341Sdelphij} 2446194206Ssimon 2447194206Ssimonstatic void jpake_send_step3b(BIO *bconn, JPAKE_CTX *ctx) 2448296341Sdelphij{ 2449296341Sdelphij JPAKE_STEP3B s3b; 2450194206Ssimon 2451296341Sdelphij JPAKE_STEP3B_init(&s3b); 2452296341Sdelphij JPAKE_STEP3B_generate(&s3b, ctx); 2453296341Sdelphij BIO_write(bconn, s3b.hk, sizeof s3b.hk); 2454296341Sdelphij (void)BIO_flush(bconn); 2455296341Sdelphij JPAKE_STEP3B_release(&s3b); 2456296341Sdelphij} 2457194206Ssimon 2458194206Ssimonstatic void readbn(BIGNUM **bn, BIO *bconn) 2459296341Sdelphij{ 2460296341Sdelphij char buf[10240]; 2461296341Sdelphij int l; 2462194206Ssimon 2463296341Sdelphij l = BIO_gets(bconn, buf, sizeof buf); 2464296341Sdelphij assert(l > 0); 2465296341Sdelphij assert(buf[l - 1] == '\n'); 2466296341Sdelphij buf[l - 1] = '\0'; 2467296341Sdelphij BN_hex2bn(bn, buf); 2468296341Sdelphij} 2469194206Ssimon 2470194206Ssimonstatic void jpake_receive_part(JPAKE_STEP_PART *p, BIO *bconn) 2471296341Sdelphij{ 2472296341Sdelphij readbn(&p->gx, bconn); 2473296341Sdelphij readbn(&p->zkpx.gr, bconn); 2474296341Sdelphij readbn(&p->zkpx.b, bconn); 2475296341Sdelphij} 2476194206Ssimon 2477194206Ssimonstatic void jpake_receive_step1(JPAKE_CTX *ctx, BIO *bconn) 2478296341Sdelphij{ 2479296341Sdelphij JPAKE_STEP1 s1; 2480194206Ssimon 2481296341Sdelphij JPAKE_STEP1_init(&s1); 2482296341Sdelphij jpake_receive_part(&s1.p1, bconn); 2483296341Sdelphij jpake_receive_part(&s1.p2, bconn); 2484296341Sdelphij if (!JPAKE_STEP1_process(ctx, &s1)) { 2485296341Sdelphij ERR_print_errors(bio_err); 2486296341Sdelphij exit(1); 2487296341Sdelphij } 2488296341Sdelphij JPAKE_STEP1_release(&s1); 2489296341Sdelphij} 2490194206Ssimon 2491194206Ssimonstatic void jpake_receive_step2(JPAKE_CTX *ctx, BIO *bconn) 2492296341Sdelphij{ 2493296341Sdelphij JPAKE_STEP2 s2; 2494194206Ssimon 2495296341Sdelphij JPAKE_STEP2_init(&s2); 2496296341Sdelphij jpake_receive_part(&s2, bconn); 2497296341Sdelphij if (!JPAKE_STEP2_process(ctx, &s2)) { 2498296341Sdelphij ERR_print_errors(bio_err); 2499296341Sdelphij exit(1); 2500296341Sdelphij } 2501296341Sdelphij JPAKE_STEP2_release(&s2); 2502296341Sdelphij} 2503194206Ssimon 2504194206Ssimonstatic void jpake_receive_step3a(JPAKE_CTX *ctx, BIO *bconn) 2505296341Sdelphij{ 2506296341Sdelphij JPAKE_STEP3A s3a; 2507296341Sdelphij int l; 2508194206Ssimon 2509296341Sdelphij JPAKE_STEP3A_init(&s3a); 2510296341Sdelphij l = BIO_read(bconn, s3a.hhk, sizeof s3a.hhk); 2511296341Sdelphij assert(l == sizeof s3a.hhk); 2512296341Sdelphij if (!JPAKE_STEP3A_process(ctx, &s3a)) { 2513296341Sdelphij ERR_print_errors(bio_err); 2514296341Sdelphij exit(1); 2515296341Sdelphij } 2516296341Sdelphij JPAKE_STEP3A_release(&s3a); 2517296341Sdelphij} 2518194206Ssimon 2519194206Ssimonstatic void jpake_receive_step3b(JPAKE_CTX *ctx, BIO *bconn) 2520296341Sdelphij{ 2521296341Sdelphij JPAKE_STEP3B s3b; 2522296341Sdelphij int l; 2523194206Ssimon 2524296341Sdelphij JPAKE_STEP3B_init(&s3b); 2525296341Sdelphij l = BIO_read(bconn, s3b.hk, sizeof s3b.hk); 2526296341Sdelphij assert(l == sizeof s3b.hk); 2527296341Sdelphij if (!JPAKE_STEP3B_process(ctx, &s3b)) { 2528296341Sdelphij ERR_print_errors(bio_err); 2529296341Sdelphij exit(1); 2530296341Sdelphij } 2531296341Sdelphij JPAKE_STEP3B_release(&s3b); 2532296341Sdelphij} 2533194206Ssimon 2534194206Ssimonvoid jpake_client_auth(BIO *out, BIO *conn, const char *secret) 2535296341Sdelphij{ 2536296341Sdelphij JPAKE_CTX *ctx; 2537296341Sdelphij BIO *bconn; 2538194206Ssimon 2539296341Sdelphij BIO_puts(out, "Authenticating with JPAKE\n"); 2540194206Ssimon 2541296341Sdelphij ctx = jpake_init("client", "server", secret); 2542194206Ssimon 2543296341Sdelphij bconn = BIO_new(BIO_f_buffer()); 2544296341Sdelphij BIO_push(bconn, conn); 2545194206Ssimon 2546296341Sdelphij jpake_send_step1(bconn, ctx); 2547296341Sdelphij jpake_receive_step1(ctx, bconn); 2548296341Sdelphij jpake_send_step2(bconn, ctx); 2549296341Sdelphij jpake_receive_step2(ctx, bconn); 2550296341Sdelphij jpake_send_step3a(bconn, ctx); 2551296341Sdelphij jpake_receive_step3b(ctx, bconn); 2552194206Ssimon 2553296341Sdelphij BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n"); 2554194206Ssimon 2555296341Sdelphij psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx)); 2556238405Sjkim 2557296341Sdelphij BIO_pop(bconn); 2558296341Sdelphij BIO_free(bconn); 2559238405Sjkim 2560296341Sdelphij JPAKE_CTX_free(ctx); 2561296341Sdelphij} 2562194206Ssimon 2563194206Ssimonvoid jpake_server_auth(BIO *out, BIO *conn, const char *secret) 2564296341Sdelphij{ 2565296341Sdelphij JPAKE_CTX *ctx; 2566296341Sdelphij BIO *bconn; 2567194206Ssimon 2568296341Sdelphij BIO_puts(out, "Authenticating with JPAKE\n"); 2569194206Ssimon 2570296341Sdelphij ctx = jpake_init("server", "client", secret); 2571194206Ssimon 2572296341Sdelphij bconn = BIO_new(BIO_f_buffer()); 2573296341Sdelphij BIO_push(bconn, conn); 2574194206Ssimon 2575296341Sdelphij jpake_receive_step1(ctx, bconn); 2576296341Sdelphij jpake_send_step1(bconn, ctx); 2577296341Sdelphij jpake_receive_step2(ctx, bconn); 2578296341Sdelphij jpake_send_step2(bconn, ctx); 2579296341Sdelphij jpake_receive_step3a(ctx, bconn); 2580296341Sdelphij jpake_send_step3b(bconn, ctx); 2581194206Ssimon 2582296341Sdelphij BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n"); 2583194206Ssimon 2584296341Sdelphij psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx)); 2585238405Sjkim 2586296341Sdelphij BIO_pop(bconn); 2587296341Sdelphij BIO_free(bconn); 2588238405Sjkim 2589296341Sdelphij JPAKE_CTX_free(ctx); 2590296341Sdelphij} 2591194206Ssimon 2592194206Ssimon#endif 2593238405Sjkim 2594238405Sjkim#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) 2595296341Sdelphij/*- 2596296341Sdelphij * next_protos_parse parses a comma separated list of strings into a string 2597238405Sjkim * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. 2598238405Sjkim * outlen: (output) set to the length of the resulting buffer on success. 2599238405Sjkim * err: (maybe NULL) on failure, an error message line is written to this BIO. 2600238405Sjkim * in: a NUL termianted string like "abc,def,ghi" 2601238405Sjkim * 2602238405Sjkim * returns: a malloced buffer or NULL on failure. 2603238405Sjkim */ 2604238405Sjkimunsigned char *next_protos_parse(unsigned short *outlen, const char *in) 2605296341Sdelphij{ 2606296341Sdelphij size_t len; 2607296341Sdelphij unsigned char *out; 2608296341Sdelphij size_t i, start = 0; 2609238405Sjkim 2610296341Sdelphij len = strlen(in); 2611296341Sdelphij if (len >= 65535) 2612296341Sdelphij return NULL; 2613238405Sjkim 2614296341Sdelphij out = OPENSSL_malloc(strlen(in) + 1); 2615296341Sdelphij if (!out) 2616296341Sdelphij return NULL; 2617238405Sjkim 2618296341Sdelphij for (i = 0; i <= len; ++i) { 2619296341Sdelphij if (i == len || in[i] == ',') { 2620296341Sdelphij if (i - start > 255) { 2621296341Sdelphij OPENSSL_free(out); 2622296341Sdelphij return NULL; 2623296341Sdelphij } 2624296341Sdelphij out[start] = i - start; 2625296341Sdelphij start = i + 1; 2626296341Sdelphij } else 2627296341Sdelphij out[i + 1] = in[i]; 2628296341Sdelphij } 2629238405Sjkim 2630296341Sdelphij *outlen = len + 1; 2631296341Sdelphij return out; 2632296341Sdelphij} 2633296341Sdelphij#endif /* !OPENSSL_NO_TLSEXT && 2634296341Sdelphij * !OPENSSL_NO_NEXTPROTONEG */ 2635238405Sjkim 2636238405Sjkim/* 2637238405Sjkim * Platform-specific sections 2638238405Sjkim */ 2639238405Sjkim#if defined(_WIN32) 2640238405Sjkim# ifdef fileno 2641238405Sjkim# undef fileno 2642238405Sjkim# define fileno(a) (int)_fileno(a) 2643238405Sjkim# endif 2644238405Sjkim 2645238405Sjkim# include <windows.h> 2646238405Sjkim# include <tchar.h> 2647238405Sjkim 2648238405Sjkimstatic int WIN32_rename(const char *from, const char *to) 2649296341Sdelphij{ 2650296341Sdelphij TCHAR *tfrom = NULL, *tto; 2651296341Sdelphij DWORD err; 2652296341Sdelphij int ret = 0; 2653238405Sjkim 2654296341Sdelphij if (sizeof(TCHAR) == 1) { 2655296341Sdelphij tfrom = (TCHAR *)from; 2656296341Sdelphij tto = (TCHAR *)to; 2657296341Sdelphij } else { /* UNICODE path */ 2658238405Sjkim 2659296341Sdelphij size_t i, flen = strlen(from) + 1, tlen = strlen(to) + 1; 2660296341Sdelphij tfrom = (TCHAR *)malloc(sizeof(TCHAR) * (flen + tlen)); 2661296341Sdelphij if (tfrom == NULL) 2662296341Sdelphij goto err; 2663296341Sdelphij tto = tfrom + flen; 2664296341Sdelphij# if !defined(_WIN32_WCE) || _WIN32_WCE>=101 2665296341Sdelphij if (!MultiByteToWideChar(CP_ACP, 0, from, flen, (WCHAR *)tfrom, flen)) 2666296341Sdelphij# endif 2667296341Sdelphij for (i = 0; i < flen; i++) 2668296341Sdelphij tfrom[i] = (TCHAR)from[i]; 2669296341Sdelphij# if !defined(_WIN32_WCE) || _WIN32_WCE>=101 2670296341Sdelphij if (!MultiByteToWideChar(CP_ACP, 0, to, tlen, (WCHAR *)tto, tlen)) 2671296341Sdelphij# endif 2672296341Sdelphij for (i = 0; i < tlen; i++) 2673296341Sdelphij tto[i] = (TCHAR)to[i]; 2674296341Sdelphij } 2675296341Sdelphij 2676296341Sdelphij if (MoveFile(tfrom, tto)) 2677296341Sdelphij goto ok; 2678296341Sdelphij err = GetLastError(); 2679296341Sdelphij if (err == ERROR_ALREADY_EXISTS || err == ERROR_FILE_EXISTS) { 2680296341Sdelphij if (DeleteFile(tto) && MoveFile(tfrom, tto)) 2681296341Sdelphij goto ok; 2682296341Sdelphij err = GetLastError(); 2683296341Sdelphij } 2684296341Sdelphij if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) 2685296341Sdelphij errno = ENOENT; 2686296341Sdelphij else if (err == ERROR_ACCESS_DENIED) 2687296341Sdelphij errno = EACCES; 2688296341Sdelphij else 2689296341Sdelphij errno = EINVAL; /* we could map more codes... */ 2690296341Sdelphij err: 2691296341Sdelphij ret = -1; 2692296341Sdelphij ok: 2693296341Sdelphij if (tfrom != NULL && tfrom != (TCHAR *)from) 2694296341Sdelphij free(tfrom); 2695296341Sdelphij return ret; 2696296341Sdelphij} 2697238405Sjkim#endif 2698238405Sjkim 2699238405Sjkim/* app_tminterval section */ 2700238405Sjkim#if defined(_WIN32) 2701296341Sdelphijdouble app_tminterval(int stop, int usertime) 2702296341Sdelphij{ 2703296341Sdelphij FILETIME now; 2704296341Sdelphij double ret = 0; 2705296341Sdelphij static ULARGE_INTEGER tmstart; 2706296341Sdelphij static int warning = 1; 2707296341Sdelphij# ifdef _WIN32_WINNT 2708296341Sdelphij static HANDLE proc = NULL; 2709238405Sjkim 2710296341Sdelphij if (proc == NULL) { 2711296341Sdelphij if (check_winnt()) 2712296341Sdelphij proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, 2713296341Sdelphij GetCurrentProcessId()); 2714296341Sdelphij if (proc == NULL) 2715296341Sdelphij proc = (HANDLE) - 1; 2716296341Sdelphij } 2717238405Sjkim 2718296341Sdelphij if (usertime && proc != (HANDLE) - 1) { 2719296341Sdelphij FILETIME junk; 2720296341Sdelphij GetProcessTimes(proc, &junk, &junk, &junk, &now); 2721296341Sdelphij } else 2722296341Sdelphij# endif 2723296341Sdelphij { 2724296341Sdelphij SYSTEMTIME systime; 2725238405Sjkim 2726296341Sdelphij if (usertime && warning) { 2727296341Sdelphij BIO_printf(bio_err, "To get meaningful results, run " 2728296341Sdelphij "this program on idle system.\n"); 2729296341Sdelphij warning = 0; 2730296341Sdelphij } 2731296341Sdelphij GetSystemTime(&systime); 2732296341Sdelphij SystemTimeToFileTime(&systime, &now); 2733296341Sdelphij } 2734238405Sjkim 2735296341Sdelphij if (stop == TM_START) { 2736296341Sdelphij tmstart.u.LowPart = now.dwLowDateTime; 2737296341Sdelphij tmstart.u.HighPart = now.dwHighDateTime; 2738296341Sdelphij } else { 2739296341Sdelphij ULARGE_INTEGER tmstop; 2740238405Sjkim 2741296341Sdelphij tmstop.u.LowPart = now.dwLowDateTime; 2742296341Sdelphij tmstop.u.HighPart = now.dwHighDateTime; 2743238405Sjkim 2744296341Sdelphij ret = (__int64)(tmstop.QuadPart - tmstart.QuadPart) * 1e-7; 2745296341Sdelphij } 2746238405Sjkim 2747296341Sdelphij return (ret); 2748296341Sdelphij} 2749238405Sjkim 2750238405Sjkim#elif defined(OPENSSL_SYS_NETWARE) 2751296341Sdelphij# include <time.h> 2752238405Sjkim 2753296341Sdelphijdouble app_tminterval(int stop, int usertime) 2754296341Sdelphij{ 2755296341Sdelphij double ret = 0; 2756296341Sdelphij static clock_t tmstart; 2757296341Sdelphij static int warning = 1; 2758238405Sjkim 2759296341Sdelphij if (usertime && warning) { 2760296341Sdelphij BIO_printf(bio_err, "To get meaningful results, run " 2761296341Sdelphij "this program on idle system.\n"); 2762296341Sdelphij warning = 0; 2763296341Sdelphij } 2764238405Sjkim 2765296341Sdelphij if (stop == TM_START) 2766296341Sdelphij tmstart = clock(); 2767296341Sdelphij else 2768296341Sdelphij ret = (clock() - tmstart) / (double)CLOCKS_PER_SEC; 2769238405Sjkim 2770296341Sdelphij return (ret); 2771296341Sdelphij} 2772238405Sjkim 2773238405Sjkim#elif defined(OPENSSL_SYSTEM_VXWORKS) 2774296341Sdelphij# include <time.h> 2775238405Sjkim 2776296341Sdelphijdouble app_tminterval(int stop, int usertime) 2777296341Sdelphij{ 2778296341Sdelphij double ret = 0; 2779296341Sdelphij# ifdef CLOCK_REALTIME 2780296341Sdelphij static struct timespec tmstart; 2781296341Sdelphij struct timespec now; 2782296341Sdelphij# else 2783296341Sdelphij static unsigned long tmstart; 2784296341Sdelphij unsigned long now; 2785296341Sdelphij# endif 2786296341Sdelphij static int warning = 1; 2787238405Sjkim 2788296341Sdelphij if (usertime && warning) { 2789296341Sdelphij BIO_printf(bio_err, "To get meaningful results, run " 2790296341Sdelphij "this program on idle system.\n"); 2791296341Sdelphij warning = 0; 2792296341Sdelphij } 2793296341Sdelphij# ifdef CLOCK_REALTIME 2794296341Sdelphij clock_gettime(CLOCK_REALTIME, &now); 2795296341Sdelphij if (stop == TM_START) 2796296341Sdelphij tmstart = now; 2797296341Sdelphij else 2798296341Sdelphij ret = ((now.tv_sec + now.tv_nsec * 1e-9) 2799296341Sdelphij - (tmstart.tv_sec + tmstart.tv_nsec * 1e-9)); 2800296341Sdelphij# else 2801296341Sdelphij now = tickGet(); 2802296341Sdelphij if (stop == TM_START) 2803296341Sdelphij tmstart = now; 2804296341Sdelphij else 2805296341Sdelphij ret = (now - tmstart) / (double)sysClkRateGet(); 2806296341Sdelphij# endif 2807296341Sdelphij return (ret); 2808296341Sdelphij} 2809238405Sjkim 2810238405Sjkim#elif defined(OPENSSL_SYSTEM_VMS) 2811296341Sdelphij# include <time.h> 2812296341Sdelphij# include <times.h> 2813238405Sjkim 2814296341Sdelphijdouble app_tminterval(int stop, int usertime) 2815296341Sdelphij{ 2816296341Sdelphij static clock_t tmstart; 2817296341Sdelphij double ret = 0; 2818296341Sdelphij clock_t now; 2819296341Sdelphij# ifdef __TMS 2820296341Sdelphij struct tms rus; 2821238405Sjkim 2822296341Sdelphij now = times(&rus); 2823296341Sdelphij if (usertime) 2824296341Sdelphij now = rus.tms_utime; 2825296341Sdelphij# else 2826296341Sdelphij if (usertime) 2827296341Sdelphij now = clock(); /* sum of user and kernel times */ 2828296341Sdelphij else { 2829296341Sdelphij struct timeval tv; 2830296341Sdelphij gettimeofday(&tv, NULL); 2831296341Sdelphij now = (clock_t)((unsigned long long)tv.tv_sec * CLK_TCK + 2832296341Sdelphij (unsigned long long)tv.tv_usec * (1000000 / CLK_TCK) 2833296341Sdelphij ); 2834296341Sdelphij } 2835296341Sdelphij# endif 2836296341Sdelphij if (stop == TM_START) 2837296341Sdelphij tmstart = now; 2838296341Sdelphij else 2839296341Sdelphij ret = (now - tmstart) / (double)(CLK_TCK); 2840238405Sjkim 2841296341Sdelphij return (ret); 2842296341Sdelphij} 2843238405Sjkim 2844296341Sdelphij#elif defined(_SC_CLK_TCK) /* by means of unistd.h */ 2845296341Sdelphij# include <sys/times.h> 2846238405Sjkim 2847296341Sdelphijdouble app_tminterval(int stop, int usertime) 2848296341Sdelphij{ 2849296341Sdelphij double ret = 0; 2850296341Sdelphij struct tms rus; 2851296341Sdelphij clock_t now = times(&rus); 2852296341Sdelphij static clock_t tmstart; 2853238405Sjkim 2854296341Sdelphij if (usertime) 2855296341Sdelphij now = rus.tms_utime; 2856238405Sjkim 2857296341Sdelphij if (stop == TM_START) 2858296341Sdelphij tmstart = now; 2859296341Sdelphij else { 2860296341Sdelphij long int tck = sysconf(_SC_CLK_TCK); 2861296341Sdelphij ret = (now - tmstart) / (double)tck; 2862296341Sdelphij } 2863238405Sjkim 2864296341Sdelphij return (ret); 2865296341Sdelphij} 2866238405Sjkim 2867238405Sjkim#else 2868296341Sdelphij# include <sys/time.h> 2869296341Sdelphij# include <sys/resource.h> 2870238405Sjkim 2871296341Sdelphijdouble app_tminterval(int stop, int usertime) 2872296341Sdelphij{ 2873296341Sdelphij double ret = 0; 2874296341Sdelphij struct rusage rus; 2875296341Sdelphij struct timeval now; 2876296341Sdelphij static struct timeval tmstart; 2877238405Sjkim 2878296341Sdelphij if (usertime) 2879296341Sdelphij getrusage(RUSAGE_SELF, &rus), now = rus.ru_utime; 2880296341Sdelphij else 2881296341Sdelphij gettimeofday(&now, NULL); 2882238405Sjkim 2883296341Sdelphij if (stop == TM_START) 2884296341Sdelphij tmstart = now; 2885296341Sdelphij else 2886296341Sdelphij ret = ((now.tv_sec + now.tv_usec * 1e-6) 2887296341Sdelphij - (tmstart.tv_sec + tmstart.tv_usec * 1e-6)); 2888238405Sjkim 2889296341Sdelphij return ret; 2890296341Sdelphij} 2891238405Sjkim#endif 2892238405Sjkim 2893238405Sjkim/* app_isdir section */ 2894238405Sjkim#ifdef _WIN32 2895238405Sjkimint app_isdir(const char *name) 2896296341Sdelphij{ 2897296341Sdelphij HANDLE hList; 2898296341Sdelphij WIN32_FIND_DATA FileData; 2899296341Sdelphij# if defined(UNICODE) || defined(_UNICODE) 2900296341Sdelphij size_t i, len_0 = strlen(name) + 1; 2901238405Sjkim 2902296341Sdelphij if (len_0 > sizeof(FileData.cFileName) / sizeof(FileData.cFileName[0])) 2903296341Sdelphij return -1; 2904238405Sjkim 2905296341Sdelphij# if !defined(_WIN32_WCE) || _WIN32_WCE>=101 2906296341Sdelphij if (!MultiByteToWideChar 2907296341Sdelphij (CP_ACP, 0, name, len_0, FileData.cFileName, len_0)) 2908296341Sdelphij# endif 2909296341Sdelphij for (i = 0; i < len_0; i++) 2910296341Sdelphij FileData.cFileName[i] = (WCHAR)name[i]; 2911238405Sjkim 2912296341Sdelphij hList = FindFirstFile(FileData.cFileName, &FileData); 2913296341Sdelphij# else 2914296341Sdelphij hList = FindFirstFile(name, &FileData); 2915296341Sdelphij# endif 2916296341Sdelphij if (hList == INVALID_HANDLE_VALUE) 2917296341Sdelphij return -1; 2918296341Sdelphij FindClose(hList); 2919296341Sdelphij return ((FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0); 2920296341Sdelphij} 2921238405Sjkim#else 2922296341Sdelphij# include <sys/stat.h> 2923296341Sdelphij# ifndef S_ISDIR 2924296341Sdelphij# if defined(_S_IFMT) && defined(_S_IFDIR) 2925296341Sdelphij# define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR) 2926296341Sdelphij# else 2927296341Sdelphij# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) 2928296341Sdelphij# endif 2929296341Sdelphij# endif 2930238405Sjkim 2931238405Sjkimint app_isdir(const char *name) 2932296341Sdelphij{ 2933296341Sdelphij# if defined(S_ISDIR) 2934296341Sdelphij struct stat st; 2935238405Sjkim 2936296341Sdelphij if (stat(name, &st) == 0) 2937296341Sdelphij return S_ISDIR(st.st_mode); 2938296341Sdelphij else 2939296341Sdelphij return -1; 2940296341Sdelphij# else 2941296341Sdelphij return -1; 2942296341Sdelphij# endif 2943296341Sdelphij} 2944238405Sjkim#endif 2945238405Sjkim 2946238405Sjkim/* raw_read|write section */ 2947238405Sjkim#if defined(_WIN32) && defined(STD_INPUT_HANDLE) 2948296341Sdelphijint raw_read_stdin(void *buf, int siz) 2949296341Sdelphij{ 2950296341Sdelphij DWORD n; 2951296341Sdelphij if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, siz, &n, NULL)) 2952296341Sdelphij return (n); 2953296341Sdelphij else 2954296341Sdelphij return (-1); 2955296341Sdelphij} 2956238405Sjkim#else 2957296341Sdelphijint raw_read_stdin(void *buf, int siz) 2958296341Sdelphij{ 2959296341Sdelphij return read(fileno(stdin), buf, siz); 2960296341Sdelphij} 2961238405Sjkim#endif 2962238405Sjkim 2963238405Sjkim#if defined(_WIN32) && defined(STD_OUTPUT_HANDLE) 2964296341Sdelphijint raw_write_stdout(const void *buf, int siz) 2965296341Sdelphij{ 2966296341Sdelphij DWORD n; 2967296341Sdelphij if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, siz, &n, NULL)) 2968296341Sdelphij return (n); 2969296341Sdelphij else 2970296341Sdelphij return (-1); 2971296341Sdelphij} 2972238405Sjkim#else 2973296341Sdelphijint raw_write_stdout(const void *buf, int siz) 2974296341Sdelphij{ 2975296341Sdelphij return write(fileno(stdout), buf, siz); 2976296341Sdelphij} 2977238405Sjkim#endif 2978