@@ -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