tls_openssl: Store TLS context per-connection
Store context for each tls_init() caller, so events are generated for the correct wpa_s instance. The tls_global variable is retained for older OpenSSL implementations that may not have app-data for SSL_CTX. Signed-hostap: Paul Stewart <pstew@chromium.org>
This commit is contained in:
parent
732118eca3
commit
7c0e1e2757
1 changed files with 70 additions and 24 deletions
|
@ -37,6 +37,10 @@
|
||||||
#define OPENSSL_d2i_TYPE unsigned char **
|
#define OPENSSL_d2i_TYPE unsigned char **
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(SSL_CTX_get_app_data) && defined(SSL_CTX_set_app_data)
|
||||||
|
#define OPENSSL_SUPPORTS_CTX_APP_DATA
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SSL_F_SSL_SET_SESSION_TICKET_EXT
|
#ifdef SSL_F_SSL_SET_SESSION_TICKET_EXT
|
||||||
#ifdef SSL_OP_NO_TICKET
|
#ifdef SSL_OP_NO_TICKET
|
||||||
/*
|
/*
|
||||||
|
@ -49,17 +53,18 @@
|
||||||
|
|
||||||
static int tls_openssl_ref_count = 0;
|
static int tls_openssl_ref_count = 0;
|
||||||
|
|
||||||
struct tls_global {
|
struct tls_context {
|
||||||
void (*event_cb)(void *ctx, enum tls_event ev,
|
void (*event_cb)(void *ctx, enum tls_event ev,
|
||||||
union tls_event_data *data);
|
union tls_event_data *data);
|
||||||
void *cb_ctx;
|
void *cb_ctx;
|
||||||
int cert_in_cb;
|
int cert_in_cb;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct tls_global *tls_global = NULL;
|
static struct tls_context *tls_global = NULL;
|
||||||
|
|
||||||
|
|
||||||
struct tls_connection {
|
struct tls_connection {
|
||||||
|
struct tls_context *context;
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
BIO *ssl_in, *ssl_out;
|
BIO *ssl_in, *ssl_out;
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
#ifndef OPENSSL_NO_ENGINE
|
||||||
|
@ -86,6 +91,20 @@ struct tls_connection {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct tls_context * tls_context_new(const struct tls_config *conf)
|
||||||
|
{
|
||||||
|
struct tls_context *context = os_zalloc(sizeof(*context));
|
||||||
|
if (context == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (conf) {
|
||||||
|
context->event_cb = conf->event_cb;
|
||||||
|
context->cb_ctx = conf->cb_ctx;
|
||||||
|
context->cert_in_cb = conf->cert_in_cb;
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_NO_STDOUT_DEBUG
|
#ifdef CONFIG_NO_STDOUT_DEBUG
|
||||||
|
|
||||||
static void _tls_show_errors(void)
|
static void _tls_show_errors(void)
|
||||||
|
@ -511,6 +530,7 @@ static void ssl_info_cb(const SSL *ssl, int where, int ret)
|
||||||
wpa_printf(MSG_DEBUG, "SSL: %s:%s",
|
wpa_printf(MSG_DEBUG, "SSL: %s:%s",
|
||||||
str, SSL_state_string_long(ssl));
|
str, SSL_state_string_long(ssl));
|
||||||
} else if (where & SSL_CB_ALERT) {
|
} else if (where & SSL_CB_ALERT) {
|
||||||
|
struct tls_connection *conn = SSL_get_app_data((SSL *) ssl);
|
||||||
wpa_printf(MSG_INFO, "SSL: SSL3 alert: %s:%s:%s",
|
wpa_printf(MSG_INFO, "SSL: SSL3 alert: %s:%s:%s",
|
||||||
where & SSL_CB_READ ?
|
where & SSL_CB_READ ?
|
||||||
"read (remote end reported an error)" :
|
"read (remote end reported an error)" :
|
||||||
|
@ -518,21 +538,19 @@ static void ssl_info_cb(const SSL *ssl, int where, int ret)
|
||||||
SSL_alert_type_string_long(ret),
|
SSL_alert_type_string_long(ret),
|
||||||
SSL_alert_desc_string_long(ret));
|
SSL_alert_desc_string_long(ret));
|
||||||
if ((ret >> 8) == SSL3_AL_FATAL) {
|
if ((ret >> 8) == SSL3_AL_FATAL) {
|
||||||
struct tls_connection *conn =
|
|
||||||
SSL_get_app_data((SSL *) ssl);
|
|
||||||
if (where & SSL_CB_READ)
|
if (where & SSL_CB_READ)
|
||||||
conn->read_alerts++;
|
conn->read_alerts++;
|
||||||
else
|
else
|
||||||
conn->write_alerts++;
|
conn->write_alerts++;
|
||||||
}
|
}
|
||||||
if (tls_global->event_cb != NULL) {
|
if (conn->context->event_cb != NULL) {
|
||||||
union tls_event_data ev;
|
union tls_event_data ev;
|
||||||
|
struct tls_context *context = conn->context;
|
||||||
os_memset(&ev, 0, sizeof(ev));
|
os_memset(&ev, 0, sizeof(ev));
|
||||||
ev.alert.is_local = !(where & SSL_CB_READ);
|
ev.alert.is_local = !(where & SSL_CB_READ);
|
||||||
ev.alert.type = SSL_alert_type_string_long(ret);
|
ev.alert.type = SSL_alert_type_string_long(ret);
|
||||||
ev.alert.description = SSL_alert_desc_string_long(ret);
|
ev.alert.description = SSL_alert_desc_string_long(ret);
|
||||||
tls_global->event_cb(tls_global->cb_ctx, TLS_ALERT,
|
context->event_cb(context->cb_ctx, TLS_ALERT, &ev);
|
||||||
&ev);
|
|
||||||
}
|
}
|
||||||
} else if (where & SSL_CB_EXIT && ret <= 0) {
|
} else if (where & SSL_CB_EXIT && ret <= 0) {
|
||||||
wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s",
|
wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s",
|
||||||
|
@ -690,17 +708,12 @@ static int tls_engine_load_dynamic_opensc(const char *opensc_so_path)
|
||||||
void * tls_init(const struct tls_config *conf)
|
void * tls_init(const struct tls_config *conf)
|
||||||
{
|
{
|
||||||
SSL_CTX *ssl;
|
SSL_CTX *ssl;
|
||||||
|
struct tls_context *context;
|
||||||
|
|
||||||
if (tls_openssl_ref_count == 0) {
|
if (tls_openssl_ref_count == 0) {
|
||||||
tls_global = os_zalloc(sizeof(*tls_global));
|
tls_global = context = tls_context_new(conf);
|
||||||
if (tls_global == NULL)
|
if (context == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (conf) {
|
|
||||||
tls_global->event_cb = conf->event_cb;
|
|
||||||
tls_global->cb_ctx = conf->cb_ctx;
|
|
||||||
tls_global->cert_in_cb = conf->cert_in_cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_FIPS
|
#ifdef CONFIG_FIPS
|
||||||
#ifdef OPENSSL_FIPS
|
#ifdef OPENSSL_FIPS
|
||||||
if (conf && conf->fips_mode) {
|
if (conf && conf->fips_mode) {
|
||||||
|
@ -746,14 +759,33 @@ void * tls_init(const struct tls_config *conf)
|
||||||
#endif /* OPENSSL_NO_RC2 */
|
#endif /* OPENSSL_NO_RC2 */
|
||||||
PKCS12_PBE_add();
|
PKCS12_PBE_add();
|
||||||
#endif /* PKCS12_FUNCS */
|
#endif /* PKCS12_FUNCS */
|
||||||
|
} else {
|
||||||
|
context = tls_global;
|
||||||
|
#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
|
||||||
|
/* Newer OpenSSL can store app-data per-SSL */
|
||||||
|
context = tls_context_new(conf);
|
||||||
|
if (context == NULL)
|
||||||
|
return NULL;
|
||||||
|
#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
|
||||||
}
|
}
|
||||||
tls_openssl_ref_count++;
|
tls_openssl_ref_count++;
|
||||||
|
|
||||||
ssl = SSL_CTX_new(TLSv1_method());
|
ssl = SSL_CTX_new(TLSv1_method());
|
||||||
if (ssl == NULL)
|
if (ssl == NULL) {
|
||||||
|
tls_openssl_ref_count--;
|
||||||
|
if (tls_openssl_ref_count == 0) {
|
||||||
|
os_free(tls_global);
|
||||||
|
tls_global = NULL;
|
||||||
|
} else if (context != tls_global) {
|
||||||
|
os_free(context);
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
SSL_CTX_set_info_callback(ssl, ssl_info_cb);
|
SSL_CTX_set_info_callback(ssl, ssl_info_cb);
|
||||||
|
#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
|
||||||
|
SSL_CTX_set_app_data(ssl, context);
|
||||||
|
#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
#ifndef OPENSSL_NO_ENGINE
|
||||||
if (conf &&
|
if (conf &&
|
||||||
|
@ -779,6 +811,11 @@ void * tls_init(const struct tls_config *conf)
|
||||||
void tls_deinit(void *ssl_ctx)
|
void tls_deinit(void *ssl_ctx)
|
||||||
{
|
{
|
||||||
SSL_CTX *ssl = ssl_ctx;
|
SSL_CTX *ssl = ssl_ctx;
|
||||||
|
#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
|
||||||
|
struct tls_context *context = SSL_CTX_get_app_data(ssl);
|
||||||
|
if (context != tls_global)
|
||||||
|
os_free(context);
|
||||||
|
#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
|
||||||
SSL_CTX_free(ssl);
|
SSL_CTX_free(ssl);
|
||||||
|
|
||||||
tls_openssl_ref_count--;
|
tls_openssl_ref_count--;
|
||||||
|
@ -915,6 +952,10 @@ struct tls_connection * tls_connection_init(void *ssl_ctx)
|
||||||
SSL_CTX *ssl = ssl_ctx;
|
SSL_CTX *ssl = ssl_ctx;
|
||||||
struct tls_connection *conn;
|
struct tls_connection *conn;
|
||||||
long options;
|
long options;
|
||||||
|
struct tls_context *context = tls_global;
|
||||||
|
#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
|
||||||
|
context = SSL_CTX_get_app_data(ssl);
|
||||||
|
#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
|
||||||
|
|
||||||
conn = os_zalloc(sizeof(*conn));
|
conn = os_zalloc(sizeof(*conn));
|
||||||
if (conn == NULL)
|
if (conn == NULL)
|
||||||
|
@ -927,6 +968,7 @@ struct tls_connection * tls_connection_init(void *ssl_ctx)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conn->context = context;
|
||||||
SSL_set_app_data(conn->ssl, conn);
|
SSL_set_app_data(conn->ssl, conn);
|
||||||
options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
||||||
SSL_OP_SINGLE_DH_USE;
|
SSL_OP_SINGLE_DH_USE;
|
||||||
|
@ -1122,8 +1164,9 @@ static void openssl_tls_fail_event(struct tls_connection *conn,
|
||||||
{
|
{
|
||||||
union tls_event_data ev;
|
union tls_event_data ev;
|
||||||
struct wpabuf *cert = NULL;
|
struct wpabuf *cert = NULL;
|
||||||
|
struct tls_context *context = conn->context;
|
||||||
|
|
||||||
if (tls_global->event_cb == NULL)
|
if (context->event_cb == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cert = get_x509_cert(err_cert);
|
cert = get_x509_cert(err_cert);
|
||||||
|
@ -1134,7 +1177,7 @@ static void openssl_tls_fail_event(struct tls_connection *conn,
|
||||||
ev.cert_fail.subject = subject;
|
ev.cert_fail.subject = subject;
|
||||||
ev.cert_fail.reason_txt = err_str;
|
ev.cert_fail.reason_txt = err_str;
|
||||||
ev.cert_fail.cert = cert;
|
ev.cert_fail.cert = cert;
|
||||||
tls_global->event_cb(tls_global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
|
context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
|
||||||
wpabuf_free(cert);
|
wpabuf_free(cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1145,15 +1188,16 @@ static void openssl_tls_cert_event(struct tls_connection *conn,
|
||||||
{
|
{
|
||||||
struct wpabuf *cert = NULL;
|
struct wpabuf *cert = NULL;
|
||||||
union tls_event_data ev;
|
union tls_event_data ev;
|
||||||
|
struct tls_context *context = conn->context;
|
||||||
#ifdef CONFIG_SHA256
|
#ifdef CONFIG_SHA256
|
||||||
u8 hash[32];
|
u8 hash[32];
|
||||||
#endif /* CONFIG_SHA256 */
|
#endif /* CONFIG_SHA256 */
|
||||||
|
|
||||||
if (tls_global->event_cb == NULL)
|
if (context->event_cb == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
os_memset(&ev, 0, sizeof(ev));
|
os_memset(&ev, 0, sizeof(ev));
|
||||||
if (conn->cert_probe || tls_global->cert_in_cb) {
|
if (conn->cert_probe || context->cert_in_cb) {
|
||||||
cert = get_x509_cert(err_cert);
|
cert = get_x509_cert(err_cert);
|
||||||
ev.peer_cert.cert = cert;
|
ev.peer_cert.cert = cert;
|
||||||
}
|
}
|
||||||
|
@ -1171,7 +1215,7 @@ static void openssl_tls_cert_event(struct tls_connection *conn,
|
||||||
#endif /* CONFIG_SHA256 */
|
#endif /* CONFIG_SHA256 */
|
||||||
ev.peer_cert.depth = depth;
|
ev.peer_cert.depth = depth;
|
||||||
ev.peer_cert.subject = subject;
|
ev.peer_cert.subject = subject;
|
||||||
tls_global->event_cb(tls_global->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
|
context->event_cb(context->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
|
||||||
wpabuf_free(cert);
|
wpabuf_free(cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1183,6 +1227,7 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
|
||||||
int err, depth;
|
int err, depth;
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
struct tls_connection *conn;
|
struct tls_connection *conn;
|
||||||
|
struct tls_context *context;
|
||||||
char *match, *altmatch;
|
char *match, *altmatch;
|
||||||
const char *err_str;
|
const char *err_str;
|
||||||
|
|
||||||
|
@ -1196,6 +1241,7 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
|
||||||
conn = SSL_get_app_data(ssl);
|
conn = SSL_get_app_data(ssl);
|
||||||
if (conn == NULL)
|
if (conn == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
context = conn->context;
|
||||||
match = conn->subject_match;
|
match = conn->subject_match;
|
||||||
altmatch = conn->altsubject_match;
|
altmatch = conn->altsubject_match;
|
||||||
|
|
||||||
|
@ -1278,8 +1324,8 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
|
||||||
TLS_FAIL_SERVER_CHAIN_PROBE);
|
TLS_FAIL_SERVER_CHAIN_PROBE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preverify_ok && tls_global->event_cb != NULL)
|
if (preverify_ok && context->event_cb != NULL)
|
||||||
tls_global->event_cb(tls_global->cb_ctx,
|
context->event_cb(context->cb_ctx,
|
||||||
TLS_CERT_CHAIN_SUCCESS, NULL);
|
TLS_CERT_CHAIN_SUCCESS, NULL);
|
||||||
|
|
||||||
return preverify_ok;
|
return preverify_ok;
|
||||||
|
|
Loading…
Reference in a new issue