You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-07 02:42:49 +03:00
Merge commit 'b0411b731f5d61df38fe3f783437df13526774f2' into 3.1
This commit is contained in:
@@ -133,11 +133,11 @@ void ma_schannel_set_win_error(MARIADB_PVIO *pvio)
|
||||
*/
|
||||
static LPBYTE ma_schannel_load_pem(MARIADB_PVIO *pvio, const char *PemFileName, DWORD *buffer_len)
|
||||
{
|
||||
HANDLE hfile;
|
||||
HANDLE hfile= 0;
|
||||
char *buffer= NULL;
|
||||
DWORD dwBytesRead= 0;
|
||||
LPBYTE der_buffer= NULL;
|
||||
DWORD der_buffer_length;
|
||||
DWORD der_buffer_length= 0;
|
||||
|
||||
if (buffer_len == NULL)
|
||||
return NULL;
|
||||
@@ -156,7 +156,7 @@ static LPBYTE ma_schannel_load_pem(MARIADB_PVIO *pvio, const char *PemFileName,
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!(buffer= LocalAlloc(0, *buffer_len + 1)))
|
||||
if (!(buffer= malloc((size_t)(*buffer_len + 1))))
|
||||
{
|
||||
pvio->set_error(pvio->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, NULL);
|
||||
goto end;
|
||||
@@ -192,7 +192,7 @@ static LPBYTE ma_schannel_load_pem(MARIADB_PVIO *pvio, const char *PemFileName,
|
||||
}
|
||||
|
||||
*buffer_len= der_buffer_length;
|
||||
LocalFree(buffer);
|
||||
free(buffer);
|
||||
|
||||
return der_buffer;
|
||||
|
||||
@@ -208,6 +208,196 @@ end:
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static LPBYTE ma_schannel_read(MARIADB_PVIO* pvio, const char* PemFile, DWORD* buffer_len)
|
||||
{
|
||||
HANDLE hfile = NULL;
|
||||
char* buffer = NULL;
|
||||
DWORD dwBytesRead = 0;
|
||||
|
||||
if ((hfile = CreateFile(PemFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
ma_schannel_set_win_error(pvio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(*buffer_len = GetFileSize(hfile, NULL)))
|
||||
{
|
||||
pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: Invalid pem format");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!(buffer = malloc((size_t)* buffer_len + 1)))
|
||||
{
|
||||
pvio->set_error(pvio->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, NULL);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!ReadFile(hfile, buffer, *buffer_len, &dwBytesRead, NULL))
|
||||
{
|
||||
ma_schannel_set_win_error(pvio);
|
||||
goto end;
|
||||
}
|
||||
|
||||
buffer[*buffer_len] = 0;
|
||||
|
||||
CloseHandle(hfile);
|
||||
return buffer;
|
||||
end:
|
||||
if (hfile != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(hfile);
|
||||
if (buffer)
|
||||
free(buffer);
|
||||
*buffer_len = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LPBYTE ma_schannel_convert_base64(MARIADB_PVIO* pvio, char* buffer, DWORD buffer_len, DWORD* der_len)
|
||||
{
|
||||
LPBYTE der_buffer = NULL;
|
||||
|
||||
*der_len = 0;
|
||||
|
||||
/* calculate the length of DER binary */
|
||||
if (!CryptStringToBinaryA(buffer, buffer_len, CRYPT_STRING_BASE64HEADER,
|
||||
NULL, der_len, NULL, NULL))
|
||||
{
|
||||
ma_schannel_set_win_error(pvio);
|
||||
goto end;
|
||||
}
|
||||
/* allocate DER binary buffer */
|
||||
if (!(der_buffer = (LPBYTE)malloc(*der_len)))
|
||||
{
|
||||
pvio->set_error(pvio->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, NULL);
|
||||
goto end;
|
||||
}
|
||||
/* convert to DER binary */
|
||||
if (!CryptStringToBinaryA(buffer, buffer_len, CRYPT_STRING_BASE64HEADER,
|
||||
der_buffer, der_len, NULL, NULL))
|
||||
{
|
||||
ma_schannel_set_win_error(pvio);
|
||||
goto end;
|
||||
}
|
||||
return der_buffer;
|
||||
end:
|
||||
if (der_buffer)
|
||||
free(der_buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
DWORD ma_schannel_load_certs_and_keys(MARIADB_PVIO* pvio, const char* PemFileName, SC_CTX* ctx)
|
||||
{
|
||||
char* buffer = NULL;
|
||||
char* p, * type;
|
||||
DWORD buffer_len = 0;
|
||||
LPBYTE der_buffer = NULL;
|
||||
DWORD der_buffer_length = 0;
|
||||
|
||||
/* check if cert and key was already loaded */
|
||||
if (ctx->client_cert_ctx && ctx->der_key)
|
||||
return 0;
|
||||
|
||||
if (!(buffer = ma_schannel_read(pvio, PemFileName, &buffer_len)))
|
||||
return 0;
|
||||
|
||||
p = buffer;
|
||||
|
||||
while ((p = strstr(p, "-----BEGIN")))
|
||||
{
|
||||
my_bool is_cert = 0;
|
||||
char* cert_end = strstr(p, "-----END");
|
||||
|
||||
if (!cert_end)
|
||||
{
|
||||
pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: Unknown or unsupported X509 PEM type"); goto error;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!(cert_end = strchr(cert_end, '\n')))
|
||||
goto error;
|
||||
|
||||
if ((type = strstr(p, "CERTIFICATE")) && type < cert_end)
|
||||
{
|
||||
is_cert = 1;
|
||||
/* We only read first certificate, further certificates will be ignored */
|
||||
if (ctx->client_cert_ctx)
|
||||
{
|
||||
p = cert_end;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if ((type = strstr(p, "PRIVATE KEY")) && type < cert_end)
|
||||
{
|
||||
/* We only read the first key, further keys will be ignored */
|
||||
if (ctx->der_key)
|
||||
{
|
||||
p = cert_end;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: Unknown or unsupported X509 PEM type");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!(der_buffer = ma_schannel_convert_base64(pvio, p, (DWORD)(cert_end - p), &der_buffer_length)))
|
||||
goto error;
|
||||
|
||||
if (is_cert)
|
||||
{
|
||||
if (!(ctx->client_cert_ctx = (CERT_CONTEXT*)CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
||||
der_buffer, der_buffer_length)))
|
||||
{
|
||||
ma_schannel_set_win_error(pvio);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(ctx->der_key= (struct st_DER *)malloc(sizeof(struct st_DER))))
|
||||
{
|
||||
pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: Not enough memory");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ctx->der_key->der_buffer = der_buffer;
|
||||
ctx->der_key->der_length = der_buffer_length;
|
||||
|
||||
der_buffer = 0;
|
||||
der_buffer_length = 0;
|
||||
p = cert_end;
|
||||
}
|
||||
|
||||
free(der_buffer);
|
||||
der_buffer = 0;
|
||||
der_buffer_length = 0;
|
||||
p = cert_end;
|
||||
|
||||
if (ctx->client_cert_ctx && ctx->der_key)
|
||||
break;
|
||||
}
|
||||
free(buffer);
|
||||
return 0;
|
||||
error:
|
||||
if (buffer)
|
||||
free(buffer);
|
||||
if (der_buffer)
|
||||
free(der_buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ma_delete_key_buffer(SC_CTX* ctx)
|
||||
{
|
||||
if (!ctx->der_key)
|
||||
return;
|
||||
free(ctx->der_key->der_buffer);
|
||||
free(ctx->der_key);
|
||||
ctx->der_key = 0;
|
||||
}
|
||||
|
||||
|
||||
/* {{{ CERT_CONTEXT *ma_schannel_create_cert_context(MARIADB_PVIO *pvio, const char *pem_file) */
|
||||
/*
|
||||
Create a certification context from ca or cert file
|
||||
@@ -281,7 +471,7 @@ PCCRL_CONTEXT ma_schannel_create_crl_context(MARIADB_PVIO *pvio, const char *pem
|
||||
ma_schannel_set_win_error(pvio);
|
||||
end:
|
||||
if (der_buffer)
|
||||
LocalFree(der_buffer);
|
||||
free(der_buffer);
|
||||
return ctx;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -306,10 +496,8 @@ end:
|
||||
PCCRL_CONTEXT A pointer to a certification context structure
|
||||
*/
|
||||
|
||||
my_bool ma_schannel_load_private_key(MARIADB_PVIO *pvio, const CERT_CONTEXT *ctx, char *key_file)
|
||||
my_bool ma_schannel_load_private_key(MARIADB_PVIO *pvio, SC_CTX *ctx)
|
||||
{
|
||||
DWORD der_buffer_len= 0;
|
||||
LPBYTE der_buffer= NULL;
|
||||
DWORD priv_key_len= 0;
|
||||
LPBYTE priv_key= NULL;
|
||||
HCRYPTPROV crypt_prov= 0;
|
||||
@@ -317,14 +505,16 @@ my_bool ma_schannel_load_private_key(MARIADB_PVIO *pvio, const CERT_CONTEXT *ctx
|
||||
CERT_KEY_CONTEXT kpi={ 0 };
|
||||
my_bool rc= 0;
|
||||
|
||||
/* load private key into der binary object */
|
||||
if (!(der_buffer= ma_schannel_load_pem(pvio, key_file, &der_buffer_len)))
|
||||
return 0;
|
||||
if (!ctx->der_key || !ctx->client_cert_ctx)
|
||||
{
|
||||
pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: Invalid certificate or key");
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* determine required buffer size for decoded private key */
|
||||
if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
||||
PKCS_RSA_PRIVATE_KEY,
|
||||
der_buffer, der_buffer_len,
|
||||
ctx->der_key->der_buffer, ctx->der_key->der_length,
|
||||
0, NULL,
|
||||
NULL, &priv_key_len))
|
||||
{
|
||||
@@ -333,18 +523,17 @@ my_bool ma_schannel_load_private_key(MARIADB_PVIO *pvio, const CERT_CONTEXT *ctx
|
||||
}
|
||||
|
||||
/* allocate buffer for decoded private key */
|
||||
if (!(priv_key= LocalAlloc(0, priv_key_len)))
|
||||
if (!(priv_key= malloc(priv_key_len)))
|
||||
{
|
||||
pvio->set_error(pvio->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, NULL);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* decode */
|
||||
if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
||||
PKCS_RSA_PRIVATE_KEY,
|
||||
der_buffer, der_buffer_len,
|
||||
0, NULL,
|
||||
priv_key, &priv_key_len))
|
||||
PKCS_RSA_PRIVATE_KEY,
|
||||
ctx->der_key->der_buffer, ctx->der_key->der_length,
|
||||
0, NULL,
|
||||
priv_key, &priv_key_len))
|
||||
{
|
||||
ma_schannel_set_win_error(pvio);
|
||||
goto end;
|
||||
@@ -368,19 +557,23 @@ my_bool ma_schannel_load_private_key(MARIADB_PVIO *pvio, const CERT_CONTEXT *ctx
|
||||
kpi.cbSize= sizeof(kpi);
|
||||
|
||||
/* assign private key to certificate context */
|
||||
if (CertSetCertificateContextProperty(ctx, CERT_KEY_CONTEXT_PROP_ID, 0, &kpi))
|
||||
if (CertSetCertificateContextProperty(ctx->client_cert_ctx, CERT_KEY_CONTEXT_PROP_ID, 0, &kpi))
|
||||
rc= 1;
|
||||
else
|
||||
ma_schannel_set_win_error(pvio);
|
||||
|
||||
end:
|
||||
if (der_buffer)
|
||||
LocalFree(der_buffer);
|
||||
if (ctx->der_key)
|
||||
{
|
||||
free(ctx->der_key->der_buffer);
|
||||
free(ctx->der_key);
|
||||
ctx->der_key = 0;
|
||||
}
|
||||
if (priv_key)
|
||||
{
|
||||
if (crypt_key)
|
||||
CryptDestroyKey(crypt_key);
|
||||
LocalFree(priv_key);
|
||||
free(priv_key);
|
||||
if (!rc)
|
||||
if (crypt_prov)
|
||||
CryptReleaseContext(crypt_prov, 0);
|
||||
|
@@ -46,9 +46,15 @@
|
||||
|
||||
#include <ma_pthread.h>
|
||||
|
||||
struct st_DER {
|
||||
char* der_buffer;
|
||||
DWORD der_length;
|
||||
};
|
||||
|
||||
struct st_schannel {
|
||||
HCERTSTORE cert_store;
|
||||
const CERT_CONTEXT *client_cert_ctx;
|
||||
struct st_DER *der_key;
|
||||
CredHandle CredHdl;
|
||||
my_bool FreeCredHdl;
|
||||
PUCHAR IoBuffer;
|
||||
@@ -70,8 +76,9 @@ extern my_bool ca_Check, crl_Check;
|
||||
CERT_CONTEXT *ma_schannel_create_cert_context(MARIADB_PVIO *pvio, const char *pem_file);
|
||||
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, const CERT_CONTEXT *ctx, char *key_file);
|
||||
my_bool ma_schannel_load_private_key(MARIADB_PVIO *pvio, SC_CTX *ctx);
|
||||
PCCRL_CONTEXT ma_schannel_create_crl_context(MARIADB_PVIO *pvio, const char *pem_file);
|
||||
void ma_delete_key_buffer(SC_CTX* ctx);
|
||||
my_bool ma_schannel_verify_certs(MARIADB_TLS *ctls);
|
||||
ssize_t ma_schannel_write_encrypt(MARIADB_PVIO *pvio,
|
||||
uchar *WriteBuffer,
|
||||
|
@@ -154,7 +154,6 @@ cipher_map[] =
|
||||
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", "DHE-RSA-AES256-GCM-SHA384",
|
||||
{ CALG_DH_EPHEM, CALG_AES_256, CALG_SHA_384, CALG_RSA_SIGN }
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#define MAX_ALG_ID 50
|
||||
@@ -206,6 +205,7 @@ static int ma_tls_set_client_certs(MARIADB_TLS *ctls)
|
||||
MARIADB_PVIO *pvio= ctls->pvio;
|
||||
|
||||
sctx->client_cert_ctx= NULL;
|
||||
sctx->der_key = NULL;
|
||||
|
||||
if (!certfile && keyfile)
|
||||
certfile= keyfile;
|
||||
@@ -215,15 +215,26 @@ static int ma_tls_set_client_certs(MARIADB_TLS *ctls)
|
||||
if (!certfile)
|
||||
return 0;
|
||||
|
||||
if (!(sctx->client_cert_ctx = ma_schannel_create_cert_context(ctls->pvio, certfile)))
|
||||
if (certfile && ma_schannel_load_certs_and_keys(pvio, certfile, sctx))
|
||||
return 1;
|
||||
|
||||
if (!ma_schannel_load_private_key(pvio, sctx->client_cert_ctx, keyfile))
|
||||
if (keyfile && ma_schannel_load_certs_and_keys(pvio, keyfile, sctx))
|
||||
return 1;
|
||||
|
||||
if (sctx->client_cert_ctx)
|
||||
{
|
||||
CertFreeCertificateContext(sctx->client_cert_ctx);
|
||||
sctx->client_cert_ctx= NULL;
|
||||
if (!ma_schannel_load_private_key(pvio, sctx))
|
||||
return 1;
|
||||
}
|
||||
else if (sctx->der_key)
|
||||
{
|
||||
free(sctx->der_key->der_buffer);
|
||||
free(sctx->der_key);
|
||||
sctx->der_key = 0;
|
||||
pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "SSL connection error: Cert not found");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -293,6 +304,9 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
|
||||
SC_CTX *sctx;
|
||||
SECURITY_STATUS sRet;
|
||||
ALG_ID AlgId[MAX_ALG_ID];
|
||||
size_t i;
|
||||
DWORD protocol = 0;
|
||||
|
||||
|
||||
if (!ctls || !ctls->pvio)
|
||||
return 1;;
|
||||
@@ -310,10 +324,8 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
|
||||
/* Set cipher */
|
||||
if (mysql->options.ssl_cipher)
|
||||
{
|
||||
size_t i;
|
||||
DWORD protocol = 0;
|
||||
|
||||
/* check if a protocol was specified as a cipher:
|
||||
/* check if a protocol was specified as a cipher:
|
||||
* In this case don't allow cipher suites which belong to newer protocols
|
||||
* Please note: There are no cipher suites for TLS1.1
|
||||
*/
|
||||
@@ -533,13 +545,15 @@ const char *ma_tls_get_cipher(MARIADB_TLS *ctls)
|
||||
SecPkgContext_CipherInfo CipherInfo = { SECPKGCONTEXT_CIPHERINFO_V1 };
|
||||
SECURITY_STATUS sRet;
|
||||
SC_CTX *sctx;
|
||||
SecPkgContext_ConnectionInfo ci;
|
||||
|
||||
if (!ctls || !ctls->ssl)
|
||||
return NULL;
|
||||
|
||||
sctx= (SC_CTX *)ctls->ssl;
|
||||
sRet = QueryContextAttributesA(&sctx->ctxt, SECPKG_ATTR_CONNECTION_INFO, (PVOID)&ci);
|
||||
sRet= QueryContextAttributesA(&sctx->ctxt, SECPKG_ATTR_CIPHER_INFO, (PVOID)&CipherInfo);
|
||||
|
||||
sRet= QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_CIPHER_INFO, (PVOID)&CipherInfo);
|
||||
if (sRet != SEC_E_OK)
|
||||
return NULL;
|
||||
|
||||
|
@@ -16,6 +16,11 @@
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
||||
*************************************************************************************/
|
||||
#if defined(WIN32) && defined(HEAP_CHECK)
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
#include "my_test.h"
|
||||
#include <ma_pthread.h>
|
||||
@@ -34,6 +39,7 @@ const char *ssluser= "ssluser";
|
||||
const char *sslpw= "sslpw";
|
||||
char sslhost[128];
|
||||
char sslcert[FNLEN];
|
||||
char sslcombined[FNLEN];
|
||||
char sslkey[FNLEN];
|
||||
char sslkey_enc[FNLEN];
|
||||
char sslca[FNLEN];
|
||||
@@ -63,6 +69,7 @@ int check_skip_ssl()
|
||||
}
|
||||
}
|
||||
snprintf(sslcert, FNLEN - 1, "%s/%s", ssldir, "client-cert.pem");
|
||||
snprintf(sslcombined, FNLEN - 1, "%s/%s", ssldir, "client-certkey.pem");
|
||||
snprintf(sslkey, FNLEN - 1, "%s/%s", ssldir, "client-key.pem");
|
||||
snprintf(sslkey_enc, FNLEN - 1, "%s/%s", ssldir, "client-key-enc.pem");
|
||||
snprintf(sslca, FNLEN - 1, "%s/%s", ssldir, "cacert.pem");
|
||||
@@ -1287,6 +1294,33 @@ static int test_mdev14101(MYSQL *my __attribute__((unused)))
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int test_conc386(MYSQL *mysql)
|
||||
{
|
||||
#ifdef WIN32
|
||||
if (_access(sslcombined, 0) == -1)
|
||||
#else
|
||||
if (access(sslcombined, R_OK) != 0)
|
||||
#endif
|
||||
{
|
||||
diag("combined cert/key file not found");
|
||||
return SKIP;
|
||||
}
|
||||
|
||||
mysql= mysql_init(NULL);
|
||||
mysql_ssl_set(mysql,
|
||||
sslcombined,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema,
|
||||
port, socketname, 0), mysql_error(mysql));
|
||||
FAIL_IF(check_cipher(mysql) != 0, "Invalid cipher");
|
||||
mysql_close(mysql);
|
||||
unlink(sslcombined);
|
||||
return OK;
|
||||
}
|
||||
|
||||
struct my_tests_st my_tests[] = {
|
||||
{"test_ssl", test_ssl, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
{"test_mdev14101", test_mdev14101, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
@@ -1323,6 +1357,8 @@ struct my_tests_st my_tests[] = {
|
||||
#else
|
||||
{"test_schannel_cipher", test_schannel_cipher, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
#endif
|
||||
|
||||
{"test_conc386", test_conc386, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
{"drop_ssl_user", drop_ssl_user, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
{NULL, NULL, 0, 0, NULL, NULL}
|
||||
};
|
||||
@@ -1330,6 +1366,15 @@ struct my_tests_st my_tests[] = {
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#if defined(WIN32) && defined(HEAP_CHECK)
|
||||
_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
|
||||
_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
|
||||
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
|
||||
_CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
|
||||
_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
|
||||
_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
|
||||
#endif
|
||||
|
||||
get_envvars();
|
||||
|
||||
if (argc > 1)
|
||||
@@ -1337,6 +1382,9 @@ int main(int argc, char **argv)
|
||||
run_tests(my_tests);
|
||||
|
||||
mysql_server_end();
|
||||
#if defined(WIN32) && defined(HEAP_CHECK)
|
||||
_CrtDumpMemoryLeaks();
|
||||
#endif
|
||||
return(exit_status());
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user