Skip to content

Commit 968b5f0

Browse files
committed
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).
1 parent 39f2e12 commit 968b5f0

File tree

7 files changed

+118
-36
lines changed

7 files changed

+118
-36
lines changed

libmariadb/ma_tls.c

+27-1
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,33 @@ int ma_pvio_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int flags)
118118
getenv("MARIADB_TLS_DISABLE_PEER_VERIFICATION")) &&
119119
(!mysql->options.extension->tls_fp && !mysql->options.extension->tls_fp_list))
120120
{
121+
/* Since OpenSSL implementation sets status during TLS handshake
122+
we need to clear verification status */
123+
mysql->net.tls_verify_status= 0;
121124
return 0;
122125
}
123126

127+
if (flags & MARIADB_TLS_VERIFY_FINGERPRINT)
128+
{
129+
if (ma_pvio_tls_check_fp(ctls, mysql->options.extension->tls_fp, mysql->options.extension->tls_fp_list))
130+
{
131+
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_FINGERPRINT;
132+
mysql->extension->tls_validation= mysql->net.tls_verify_status;
133+
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
134+
ER(CR_SSL_CONNECTION_ERROR),
135+
"Fingerprint validation of peer certificate failed");
136+
return 1;
137+
}
138+
#ifdef HAVE_OPENSSL
139+
/* verification already happened via callback */
140+
if (!(mysql->net.tls_verify_status & flags))
141+
{
142+
mysql->extension->tls_validation= mysql->net.tls_verify_status;
143+
mysql->net.tls_verify_status= MARIADB_TLS_VERIFY_OK;
144+
return 0;
145+
}
146+
#endif
147+
}
124148
rc= ma_tls_verify_server_cert(ctls, flags);
125149

126150
/* Set error messages */
@@ -151,7 +175,9 @@ int ma_pvio_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int flags)
151175
ER(CR_SSL_CONNECTION_ERROR),
152176
"Peer certificate is not trusted");
153177
}
154-
178+
/* Save original validation, since we might unset trust flag in
179+
my_auth */
180+
mysql->extension->tls_validation= mysql->net.tls_verify_status;
155181
return rc;
156182
}
157183

libmariadb/secure/gnutls.c

-9
Original file line numberDiff line numberDiff line change
@@ -1445,15 +1445,6 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int flags)
14451445

14461446
CLEAR_CLIENT_ERROR(mysql);
14471447

1448-
if (flags & MARIADB_TLS_VERIFY_FINGERPRINT)
1449-
{
1450-
if (ma_pvio_tls_check_fp(ctls, mysql->options.extension->tls_fp, mysql->options.extension->tls_fp_list))
1451-
{
1452-
mysql->net.tls_verify_status= MARIADB_TLS_VERIFY_FINGERPRINT;
1453-
goto end;
1454-
}
1455-
}
1456-
14571448
if (gnutls_certificate_verify_peers2(ssl, &status))
14581449
return GNUTLS_E_CERTIFICATE_ERROR;
14591450

libmariadb/secure/openssl.c

+1-13
Original file line numberDiff line numberDiff line change
@@ -786,19 +786,7 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int verify_flags)
786786
if ((mysql->net.tls_verify_status > MARIADB_TLS_VERIFY_FINGERPRINT) ||
787787
(mysql->net.tls_verify_status & verify_flags))
788788
{
789-
return 1;
790-
}
791-
792-
if (verify_flags & MARIADB_TLS_VERIFY_FINGERPRINT)
793-
{
794-
if (ma_pvio_tls_check_fp(ctls, mysql->options.extension->tls_fp, mysql->options.extension->tls_fp_list))
795-
{
796-
mysql->net.tls_verify_status |= MARIADB_TLS_VERIFY_FINGERPRINT;
797-
return 1;
798-
}
799-
800-
mysql->net.tls_verify_status= MARIADB_TLS_VERIFY_OK;
801-
return 0;
789+
return MARIADB_TLS_VERIFY_ERROR;
802790
}
803791

804792
if (verify_flags & MARIADB_TLS_VERIFY_HOST)

libmariadb/secure/schannel.c

-9
Original file line numberDiff line numberDiff line change
@@ -719,15 +719,6 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int verify_flags)
719719
return 1;
720720
}
721721
}
722-
723-
if (verify_flags & MARIADB_TLS_VERIFY_FINGERPRINT)
724-
{
725-
if (ma_pvio_tls_check_fp(ctls, mysql->options.extension->tls_fp, mysql->options.extension->tls_fp_list))
726-
{
727-
mysql->net.tls_verify_status |= MARIADB_TLS_VERIFY_FINGERPRINT;
728-
return 1;
729-
}
730-
}
731722
return ma_schannel_verify_certs(ctls, verify_flags);
732723
}
733724

plugins/auth/my_auth.c

-4
Original file line numberDiff line numberDiff line change
@@ -435,8 +435,6 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
435435

436436
if (mysql->options.extension->tls_verification_callback(mysql->net.pvio->ctls, verify_flags))
437437
{
438-
/* Save original verification result */
439-
mysql->extension->tls_validation= mysql->net.tls_verify_status;
440438
if (mysql->net.tls_verify_status > MARIADB_TLS_VERIFY_TRUST ||
441439
(mysql->options.ssl_ca || mysql->options.ssl_capath))
442440
goto error;
@@ -449,8 +447,6 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
449447
else if (!password_and_hashing(mysql, mpvio->plugin))
450448
goto error;
451449
}
452-
else
453-
mysql->extension->tls_validation= mysql->net.tls_verify_status;
454450
}
455451
#endif /* HAVE_TLS */
456452

unittest/libmariadb/CMakeLists.txt

+9
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@ ENDIF()
6060
ADD_LIBRARY(ma_getopt ma_getopt.c)
6161

6262
IF(${Python3_FOUND})
63+
execute_process(COMMAND ${Python3_EXECUTABLE} -m pip show pyopenssl
64+
RESULT_VARIABLE EXIT_CODE
65+
OUTPUT_QUIET)
66+
if (${EXIT_CODE} EQUAL 0)
67+
SET(RUN_TLS 1)
68+
endif()
69+
ENDIF()
70+
71+
IF(${RUN_TLS})
6372
CONFIGURE_FILE(${CC_SOURCE_DIR}/unittest/libmariadb/tls.c.in
6473
${CC_BINARY_DIR}/unittest/libmariadb/tls.c)
6574

unittest/libmariadb/tls.c.in

+81
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,9 @@ static int test_cert_wildcard(MYSQL *my __attribute((unused)))
672672
if (!my_test_connect(mysql, tls_dummy_host, "tlsuser", "foo", NULL, tls_dummy_port, NULL, 0, 0))
673673
{
674674
CHECK_NO_TLS_FLAG(mysql, MARIADB_TLS_VERIFY_HOST, "Hostname verification didn't pass");
675+
#ifndef HAVE_SCHANNEL
675676
CHECK_TLS_FLAGS(mysql, MARIADB_TLS_VERIFY_TRUST, "Self signed certificate expected");
677+
#endif
676678
mysql_close(mysql);
677679
} else {
678680
mysql_close(mysql);
@@ -699,12 +701,91 @@ static int test_cert_wildcard(MYSQL *my __attribute((unused)))
699701
return OK;
700702
}
701703

704+
static int test_env_var(MYSQL *my __attribute__((unused)))
705+
{
706+
MYSQL *mysql= mysql_init(NULL);
707+
int rc= FAIL;
708+
unsigned int status;
709+
710+
#ifdef _WIN32
711+
_putenv_s("MARIADB_TLS_DISABLE_PEER_VERIFICATION", "1");
712+
#else
713+
setenv("MARIADB_TLS_DISABLE_PEER_VERIFICATION", "1", 1);
714+
#endif
715+
716+
if (!my_test_connect(mysql, hostname, username, password, schema,
717+
port, socketname, 0, 0))
718+
{
719+
diag("expected to pass, since environment variable was set");
720+
goto end;
721+
}
722+
723+
mariadb_get_infov(mysql, MARIADB_TLS_VERIFY_STATUS, &status);
724+
725+
if (status)
726+
{
727+
diag("expected status=0, since environment variable was set");
728+
goto end;
729+
}
730+
731+
rc= OK;
732+
733+
end:
734+
#ifdef _WIN32
735+
_putenv_s("MARIADB_TLS_DISABLE_PEER_VERIFICATION", "");
736+
#else
737+
unsetenv("MARIADB_TLS_DISABLE_PEER_VERIFICATION");
738+
#endif
739+
mysql_close(mysql);
740+
return rc;
741+
}
742+
743+
static int test_fp_and_verify(MYSQL *my __attribute__((unused)))
744+
{
745+
MYSQL *mysql= mysql_init(NULL);
746+
int rc= FAIL;
747+
#ifndef HAVE_SCHANNEL
748+
unsigned int status;
749+
#endif
750+
my_bool verify= 1;
751+
752+
mysql_options(mysql, MARIADB_OPT_SSL_FP, fingerprint);
753+
mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify);
754+
755+
if (!my_test_connect(mysql, hostname, username, password, schema,
756+
port, socketname, 0, 0))
757+
{
758+
diag("expected to pass, since fingerprint was specified");
759+
diag("error: %s", mysql_error(mysql));
760+
goto end;
761+
}
762+
763+
/* Schannel aborts on first error, if fingerprint was specified,
764+
MARIADB_TLS_VERIFY_TRUST is unset */
765+
#ifndef HAVE_SCHANNEL
766+
mariadb_get_infov(mysql, MARIADB_TLS_VERIFY_STATUS, &status);
767+
768+
if (!status)
769+
{
770+
diag("expected status flag set (self signed)");
771+
goto end;
772+
}
773+
#endif
774+
rc= OK;
775+
776+
end:
777+
mysql_close(mysql);
778+
return rc;
779+
}
780+
702781

703782
struct my_tests_st my_tests[] = {
704783
/* Don't add test above, test_init needs to be run first */
705784
{"test_start_tls_server", test_start_tls_server, TEST_CONNECTION_NONE, 0, NULL, NULL},
706785
{"test_init", test_init, TEST_CONNECTION_NONE, 0, NULL, NULL},
707786
/* Here you can add more tests */
787+
{"test_fp_and_verify", test_fp_and_verify, TEST_CONNECTION_NEW, 0, NULL, NULL},
788+
{"test_env_var", test_env_var, TEST_CONNECTION_NEW, 0, NULL, NULL},
708789
{"test_cert_wildcard", test_cert_wildcard, TEST_CONNECTION_NEW, 0, NULL, NULL},
709790
{"test_cert_expired", test_cert_expired, TEST_CONNECTION_NEW, 0, NULL, NULL},
710791
{"test_pw_check", test_pw_check, TEST_CONNECTION_NEW, 0, NULL, NULL},

0 commit comments

Comments
 (0)