diff --git a/libmariadb/secure/ma_schannel.c b/libmariadb/secure/ma_schannel.c index 99fad1a3..f7f8bcbb 100644 --- a/libmariadb/secure/ma_schannel.c +++ b/libmariadb/secure/ma_schannel.c @@ -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; - MYSQL *mysql=sctx->mysql; + + MARIADB_PVIO *pvio= ctls->pvio; + MYSQL *mysql= pvio->mysql; + SC_CTX *sctx = (SC_CTX *)ctls->ssl; - MARIADB_PVIO *pvio= mysql->net.pvio; const char *ca_file= mysql->options.ssl_ca; const char *crl_file= mysql->options.extension ? mysql->options.extension->ssl_crl : NULL; PCCERT_CONTEXT pServerCert= NULL; @@ -868,13 +870,13 @@ my_bool ma_schannel_verify_certs(SC_CTX *sctx) if (flags) { 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) - 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) - 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 - 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; } } diff --git a/libmariadb/secure/ma_schannel.h b/libmariadb/secure/ma_schannel.h index 4e398fe2..08ff3e7f 100644 --- a/libmariadb/secure/ma_schannel.h +++ b/libmariadb/secure/ma_schannel.h @@ -55,7 +55,6 @@ struct st_schannel { DWORD IoBufferSize; SecPkgContext_StreamSizes Sizes; CtxtHandle ctxt; - MYSQL *mysql; /* Cached data from the last read/decrypt call.*/ 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); 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); -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, uchar *WriteBuffer, size_t WriteBufferSize); diff --git a/libmariadb/secure/schannel.c b/libmariadb/secure/schannel.c index 2da5a3ef..89918d0b 100644 --- a/libmariadb/secure/schannel.c +++ b/libmariadb/secure/schannel.c @@ -235,10 +235,7 @@ void *ma_tls_init(MYSQL *mysql) { SC_CTX *sctx= NULL; if ((sctx= (SC_CTX *)LocalAlloc(0, sizeof(SC_CTX)))) - { ZeroMemory(sctx, sizeof(SC_CTX)); - sctx->mysql= mysql; - } return sctx; } /* }}} */ @@ -373,7 +370,7 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls) if (ma_schannel_client_handshake(ctls) != SEC_E_OK) goto end; - if (!ma_schannel_verify_certs(sctx)) + if (!ma_schannel_verify_certs(ctls)) goto end; return 0; @@ -391,7 +388,7 @@ end: ssize_t ma_tls_read(MARIADB_TLS *ctls, const uchar* buffer, size_t length) { SC_CTX *sctx= (SC_CTX *)ctls->ssl; - MARIADB_PVIO *pvio= sctx->mysql->net.pvio; + MARIADB_PVIO *pvio= ctls->pvio; DWORD dlength= 0; SECURITY_STATUS status = ma_schannel_read_decrypt(pvio, &sctx->CredHdl, &sctx->ctxt, &dlength, (uchar *)buffer, (DWORD)length); 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) { 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 remain= length; @@ -448,7 +445,7 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls) PCCERT_CONTEXT pServerCert= NULL; /* 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; char *p1; @@ -465,13 +462,13 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls) CERT_NAME_SEARCH_ALL_NAMES_FLAG, 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; } 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; } @@ -481,14 +478,14 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls) 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; } /* szName may contain multiple names: Each name is zero terminated, the last name is double zero terminated */ - + p1 = szName; while (p1 && *p1 != 0) { diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index aa764893..887b6a20 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -1248,8 +1248,37 @@ if (!(fp= fopen("./mdev13100.cnf", "w"))) 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[] = { + {"test_conc276", test_conc276, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"test_mdev13100", test_mdev13100, 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},