1
0
mirror of https://github.com/mariadb-corporation/mariadb-connector-c.git synced 2025-08-08 14:02:17 +03:00

Fix for CONC-276: client library crashes on Windows after TLS reconnect:

The connection pointer mysql is now no longer part (and doesn't need to be updated) of schannel security context, since it can be obtained directly from tls container.
This commit is contained in:
Georg Richter
2017-08-24 18:05:58 +02:00
parent 11321f16bf
commit 02f57a9c14
4 changed files with 47 additions and 20 deletions

View File

@@ -828,12 +828,14 @@ SECURITY_STATUS ma_schannel_read_decrypt(MARIADB_PVIO *pvio,
} }
/* }}} */ /* }}} */
my_bool ma_schannel_verify_certs(SC_CTX *sctx) my_bool ma_schannel_verify_certs(MARIADB_TLS *ctls)
{ {
SECURITY_STATUS sRet; SECURITY_STATUS sRet;
MYSQL *mysql=sctx->mysql;
MARIADB_PVIO *pvio= mysql->net.pvio; MARIADB_PVIO *pvio= ctls->pvio;
MYSQL *mysql= pvio->mysql;
SC_CTX *sctx = (SC_CTX *)ctls->ssl;
const char *ca_file= mysql->options.ssl_ca; const char *ca_file= mysql->options.ssl_ca;
const char *crl_file= mysql->options.extension ? mysql->options.extension->ssl_crl : NULL; const char *crl_file= mysql->options.extension ? mysql->options.extension->ssl_crl : NULL;
PCCERT_CONTEXT pServerCert= NULL; PCCERT_CONTEXT pServerCert= NULL;
@@ -868,13 +870,13 @@ my_bool ma_schannel_verify_certs(SC_CTX *sctx)
if (flags) if (flags)
{ {
if ((flags & CERT_STORE_SIGNATURE_FLAG) != 0) if ((flags & CERT_STORE_SIGNATURE_FLAG) != 0)
pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: Certificate signature check failed"); pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: Certificate signature check failed");
else if ((flags & CERT_STORE_REVOCATION_FLAG) != 0) else if ((flags & CERT_STORE_REVOCATION_FLAG) != 0)
pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: certificate was revoked"); pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: certificate was revoked");
else if ((flags & CERT_STORE_TIME_VALIDITY_FLAG) != 0) else if ((flags & CERT_STORE_TIME_VALIDITY_FLAG) != 0)
pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: certificate has expired"); pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: certificate has expired");
else else
pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: Unknown error during certificate validation"); pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: Unknown error during certificate validation");
goto end; goto end;
} }
} }

View File

@@ -55,7 +55,6 @@ struct st_schannel {
DWORD IoBufferSize; DWORD IoBufferSize;
SecPkgContext_StreamSizes Sizes; SecPkgContext_StreamSizes Sizes;
CtxtHandle ctxt; CtxtHandle ctxt;
MYSQL *mysql;
/* Cached data from the last read/decrypt call.*/ /* Cached data from the last read/decrypt call.*/
SecBuffer extraBuf; /* encrypted data read from server. */ SecBuffer extraBuf; /* encrypted data read from server. */
@@ -73,7 +72,7 @@ SECURITY_STATUS ma_schannel_client_handshake(MARIADB_TLS *ctls);
SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRead, SecBuffer *pExtraData); SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRead, SecBuffer *pExtraData);
my_bool ma_schannel_load_private_key(MARIADB_PVIO *pvio, CERT_CONTEXT *ctx, char *key_file); my_bool ma_schannel_load_private_key(MARIADB_PVIO *pvio, CERT_CONTEXT *ctx, char *key_file);
PCCRL_CONTEXT ma_schannel_create_crl_context(MARIADB_PVIO *pvio, const char *pem_file); PCCRL_CONTEXT ma_schannel_create_crl_context(MARIADB_PVIO *pvio, const char *pem_file);
my_bool ma_schannel_verify_certs(SC_CTX *sctx); my_bool ma_schannel_verify_certs(MARIADB_TLS *ctls);
ssize_t ma_schannel_write_encrypt(MARIADB_PVIO *pvio, ssize_t ma_schannel_write_encrypt(MARIADB_PVIO *pvio,
uchar *WriteBuffer, uchar *WriteBuffer,
size_t WriteBufferSize); size_t WriteBufferSize);

View File

@@ -235,10 +235,7 @@ void *ma_tls_init(MYSQL *mysql)
{ {
SC_CTX *sctx= NULL; SC_CTX *sctx= NULL;
if ((sctx= (SC_CTX *)LocalAlloc(0, sizeof(SC_CTX)))) if ((sctx= (SC_CTX *)LocalAlloc(0, sizeof(SC_CTX))))
{
ZeroMemory(sctx, sizeof(SC_CTX)); ZeroMemory(sctx, sizeof(SC_CTX));
sctx->mysql= mysql;
}
return sctx; return sctx;
} }
/* }}} */ /* }}} */
@@ -373,7 +370,7 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
if (ma_schannel_client_handshake(ctls) != SEC_E_OK) if (ma_schannel_client_handshake(ctls) != SEC_E_OK)
goto end; goto end;
if (!ma_schannel_verify_certs(sctx)) if (!ma_schannel_verify_certs(ctls))
goto end; goto end;
return 0; return 0;
@@ -391,7 +388,7 @@ end:
ssize_t ma_tls_read(MARIADB_TLS *ctls, const uchar* buffer, size_t length) ssize_t ma_tls_read(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
{ {
SC_CTX *sctx= (SC_CTX *)ctls->ssl; SC_CTX *sctx= (SC_CTX *)ctls->ssl;
MARIADB_PVIO *pvio= sctx->mysql->net.pvio; MARIADB_PVIO *pvio= ctls->pvio;
DWORD dlength= 0; DWORD dlength= 0;
SECURITY_STATUS status = ma_schannel_read_decrypt(pvio, &sctx->CredHdl, &sctx->ctxt, &dlength, (uchar *)buffer, (DWORD)length); SECURITY_STATUS status = ma_schannel_read_decrypt(pvio, &sctx->CredHdl, &sctx->ctxt, &dlength, (uchar *)buffer, (DWORD)length);
if (status == SEC_I_CONTEXT_EXPIRED) if (status == SEC_I_CONTEXT_EXPIRED)
@@ -405,7 +402,7 @@ ssize_t ma_tls_read(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
ssize_t ma_tls_write(MARIADB_TLS *ctls, const uchar* buffer, size_t length) ssize_t ma_tls_write(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
{ {
SC_CTX *sctx= (SC_CTX *)ctls->ssl; SC_CTX *sctx= (SC_CTX *)ctls->ssl;
MARIADB_PVIO *pvio= sctx->mysql->net.pvio; MARIADB_PVIO *pvio= ctls->pvio;
ssize_t rc, wlength= 0; ssize_t rc, wlength= 0;
ssize_t remain= length; ssize_t remain= length;
@@ -448,7 +445,7 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls)
PCCERT_CONTEXT pServerCert= NULL; PCCERT_CONTEXT pServerCert= NULL;
/* check server name */ /* check server name */
if (pszServerName && (sctx->mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT)) if (pszServerName && (ctls->pvio->mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT))
{ {
DWORD NameSize= 0; DWORD NameSize= 0;
char *p1; char *p1;
@@ -465,13 +462,13 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls)
CERT_NAME_SEARCH_ALL_NAMES_FLAG, CERT_NAME_SEARCH_ALL_NAMES_FLAG,
NULL, NULL, 0))) NULL, NULL, 0)))
{ {
pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: Can't retrieve name of server certificate"); pvio->set_error(ctls->pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: Can't retrieve name of server certificate");
goto end; goto end;
} }
if (!(szName= (char *)LocalAlloc(0, NameSize + 1))) if (!(szName= (char *)LocalAlloc(0, NameSize + 1)))
{ {
pvio->set_error(sctx->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, NULL); pvio->set_error(ctls->pvio->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, NULL);
goto end; goto end;
} }
@@ -481,7 +478,7 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls)
NULL, szName, NameSize)) NULL, szName, NameSize))
{ {
pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: Can't retrieve name of server certificate"); pvio->set_error(ctls->pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: Can't retrieve name of server certificate");
goto end; goto end;
} }

View File

@@ -1248,8 +1248,37 @@ if (!(fp= fopen("./mdev13100.cnf", "w")))
return OK; return OK;
} }
static int test_conc276(MYSQL *unused __attribute__((unused)))
{
MYSQL *mysql= mysql_init(NULL);
int rc;
my_bool val= 1;
mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &val);
mysql_options(mysql, MYSQL_OPT_RECONNECT, &val);
if (!mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0))
{
diag("Connection failed. Error: %s", mysql_error(mysql));
mysql_close(mysql);
return FAIL;
}
diag("Cipher in use: %s", mysql_get_ssl_cipher(mysql));
rc= mariadb_reconnect(mysql);
check_mysql_rc(rc, mysql);
diag("Cipher in use: %s", mysql_get_ssl_cipher(mysql));
/* this shouldn't crash anymore */
rc= mysql_query(mysql, "SET @a:=1");
check_mysql_rc(rc, mysql);
mysql_close(mysql);
return OK;
}
struct my_tests_st my_tests[] = { struct my_tests_st my_tests[] = {
{"test_conc276", test_conc276, TEST_CONNECTION_NONE, 0, NULL, NULL},
{"test_mdev13100", test_mdev13100, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_mdev13100", test_mdev13100, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_auth256", test_auth256, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_auth256", test_auth256, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_reset", test_reset, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_reset", test_reset, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},