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-731: wrong error message (incorrect fp)

- moved fingerprint verification to ma_tls.c
- don't verify cert again if fingerprint check
  succeeded.
- Disable self signed check in fingerprint tests
  (Schannel only).
This commit is contained in:
Georg Richter
2024-09-24 12:08:42 +02:00
parent 39f2e12f9a
commit 968b5f0aa2
7 changed files with 118 additions and 36 deletions

View File

@@ -118,9 +118,33 @@ int ma_pvio_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int flags)
getenv("MARIADB_TLS_DISABLE_PEER_VERIFICATION")) && getenv("MARIADB_TLS_DISABLE_PEER_VERIFICATION")) &&
(!mysql->options.extension->tls_fp && !mysql->options.extension->tls_fp_list)) (!mysql->options.extension->tls_fp && !mysql->options.extension->tls_fp_list))
{ {
/* Since OpenSSL implementation sets status during TLS handshake
we need to clear verification status */
mysql->net.tls_verify_status= 0;
return 0; return 0;
} }
if (flags & MARIADB_TLS_VERIFY_FINGERPRINT)
{
if (ma_pvio_tls_check_fp(ctls, mysql->options.extension->tls_fp, mysql->options.extension->tls_fp_list))
{
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_FINGERPRINT;
mysql->extension->tls_validation= mysql->net.tls_verify_status;
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Fingerprint validation of peer certificate failed");
return 1;
}
#ifdef HAVE_OPENSSL
/* verification already happened via callback */
if (!(mysql->net.tls_verify_status & flags))
{
mysql->extension->tls_validation= mysql->net.tls_verify_status;
mysql->net.tls_verify_status= MARIADB_TLS_VERIFY_OK;
return 0;
}
#endif
}
rc= ma_tls_verify_server_cert(ctls, flags); rc= ma_tls_verify_server_cert(ctls, flags);
/* Set error messages */ /* Set error messages */
@@ -151,7 +175,9 @@ int ma_pvio_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int flags)
ER(CR_SSL_CONNECTION_ERROR), ER(CR_SSL_CONNECTION_ERROR),
"Peer certificate is not trusted"); "Peer certificate is not trusted");
} }
/* Save original validation, since we might unset trust flag in
my_auth */
mysql->extension->tls_validation= mysql->net.tls_verify_status;
return rc; return rc;
} }

View File

@@ -1445,15 +1445,6 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int flags)
CLEAR_CLIENT_ERROR(mysql); CLEAR_CLIENT_ERROR(mysql);
if (flags & MARIADB_TLS_VERIFY_FINGERPRINT)
{
if (ma_pvio_tls_check_fp(ctls, mysql->options.extension->tls_fp, mysql->options.extension->tls_fp_list))
{
mysql->net.tls_verify_status= MARIADB_TLS_VERIFY_FINGERPRINT;
goto end;
}
}
if (gnutls_certificate_verify_peers2(ssl, &status)) if (gnutls_certificate_verify_peers2(ssl, &status))
return GNUTLS_E_CERTIFICATE_ERROR; return GNUTLS_E_CERTIFICATE_ERROR;

View File

@@ -786,19 +786,7 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int verify_flags)
if ((mysql->net.tls_verify_status > MARIADB_TLS_VERIFY_FINGERPRINT) || if ((mysql->net.tls_verify_status > MARIADB_TLS_VERIFY_FINGERPRINT) ||
(mysql->net.tls_verify_status & verify_flags)) (mysql->net.tls_verify_status & verify_flags))
{ {
return 1; return MARIADB_TLS_VERIFY_ERROR;
}
if (verify_flags & MARIADB_TLS_VERIFY_FINGERPRINT)
{
if (ma_pvio_tls_check_fp(ctls, mysql->options.extension->tls_fp, mysql->options.extension->tls_fp_list))
{
mysql->net.tls_verify_status |= MARIADB_TLS_VERIFY_FINGERPRINT;
return 1;
}
mysql->net.tls_verify_status= MARIADB_TLS_VERIFY_OK;
return 0;
} }
if (verify_flags & MARIADB_TLS_VERIFY_HOST) if (verify_flags & MARIADB_TLS_VERIFY_HOST)

View File

@@ -719,15 +719,6 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int verify_flags)
return 1; return 1;
} }
} }
if (verify_flags & MARIADB_TLS_VERIFY_FINGERPRINT)
{
if (ma_pvio_tls_check_fp(ctls, mysql->options.extension->tls_fp, mysql->options.extension->tls_fp_list))
{
mysql->net.tls_verify_status |= MARIADB_TLS_VERIFY_FINGERPRINT;
return 1;
}
}
return ma_schannel_verify_certs(ctls, verify_flags); return ma_schannel_verify_certs(ctls, verify_flags);
} }

View File

@@ -435,8 +435,6 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
if (mysql->options.extension->tls_verification_callback(mysql->net.pvio->ctls, verify_flags)) if (mysql->options.extension->tls_verification_callback(mysql->net.pvio->ctls, verify_flags))
{ {
/* Save original verification result */
mysql->extension->tls_validation= mysql->net.tls_verify_status;
if (mysql->net.tls_verify_status > MARIADB_TLS_VERIFY_TRUST || if (mysql->net.tls_verify_status > MARIADB_TLS_VERIFY_TRUST ||
(mysql->options.ssl_ca || mysql->options.ssl_capath)) (mysql->options.ssl_ca || mysql->options.ssl_capath))
goto error; goto error;
@@ -449,8 +447,6 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
else if (!password_and_hashing(mysql, mpvio->plugin)) else if (!password_and_hashing(mysql, mpvio->plugin))
goto error; goto error;
} }
else
mysql->extension->tls_validation= mysql->net.tls_verify_status;
} }
#endif /* HAVE_TLS */ #endif /* HAVE_TLS */

View File

@@ -60,6 +60,15 @@ ENDIF()
ADD_LIBRARY(ma_getopt ma_getopt.c) ADD_LIBRARY(ma_getopt ma_getopt.c)
IF(${Python3_FOUND}) IF(${Python3_FOUND})
execute_process(COMMAND ${Python3_EXECUTABLE} -m pip show pyopenssl
RESULT_VARIABLE EXIT_CODE
OUTPUT_QUIET)
if (${EXIT_CODE} EQUAL 0)
SET(RUN_TLS 1)
endif()
ENDIF()
IF(${RUN_TLS})
CONFIGURE_FILE(${CC_SOURCE_DIR}/unittest/libmariadb/tls.c.in CONFIGURE_FILE(${CC_SOURCE_DIR}/unittest/libmariadb/tls.c.in
${CC_BINARY_DIR}/unittest/libmariadb/tls.c) ${CC_BINARY_DIR}/unittest/libmariadb/tls.c)

View File

@@ -672,7 +672,9 @@ static int test_cert_wildcard(MYSQL *my __attribute((unused)))
if (!my_test_connect(mysql, tls_dummy_host, "tlsuser", "foo", NULL, tls_dummy_port, NULL, 0, 0)) if (!my_test_connect(mysql, tls_dummy_host, "tlsuser", "foo", NULL, tls_dummy_port, NULL, 0, 0))
{ {
CHECK_NO_TLS_FLAG(mysql, MARIADB_TLS_VERIFY_HOST, "Hostname verification didn't pass"); CHECK_NO_TLS_FLAG(mysql, MARIADB_TLS_VERIFY_HOST, "Hostname verification didn't pass");
#ifndef HAVE_SCHANNEL
CHECK_TLS_FLAGS(mysql, MARIADB_TLS_VERIFY_TRUST, "Self signed certificate expected"); CHECK_TLS_FLAGS(mysql, MARIADB_TLS_VERIFY_TRUST, "Self signed certificate expected");
#endif
mysql_close(mysql); mysql_close(mysql);
} else { } else {
mysql_close(mysql); mysql_close(mysql);
@@ -699,12 +701,91 @@ static int test_cert_wildcard(MYSQL *my __attribute((unused)))
return OK; return OK;
} }
static int test_env_var(MYSQL *my __attribute__((unused)))
{
MYSQL *mysql= mysql_init(NULL);
int rc= FAIL;
unsigned int status;
#ifdef _WIN32
_putenv_s("MARIADB_TLS_DISABLE_PEER_VERIFICATION", "1");
#else
setenv("MARIADB_TLS_DISABLE_PEER_VERIFICATION", "1", 1);
#endif
if (!my_test_connect(mysql, hostname, username, password, schema,
port, socketname, 0, 0))
{
diag("expected to pass, since environment variable was set");
goto end;
}
mariadb_get_infov(mysql, MARIADB_TLS_VERIFY_STATUS, &status);
if (status)
{
diag("expected status=0, since environment variable was set");
goto end;
}
rc= OK;
end:
#ifdef _WIN32
_putenv_s("MARIADB_TLS_DISABLE_PEER_VERIFICATION", "");
#else
unsetenv("MARIADB_TLS_DISABLE_PEER_VERIFICATION");
#endif
mysql_close(mysql);
return rc;
}
static int test_fp_and_verify(MYSQL *my __attribute__((unused)))
{
MYSQL *mysql= mysql_init(NULL);
int rc= FAIL;
#ifndef HAVE_SCHANNEL
unsigned int status;
#endif
my_bool verify= 1;
mysql_options(mysql, MARIADB_OPT_SSL_FP, fingerprint);
mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify);
if (!my_test_connect(mysql, hostname, username, password, schema,
port, socketname, 0, 0))
{
diag("expected to pass, since fingerprint was specified");
diag("error: %s", mysql_error(mysql));
goto end;
}
/* Schannel aborts on first error, if fingerprint was specified,
MARIADB_TLS_VERIFY_TRUST is unset */
#ifndef HAVE_SCHANNEL
mariadb_get_infov(mysql, MARIADB_TLS_VERIFY_STATUS, &status);
if (!status)
{
diag("expected status flag set (self signed)");
goto end;
}
#endif
rc= OK;
end:
mysql_close(mysql);
return rc;
}
struct my_tests_st my_tests[] = { struct my_tests_st my_tests[] = {
/* Don't add test above, test_init needs to be run first */ /* Don't add test above, test_init needs to be run first */
{"test_start_tls_server", test_start_tls_server, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"test_start_tls_server", test_start_tls_server, TEST_CONNECTION_NONE, 0, NULL, NULL},
{"test_init", test_init, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"test_init", test_init, TEST_CONNECTION_NONE, 0, NULL, NULL},
/* Here you can add more tests */ /* Here you can add more tests */
{"test_fp_and_verify", test_fp_and_verify, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_env_var", test_env_var, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_cert_wildcard", test_cert_wildcard, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_cert_wildcard", test_cert_wildcard, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_cert_expired", test_cert_expired, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_cert_expired", test_cert_expired, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_pw_check", test_pw_check, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_pw_check", test_pw_check, TEST_CONNECTION_NEW, 0, NULL, NULL},