2015-01-22 11:40:55 +08:00
|
|
|
/*
|
2017-08-18 11:52:46 +08:00
|
|
|
* Copyright 2012-2017 The OpenSSL Project Authors. All Rights Reserved.
|
2012-11-17 03:12:24 +08:00
|
|
|
*
|
2016-05-18 02:18:30 +08:00
|
|
|
* Licensed under the OpenSSL license (the "License"). You may not use
|
|
|
|
* this file except in compliance with the License. You can obtain a copy
|
|
|
|
* in the file LICENSE in the source distribution or at
|
|
|
|
* https://www.openssl.org/source/license.html
|
2012-11-17 03:12:24 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "ssl_locl.h"
|
|
|
|
#include <openssl/conf.h>
|
|
|
|
#include <openssl/objects.h>
|
2016-03-19 02:30:20 +08:00
|
|
|
#include <openssl/dh.h>
|
2017-08-18 11:52:46 +08:00
|
|
|
#include "internal/nelem.h"
|
2012-11-17 03:12:24 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
/*
|
2016-06-20 01:39:01 +08:00
|
|
|
* structure holding name tables. This is used for permitted elements in lists
|
2015-04-26 20:56:40 +08:00
|
|
|
* such as TLSv1.
|
2012-11-17 03:12:24 +08:00
|
|
|
*/
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
typedef struct {
|
|
|
|
const char *name;
|
|
|
|
int namelen;
|
|
|
|
unsigned int name_flags;
|
|
|
|
unsigned long option_value;
|
|
|
|
} ssl_flag_tbl;
|
2012-11-17 03:12:24 +08:00
|
|
|
|
2015-04-26 20:56:40 +08:00
|
|
|
/* Switch table: use for single command line switches like no_tls2 */
|
|
|
|
typedef struct {
|
|
|
|
unsigned long option_value;
|
|
|
|
unsigned int name_flags;
|
|
|
|
} ssl_switch_tbl;
|
|
|
|
|
2012-11-17 03:12:24 +08:00
|
|
|
/* Sense of name is inverted e.g. "TLSv1" will clear SSL_OP_NO_TLSv1 */
|
2015-01-22 11:40:55 +08:00
|
|
|
#define SSL_TFLAG_INV 0x1
|
2015-07-14 21:18:37 +08:00
|
|
|
/* Mask for type of flag referred to */
|
|
|
|
#define SSL_TFLAG_TYPE_MASK 0xf00
|
|
|
|
/* Flag is for options */
|
|
|
|
#define SSL_TFLAG_OPTION 0x000
|
|
|
|
/* Flag is for cert_flags */
|
|
|
|
#define SSL_TFLAG_CERT 0x100
|
|
|
|
/* Flag is for verify mode */
|
|
|
|
#define SSL_TFLAG_VFY 0x200
|
2012-11-17 03:12:24 +08:00
|
|
|
/* Option can only be used for clients */
|
|
|
|
#define SSL_TFLAG_CLIENT SSL_CONF_FLAG_CLIENT
|
|
|
|
/* Option can only be used for servers */
|
|
|
|
#define SSL_TFLAG_SERVER SSL_CONF_FLAG_SERVER
|
|
|
|
#define SSL_TFLAG_BOTH (SSL_TFLAG_CLIENT|SSL_TFLAG_SERVER)
|
|
|
|
|
|
|
|
#define SSL_FLAG_TBL(str, flag) \
|
2015-01-22 11:40:55 +08:00
|
|
|
{str, (int)(sizeof(str) - 1), SSL_TFLAG_BOTH, flag}
|
2012-11-17 03:12:24 +08:00
|
|
|
#define SSL_FLAG_TBL_SRV(str, flag) \
|
2015-01-22 11:40:55 +08:00
|
|
|
{str, (int)(sizeof(str) - 1), SSL_TFLAG_SERVER, flag}
|
2012-11-17 03:12:24 +08:00
|
|
|
#define SSL_FLAG_TBL_CLI(str, flag) \
|
2015-01-22 11:40:55 +08:00
|
|
|
{str, (int)(sizeof(str) - 1), SSL_TFLAG_CLIENT, flag}
|
2012-11-17 03:12:24 +08:00
|
|
|
#define SSL_FLAG_TBL_INV(str, flag) \
|
2015-01-22 11:40:55 +08:00
|
|
|
{str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_BOTH, flag}
|
2012-11-17 03:12:24 +08:00
|
|
|
#define SSL_FLAG_TBL_SRV_INV(str, flag) \
|
2015-01-22 11:40:55 +08:00
|
|
|
{str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_SERVER, flag}
|
2012-11-17 03:12:24 +08:00
|
|
|
#define SSL_FLAG_TBL_CERT(str, flag) \
|
2015-01-22 11:40:55 +08:00
|
|
|
{str, (int)(sizeof(str) - 1), SSL_TFLAG_CERT|SSL_TFLAG_BOTH, flag}
|
2012-11-17 03:12:24 +08:00
|
|
|
|
2015-07-14 21:18:37 +08:00
|
|
|
#define SSL_FLAG_VFY_CLI(str, flag) \
|
|
|
|
{str, (int)(sizeof(str) - 1), SSL_TFLAG_VFY | SSL_TFLAG_CLIENT, flag}
|
|
|
|
#define SSL_FLAG_VFY_SRV(str, flag) \
|
|
|
|
{str, (int)(sizeof(str) - 1), SSL_TFLAG_VFY | SSL_TFLAG_SERVER, flag}
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
/*
|
|
|
|
* Opaque structure containing SSL configuration context.
|
2012-11-17 03:12:24 +08:00
|
|
|
*/
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
struct ssl_conf_ctx_st {
|
|
|
|
/*
|
|
|
|
* Various flags indicating (among other things) which options we will
|
|
|
|
* recognise.
|
|
|
|
*/
|
|
|
|
unsigned int flags;
|
|
|
|
/* Prefix and length of commands */
|
|
|
|
char *prefix;
|
|
|
|
size_t prefixlen;
|
|
|
|
/* SSL_CTX or SSL structure to perform operations on */
|
|
|
|
SSL_CTX *ctx;
|
|
|
|
SSL *ssl;
|
|
|
|
/* Pointer to SSL or SSL_CTX options field or NULL if none */
|
2015-07-15 06:19:11 +08:00
|
|
|
uint32_t *poptions;
|
2015-02-16 21:44:22 +08:00
|
|
|
/* Certificate filenames for each type */
|
|
|
|
char *cert_filename[SSL_PKEY_NUM];
|
2015-01-22 11:40:55 +08:00
|
|
|
/* Pointer to SSL or SSL_CTX cert_flags or NULL if none */
|
2015-07-15 06:19:11 +08:00
|
|
|
uint32_t *pcert_flags;
|
2015-07-14 21:18:37 +08:00
|
|
|
/* Pointer to SSL or SSL_CTX verify_mode or NULL if none */
|
|
|
|
uint32_t *pvfy_flags;
|
2015-12-07 00:56:41 +08:00
|
|
|
/* Pointer to SSL or SSL_CTX min_version field or NULL if none */
|
|
|
|
int *min_version;
|
|
|
|
/* Pointer to SSL or SSL_CTX max_version field or NULL if none */
|
|
|
|
int *max_version;
|
2015-01-22 11:40:55 +08:00
|
|
|
/* Current flag table being worked on */
|
|
|
|
const ssl_flag_tbl *tbl;
|
|
|
|
/* Size of table */
|
|
|
|
size_t ntbl;
|
2015-07-14 21:18:37 +08:00
|
|
|
/* Client CA names */
|
|
|
|
STACK_OF(X509_NAME) *canames;
|
2015-01-22 11:40:55 +08:00
|
|
|
};
|
2012-11-17 03:12:24 +08:00
|
|
|
|
2015-04-26 20:56:40 +08:00
|
|
|
static void ssl_set_option(SSL_CONF_CTX *cctx, unsigned int name_flags,
|
|
|
|
unsigned long option_value, int onoff)
|
|
|
|
{
|
2015-07-21 21:16:09 +08:00
|
|
|
uint32_t *pflags;
|
2015-04-26 20:56:40 +08:00
|
|
|
if (cctx->poptions == NULL)
|
|
|
|
return;
|
|
|
|
if (name_flags & SSL_TFLAG_INV)
|
|
|
|
onoff ^= 1;
|
2015-07-14 21:18:37 +08:00
|
|
|
switch (name_flags & SSL_TFLAG_TYPE_MASK) {
|
|
|
|
|
|
|
|
case SSL_TFLAG_CERT:
|
|
|
|
pflags = cctx->pcert_flags;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SSL_TFLAG_VFY:
|
2016-08-06 01:03:17 +08:00
|
|
|
pflags = cctx->pvfy_flags;
|
2015-07-14 21:18:37 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SSL_TFLAG_OPTION:
|
|
|
|
pflags = cctx->poptions;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
|
2015-04-26 20:56:40 +08:00
|
|
|
}
|
2015-07-14 21:18:37 +08:00
|
|
|
if (onoff)
|
|
|
|
*pflags |= option_value;
|
|
|
|
else
|
|
|
|
*pflags &= ~option_value;
|
2015-04-26 20:56:40 +08:00
|
|
|
}
|
|
|
|
|
2012-11-17 03:12:24 +08:00
|
|
|
static int ssl_match_option(SSL_CONF_CTX *cctx, const ssl_flag_tbl *tbl,
|
2015-01-22 11:40:55 +08:00
|
|
|
const char *name, int namelen, int onoff)
|
|
|
|
{
|
|
|
|
/* If name not relevant for context skip */
|
|
|
|
if (!(cctx->flags & tbl->name_flags & SSL_TFLAG_BOTH))
|
|
|
|
return 0;
|
|
|
|
if (namelen == -1) {
|
|
|
|
if (strcmp(tbl->name, name))
|
|
|
|
return 0;
|
2016-08-06 01:03:17 +08:00
|
|
|
} else if (tbl->namelen != namelen || strncasecmp(tbl->name, name, namelen))
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
2015-04-26 20:56:40 +08:00
|
|
|
ssl_set_option(cctx, tbl->name_flags, tbl->option_value, onoff);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2012-11-17 03:12:24 +08:00
|
|
|
|
|
|
|
static int ssl_set_option_list(const char *elem, int len, void *usr)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
SSL_CONF_CTX *cctx = usr;
|
|
|
|
size_t i;
|
|
|
|
const ssl_flag_tbl *tbl;
|
|
|
|
int onoff = 1;
|
|
|
|
/*
|
|
|
|
* len == -1 indicates not being called in list context, just for single
|
|
|
|
* command line switches, so don't allow +, -.
|
|
|
|
*/
|
2015-01-24 21:46:50 +08:00
|
|
|
if (elem == NULL)
|
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
if (len != -1) {
|
|
|
|
if (*elem == '+') {
|
|
|
|
elem++;
|
|
|
|
len--;
|
|
|
|
onoff = 1;
|
|
|
|
} else if (*elem == '-') {
|
|
|
|
elem++;
|
|
|
|
len--;
|
|
|
|
onoff = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i = 0, tbl = cctx->tbl; i < cctx->ntbl; i++, tbl++) {
|
|
|
|
if (ssl_match_option(cctx, tbl, elem, len, onoff))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2012-11-17 03:12:24 +08:00
|
|
|
|
|
|
|
/* Set supported signature algorithms */
|
2013-10-18 23:09:12 +08:00
|
|
|
static int cmd_SignatureAlgorithms(SSL_CONF_CTX *cctx, const char *value)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
if (cctx->ssl)
|
|
|
|
rv = SSL_set1_sigalgs_list(cctx->ssl, value);
|
|
|
|
/* NB: ctx == NULL performs syntax checking only */
|
|
|
|
else
|
|
|
|
rv = SSL_CTX_set1_sigalgs_list(cctx->ctx, value);
|
|
|
|
return rv > 0;
|
|
|
|
}
|
|
|
|
|
2012-11-17 03:12:24 +08:00
|
|
|
/* Set supported client signature algorithms */
|
2016-08-06 01:03:17 +08:00
|
|
|
static int cmd_ClientSignatureAlgorithms(SSL_CONF_CTX *cctx, const char *value)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
if (cctx->ssl)
|
|
|
|
rv = SSL_set1_client_sigalgs_list(cctx->ssl, value);
|
|
|
|
/* NB: ctx == NULL performs syntax checking only */
|
|
|
|
else
|
|
|
|
rv = SSL_CTX_set1_client_sigalgs_list(cctx->ctx, value);
|
|
|
|
return rv > 0;
|
|
|
|
}
|
2012-11-17 03:12:24 +08:00
|
|
|
|
2016-11-09 22:51:06 +08:00
|
|
|
static int cmd_Groups(SSL_CONF_CTX *cctx, const char *value)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
if (cctx->ssl)
|
2016-11-09 22:51:06 +08:00
|
|
|
rv = SSL_set1_groups_list(cctx->ssl, value);
|
2015-01-22 11:40:55 +08:00
|
|
|
/* NB: ctx == NULL performs syntax checking only */
|
|
|
|
else
|
2016-11-09 22:51:06 +08:00
|
|
|
rv = SSL_CTX_set1_groups_list(cctx->ctx, value);
|
2015-01-22 11:40:55 +08:00
|
|
|
return rv > 0;
|
|
|
|
}
|
|
|
|
|
2016-11-09 22:51:06 +08:00
|
|
|
/* This is the old name for cmd_Groups - retained for backwards compatibility */
|
|
|
|
static int cmd_Curves(SSL_CONF_CTX *cctx, const char *value)
|
|
|
|
{
|
|
|
|
return cmd_Groups(cctx, value);
|
|
|
|
}
|
|
|
|
|
2015-03-11 07:09:27 +08:00
|
|
|
#ifndef OPENSSL_NO_EC
|
2012-11-17 03:12:24 +08:00
|
|
|
/* ECDH temporary parameters */
|
2013-10-18 23:09:12 +08:00
|
|
|
static int cmd_ECDHParameters(SSL_CONF_CTX *cctx, const char *value)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2015-12-05 05:30:36 +08:00
|
|
|
int rv = 1;
|
|
|
|
EC_KEY *ecdh;
|
|
|
|
int nid;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2017-05-22 22:20:21 +08:00
|
|
|
/* Ignore values supported by 1.0.2 for the automatic selection */
|
|
|
|
if ((cctx->flags & SSL_CONF_FLAG_FILE) &&
|
|
|
|
strcasecmp(value, "+automatic") == 0)
|
|
|
|
return 1;
|
|
|
|
if ((cctx->flags & SSL_CONF_FLAG_CMDLINE) &&
|
|
|
|
strcmp(value, "auto") == 0)
|
|
|
|
return 1;
|
|
|
|
|
2015-12-05 05:30:36 +08:00
|
|
|
nid = EC_curve_nist2nid(value);
|
|
|
|
if (nid == NID_undef)
|
|
|
|
nid = OBJ_sn2nid(value);
|
|
|
|
if (nid == 0)
|
|
|
|
return 0;
|
|
|
|
ecdh = EC_KEY_new_by_curve_name(nid);
|
|
|
|
if (!ecdh)
|
|
|
|
return 0;
|
|
|
|
if (cctx->ctx)
|
|
|
|
rv = SSL_CTX_set_tmp_ecdh(cctx->ctx, ecdh);
|
|
|
|
else if (cctx->ssl)
|
|
|
|
rv = SSL_set_tmp_ecdh(cctx->ssl, ecdh);
|
|
|
|
EC_KEY_free(ecdh);
|
2015-01-22 11:40:55 +08:00
|
|
|
|
|
|
|
return rv > 0;
|
|
|
|
}
|
2013-08-18 00:40:08 +08:00
|
|
|
#endif
|
2013-10-18 23:09:12 +08:00
|
|
|
static int cmd_CipherString(SSL_CONF_CTX *cctx, const char *value)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int rv = 1;
|
|
|
|
if (cctx->ctx)
|
|
|
|
rv = SSL_CTX_set_cipher_list(cctx->ctx, value);
|
|
|
|
if (cctx->ssl)
|
|
|
|
rv = SSL_set_cipher_list(cctx->ssl, value);
|
|
|
|
return rv > 0;
|
|
|
|
}
|
2012-11-17 03:12:24 +08:00
|
|
|
|
2013-10-18 23:09:12 +08:00
|
|
|
static int cmd_Protocol(SSL_CONF_CTX *cctx, const char *value)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
static const ssl_flag_tbl ssl_protocol_list[] = {
|
|
|
|
SSL_FLAG_TBL_INV("ALL", SSL_OP_NO_SSL_MASK),
|
|
|
|
SSL_FLAG_TBL_INV("SSLv2", SSL_OP_NO_SSLv2),
|
|
|
|
SSL_FLAG_TBL_INV("SSLv3", SSL_OP_NO_SSLv3),
|
|
|
|
SSL_FLAG_TBL_INV("TLSv1", SSL_OP_NO_TLSv1),
|
|
|
|
SSL_FLAG_TBL_INV("TLSv1.1", SSL_OP_NO_TLSv1_1),
|
2015-12-07 00:56:41 +08:00
|
|
|
SSL_FLAG_TBL_INV("TLSv1.2", SSL_OP_NO_TLSv1_2),
|
2016-10-22 00:39:33 +08:00
|
|
|
SSL_FLAG_TBL_INV("TLSv1.3", SSL_OP_NO_TLSv1_3),
|
2015-12-07 00:56:41 +08:00
|
|
|
SSL_FLAG_TBL_INV("DTLSv1", SSL_OP_NO_DTLSv1),
|
|
|
|
SSL_FLAG_TBL_INV("DTLSv1.2", SSL_OP_NO_DTLSv1_2)
|
2015-01-22 11:40:55 +08:00
|
|
|
};
|
|
|
|
cctx->tbl = ssl_protocol_list;
|
2015-05-03 01:30:00 +08:00
|
|
|
cctx->ntbl = OSSL_NELEM(ssl_protocol_list);
|
2015-01-22 11:40:55 +08:00
|
|
|
return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
|
|
|
|
}
|
2012-11-17 03:12:24 +08:00
|
|
|
|
2015-12-07 00:56:41 +08:00
|
|
|
/*
|
|
|
|
* protocol_from_string - converts a protocol version string to a number
|
|
|
|
*
|
|
|
|
* Returns -1 on failure or the version on success
|
|
|
|
*/
|
|
|
|
static int protocol_from_string(const char *value)
|
|
|
|
{
|
|
|
|
struct protocol_versions {
|
|
|
|
const char *name;
|
|
|
|
int version;
|
|
|
|
};
|
|
|
|
static const struct protocol_versions versions[] = {
|
2016-01-03 03:06:07 +08:00
|
|
|
{"None", 0},
|
2015-12-07 00:56:41 +08:00
|
|
|
{"SSLv3", SSL3_VERSION},
|
|
|
|
{"TLSv1", TLS1_VERSION},
|
|
|
|
{"TLSv1.1", TLS1_1_VERSION},
|
|
|
|
{"TLSv1.2", TLS1_2_VERSION},
|
2016-10-22 00:39:33 +08:00
|
|
|
{"TLSv1.3", TLS1_3_VERSION},
|
2015-12-07 00:56:41 +08:00
|
|
|
{"DTLSv1", DTLS1_VERSION},
|
2016-08-06 01:03:17 +08:00
|
|
|
{"DTLSv1.2", DTLS1_2_VERSION}
|
|
|
|
};
|
2015-12-07 00:56:41 +08:00
|
|
|
size_t i;
|
|
|
|
size_t n = OSSL_NELEM(versions);
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
if (strcmp(versions[i].name, value) == 0)
|
|
|
|
return versions[i].version;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-12-29 16:24:17 +08:00
|
|
|
static int min_max_proto(SSL_CONF_CTX *cctx, const char *value, int *bound)
|
|
|
|
{
|
|
|
|
int method_version;
|
|
|
|
int new_version;
|
|
|
|
|
|
|
|
if (cctx->ctx != NULL)
|
|
|
|
method_version = cctx->ctx->method->version;
|
|
|
|
else if (cctx->ssl != NULL)
|
|
|
|
method_version = cctx->ssl->ctx->method->version;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
if ((new_version = protocol_from_string(value)) < 0)
|
|
|
|
return 0;
|
|
|
|
return ssl_set_version_bound(method_version, new_version, bound);
|
|
|
|
}
|
|
|
|
|
2015-12-07 00:56:41 +08:00
|
|
|
/*
|
|
|
|
* cmd_MinProtocol - Set min protocol version
|
|
|
|
* @cctx: config structure to save settings in
|
|
|
|
* @value: The min protocol version in string form
|
|
|
|
*
|
|
|
|
* Returns 1 on success and 0 on failure.
|
|
|
|
*/
|
|
|
|
static int cmd_MinProtocol(SSL_CONF_CTX *cctx, const char *value)
|
|
|
|
{
|
2015-12-29 16:24:17 +08:00
|
|
|
return min_max_proto(cctx, value, cctx->min_version);
|
2015-12-07 00:56:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* cmd_MaxProtocol - Set max protocol version
|
|
|
|
* @cctx: config structure to save settings in
|
|
|
|
* @value: The max protocol version in string form
|
|
|
|
*
|
|
|
|
* Returns 1 on success and 0 on failure.
|
|
|
|
*/
|
|
|
|
static int cmd_MaxProtocol(SSL_CONF_CTX *cctx, const char *value)
|
|
|
|
{
|
2015-12-29 16:24:17 +08:00
|
|
|
return min_max_proto(cctx, value, cctx->max_version);
|
2015-12-07 00:56:41 +08:00
|
|
|
}
|
|
|
|
|
2013-10-18 23:09:12 +08:00
|
|
|
static int cmd_Options(SSL_CONF_CTX *cctx, const char *value)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
static const ssl_flag_tbl ssl_option_list[] = {
|
|
|
|
SSL_FLAG_TBL_INV("SessionTicket", SSL_OP_NO_TICKET),
|
|
|
|
SSL_FLAG_TBL_INV("EmptyFragments",
|
|
|
|
SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS),
|
|
|
|
SSL_FLAG_TBL("Bugs", SSL_OP_ALL),
|
|
|
|
SSL_FLAG_TBL_INV("Compression", SSL_OP_NO_COMPRESSION),
|
|
|
|
SSL_FLAG_TBL_SRV("ServerPreference", SSL_OP_CIPHER_SERVER_PREFERENCE),
|
|
|
|
SSL_FLAG_TBL_SRV("NoResumptionOnRenegotiation",
|
|
|
|
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION),
|
|
|
|
SSL_FLAG_TBL_SRV("DHSingle", SSL_OP_SINGLE_DH_USE),
|
|
|
|
SSL_FLAG_TBL_SRV("ECDHSingle", SSL_OP_SINGLE_ECDH_USE),
|
|
|
|
SSL_FLAG_TBL("UnsafeLegacyRenegotiation",
|
|
|
|
SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION),
|
2016-11-26 00:05:30 +08:00
|
|
|
SSL_FLAG_TBL_INV("EncryptThenMac", SSL_OP_NO_ENCRYPT_THEN_MAC),
|
2017-05-11 04:46:14 +08:00
|
|
|
SSL_FLAG_TBL("NoRenegotiation", SSL_OP_NO_RENEGOTIATION),
|
2015-12-22 04:19:29 +08:00
|
|
|
SSL_FLAG_TBL("AllowNoDHEKEX", SSL_OP_ALLOW_NO_DHE_KEX),
|
2017-11-07 18:45:43 +08:00
|
|
|
SSL_FLAG_TBL("PrioritizeChaCha", SSL_OP_PRIORITIZE_CHACHA),
|
|
|
|
SSL_FLAG_TBL("MiddleboxCompat", SSL_OP_ENABLE_MIDDLEBOX_COMPAT)
|
2015-01-22 11:40:55 +08:00
|
|
|
};
|
|
|
|
if (value == NULL)
|
|
|
|
return -3;
|
|
|
|
cctx->tbl = ssl_option_list;
|
2015-05-03 01:30:00 +08:00
|
|
|
cctx->ntbl = OSSL_NELEM(ssl_option_list);
|
2015-01-22 11:40:55 +08:00
|
|
|
return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
|
|
|
|
}
|
2012-11-17 03:12:24 +08:00
|
|
|
|
2015-07-14 21:18:37 +08:00
|
|
|
static int cmd_VerifyMode(SSL_CONF_CTX *cctx, const char *value)
|
|
|
|
{
|
|
|
|
static const ssl_flag_tbl ssl_vfy_list[] = {
|
|
|
|
SSL_FLAG_VFY_CLI("Peer", SSL_VERIFY_PEER),
|
|
|
|
SSL_FLAG_VFY_SRV("Request", SSL_VERIFY_PEER),
|
|
|
|
SSL_FLAG_VFY_SRV("Require",
|
|
|
|
SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT),
|
Add TLSv1.3 post-handshake authentication (PHA)
Add SSL_verify_client_post_handshake() for servers to initiate PHA
Add SSL_force_post_handshake_auth() for clients that don't have certificates
initially configured, but use a certificate callback.
Update SSL_CTX_set_verify()/SSL_set_verify() mode:
* Add SSL_VERIFY_POST_HANDSHAKE to postpone client authentication until after
the initial handshake.
* Update SSL_VERIFY_CLIENT_ONCE now only sends out one CertRequest regardless
of when the certificate authentication takes place; either initial handshake,
re-negotiation, or post-handshake authentication.
Add 'RequestPostHandshake' and 'RequirePostHandshake' SSL_CONF options that
add the SSL_VERIFY_POST_HANDSHAKE to the 'Request' and 'Require' options
Add support to s_client:
* Enabled automatically when cert is configured
* Can be forced enabled via -force_pha
Add support to s_server:
* Use 'c' to invoke PHA in s_server
* Remove some dead code
Update documentation
Update unit tests:
* Illegal use of PHA extension
* TLSv1.3 certificate tests
DTLS and TLS behave ever-so-slightly differently. So, when DTLS1.3 is
implemented, it's PHA support state machine may need to be different.
Add a TODO and a #error
Update handshake context to deal with PHA.
The handshake context for TLSv1.3 post-handshake auth is up through the
ClientFinish message, plus the CertificateRequest message. Subsequent
Certificate, CertificateVerify, and Finish messages are based on this
handshake context (not the Certificate message per se, but it's included
after the hash). KeyUpdate, NewSessionTicket, and prior Certificate
Request messages are not included in post-handshake authentication.
After the ClientFinished message is processed, save off the digest state
for future post-handshake authentication. When post-handshake auth occurs,
copy over the saved handshake context into the "main" handshake digest.
This effectively discards the any KeyUpdate or NewSessionTicket messages
and any prior post-handshake authentication.
This, of course, assumes that the ID-22 did not mean to include any
previous post-handshake authentication into the new handshake transcript.
This is implied by section 4.4.1 that lists messages only up to the
first ClientFinished.
Reviewed-by: Ben Kaduk <kaduk@mit.edu>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4964)
2017-12-19 05:52:28 +08:00
|
|
|
SSL_FLAG_VFY_SRV("Once", SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE),
|
|
|
|
SSL_FLAG_VFY_SRV("RequestPostHandshake",
|
|
|
|
SSL_VERIFY_PEER | SSL_VERIFY_POST_HANDSHAKE),
|
|
|
|
SSL_FLAG_VFY_SRV("RequirePostHandshake",
|
|
|
|
SSL_VERIFY_PEER | SSL_VERIFY_POST_HANDSHAKE |
|
|
|
|
SSL_VERIFY_FAIL_IF_NO_PEER_CERT),
|
2015-07-14 21:18:37 +08:00
|
|
|
};
|
|
|
|
if (value == NULL)
|
|
|
|
return -3;
|
|
|
|
cctx->tbl = ssl_vfy_list;
|
|
|
|
cctx->ntbl = OSSL_NELEM(ssl_vfy_list);
|
|
|
|
return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
|
|
|
|
}
|
|
|
|
|
2013-10-18 23:09:12 +08:00
|
|
|
static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int rv = 1;
|
2015-02-16 21:44:22 +08:00
|
|
|
CERT *c = NULL;
|
|
|
|
if (cctx->ctx) {
|
2015-01-22 11:40:55 +08:00
|
|
|
rv = SSL_CTX_use_certificate_chain_file(cctx->ctx, value);
|
2015-02-16 21:44:22 +08:00
|
|
|
c = cctx->ctx->cert;
|
|
|
|
}
|
|
|
|
if (cctx->ssl) {
|
2015-05-07 21:59:08 +08:00
|
|
|
rv = SSL_use_certificate_chain_file(cctx->ssl, value);
|
2015-02-16 21:44:22 +08:00
|
|
|
c = cctx->ssl->cert;
|
|
|
|
}
|
|
|
|
if (rv > 0 && c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) {
|
|
|
|
char **pfilename = &cctx->cert_filename[c->key - c->pkeys];
|
2015-05-01 22:02:07 +08:00
|
|
|
OPENSSL_free(*pfilename);
|
Rename some BUF_xxx to OPENSSL_xxx
Rename BUF_{strdup,strlcat,strlcpy,memdup,strndup,strnlen}
to OPENSSL_{strdup,strlcat,strlcpy,memdup,strndup,strnlen}
Add #define's for the old names.
Add CRYPTO_{memdup,strndup}, called by OPENSSL_{memdup,strndup} macros.
Reviewed-by: Tim Hudson <tjh@openssl.org>
2015-12-17 05:12:24 +08:00
|
|
|
*pfilename = OPENSSL_strdup(value);
|
2015-02-16 21:44:22 +08:00
|
|
|
if (!*pfilename)
|
|
|
|
rv = 0;
|
|
|
|
}
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
return rv > 0;
|
|
|
|
}
|
2013-10-18 23:09:12 +08:00
|
|
|
|
|
|
|
static int cmd_PrivateKey(SSL_CONF_CTX *cctx, const char *value)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int rv = 1;
|
|
|
|
if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE))
|
|
|
|
return -2;
|
|
|
|
if (cctx->ctx)
|
|
|
|
rv = SSL_CTX_use_PrivateKey_file(cctx->ctx, value, SSL_FILETYPE_PEM);
|
|
|
|
if (cctx->ssl)
|
|
|
|
rv = SSL_use_PrivateKey_file(cctx->ssl, value, SSL_FILETYPE_PEM);
|
|
|
|
return rv > 0;
|
|
|
|
}
|
2014-01-04 07:13:40 +08:00
|
|
|
|
|
|
|
static int cmd_ServerInfoFile(SSL_CONF_CTX *cctx, const char *value)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int rv = 1;
|
|
|
|
if (cctx->ctx)
|
|
|
|
rv = SSL_CTX_use_serverinfo_file(cctx->ctx, value);
|
|
|
|
return rv > 0;
|
|
|
|
}
|
2014-01-04 07:13:40 +08:00
|
|
|
|
2015-07-14 21:18:37 +08:00
|
|
|
static int do_store(SSL_CONF_CTX *cctx,
|
|
|
|
const char *CAfile, const char *CApath, int verify_store)
|
|
|
|
{
|
|
|
|
CERT *cert;
|
|
|
|
X509_STORE **st;
|
|
|
|
if (cctx->ctx)
|
|
|
|
cert = cctx->ctx->cert;
|
|
|
|
else if (cctx->ssl)
|
|
|
|
cert = cctx->ssl->cert;
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
st = verify_store ? &cert->verify_store : &cert->chain_store;
|
|
|
|
if (*st == NULL) {
|
|
|
|
*st = X509_STORE_new();
|
|
|
|
if (*st == NULL)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return X509_STORE_load_locations(*st, CAfile, CApath) > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cmd_ChainCAPath(SSL_CONF_CTX *cctx, const char *value)
|
|
|
|
{
|
|
|
|
return do_store(cctx, NULL, value, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cmd_ChainCAFile(SSL_CONF_CTX *cctx, const char *value)
|
|
|
|
{
|
|
|
|
return do_store(cctx, value, NULL, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cmd_VerifyCAPath(SSL_CONF_CTX *cctx, const char *value)
|
|
|
|
{
|
|
|
|
return do_store(cctx, NULL, value, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cmd_VerifyCAFile(SSL_CONF_CTX *cctx, const char *value)
|
|
|
|
{
|
|
|
|
return do_store(cctx, value, NULL, 1);
|
|
|
|
}
|
|
|
|
|
2017-03-18 21:44:13 +08:00
|
|
|
static int cmd_RequestCAFile(SSL_CONF_CTX *cctx, const char *value)
|
2015-07-14 21:18:37 +08:00
|
|
|
{
|
|
|
|
if (cctx->canames == NULL)
|
|
|
|
cctx->canames = sk_X509_NAME_new_null();
|
|
|
|
if (cctx->canames == NULL)
|
|
|
|
return 0;
|
|
|
|
return SSL_add_file_cert_subjects_to_stack(cctx->canames, value);
|
|
|
|
}
|
|
|
|
|
2017-03-18 21:44:13 +08:00
|
|
|
static int cmd_ClientCAFile(SSL_CONF_CTX *cctx, const char *value)
|
|
|
|
{
|
|
|
|
return cmd_RequestCAFile(cctx, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cmd_RequestCAPath(SSL_CONF_CTX *cctx, const char *value)
|
2015-07-14 21:18:37 +08:00
|
|
|
{
|
|
|
|
if (cctx->canames == NULL)
|
|
|
|
cctx->canames = sk_X509_NAME_new_null();
|
|
|
|
if (cctx->canames == NULL)
|
|
|
|
return 0;
|
|
|
|
return SSL_add_dir_cert_subjects_to_stack(cctx->canames, value);
|
|
|
|
}
|
|
|
|
|
2017-03-18 21:44:13 +08:00
|
|
|
static int cmd_ClientCAPath(SSL_CONF_CTX *cctx, const char *value)
|
|
|
|
{
|
|
|
|
return cmd_RequestCAPath(cctx, value);
|
|
|
|
}
|
|
|
|
|
2013-10-22 14:35:22 +08:00
|
|
|
#ifndef OPENSSL_NO_DH
|
|
|
|
static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int rv = 0;
|
|
|
|
DH *dh = NULL;
|
|
|
|
BIO *in = NULL;
|
|
|
|
if (cctx->ctx || cctx->ssl) {
|
2015-10-01 02:32:49 +08:00
|
|
|
in = BIO_new(BIO_s_file());
|
2015-10-30 18:05:53 +08:00
|
|
|
if (in == NULL)
|
2015-01-22 11:40:55 +08:00
|
|
|
goto end;
|
|
|
|
if (BIO_read_filename(in, value) <= 0)
|
|
|
|
goto end;
|
|
|
|
dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
|
2015-10-30 18:05:53 +08:00
|
|
|
if (dh == NULL)
|
2015-01-22 11:40:55 +08:00
|
|
|
goto end;
|
|
|
|
} else
|
|
|
|
return 1;
|
|
|
|
if (cctx->ctx)
|
|
|
|
rv = SSL_CTX_set_tmp_dh(cctx->ctx, dh);
|
|
|
|
if (cctx->ssl)
|
|
|
|
rv = SSL_set_tmp_dh(cctx->ssl, dh);
|
|
|
|
end:
|
2015-03-24 22:17:37 +08:00
|
|
|
DH_free(dh);
|
2015-03-25 23:31:18 +08:00
|
|
|
BIO_free(in);
|
2015-01-22 11:40:55 +08:00
|
|
|
return rv > 0;
|
|
|
|
}
|
2013-10-22 14:35:22 +08:00
|
|
|
#endif
|
2017-04-06 00:35:25 +08:00
|
|
|
|
|
|
|
static int cmd_RecordPadding(SSL_CONF_CTX *cctx, const char *value)
|
|
|
|
{
|
|
|
|
int rv = 0;
|
|
|
|
int block_size = atoi(value);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* All we care about is a non-negative value,
|
|
|
|
* the setters check the range
|
|
|
|
*/
|
|
|
|
if (block_size >= 0) {
|
|
|
|
if (cctx->ctx)
|
|
|
|
rv = SSL_CTX_set_block_padding(cctx->ctx, block_size);
|
|
|
|
if (cctx->ssl)
|
|
|
|
rv = SSL_set_block_padding(cctx->ssl, block_size);
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
typedef struct {
|
|
|
|
int (*cmd) (SSL_CONF_CTX *cctx, const char *value);
|
|
|
|
const char *str_file;
|
|
|
|
const char *str_cmdline;
|
2015-04-26 20:56:40 +08:00
|
|
|
unsigned short flags;
|
|
|
|
unsigned short value_type;
|
2015-01-22 11:40:55 +08:00
|
|
|
} ssl_conf_cmd_tbl;
|
2012-11-17 03:12:24 +08:00
|
|
|
|
2013-10-18 23:09:12 +08:00
|
|
|
/* Table of supported parameters */
|
|
|
|
|
2015-04-26 20:56:40 +08:00
|
|
|
#define SSL_CONF_CMD(name, cmdopt, flags, type) \
|
|
|
|
{cmd_##name, #name, cmdopt, flags, type}
|
|
|
|
|
|
|
|
#define SSL_CONF_CMD_STRING(name, cmdopt, flags) \
|
|
|
|
SSL_CONF_CMD(name, cmdopt, flags, SSL_CONF_TYPE_STRING)
|
2013-10-18 23:09:12 +08:00
|
|
|
|
2015-04-26 20:56:40 +08:00
|
|
|
#define SSL_CONF_CMD_SWITCH(name, flags) \
|
|
|
|
{0, NULL, name, flags, SSL_CONF_TYPE_NONE}
|
2012-11-17 03:12:24 +08:00
|
|
|
|
Big apps cleanup (option-parsing, etc)
This is merges the old "rsalz-monolith" branch over to master. The biggest
change is that option parsing switch from cascasding 'else if strcmp("-foo")'
to a utility routine and somethin akin to getopt. Also, an error in the
command line no longer prints the full summary; use -help (or --help :)
for that. There have been many other changes and code-cleanup, see
bullet list below.
Special thanks to Matt for the long and detailed code review.
TEMPORARY:
For now, comment out CRYPTO_mem_leaks() at end of main
Tickets closed:
RT3515: Use 3DES in pkcs12 if built with no-rc2
RT1766: s_client -reconnect and -starttls broke
RT2932: Catch write errors
RT2604: port should be 'unsigned short'
RT2983: total_bytes undeclared #ifdef RENEG
RT1523: Add -nocert to fix output in x509 app
RT3508: Remove unused variable introduced by b09eb24
RT3511: doc fix; req default serial is random
RT1325,2973: Add more extensions to c_rehash
RT2119,3407: Updated to dgst.pod
RT2379: Additional typo fix
RT2693: Extra include of string.h
RT2880: HFS is case-insensitive filenames
RT3246: req command prints version number wrong
Other changes; incompatibilities marked with *:
Add SCSV support
Add -misalign to speed command
Make dhparam, dsaparam, ecparam, x509 output C in proper style
Make some internal ocsp.c functions void
Only display cert usages with -help in verify
Use global bio_err, remove "BIO*err" parameter from functions
For filenames, - always means stdin (or stdout as appropriate)
Add aliases for -des/aes "wrap" ciphers.
*Remove support for IISSGC (server gated crypto)
*The undocumented OCSP -header flag is now "-header name=value"
*Documented the OCSP -header flag
Reviewed-by: Matt Caswell <matt@openssl.org>
2015-04-25 03:26:15 +08:00
|
|
|
/* See apps/apps.h if you change this table. */
|
2013-10-21 14:19:01 +08:00
|
|
|
static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
|
2015-04-26 20:56:40 +08:00
|
|
|
SSL_CONF_CMD_SWITCH("no_ssl3", 0),
|
|
|
|
SSL_CONF_CMD_SWITCH("no_tls1", 0),
|
|
|
|
SSL_CONF_CMD_SWITCH("no_tls1_1", 0),
|
|
|
|
SSL_CONF_CMD_SWITCH("no_tls1_2", 0),
|
2016-10-22 00:39:33 +08:00
|
|
|
SSL_CONF_CMD_SWITCH("no_tls1_3", 0),
|
2015-04-26 20:56:40 +08:00
|
|
|
SSL_CONF_CMD_SWITCH("bugs", 0),
|
2016-02-04 05:45:39 +08:00
|
|
|
SSL_CONF_CMD_SWITCH("no_comp", 0),
|
2016-02-02 23:26:38 +08:00
|
|
|
SSL_CONF_CMD_SWITCH("comp", 0),
|
2015-04-26 20:56:40 +08:00
|
|
|
SSL_CONF_CMD_SWITCH("ecdh_single", SSL_CONF_FLAG_SERVER),
|
|
|
|
SSL_CONF_CMD_SWITCH("no_ticket", 0),
|
|
|
|
SSL_CONF_CMD_SWITCH("serverpref", SSL_CONF_FLAG_SERVER),
|
|
|
|
SSL_CONF_CMD_SWITCH("legacy_renegotiation", 0),
|
|
|
|
SSL_CONF_CMD_SWITCH("legacy_server_connect", SSL_CONF_FLAG_SERVER),
|
2017-05-11 04:46:14 +08:00
|
|
|
SSL_CONF_CMD_SWITCH("no_renegotiation", 0),
|
2015-04-26 20:56:40 +08:00
|
|
|
SSL_CONF_CMD_SWITCH("no_resumption_on_reneg", SSL_CONF_FLAG_SERVER),
|
|
|
|
SSL_CONF_CMD_SWITCH("no_legacy_server_connect", SSL_CONF_FLAG_SERVER),
|
2017-06-30 16:41:03 +08:00
|
|
|
SSL_CONF_CMD_SWITCH("allow_no_dhe_kex", 0),
|
2015-12-22 04:19:29 +08:00
|
|
|
SSL_CONF_CMD_SWITCH("prioritize_chacha", SSL_CONF_FLAG_SERVER),
|
2015-04-26 20:56:40 +08:00
|
|
|
SSL_CONF_CMD_SWITCH("strict", 0),
|
2017-11-08 23:00:48 +08:00
|
|
|
SSL_CONF_CMD_SWITCH("no_middlebox", 0),
|
2015-04-26 20:56:40 +08:00
|
|
|
SSL_CONF_CMD_STRING(SignatureAlgorithms, "sigalgs", 0),
|
|
|
|
SSL_CONF_CMD_STRING(ClientSignatureAlgorithms, "client_sigalgs", 0),
|
|
|
|
SSL_CONF_CMD_STRING(Curves, "curves", 0),
|
2016-11-09 22:51:06 +08:00
|
|
|
SSL_CONF_CMD_STRING(Groups, "groups", 0),
|
2015-03-11 07:09:27 +08:00
|
|
|
#ifndef OPENSSL_NO_EC
|
2015-04-26 20:56:40 +08:00
|
|
|
SSL_CONF_CMD_STRING(ECDHParameters, "named_curve", SSL_CONF_FLAG_SERVER),
|
2013-08-18 00:40:08 +08:00
|
|
|
#endif
|
2015-04-26 20:56:40 +08:00
|
|
|
SSL_CONF_CMD_STRING(CipherString, "cipher", 0),
|
|
|
|
SSL_CONF_CMD_STRING(Protocol, NULL, 0),
|
2016-03-17 22:14:30 +08:00
|
|
|
SSL_CONF_CMD_STRING(MinProtocol, "min_protocol", 0),
|
|
|
|
SSL_CONF_CMD_STRING(MaxProtocol, "max_protocol", 0),
|
2015-04-26 20:56:40 +08:00
|
|
|
SSL_CONF_CMD_STRING(Options, NULL, 0),
|
2015-07-14 21:18:37 +08:00
|
|
|
SSL_CONF_CMD_STRING(VerifyMode, NULL, 0),
|
2015-04-26 20:56:40 +08:00
|
|
|
SSL_CONF_CMD(Certificate, "cert", SSL_CONF_FLAG_CERTIFICATE,
|
|
|
|
SSL_CONF_TYPE_FILE),
|
|
|
|
SSL_CONF_CMD(PrivateKey, "key", SSL_CONF_FLAG_CERTIFICATE,
|
|
|
|
SSL_CONF_TYPE_FILE),
|
|
|
|
SSL_CONF_CMD(ServerInfoFile, NULL,
|
|
|
|
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
|
|
|
|
SSL_CONF_TYPE_FILE),
|
2015-07-14 21:18:37 +08:00
|
|
|
SSL_CONF_CMD(ChainCAPath, "chainCApath", SSL_CONF_FLAG_CERTIFICATE,
|
|
|
|
SSL_CONF_TYPE_DIR),
|
|
|
|
SSL_CONF_CMD(ChainCAFile, "chainCAfile", SSL_CONF_FLAG_CERTIFICATE,
|
|
|
|
SSL_CONF_TYPE_FILE),
|
|
|
|
SSL_CONF_CMD(VerifyCAPath, "verifyCApath", SSL_CONF_FLAG_CERTIFICATE,
|
|
|
|
SSL_CONF_TYPE_DIR),
|
|
|
|
SSL_CONF_CMD(VerifyCAFile, "verifyCAfile", SSL_CONF_FLAG_CERTIFICATE,
|
|
|
|
SSL_CONF_TYPE_FILE),
|
2017-03-18 21:44:13 +08:00
|
|
|
SSL_CONF_CMD(RequestCAFile, "requestCAFile", SSL_CONF_FLAG_CERTIFICATE,
|
|
|
|
SSL_CONF_TYPE_FILE),
|
2015-07-14 21:18:37 +08:00
|
|
|
SSL_CONF_CMD(ClientCAFile, NULL,
|
|
|
|
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
|
|
|
|
SSL_CONF_TYPE_FILE),
|
2017-03-18 21:44:13 +08:00
|
|
|
SSL_CONF_CMD(RequestCAPath, NULL, SSL_CONF_FLAG_CERTIFICATE,
|
|
|
|
SSL_CONF_TYPE_DIR),
|
2015-07-14 21:18:37 +08:00
|
|
|
SSL_CONF_CMD(ClientCAPath, NULL,
|
|
|
|
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
|
|
|
|
SSL_CONF_TYPE_DIR),
|
2013-10-22 14:35:22 +08:00
|
|
|
#ifndef OPENSSL_NO_DH
|
2015-04-26 20:56:40 +08:00
|
|
|
SSL_CONF_CMD(DHParameters, "dhparam",
|
|
|
|
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
|
2017-04-06 00:35:25 +08:00
|
|
|
SSL_CONF_TYPE_FILE),
|
2015-04-26 20:56:40 +08:00
|
|
|
#endif
|
2017-04-06 00:35:25 +08:00
|
|
|
SSL_CONF_CMD_STRING(RecordPadding, "record_padding", 0)
|
2015-04-26 20:56:40 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Supported switches: must match order of switches in ssl_conf_cmds */
|
|
|
|
static const ssl_switch_tbl ssl_cmd_switches[] = {
|
|
|
|
{SSL_OP_NO_SSLv3, 0}, /* no_ssl3 */
|
|
|
|
{SSL_OP_NO_TLSv1, 0}, /* no_tls1 */
|
|
|
|
{SSL_OP_NO_TLSv1_1, 0}, /* no_tls1_1 */
|
|
|
|
{SSL_OP_NO_TLSv1_2, 0}, /* no_tls1_2 */
|
2016-10-22 00:39:33 +08:00
|
|
|
{SSL_OP_NO_TLSv1_3, 0}, /* no_tls1_3 */
|
2015-04-26 20:56:40 +08:00
|
|
|
{SSL_OP_ALL, 0}, /* bugs */
|
2016-02-04 05:45:39 +08:00
|
|
|
{SSL_OP_NO_COMPRESSION, 0}, /* no_comp */
|
|
|
|
{SSL_OP_NO_COMPRESSION, SSL_TFLAG_INV}, /* comp */
|
2015-04-26 20:56:40 +08:00
|
|
|
{SSL_OP_SINGLE_ECDH_USE, 0}, /* ecdh_single */
|
|
|
|
{SSL_OP_NO_TICKET, 0}, /* no_ticket */
|
|
|
|
{SSL_OP_CIPHER_SERVER_PREFERENCE, 0}, /* serverpref */
|
|
|
|
/* legacy_renegotiation */
|
|
|
|
{SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION, 0},
|
|
|
|
/* legacy_server_connect */
|
|
|
|
{SSL_OP_LEGACY_SERVER_CONNECT, 0},
|
2017-05-11 04:46:14 +08:00
|
|
|
/* no_renegotiation */
|
|
|
|
{SSL_OP_NO_RENEGOTIATION, 0},
|
2015-04-26 20:56:40 +08:00
|
|
|
/* no_resumption_on_reneg */
|
|
|
|
{SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION, 0},
|
|
|
|
/* no_legacy_server_connect */
|
|
|
|
{SSL_OP_LEGACY_SERVER_CONNECT, SSL_TFLAG_INV},
|
2017-06-30 16:41:03 +08:00
|
|
|
/* allow_no_dhe_kex */
|
|
|
|
{SSL_OP_ALLOW_NO_DHE_KEX, 0},
|
2015-12-22 04:19:29 +08:00
|
|
|
/* chacha reprioritization */
|
|
|
|
{SSL_OP_PRIORITIZE_CHACHA, 0},
|
2015-04-26 20:56:40 +08:00
|
|
|
{SSL_CERT_FLAG_TLS_STRICT, SSL_TFLAG_CERT}, /* strict */
|
2017-11-07 18:45:43 +08:00
|
|
|
/* no_middlebox */
|
|
|
|
{SSL_OP_ENABLE_MIDDLEBOX_COMPAT, SSL_TFLAG_INV},
|
2012-11-17 03:12:24 +08:00
|
|
|
};
|
|
|
|
|
2013-10-18 23:09:12 +08:00
|
|
|
static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (!pcmd || !*pcmd)
|
|
|
|
return 0;
|
|
|
|
/* If a prefix is set, check and skip */
|
|
|
|
if (cctx->prefix) {
|
|
|
|
if (strlen(*pcmd) <= cctx->prefixlen)
|
|
|
|
return 0;
|
|
|
|
if (cctx->flags & SSL_CONF_FLAG_CMDLINE &&
|
|
|
|
strncmp(*pcmd, cctx->prefix, cctx->prefixlen))
|
|
|
|
return 0;
|
|
|
|
if (cctx->flags & SSL_CONF_FLAG_FILE &&
|
|
|
|
strncasecmp(*pcmd, cctx->prefix, cctx->prefixlen))
|
|
|
|
return 0;
|
|
|
|
*pcmd += cctx->prefixlen;
|
|
|
|
} else if (cctx->flags & SSL_CONF_FLAG_CMDLINE) {
|
|
|
|
if (**pcmd != '-' || !(*pcmd)[1])
|
|
|
|
return 0;
|
|
|
|
*pcmd += 1;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-04-26 20:56:40 +08:00
|
|
|
/* Determine if a command is allowed according to cctx flags */
|
2016-08-06 01:03:17 +08:00
|
|
|
static int ssl_conf_cmd_allowed(SSL_CONF_CTX *cctx, const ssl_conf_cmd_tbl * t)
|
2015-04-26 20:56:40 +08:00
|
|
|
{
|
|
|
|
unsigned int tfl = t->flags;
|
|
|
|
unsigned int cfl = cctx->flags;
|
|
|
|
if ((tfl & SSL_CONF_FLAG_SERVER) && !(cfl & SSL_CONF_FLAG_SERVER))
|
|
|
|
return 0;
|
|
|
|
if ((tfl & SSL_CONF_FLAG_CLIENT) && !(cfl & SSL_CONF_FLAG_CLIENT))
|
|
|
|
return 0;
|
|
|
|
if ((tfl & SSL_CONF_FLAG_CERTIFICATE)
|
|
|
|
&& !(cfl & SSL_CONF_FLAG_CERTIFICATE))
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
static const ssl_conf_cmd_tbl *ssl_conf_cmd_lookup(SSL_CONF_CTX *cctx,
|
|
|
|
const char *cmd)
|
|
|
|
{
|
|
|
|
const ssl_conf_cmd_tbl *t;
|
|
|
|
size_t i;
|
|
|
|
if (cmd == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* Look for matching parameter name in table */
|
2015-05-03 01:30:00 +08:00
|
|
|
for (i = 0, t = ssl_conf_cmds; i < OSSL_NELEM(ssl_conf_cmds); i++, t++) {
|
2015-04-26 20:56:40 +08:00
|
|
|
if (ssl_conf_cmd_allowed(cctx, t)) {
|
|
|
|
if (cctx->flags & SSL_CONF_FLAG_CMDLINE) {
|
2015-05-07 02:56:14 +08:00
|
|
|
if (t->str_cmdline && strcmp(t->str_cmdline, cmd) == 0)
|
2015-04-26 20:56:40 +08:00
|
|
|
return t;
|
|
|
|
}
|
|
|
|
if (cctx->flags & SSL_CONF_FLAG_FILE) {
|
2015-05-07 02:56:14 +08:00
|
|
|
if (t->str_file && strcasecmp(t->str_file, cmd) == 0)
|
2015-04-26 20:56:40 +08:00
|
|
|
return t;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-10-18 23:09:12 +08:00
|
|
|
|
2016-08-06 01:03:17 +08:00
|
|
|
static int ctrl_switch_option(SSL_CONF_CTX *cctx, const ssl_conf_cmd_tbl * cmd)
|
2015-04-26 20:56:40 +08:00
|
|
|
{
|
|
|
|
/* Find index of command in table */
|
|
|
|
size_t idx = cmd - ssl_conf_cmds;
|
|
|
|
const ssl_switch_tbl *scmd;
|
|
|
|
/* Sanity check index */
|
|
|
|
if (idx >= OSSL_NELEM(ssl_cmd_switches))
|
|
|
|
return 0;
|
|
|
|
/* Obtain switches entry with same index */
|
|
|
|
scmd = ssl_cmd_switches + idx;
|
|
|
|
ssl_set_option(cctx, scmd->name_flags, scmd->option_value, 1);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2013-10-18 23:09:12 +08:00
|
|
|
int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
const ssl_conf_cmd_tbl *runcmd;
|
|
|
|
if (cmd == NULL) {
|
|
|
|
SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_INVALID_NULL_CMD_NAME);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ssl_conf_cmd_skip_prefix(cctx, &cmd))
|
|
|
|
return -2;
|
|
|
|
|
|
|
|
runcmd = ssl_conf_cmd_lookup(cctx, cmd);
|
|
|
|
|
|
|
|
if (runcmd) {
|
|
|
|
int rv;
|
2015-04-26 20:56:40 +08:00
|
|
|
if (runcmd->value_type == SSL_CONF_TYPE_NONE) {
|
|
|
|
return ctrl_switch_option(cctx, runcmd);
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
if (value == NULL)
|
|
|
|
return -3;
|
|
|
|
rv = runcmd->cmd(cctx, value);
|
|
|
|
if (rv > 0)
|
|
|
|
return 2;
|
|
|
|
if (rv == -2)
|
|
|
|
return -2;
|
|
|
|
if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) {
|
|
|
|
SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_BAD_VALUE);
|
|
|
|
ERR_add_error_data(4, "cmd=", cmd, ", value=", value);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) {
|
|
|
|
SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_UNKNOWN_CMD_NAME);
|
|
|
|
ERR_add_error_data(2, "cmd=", cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
return -2;
|
|
|
|
}
|
2012-11-17 03:12:24 +08:00
|
|
|
|
|
|
|
int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
const char *arg = NULL, *argn;
|
|
|
|
if (pargc && *pargc == 0)
|
|
|
|
return 0;
|
|
|
|
if (!pargc || *pargc > 0)
|
|
|
|
arg = **pargv;
|
|
|
|
if (arg == NULL)
|
|
|
|
return 0;
|
|
|
|
if (!pargc || *pargc > 1)
|
|
|
|
argn = (*pargv)[1];
|
|
|
|
else
|
|
|
|
argn = NULL;
|
|
|
|
cctx->flags &= ~SSL_CONF_FLAG_FILE;
|
|
|
|
cctx->flags |= SSL_CONF_FLAG_CMDLINE;
|
|
|
|
rv = SSL_CONF_cmd(cctx, arg, argn);
|
|
|
|
if (rv > 0) {
|
|
|
|
/* Success: update pargc, pargv */
|
|
|
|
(*pargv) += rv;
|
|
|
|
if (pargc)
|
|
|
|
(*pargc) -= rv;
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
/* Unknown switch: indicate no arguments processed */
|
|
|
|
if (rv == -2)
|
|
|
|
return 0;
|
|
|
|
/* Some error occurred processing command, return fatal error */
|
|
|
|
if (rv == 0)
|
|
|
|
return -1;
|
|
|
|
return rv;
|
|
|
|
}
|
2012-11-17 03:12:24 +08:00
|
|
|
|
2013-10-18 23:09:12 +08:00
|
|
|
int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (ssl_conf_cmd_skip_prefix(cctx, &cmd)) {
|
|
|
|
const ssl_conf_cmd_tbl *runcmd;
|
|
|
|
runcmd = ssl_conf_cmd_lookup(cctx, cmd);
|
|
|
|
if (runcmd)
|
|
|
|
return runcmd->value_type;
|
|
|
|
}
|
|
|
|
return SSL_CONF_TYPE_UNKNOWN;
|
|
|
|
}
|
2013-10-18 23:09:12 +08:00
|
|
|
|
2012-11-17 03:12:24 +08:00
|
|
|
SSL_CONF_CTX *SSL_CONF_CTX_new(void)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2015-09-03 21:15:26 +08:00
|
|
|
SSL_CONF_CTX *ret = OPENSSL_zalloc(sizeof(*ret));
|
2015-05-02 11:10:31 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
return ret;
|
|
|
|
}
|
2012-11-17 03:12:24 +08:00
|
|
|
|
2013-10-18 23:09:12 +08:00
|
|
|
int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2015-02-16 21:44:22 +08:00
|
|
|
/* See if any certificates are missing private keys */
|
|
|
|
size_t i;
|
|
|
|
CERT *c = NULL;
|
|
|
|
if (cctx->ctx)
|
|
|
|
c = cctx->ctx->cert;
|
|
|
|
else if (cctx->ssl)
|
|
|
|
c = cctx->ssl->cert;
|
|
|
|
if (c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) {
|
|
|
|
for (i = 0; i < SSL_PKEY_NUM; i++) {
|
|
|
|
const char *p = cctx->cert_filename[i];
|
|
|
|
/*
|
|
|
|
* If missing private key try to load one from certificate file
|
|
|
|
*/
|
|
|
|
if (p && !c->pkeys[i].privatekey) {
|
|
|
|
if (!cmd_PrivateKey(cctx, p))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-07-14 21:18:37 +08:00
|
|
|
if (cctx->canames) {
|
|
|
|
if (cctx->ssl)
|
2017-03-18 21:44:13 +08:00
|
|
|
SSL_set0_CA_list(cctx->ssl, cctx->canames);
|
2015-07-14 21:18:37 +08:00
|
|
|
else if (cctx->ctx)
|
2017-03-18 21:44:13 +08:00
|
|
|
SSL_CTX_set0_CA_list(cctx->ctx, cctx->canames);
|
2015-07-14 21:18:37 +08:00
|
|
|
else
|
|
|
|
sk_X509_NAME_pop_free(cctx->canames, X509_NAME_free);
|
|
|
|
cctx->canames = NULL;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2013-10-18 23:09:12 +08:00
|
|
|
|
2012-11-17 03:12:24 +08:00
|
|
|
void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (cctx) {
|
2015-02-16 21:44:22 +08:00
|
|
|
size_t i;
|
2015-04-26 20:56:40 +08:00
|
|
|
for (i = 0; i < SSL_PKEY_NUM; i++)
|
2015-05-01 22:02:07 +08:00
|
|
|
OPENSSL_free(cctx->cert_filename[i]);
|
|
|
|
OPENSSL_free(cctx->prefix);
|
2015-07-14 21:18:37 +08:00
|
|
|
sk_X509_NAME_pop_free(cctx->canames, X509_NAME_free);
|
2015-07-21 21:27:10 +08:00
|
|
|
OPENSSL_free(cctx);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
}
|
2012-11-17 03:12:24 +08:00
|
|
|
|
|
|
|
unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
cctx->flags |= flags;
|
|
|
|
return cctx->flags;
|
|
|
|
}
|
2012-11-17 03:12:24 +08:00
|
|
|
|
|
|
|
unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx, unsigned int flags)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
cctx->flags &= ~flags;
|
|
|
|
return cctx->flags;
|
|
|
|
}
|
2012-11-17 03:12:24 +08:00
|
|
|
|
|
|
|
int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
char *tmp = NULL;
|
|
|
|
if (pre) {
|
Rename some BUF_xxx to OPENSSL_xxx
Rename BUF_{strdup,strlcat,strlcpy,memdup,strndup,strnlen}
to OPENSSL_{strdup,strlcat,strlcpy,memdup,strndup,strnlen}
Add #define's for the old names.
Add CRYPTO_{memdup,strndup}, called by OPENSSL_{memdup,strndup} macros.
Reviewed-by: Tim Hudson <tjh@openssl.org>
2015-12-17 05:12:24 +08:00
|
|
|
tmp = OPENSSL_strdup(pre);
|
2015-01-22 11:40:55 +08:00
|
|
|
if (tmp == NULL)
|
|
|
|
return 0;
|
|
|
|
}
|
2015-05-01 22:02:07 +08:00
|
|
|
OPENSSL_free(cctx->prefix);
|
2015-01-22 11:40:55 +08:00
|
|
|
cctx->prefix = tmp;
|
|
|
|
if (tmp)
|
|
|
|
cctx->prefixlen = strlen(tmp);
|
|
|
|
else
|
|
|
|
cctx->prefixlen = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
2012-11-17 03:12:24 +08:00
|
|
|
|
|
|
|
void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
cctx->ssl = ssl;
|
|
|
|
cctx->ctx = NULL;
|
|
|
|
if (ssl) {
|
|
|
|
cctx->poptions = &ssl->options;
|
2015-12-07 00:56:41 +08:00
|
|
|
cctx->min_version = &ssl->min_proto_version;
|
|
|
|
cctx->max_version = &ssl->max_proto_version;
|
2015-01-22 11:40:55 +08:00
|
|
|
cctx->pcert_flags = &ssl->cert->cert_flags;
|
2015-07-14 21:18:37 +08:00
|
|
|
cctx->pvfy_flags = &ssl->verify_mode;
|
2015-01-22 11:40:55 +08:00
|
|
|
} else {
|
|
|
|
cctx->poptions = NULL;
|
2015-12-07 00:56:41 +08:00
|
|
|
cctx->min_version = NULL;
|
|
|
|
cctx->max_version = NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
cctx->pcert_flags = NULL;
|
2015-07-14 21:18:37 +08:00
|
|
|
cctx->pvfy_flags = NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
}
|
2012-11-17 03:12:24 +08:00
|
|
|
|
|
|
|
void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
cctx->ctx = ctx;
|
|
|
|
cctx->ssl = NULL;
|
|
|
|
if (ctx) {
|
|
|
|
cctx->poptions = &ctx->options;
|
2015-12-07 00:56:41 +08:00
|
|
|
cctx->min_version = &ctx->min_proto_version;
|
|
|
|
cctx->max_version = &ctx->max_proto_version;
|
2015-01-22 11:40:55 +08:00
|
|
|
cctx->pcert_flags = &ctx->cert->cert_flags;
|
2015-07-14 21:18:37 +08:00
|
|
|
cctx->pvfy_flags = &ctx->verify_mode;
|
2015-01-22 11:40:55 +08:00
|
|
|
} else {
|
|
|
|
cctx->poptions = NULL;
|
2015-12-07 00:56:41 +08:00
|
|
|
cctx->min_version = NULL;
|
|
|
|
cctx->max_version = NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
cctx->pcert_flags = NULL;
|
2015-07-14 21:18:37 +08:00
|
|
|
cctx->pvfy_flags = NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
}
|