1289848Sjkim/* 2289848Sjkim * ! \file ssl/ssl_conf.c \brief SSL configuration functions 3289848Sjkim */ 4289848Sjkim/* ==================================================================== 5289848Sjkim * Copyright (c) 2012 The OpenSSL Project. All rights reserved. 6289848Sjkim * 7289848Sjkim * Redistribution and use in source and binary forms, with or without 8289848Sjkim * modification, are permitted provided that the following conditions 9289848Sjkim * are met: 10289848Sjkim * 11289848Sjkim * 1. Redistributions of source code must retain the above copyright 12289848Sjkim * notice, this list of conditions and the following disclaimer. 13289848Sjkim * 14289848Sjkim * 2. Redistributions in binary form must reproduce the above copyright 15289848Sjkim * notice, this list of conditions and the following disclaimer in 16289848Sjkim * the documentation and/or other materials provided with the 17289848Sjkim * distribution. 18289848Sjkim * 19289848Sjkim * 3. All advertising materials mentioning features or use of this 20289848Sjkim * software must display the following acknowledgment: 21289848Sjkim * "This product includes software developed by the OpenSSL Project 22289848Sjkim * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 23289848Sjkim * 24289848Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 25289848Sjkim * endorse or promote products derived from this software without 26289848Sjkim * prior written permission. For written permission, please contact 27289848Sjkim * openssl-core@openssl.org. 28289848Sjkim * 29289848Sjkim * 5. Products derived from this software may not be called "OpenSSL" 30289848Sjkim * nor may "OpenSSL" appear in their names without prior written 31289848Sjkim * permission of the OpenSSL Project. 32289848Sjkim * 33289848Sjkim * 6. Redistributions of any form whatsoever must retain the following 34289848Sjkim * acknowledgment: 35289848Sjkim * "This product includes software developed by the OpenSSL Project 36289848Sjkim * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 37289848Sjkim * 38289848Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 39289848Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40289848Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 41289848Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 42289848Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43289848Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 44289848Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 45289848Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46289848Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 47289848Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 48289848Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 49289848Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 50289848Sjkim * ==================================================================== 51289848Sjkim * 52289848Sjkim * This product includes cryptographic software written by Eric Young 53289848Sjkim * (eay@cryptsoft.com). This product includes software written by Tim 54289848Sjkim * Hudson (tjh@cryptsoft.com). 55289848Sjkim * 56289848Sjkim */ 57289848Sjkim 58289848Sjkim#ifdef REF_CHECK 59289848Sjkim# include <assert.h> 60289848Sjkim#endif 61289848Sjkim#include <stdio.h> 62289848Sjkim#include "ssl_locl.h" 63289848Sjkim#include <openssl/conf.h> 64289848Sjkim#include <openssl/objects.h> 65289848Sjkim#ifndef OPENSSL_NO_DH 66289848Sjkim# include <openssl/dh.h> 67289848Sjkim#endif 68289848Sjkim 69289848Sjkim/* 70289848Sjkim * structure holding name tables. This is used for pemitted elements in lists 71289848Sjkim * such as TLSv1 and single command line switches such as no_tls1 72289848Sjkim */ 73289848Sjkim 74289848Sjkimtypedef struct { 75289848Sjkim const char *name; 76289848Sjkim int namelen; 77289848Sjkim unsigned int name_flags; 78289848Sjkim unsigned long option_value; 79289848Sjkim} ssl_flag_tbl; 80289848Sjkim 81289848Sjkim/* Sense of name is inverted e.g. "TLSv1" will clear SSL_OP_NO_TLSv1 */ 82289848Sjkim#define SSL_TFLAG_INV 0x1 83289848Sjkim/* Flags refers to cert_flags not options */ 84289848Sjkim#define SSL_TFLAG_CERT 0x2 85289848Sjkim/* Option can only be used for clients */ 86289848Sjkim#define SSL_TFLAG_CLIENT SSL_CONF_FLAG_CLIENT 87289848Sjkim/* Option can only be used for servers */ 88289848Sjkim#define SSL_TFLAG_SERVER SSL_CONF_FLAG_SERVER 89289848Sjkim#define SSL_TFLAG_BOTH (SSL_TFLAG_CLIENT|SSL_TFLAG_SERVER) 90289848Sjkim 91289848Sjkim#define SSL_FLAG_TBL(str, flag) \ 92289848Sjkim {str, (int)(sizeof(str) - 1), SSL_TFLAG_BOTH, flag} 93289848Sjkim#define SSL_FLAG_TBL_SRV(str, flag) \ 94289848Sjkim {str, (int)(sizeof(str) - 1), SSL_TFLAG_SERVER, flag} 95289848Sjkim#define SSL_FLAG_TBL_CLI(str, flag) \ 96289848Sjkim {str, (int)(sizeof(str) - 1), SSL_TFLAG_CLIENT, flag} 97289848Sjkim#define SSL_FLAG_TBL_INV(str, flag) \ 98289848Sjkim {str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_BOTH, flag} 99289848Sjkim#define SSL_FLAG_TBL_SRV_INV(str, flag) \ 100289848Sjkim {str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_SERVER, flag} 101289848Sjkim#define SSL_FLAG_TBL_CERT(str, flag) \ 102289848Sjkim {str, (int)(sizeof(str) - 1), SSL_TFLAG_CERT|SSL_TFLAG_BOTH, flag} 103289848Sjkim 104289848Sjkim/* 105289848Sjkim * Opaque structure containing SSL configuration context. 106289848Sjkim */ 107289848Sjkim 108289848Sjkimstruct ssl_conf_ctx_st { 109289848Sjkim /* 110289848Sjkim * Various flags indicating (among other things) which options we will 111289848Sjkim * recognise. 112289848Sjkim */ 113289848Sjkim unsigned int flags; 114289848Sjkim /* Prefix and length of commands */ 115289848Sjkim char *prefix; 116289848Sjkim size_t prefixlen; 117289848Sjkim /* SSL_CTX or SSL structure to perform operations on */ 118289848Sjkim SSL_CTX *ctx; 119289848Sjkim SSL *ssl; 120289848Sjkim /* Pointer to SSL or SSL_CTX options field or NULL if none */ 121289848Sjkim unsigned long *poptions; 122289848Sjkim /* Pointer to SSL or SSL_CTX cert_flags or NULL if none */ 123289848Sjkim unsigned int *pcert_flags; 124289848Sjkim /* Current flag table being worked on */ 125289848Sjkim const ssl_flag_tbl *tbl; 126289848Sjkim /* Size of table */ 127289848Sjkim size_t ntbl; 128289848Sjkim}; 129289848Sjkim 130289848Sjkimstatic int ssl_match_option(SSL_CONF_CTX *cctx, const ssl_flag_tbl *tbl, 131289848Sjkim const char *name, int namelen, int onoff) 132289848Sjkim{ 133289848Sjkim /* If name not relevant for context skip */ 134289848Sjkim if (!(cctx->flags & tbl->name_flags & SSL_TFLAG_BOTH)) 135289848Sjkim return 0; 136289848Sjkim if (namelen == -1) { 137289848Sjkim if (strcmp(tbl->name, name)) 138289848Sjkim return 0; 139289848Sjkim } else if (tbl->namelen != namelen 140289848Sjkim || strncasecmp(tbl->name, name, namelen)) 141289848Sjkim return 0; 142289848Sjkim if (cctx->poptions) { 143289848Sjkim if (tbl->name_flags & SSL_TFLAG_INV) 144289848Sjkim onoff ^= 1; 145289848Sjkim if (tbl->name_flags & SSL_TFLAG_CERT) { 146289848Sjkim if (onoff) 147289848Sjkim *cctx->pcert_flags |= tbl->option_value; 148289848Sjkim else 149289848Sjkim *cctx->pcert_flags &= ~tbl->option_value; 150289848Sjkim } else { 151289848Sjkim if (onoff) 152289848Sjkim *cctx->poptions |= tbl->option_value; 153289848Sjkim else 154289848Sjkim *cctx->poptions &= ~tbl->option_value; 155289848Sjkim } 156289848Sjkim } 157289848Sjkim return 1; 158289848Sjkim} 159289848Sjkim 160289848Sjkimstatic int ssl_set_option_list(const char *elem, int len, void *usr) 161289848Sjkim{ 162289848Sjkim SSL_CONF_CTX *cctx = usr; 163289848Sjkim size_t i; 164289848Sjkim const ssl_flag_tbl *tbl; 165289848Sjkim int onoff = 1; 166289848Sjkim /* 167289848Sjkim * len == -1 indicates not being called in list context, just for single 168289848Sjkim * command line switches, so don't allow +, -. 169289848Sjkim */ 170289848Sjkim if (elem == NULL) 171289848Sjkim return 0; 172289848Sjkim if (len != -1) { 173289848Sjkim if (*elem == '+') { 174289848Sjkim elem++; 175289848Sjkim len--; 176289848Sjkim onoff = 1; 177289848Sjkim } else if (*elem == '-') { 178289848Sjkim elem++; 179289848Sjkim len--; 180289848Sjkim onoff = 0; 181289848Sjkim } 182289848Sjkim } 183289848Sjkim for (i = 0, tbl = cctx->tbl; i < cctx->ntbl; i++, tbl++) { 184289848Sjkim if (ssl_match_option(cctx, tbl, elem, len, onoff)) 185289848Sjkim return 1; 186289848Sjkim } 187289848Sjkim return 0; 188289848Sjkim} 189289848Sjkim 190289848Sjkim/* Single command line switches with no argument e.g. -no_ssl3 */ 191289848Sjkimstatic int ctrl_str_option(SSL_CONF_CTX *cctx, const char *cmd) 192289848Sjkim{ 193289848Sjkim static const ssl_flag_tbl ssl_option_single[] = { 194289848Sjkim SSL_FLAG_TBL("no_ssl2", SSL_OP_NO_SSLv2), 195289848Sjkim SSL_FLAG_TBL("no_ssl3", SSL_OP_NO_SSLv3), 196289848Sjkim SSL_FLAG_TBL("no_tls1", SSL_OP_NO_TLSv1), 197289848Sjkim SSL_FLAG_TBL("no_tls1_1", SSL_OP_NO_TLSv1_1), 198289848Sjkim SSL_FLAG_TBL("no_tls1_2", SSL_OP_NO_TLSv1_2), 199289848Sjkim SSL_FLAG_TBL("bugs", SSL_OP_ALL), 200289848Sjkim SSL_FLAG_TBL("no_comp", SSL_OP_NO_COMPRESSION), 201289848Sjkim SSL_FLAG_TBL_SRV("ecdh_single", SSL_OP_SINGLE_ECDH_USE), 202289848Sjkim#ifndef OPENSSL_NO_TLSEXT 203289848Sjkim SSL_FLAG_TBL("no_ticket", SSL_OP_NO_TICKET), 204289848Sjkim#endif 205289848Sjkim SSL_FLAG_TBL_SRV("serverpref", SSL_OP_CIPHER_SERVER_PREFERENCE), 206289848Sjkim SSL_FLAG_TBL("legacy_renegotiation", 207289848Sjkim SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION), 208289848Sjkim SSL_FLAG_TBL_SRV("legacy_server_connect", 209289848Sjkim SSL_OP_LEGACY_SERVER_CONNECT), 210289848Sjkim SSL_FLAG_TBL_SRV("no_resumption_on_reneg", 211289848Sjkim SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION), 212289848Sjkim SSL_FLAG_TBL_SRV_INV("no_legacy_server_connect", 213289848Sjkim SSL_OP_LEGACY_SERVER_CONNECT), 214289848Sjkim SSL_FLAG_TBL_CERT("strict", SSL_CERT_FLAG_TLS_STRICT), 215289848Sjkim#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL 216289848Sjkim SSL_FLAG_TBL_CERT("debug_broken_protocol", 217289848Sjkim SSL_CERT_FLAG_BROKEN_PROTOCOL), 218289848Sjkim#endif 219289848Sjkim }; 220289848Sjkim cctx->tbl = ssl_option_single; 221289848Sjkim cctx->ntbl = sizeof(ssl_option_single) / sizeof(ssl_flag_tbl); 222289848Sjkim return ssl_set_option_list(cmd, -1, cctx); 223289848Sjkim} 224289848Sjkim 225289848Sjkim/* Set supported signature algorithms */ 226289848Sjkimstatic int cmd_SignatureAlgorithms(SSL_CONF_CTX *cctx, const char *value) 227289848Sjkim{ 228289848Sjkim int rv; 229289848Sjkim if (cctx->ssl) 230289848Sjkim rv = SSL_set1_sigalgs_list(cctx->ssl, value); 231289848Sjkim /* NB: ctx == NULL performs syntax checking only */ 232289848Sjkim else 233289848Sjkim rv = SSL_CTX_set1_sigalgs_list(cctx->ctx, value); 234289848Sjkim return rv > 0; 235289848Sjkim} 236289848Sjkim 237289848Sjkim/* Set supported client signature algorithms */ 238289848Sjkimstatic int cmd_ClientSignatureAlgorithms(SSL_CONF_CTX *cctx, 239289848Sjkim const char *value) 240289848Sjkim{ 241289848Sjkim int rv; 242289848Sjkim if (cctx->ssl) 243289848Sjkim rv = SSL_set1_client_sigalgs_list(cctx->ssl, value); 244289848Sjkim /* NB: ctx == NULL performs syntax checking only */ 245289848Sjkim else 246289848Sjkim rv = SSL_CTX_set1_client_sigalgs_list(cctx->ctx, value); 247289848Sjkim return rv > 0; 248289848Sjkim} 249289848Sjkim 250289848Sjkimstatic int cmd_Curves(SSL_CONF_CTX *cctx, const char *value) 251289848Sjkim{ 252289848Sjkim int rv; 253289848Sjkim if (cctx->ssl) 254289848Sjkim rv = SSL_set1_curves_list(cctx->ssl, value); 255289848Sjkim /* NB: ctx == NULL performs syntax checking only */ 256289848Sjkim else 257289848Sjkim rv = SSL_CTX_set1_curves_list(cctx->ctx, value); 258289848Sjkim return rv > 0; 259289848Sjkim} 260289848Sjkim 261289848Sjkim#ifndef OPENSSL_NO_ECDH 262289848Sjkim/* ECDH temporary parameters */ 263289848Sjkimstatic int cmd_ECDHParameters(SSL_CONF_CTX *cctx, const char *value) 264289848Sjkim{ 265289848Sjkim int onoff = -1, rv = 1; 266289848Sjkim if (!(cctx->flags & SSL_CONF_FLAG_SERVER)) 267289848Sjkim return -2; 268289848Sjkim if (cctx->flags & SSL_CONF_FLAG_FILE) { 269289848Sjkim if (*value == '+') { 270289848Sjkim onoff = 1; 271289848Sjkim value++; 272289848Sjkim } 273289848Sjkim if (*value == '-') { 274289848Sjkim onoff = 0; 275289848Sjkim value++; 276289848Sjkim } 277289848Sjkim if (!strcasecmp(value, "automatic")) { 278289848Sjkim if (onoff == -1) 279289848Sjkim onoff = 1; 280289848Sjkim } else if (onoff != -1) 281289848Sjkim return 0; 282289848Sjkim } else if (cctx->flags & SSL_CONF_FLAG_CMDLINE) { 283289848Sjkim if (!strcmp(value, "auto")) 284289848Sjkim onoff = 1; 285289848Sjkim } 286289848Sjkim 287289848Sjkim if (onoff != -1) { 288289848Sjkim if (cctx->ctx) 289289848Sjkim rv = SSL_CTX_set_ecdh_auto(cctx->ctx, onoff); 290289848Sjkim else if (cctx->ssl) 291289848Sjkim rv = SSL_set_ecdh_auto(cctx->ssl, onoff); 292289848Sjkim } else { 293289848Sjkim EC_KEY *ecdh; 294289848Sjkim int nid; 295289848Sjkim nid = EC_curve_nist2nid(value); 296289848Sjkim if (nid == NID_undef) 297289848Sjkim nid = OBJ_sn2nid(value); 298289848Sjkim if (nid == 0) 299289848Sjkim return 0; 300289848Sjkim ecdh = EC_KEY_new_by_curve_name(nid); 301289848Sjkim if (!ecdh) 302289848Sjkim return 0; 303289848Sjkim if (cctx->ctx) 304289848Sjkim rv = SSL_CTX_set_tmp_ecdh(cctx->ctx, ecdh); 305289848Sjkim else if (cctx->ssl) 306289848Sjkim rv = SSL_set_tmp_ecdh(cctx->ssl, ecdh); 307289848Sjkim EC_KEY_free(ecdh); 308289848Sjkim } 309289848Sjkim 310289848Sjkim return rv > 0; 311289848Sjkim} 312289848Sjkim#endif 313289848Sjkimstatic int cmd_CipherString(SSL_CONF_CTX *cctx, const char *value) 314289848Sjkim{ 315289848Sjkim int rv = 1; 316289848Sjkim if (cctx->ctx) 317289848Sjkim rv = SSL_CTX_set_cipher_list(cctx->ctx, value); 318289848Sjkim if (cctx->ssl) 319289848Sjkim rv = SSL_set_cipher_list(cctx->ssl, value); 320289848Sjkim return rv > 0; 321289848Sjkim} 322289848Sjkim 323289848Sjkimstatic int cmd_Protocol(SSL_CONF_CTX *cctx, const char *value) 324289848Sjkim{ 325289848Sjkim static const ssl_flag_tbl ssl_protocol_list[] = { 326289848Sjkim SSL_FLAG_TBL_INV("ALL", SSL_OP_NO_SSL_MASK), 327289848Sjkim SSL_FLAG_TBL_INV("SSLv2", SSL_OP_NO_SSLv2), 328289848Sjkim SSL_FLAG_TBL_INV("SSLv3", SSL_OP_NO_SSLv3), 329289848Sjkim SSL_FLAG_TBL_INV("TLSv1", SSL_OP_NO_TLSv1), 330289848Sjkim SSL_FLAG_TBL_INV("TLSv1.1", SSL_OP_NO_TLSv1_1), 331289848Sjkim SSL_FLAG_TBL_INV("TLSv1.2", SSL_OP_NO_TLSv1_2) 332289848Sjkim }; 333296279Sjkim int ret; 334296279Sjkim int sslv2off; 335296279Sjkim 336289848Sjkim if (!(cctx->flags & SSL_CONF_FLAG_FILE)) 337289848Sjkim return -2; 338289848Sjkim cctx->tbl = ssl_protocol_list; 339289848Sjkim cctx->ntbl = sizeof(ssl_protocol_list) / sizeof(ssl_flag_tbl); 340296279Sjkim 341296279Sjkim sslv2off = *cctx->poptions & SSL_OP_NO_SSLv2; 342296279Sjkim ret = CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx); 343296279Sjkim /* Never turn on SSLv2 through configuration */ 344296279Sjkim *cctx->poptions |= sslv2off; 345296279Sjkim return ret; 346289848Sjkim} 347289848Sjkim 348289848Sjkimstatic int cmd_Options(SSL_CONF_CTX *cctx, const char *value) 349289848Sjkim{ 350289848Sjkim static const ssl_flag_tbl ssl_option_list[] = { 351289848Sjkim SSL_FLAG_TBL_INV("SessionTicket", SSL_OP_NO_TICKET), 352289848Sjkim SSL_FLAG_TBL_INV("EmptyFragments", 353289848Sjkim SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS), 354289848Sjkim SSL_FLAG_TBL("Bugs", SSL_OP_ALL), 355289848Sjkim SSL_FLAG_TBL_INV("Compression", SSL_OP_NO_COMPRESSION), 356289848Sjkim SSL_FLAG_TBL_SRV("ServerPreference", SSL_OP_CIPHER_SERVER_PREFERENCE), 357289848Sjkim SSL_FLAG_TBL_SRV("NoResumptionOnRenegotiation", 358289848Sjkim SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION), 359289848Sjkim SSL_FLAG_TBL_SRV("DHSingle", SSL_OP_SINGLE_DH_USE), 360289848Sjkim SSL_FLAG_TBL_SRV("ECDHSingle", SSL_OP_SINGLE_ECDH_USE), 361289848Sjkim SSL_FLAG_TBL("UnsafeLegacyRenegotiation", 362289848Sjkim SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION), 363289848Sjkim }; 364289848Sjkim if (!(cctx->flags & SSL_CONF_FLAG_FILE)) 365289848Sjkim return -2; 366289848Sjkim if (value == NULL) 367289848Sjkim return -3; 368289848Sjkim cctx->tbl = ssl_option_list; 369289848Sjkim cctx->ntbl = sizeof(ssl_option_list) / sizeof(ssl_flag_tbl); 370289848Sjkim return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx); 371289848Sjkim} 372289848Sjkim 373289848Sjkimstatic int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value) 374289848Sjkim{ 375289848Sjkim int rv = 1; 376289848Sjkim if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE)) 377289848Sjkim return -2; 378289848Sjkim if (cctx->ctx) 379289848Sjkim rv = SSL_CTX_use_certificate_chain_file(cctx->ctx, value); 380289848Sjkim if (cctx->ssl) 381289848Sjkim rv = SSL_use_certificate_file(cctx->ssl, value, SSL_FILETYPE_PEM); 382289848Sjkim return rv > 0; 383289848Sjkim} 384289848Sjkim 385289848Sjkimstatic int cmd_PrivateKey(SSL_CONF_CTX *cctx, const char *value) 386289848Sjkim{ 387289848Sjkim int rv = 1; 388289848Sjkim if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE)) 389289848Sjkim return -2; 390289848Sjkim if (cctx->ctx) 391289848Sjkim rv = SSL_CTX_use_PrivateKey_file(cctx->ctx, value, SSL_FILETYPE_PEM); 392289848Sjkim if (cctx->ssl) 393289848Sjkim rv = SSL_use_PrivateKey_file(cctx->ssl, value, SSL_FILETYPE_PEM); 394289848Sjkim return rv > 0; 395289848Sjkim} 396289848Sjkim 397289848Sjkimstatic int cmd_ServerInfoFile(SSL_CONF_CTX *cctx, const char *value) 398289848Sjkim{ 399289848Sjkim int rv = 1; 400289848Sjkim if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE)) 401289848Sjkim return -2; 402289848Sjkim if (!(cctx->flags & SSL_CONF_FLAG_SERVER)) 403289848Sjkim return -2; 404289848Sjkim if (cctx->ctx) 405289848Sjkim rv = SSL_CTX_use_serverinfo_file(cctx->ctx, value); 406289848Sjkim return rv > 0; 407289848Sjkim} 408289848Sjkim 409289848Sjkim#ifndef OPENSSL_NO_DH 410289848Sjkimstatic int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value) 411289848Sjkim{ 412289848Sjkim int rv = 0; 413289848Sjkim DH *dh = NULL; 414289848Sjkim BIO *in = NULL; 415289848Sjkim if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE)) 416289848Sjkim return -2; 417289848Sjkim if (cctx->ctx || cctx->ssl) { 418289848Sjkim in = BIO_new(BIO_s_file_internal()); 419289848Sjkim if (!in) 420289848Sjkim goto end; 421289848Sjkim if (BIO_read_filename(in, value) <= 0) 422289848Sjkim goto end; 423289848Sjkim dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); 424289848Sjkim if (!dh) 425289848Sjkim goto end; 426289848Sjkim } else 427289848Sjkim return 1; 428289848Sjkim if (cctx->ctx) 429289848Sjkim rv = SSL_CTX_set_tmp_dh(cctx->ctx, dh); 430289848Sjkim if (cctx->ssl) 431289848Sjkim rv = SSL_set_tmp_dh(cctx->ssl, dh); 432289848Sjkim end: 433289848Sjkim if (dh) 434289848Sjkim DH_free(dh); 435289848Sjkim if (in) 436289848Sjkim BIO_free(in); 437289848Sjkim return rv > 0; 438289848Sjkim} 439289848Sjkim#endif 440289848Sjkimtypedef struct { 441289848Sjkim int (*cmd) (SSL_CONF_CTX *cctx, const char *value); 442289848Sjkim const char *str_file; 443289848Sjkim const char *str_cmdline; 444289848Sjkim unsigned int value_type; 445289848Sjkim} ssl_conf_cmd_tbl; 446289848Sjkim 447289848Sjkim/* Table of supported parameters */ 448289848Sjkim 449289848Sjkim#define SSL_CONF_CMD(name, cmdopt, type) \ 450289848Sjkim {cmd_##name, #name, cmdopt, type} 451289848Sjkim 452289848Sjkim#define SSL_CONF_CMD_STRING(name, cmdopt) \ 453289848Sjkim SSL_CONF_CMD(name, cmdopt, SSL_CONF_TYPE_STRING) 454289848Sjkim 455289848Sjkimstatic const ssl_conf_cmd_tbl ssl_conf_cmds[] = { 456289848Sjkim SSL_CONF_CMD_STRING(SignatureAlgorithms, "sigalgs"), 457289848Sjkim SSL_CONF_CMD_STRING(ClientSignatureAlgorithms, "client_sigalgs"), 458289848Sjkim SSL_CONF_CMD_STRING(Curves, "curves"), 459289848Sjkim#ifndef OPENSSL_NO_ECDH 460289848Sjkim SSL_CONF_CMD_STRING(ECDHParameters, "named_curve"), 461289848Sjkim#endif 462289848Sjkim SSL_CONF_CMD_STRING(CipherString, "cipher"), 463289848Sjkim SSL_CONF_CMD_STRING(Protocol, NULL), 464289848Sjkim SSL_CONF_CMD_STRING(Options, NULL), 465289848Sjkim SSL_CONF_CMD(Certificate, "cert", SSL_CONF_TYPE_FILE), 466289848Sjkim SSL_CONF_CMD(PrivateKey, "key", SSL_CONF_TYPE_FILE), 467289848Sjkim SSL_CONF_CMD(ServerInfoFile, NULL, SSL_CONF_TYPE_FILE), 468289848Sjkim#ifndef OPENSSL_NO_DH 469289848Sjkim SSL_CONF_CMD(DHParameters, "dhparam", SSL_CONF_TYPE_FILE) 470289848Sjkim#endif 471289848Sjkim}; 472289848Sjkim 473289848Sjkimstatic int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd) 474289848Sjkim{ 475289848Sjkim if (!pcmd || !*pcmd) 476289848Sjkim return 0; 477289848Sjkim /* If a prefix is set, check and skip */ 478289848Sjkim if (cctx->prefix) { 479289848Sjkim if (strlen(*pcmd) <= cctx->prefixlen) 480289848Sjkim return 0; 481289848Sjkim if (cctx->flags & SSL_CONF_FLAG_CMDLINE && 482289848Sjkim strncmp(*pcmd, cctx->prefix, cctx->prefixlen)) 483289848Sjkim return 0; 484289848Sjkim if (cctx->flags & SSL_CONF_FLAG_FILE && 485289848Sjkim strncasecmp(*pcmd, cctx->prefix, cctx->prefixlen)) 486289848Sjkim return 0; 487289848Sjkim *pcmd += cctx->prefixlen; 488289848Sjkim } else if (cctx->flags & SSL_CONF_FLAG_CMDLINE) { 489289848Sjkim if (**pcmd != '-' || !(*pcmd)[1]) 490289848Sjkim return 0; 491289848Sjkim *pcmd += 1; 492289848Sjkim } 493289848Sjkim return 1; 494289848Sjkim} 495289848Sjkim 496289848Sjkimstatic const ssl_conf_cmd_tbl *ssl_conf_cmd_lookup(SSL_CONF_CTX *cctx, 497289848Sjkim const char *cmd) 498289848Sjkim{ 499289848Sjkim const ssl_conf_cmd_tbl *t; 500289848Sjkim size_t i; 501289848Sjkim if (cmd == NULL) 502289848Sjkim return NULL; 503289848Sjkim 504289848Sjkim /* Look for matching parameter name in table */ 505289848Sjkim for (i = 0, t = ssl_conf_cmds; 506289848Sjkim i < sizeof(ssl_conf_cmds) / sizeof(ssl_conf_cmd_tbl); i++, t++) { 507289848Sjkim if (cctx->flags & SSL_CONF_FLAG_CMDLINE) { 508289848Sjkim if (t->str_cmdline && !strcmp(t->str_cmdline, cmd)) 509289848Sjkim return t; 510289848Sjkim } 511289848Sjkim if (cctx->flags & SSL_CONF_FLAG_FILE) { 512289848Sjkim if (t->str_file && !strcasecmp(t->str_file, cmd)) 513289848Sjkim return t; 514289848Sjkim } 515289848Sjkim } 516289848Sjkim return NULL; 517289848Sjkim} 518289848Sjkim 519289848Sjkimint SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value) 520289848Sjkim{ 521289848Sjkim const ssl_conf_cmd_tbl *runcmd; 522289848Sjkim if (cmd == NULL) { 523289848Sjkim SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_INVALID_NULL_CMD_NAME); 524289848Sjkim return 0; 525289848Sjkim } 526289848Sjkim 527289848Sjkim if (!ssl_conf_cmd_skip_prefix(cctx, &cmd)) 528289848Sjkim return -2; 529289848Sjkim 530289848Sjkim runcmd = ssl_conf_cmd_lookup(cctx, cmd); 531289848Sjkim 532289848Sjkim if (runcmd) { 533289848Sjkim int rv; 534289848Sjkim if (value == NULL) 535289848Sjkim return -3; 536289848Sjkim rv = runcmd->cmd(cctx, value); 537289848Sjkim if (rv > 0) 538289848Sjkim return 2; 539289848Sjkim if (rv == -2) 540289848Sjkim return -2; 541289848Sjkim if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) { 542289848Sjkim SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_BAD_VALUE); 543289848Sjkim ERR_add_error_data(4, "cmd=", cmd, ", value=", value); 544289848Sjkim } 545289848Sjkim return 0; 546289848Sjkim } 547289848Sjkim 548289848Sjkim if (cctx->flags & SSL_CONF_FLAG_CMDLINE) { 549289848Sjkim if (ctrl_str_option(cctx, cmd)) 550289848Sjkim return 1; 551289848Sjkim } 552289848Sjkim 553289848Sjkim if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) { 554289848Sjkim SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_UNKNOWN_CMD_NAME); 555289848Sjkim ERR_add_error_data(2, "cmd=", cmd); 556289848Sjkim } 557289848Sjkim 558289848Sjkim return -2; 559289848Sjkim} 560289848Sjkim 561289848Sjkimint SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv) 562289848Sjkim{ 563289848Sjkim int rv; 564289848Sjkim const char *arg = NULL, *argn; 565289848Sjkim if (pargc && *pargc == 0) 566289848Sjkim return 0; 567289848Sjkim if (!pargc || *pargc > 0) 568289848Sjkim arg = **pargv; 569289848Sjkim if (arg == NULL) 570289848Sjkim return 0; 571289848Sjkim if (!pargc || *pargc > 1) 572289848Sjkim argn = (*pargv)[1]; 573289848Sjkim else 574289848Sjkim argn = NULL; 575289848Sjkim cctx->flags &= ~SSL_CONF_FLAG_FILE; 576289848Sjkim cctx->flags |= SSL_CONF_FLAG_CMDLINE; 577289848Sjkim rv = SSL_CONF_cmd(cctx, arg, argn); 578289848Sjkim if (rv > 0) { 579289848Sjkim /* Success: update pargc, pargv */ 580289848Sjkim (*pargv) += rv; 581289848Sjkim if (pargc) 582289848Sjkim (*pargc) -= rv; 583289848Sjkim return rv; 584289848Sjkim } 585289848Sjkim /* Unknown switch: indicate no arguments processed */ 586289848Sjkim if (rv == -2) 587289848Sjkim return 0; 588289848Sjkim /* Some error occurred processing command, return fatal error */ 589289848Sjkim if (rv == 0) 590289848Sjkim return -1; 591289848Sjkim return rv; 592289848Sjkim} 593289848Sjkim 594289848Sjkimint SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd) 595289848Sjkim{ 596289848Sjkim if (ssl_conf_cmd_skip_prefix(cctx, &cmd)) { 597289848Sjkim const ssl_conf_cmd_tbl *runcmd; 598289848Sjkim runcmd = ssl_conf_cmd_lookup(cctx, cmd); 599289848Sjkim if (runcmd) 600289848Sjkim return runcmd->value_type; 601289848Sjkim } 602289848Sjkim return SSL_CONF_TYPE_UNKNOWN; 603289848Sjkim} 604289848Sjkim 605289848SjkimSSL_CONF_CTX *SSL_CONF_CTX_new(void) 606289848Sjkim{ 607289848Sjkim SSL_CONF_CTX *ret; 608289848Sjkim ret = OPENSSL_malloc(sizeof(SSL_CONF_CTX)); 609289848Sjkim if (ret) { 610289848Sjkim ret->flags = 0; 611289848Sjkim ret->prefix = NULL; 612289848Sjkim ret->prefixlen = 0; 613289848Sjkim ret->ssl = NULL; 614289848Sjkim ret->ctx = NULL; 615289848Sjkim ret->poptions = NULL; 616289848Sjkim ret->pcert_flags = NULL; 617289848Sjkim ret->tbl = NULL; 618289848Sjkim ret->ntbl = 0; 619289848Sjkim } 620289848Sjkim return ret; 621289848Sjkim} 622289848Sjkim 623289848Sjkimint SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx) 624289848Sjkim{ 625289848Sjkim return 1; 626289848Sjkim} 627289848Sjkim 628289848Sjkimvoid SSL_CONF_CTX_free(SSL_CONF_CTX *cctx) 629289848Sjkim{ 630289848Sjkim if (cctx) { 631289848Sjkim if (cctx->prefix) 632289848Sjkim OPENSSL_free(cctx->prefix); 633289848Sjkim OPENSSL_free(cctx); 634289848Sjkim } 635289848Sjkim} 636289848Sjkim 637289848Sjkimunsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags) 638289848Sjkim{ 639289848Sjkim cctx->flags |= flags; 640289848Sjkim return cctx->flags; 641289848Sjkim} 642289848Sjkim 643289848Sjkimunsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx, unsigned int flags) 644289848Sjkim{ 645289848Sjkim cctx->flags &= ~flags; 646289848Sjkim return cctx->flags; 647289848Sjkim} 648289848Sjkim 649289848Sjkimint SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre) 650289848Sjkim{ 651289848Sjkim char *tmp = NULL; 652289848Sjkim if (pre) { 653289848Sjkim tmp = BUF_strdup(pre); 654289848Sjkim if (tmp == NULL) 655289848Sjkim return 0; 656289848Sjkim } 657289848Sjkim if (cctx->prefix) 658289848Sjkim OPENSSL_free(cctx->prefix); 659289848Sjkim cctx->prefix = tmp; 660289848Sjkim if (tmp) 661289848Sjkim cctx->prefixlen = strlen(tmp); 662289848Sjkim else 663289848Sjkim cctx->prefixlen = 0; 664289848Sjkim return 1; 665289848Sjkim} 666289848Sjkim 667289848Sjkimvoid SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl) 668289848Sjkim{ 669289848Sjkim cctx->ssl = ssl; 670289848Sjkim cctx->ctx = NULL; 671289848Sjkim if (ssl) { 672289848Sjkim cctx->poptions = &ssl->options; 673289848Sjkim cctx->pcert_flags = &ssl->cert->cert_flags; 674289848Sjkim } else { 675289848Sjkim cctx->poptions = NULL; 676289848Sjkim cctx->pcert_flags = NULL; 677289848Sjkim } 678289848Sjkim} 679289848Sjkim 680289848Sjkimvoid SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx) 681289848Sjkim{ 682289848Sjkim cctx->ctx = ctx; 683289848Sjkim cctx->ssl = NULL; 684289848Sjkim if (ctx) { 685289848Sjkim cctx->poptions = &ctx->options; 686289848Sjkim cctx->pcert_flags = &ctx->cert->cert_flags; 687289848Sjkim } else { 688289848Sjkim cctx->poptions = NULL; 689289848Sjkim cctx->pcert_flags = NULL; 690289848Sjkim } 691289848Sjkim} 692