Skip to content
This repository was archived by the owner on Mar 1, 2026. It is now read-only.

Commit e516414

Browse files
hermanleefacebook-github-bot
authored andcommitted
Add functions to retrieve and set SSL sessions for connections
Summary: Port forward the ssl_session feature to 8.0.28. While similar functionality via ssl_session_data is provided, it is more difficult to integrate due to management of the ssl_session_data memory since existing APIs call SESSION_SSL_free directly. Most of the code has already been added by the ssl_session_data codepath. This adds the API to fetch and set the ssl_session parameter. During connection setup, ssl_session is used before ssl_session_data. Reference patch: 2e261e6 Differential Revision: D57133792 fbshipit-source-id: d030b2e
1 parent b36dc3d commit e516414

5 files changed

Lines changed: 85 additions & 4 deletions

File tree

‎include/mysql.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ enum mysql_option {
225225
MYSQL_OPT_TLS_CERT_CALLBACK,
226226
MYSQL_OPT_TLS_CERT_CALLBACK_CONTEXT,
227227
MYSQL_OPT_TOS,
228+
MYSQL_OPT_SSL_SESSION,
228229
};
229230

230231
/**
@@ -482,6 +483,7 @@ bool STDCALL mysql_get_ssl_session_reused(MYSQL *mysql);
482483
void *STDCALL mysql_get_ssl_session_data(MYSQL *mysql, unsigned int n_ticket,
483484
unsigned int *out_len);
484485
bool STDCALL mysql_free_ssl_session_data(MYSQL *mysql, void *data);
486+
void *STDCALL mysql_get_ssl_session(MYSQL *mysql);
485487
/*
486488
Take ownership of the OpenSSL SSL_CTX instance associated with this
487489
connection. In general, SSL_CTX objects should be re-used. Either one can

‎include/mysql.h.pp‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,7 @@
523523
MYSQL_OPT_TLS_CERT_CALLBACK,
524524
MYSQL_OPT_TLS_CERT_CALLBACK_CONTEXT,
525525
MYSQL_OPT_TOS,
526+
MYSQL_OPT_SSL_SESSION,
526527
};
527528
struct st_mysql_options_extention;
528529
struct st_mysql_options {
@@ -683,6 +684,7 @@
683684
void * mysql_get_ssl_session_data(MYSQL *mysql, unsigned int n_ticket,
684685
unsigned int *out_len);
685686
bool mysql_free_ssl_session_data(MYSQL *mysql, void *data);
687+
void * mysql_get_ssl_session(MYSQL *mysql);
686688
void * mysql_take_ssl_context_ownership(MYSQL *mysql);
687689
bool mysql_change_user(MYSQL *mysql, const char *user,
688690
const char *passwd, const char *db);

‎include/sql_common.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ struct st_mysql_options_extention {
221221
const void *server_cert_validator_context;
222222
#endif
223223
unsigned int tos;
224+
void *ssl_session;
224225
};
225226

226227
struct MYSQL_METHODS {

‎libmysql/CMakeLists.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ SET(CLIENT_API_FUNCTIONS
158158
net_clear
159159
my_net_write
160160
mysql_get_ssl_version
161+
mysql_get_ssl_session
161162

162163
CACHE INTERNAL "Functions exported by client API"
163164
)

‎sql-common/client.cc‎

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3620,6 +3620,10 @@ static void mysql_ssl_free(MYSQL *mysql) {
36203620
mysql->options.extension->tls_ciphersuites = nullptr;
36213621
mysql->options.extension->load_data_dir = nullptr;
36223622
mysql->options.extension->tls_sni_servername = nullptr;
3623+
if (mysql->options.extension->ssl_session) {
3624+
SSL_SESSION_free((SSL_SESSION *)mysql->options.extension->ssl_session);
3625+
mysql->options.extension->ssl_session = nullptr;
3626+
}
36233627
}
36243628
mysql->connector_fd = nullptr;
36253629
}
@@ -3770,6 +3774,21 @@ bool STDCALL mysql_free_ssl_session_data(MYSQL *mysql, void *data) {
37703774
return true;
37713775
}
37723776

3777+
/**
3778+
Returns the current ssl_session and increment its reference count.
3779+
The caller is responsible for freeing it.
3780+
3781+
@param mysql pointer to the mysql connection
3782+
@retval pointer to the SSL_SESSION
3783+
*/
3784+
void *STDCALL mysql_get_ssl_session(MYSQL *mysql) {
3785+
DBUG_TRACE;
3786+
if (mysql->net.vio && mysql->net.vio->ssl_arg) {
3787+
return SSL_get1_session((SSL *)mysql->net.vio->ssl_arg);
3788+
}
3789+
return nullptr;
3790+
}
3791+
37733792
/**
37743793
Check if the current ssl session is reused
37753794
@@ -4853,7 +4872,17 @@ static int cli_establish_ssl(MYSQL *mysql) {
48534872
} else {
48544873
ssl_fd = (struct st_VioSSLFd *)mysql->connector_fd;
48554874
}
4856-
SSL_SESSION *ssl_session = ssl_session_deserialize_from_data(mysql);
4875+
4876+
/* Prioritize ssl_session over ssl_session_data if both are set */
4877+
bool is_ssl_session_data;
4878+
SSL_SESSION *ssl_session;
4879+
if (options->extension && options->extension->ssl_session != nullptr) {
4880+
ssl_session = (SSL_SESSION *)options->extension->ssl_session;
4881+
is_ssl_session_data = false;
4882+
} else {
4883+
ssl_session = ssl_session_deserialize_from_data(mysql);
4884+
is_ssl_session_data = true;
4885+
}
48574886

48584887
/* Connect to the server */
48594888
DBUG_PRINT("info", ("IO layer change in progress..."));
@@ -4867,7 +4896,9 @@ static int cli_establish_ssl(MYSQL *mysql) {
48674896
const_cast<void *>(static_cast<const void *>(mysql)),
48684897
options->extension->server_cert_validator ? ssl_get_ex_data_index()
48694898
: -1);
4870-
if (ssl_session != nullptr) SSL_SESSION_free(ssl_session);
4899+
if (is_ssl_session_data && ssl_session != nullptr) {
4900+
SSL_SESSION_free(ssl_session);
4901+
}
48714902
if (ret) {
48724903
switch (ret) {
48734904
case VIO_SOCKET_READ_TIMEOUT:
@@ -4897,6 +4928,11 @@ static int cli_establish_ssl(MYSQL *mysql) {
48974928
}
48984929
goto error;
48994930
}
4931+
/* Free the SSL session early */
4932+
if (!is_ssl_session_data && options->extension->ssl_session != nullptr) {
4933+
SSL_SESSION_free((SSL_SESSION *)options->extension->ssl_session);
4934+
options->extension->ssl_session = nullptr;
4935+
}
49004936
DBUG_PRINT("info", ("IO layer change done!"));
49014937

49024938
/* Verify server cert */
@@ -5053,7 +5089,16 @@ static net_async_status cli_establish_ssl_nonblocking(MYSQL *mysql, int *res) {
50535089
} else {
50545090
ssl_fd = (struct st_VioSSLFd *)mysql->connector_fd;
50555091
}
5056-
SSL_SESSION *ssl_session = ssl_session_deserialize_from_data(mysql);
5092+
/* Prioritize ssl_session over ssl_session_data if both are set */
5093+
bool is_ssl_session_data;
5094+
SSL_SESSION *ssl_session;
5095+
if (options->extension && options->extension->ssl_session != nullptr) {
5096+
ssl_session = (SSL_SESSION *)options->extension->ssl_session;
5097+
is_ssl_session_data = false;
5098+
} else {
5099+
ssl_session = ssl_session_deserialize_from_data(mysql);
5100+
is_ssl_session_data = true;
5101+
}
50575102

50585103
/* Connect to the server */
50595104
DBUG_PRINT("info", ("IO layer change in progress..."));
@@ -5069,7 +5114,9 @@ static net_async_status cli_establish_ssl_nonblocking(MYSQL *mysql, int *res) {
50695114
const_cast<void *>(static_cast<const void *>(mysql)),
50705115
options->extension->server_cert_validator ? ssl_get_ex_data_index()
50715116
: -1))) {
5072-
if (ssl_session != nullptr) SSL_SESSION_free(ssl_session);
5117+
if (is_ssl_session_data && ssl_session != nullptr) {
5118+
SSL_SESSION_free(ssl_session);
5119+
}
50735120
switch (ret) {
50745121
case VIO_SOCKET_WANT_READ:
50755122
net_async->async_blocking_state = NET_NONBLOCKING_READ;
@@ -5107,6 +5154,8 @@ static net_async_status cli_establish_ssl_nonblocking(MYSQL *mysql, int *res) {
51075154
goto error;
51085155
}
51095156
if (ssl_session != nullptr) SSL_SESSION_free(ssl_session);
5157+
/* Free the SSL session early */
5158+
if (!is_ssl_session_data) options->extension->ssl_session = nullptr;
51105159
DBUG_PRINT("info", ("IO layer change done!"));
51115160

51125161
/* sslconnect creates a new vio, so update it. */
@@ -9968,6 +10017,32 @@ int STDCALL mysql_options4(MYSQL *mysql, enum mysql_option option,
996810017
}
996910018
break;
997010019
}
10020+
case MYSQL_OPT_SSL_SESSION: {
10021+
/*
10022+
Set the SSL session to be used during sslconnect. The client will hold
10023+
a reference to the session until the connection is closed.
10024+
10025+
@param take_ownership if true, the client will assume the caller's
10026+
reference count to session.
10027+
*/
10028+
ENSURE_EXTENSIONS_PRESENT(&mysql->options);
10029+
SSL_SESSION *ssl_session = (SSL_SESSION *)const_cast<void *>(arg1);
10030+
bool take_ownership = (bool)arg2;
10031+
10032+
/* Increment the reference count */
10033+
if (!take_ownership && ssl_session != nullptr)
10034+
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
10035+
SSL_SESSION_up_ref(ssl_session);
10036+
#else
10037+
CRYPTO_add(&ssl_session->references, 1, CRYPTO_LOCK_SSL_SESSION);
10038+
#endif
10039+
10040+
if (mysql->options.extension->ssl_session)
10041+
SSL_SESSION_free((SSL_SESSION *)mysql->options.extension->ssl_session);
10042+
10043+
mysql->options.extension->ssl_session = (void *)ssl_session;
10044+
break;
10045+
}
997110046
default:
997210047
return 1;
997310048
}

0 commit comments

Comments
 (0)