Skip to content

Commit 18b3dc2

Browse files
committed
WL#15239: Add webauthn_test to use for manual testing.
1 parent c3ca11a commit 18b3dc2

File tree

2 files changed

+179
-131
lines changed

2 files changed

+179
-131
lines changed

jdbc/test/unit/classes/connection.cpp

Lines changed: 174 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -3962,6 +3962,29 @@ void connection::tls_deprecation()
39623962

39633963
}
39643964

3965+
3966+
/*
3967+
Testing FIDO/WebAuthn connection and callback functionality.
3968+
3969+
These tests are designed for manual run. They require the following preparation steps:
3970+
3971+
1. Install FIDO auth plugin on the server:
3972+
3973+
INSTALL PLUGIN authentication_fido SONAME 'authentication_fido.so'
3974+
3975+
2. Create user with FIDO/Webauthn authentication:
3976+
3977+
CREATE USER 'u2'@'localhost'
3978+
IDENTIFIED WITH caching_sha2_password BY 'sha2_password'
3979+
AND IDENTIFIED WITH authentication_webauthn
3980+
3981+
3. Register FIDO:
3982+
3983+
mysql --port=13000 --protocol=tcp --user=u2 --password1 --fido-register-factor=2
3984+
3985+
4. Set env variable MYSQL_FIDO to non-empty value
3986+
*/
3987+
39653988
/* Variable value will be changed by callbacks */
39663989
int callback_variable = -1;
39673990

@@ -3971,171 +3994,131 @@ void my_callback(sql::SQLString s)
39713994
callback_variable = 1;
39723995
}
39733996

3974-
/**
3975-
* Testing FIDO connection and callback functionality.
3976-
*
3977-
* The test is designed for manual run.
3978-
* It requires the following preparation steps:
3979-
*
3980-
* 1. Install FIDO auth plugin on the server:
3981-
* INSTALL PLUGIN authentication_fido SONAME 'authentication_fido.so'
3982-
*
3983-
* 2. Create user with FIDO authentication:
3984-
* CREATE USER 'u2'@'localhost' IDENTIFIED WITH caching_sha2_password
3985-
* BY 'sha2_password' AND IDENTIFIED WITH authentication_fido
3986-
*
3987-
* 3. Register FIDO:
3988-
* mysql --port=13000 --protocol=tcp --user=u2 --password1
3989-
* --fido-register-factor=2
3990-
*
3991-
* 4. Set env variable MYSQL_FIDO to non-empty value
3992-
*/
3993-
void connection::fido_test()
3997+
class MyWindowFido : public sql::Fido_Callback
39943998
{
3995-
if(!getenv("MYSQL_FIDO"))
3996-
return;
3999+
public:
39974000

3998-
class MyWindow : public sql::Fido_Callback
4001+
virtual void FidoActionRequested(sql::SQLString msg) override
39994002
{
4000-
public:
4003+
std::cout << "Method Override (3): " << msg << std::endl;
4004+
callback_variable = 3;
4005+
}
4006+
};
40014007

4002-
virtual void FidoActionRequested(sql::SQLString msg) override
4003-
{
4004-
std::cout << "Method Override (3): " << msg << std::endl;
4005-
callback_variable = 3;
4006-
}
4008+
class MyWindowWebAuthn : public sql::WebAuthn_Callback
4009+
{
4010+
public:
4011+
4012+
virtual void ActionRequested(sql::SQLString msg) override
4013+
{
4014+
std::cout << "Method Override (3): " << msg << std::endl;
4015+
callback_variable = 3;
4016+
}
4017+
};
4018+
4019+
4020+
/*
4021+
Note: If `callback_ignored` parameter is set to true then we are testing
4022+
scenario where registered callback should not be called. In this case only
4023+
this simple scenario is tested.
4024+
*/
4025+
4026+
template <class CB, class MY>
4027+
void connection::test_fido_webauthn(bool callback_ignored)
4028+
{
4029+
using std::string;
4030+
using std::cout;
4031+
using std::endl;
4032+
4033+
String fido_user = "u2";
4034+
String fido_pwd = "sha2_password";
4035+
4036+
sql::ConnectOptionsMap opt;
4037+
opt[OPT_HOSTNAME] = url;
4038+
opt[OPT_USERNAME] = fido_user;
4039+
opt[OPT_PASSWORD] = fido_pwd;
4040+
4041+
sql::Driver * driver = sql::mysql::get_driver_instance();
4042+
4043+
auto test_connection_drv = [&opt](int expected, sql::Driver *drv)
4044+
{
4045+
callback_variable = 0;
4046+
cout << "Before connect: " << callback_variable << endl;
4047+
Connection fido_connection(drv->connect(opt));
4048+
cout << "After connect: " << callback_variable << endl;
4049+
ASSERT_EQUALS(expected, callback_variable);
40074050
};
40084051

4009-
std::string fido_user = "u2";
4010-
std::string fido_pwd = "sha2_password";
4052+
auto test_connection = [test_connection_drv, driver](int expected)
4053+
{
4054+
test_connection_drv(expected, driver);
4055+
};
40114056

40124057
try
40134058
{
4014-
sql::ConnectOptionsMap opt;
4015-
opt[OPT_HOSTNAME] = url;
4016-
opt[OPT_USERNAME] = fido_user;
4017-
opt[OPT_PASSWORD] = fido_pwd;
40184059

4019-
/* No callback */
4020-
{
4021-
callback_variable = 0;
4022-
sql::Driver * driver = sql::mysql::get_driver_instance();
4023-
std::cout << "\nBefore connect: " << callback_variable << std::endl;
4024-
std::cout << "Default callback (0): ";
4025-
Connection fido_connection(driver->connect(opt));
4026-
std::cout << "After connect: " << callback_variable << std::endl;
4027-
ASSERT_EQUALS(0, callback_variable);
4028-
}
40294060

4030-
/* Callback Function */
4031-
{
4032-
sql::Driver * driver = sql::mysql::get_driver_instance();
4033-
driver->setCallBack(sql::Fido_Callback(my_callback));
4061+
cout << endl << "Default callback (0)" << endl;
4062+
test_connection(0);
40344063

4035-
std::cout << "\nBefore connect: " << callback_variable << std::endl;
4036-
Connection fido_connection(driver->connect(opt));
4037-
std::cout << "After connect: " << callback_variable << std::endl;
4038-
ASSERT_EQUALS(1, callback_variable);
4039-
}
4064+
cout << endl << "Callback Function (1)" << endl;
4065+
driver->setCallBack(CB{my_callback});
4066+
test_connection(callback_ignored ? 0 : 1);
40404067

4041-
/* Callback Lambda */
4042-
{
4043-
sql::Driver * driver = sql::mysql::get_driver_instance();
4044-
driver->setCallBack(sql::Fido_Callback([](sql::SQLString msg) {
4045-
std::cout << "Callback Lambda (2): " << msg << std::endl;
4046-
callback_variable = 2;
4047-
}));
4068+
if(callback_ignored)
4069+
return;
40484070

4049-
std::cout << "\nBefore connect: " << callback_variable << std::endl;
4050-
Connection fido_connection(driver->connect(opt));
4051-
std::cout << "After connect: " << callback_variable << std::endl;
4052-
ASSERT_EQUALS(2, callback_variable);
4053-
}
4071+
cout << endl << "Callback Lambda (2)" << endl;
4072+
driver->setCallBack(CB{[](sql::SQLString msg) {
4073+
std::cout << "Callback Lambda (2): " << msg << std::endl;
4074+
callback_variable = 2;
4075+
}});
4076+
test_connection(2);
40544077

4055-
/* Callback class */
4078+
cout << endl << "Callback Class (3)" << endl;
40564079
{
4057-
MyWindow window;
4080+
MY window;
40584081

40594082
sql::Driver * driver = sql::mysql::get_driver_instance();
40604083
driver->setCallBack(window);
4084+
test_connection(3);
4085+
}
40614086

4062-
std::cout << "\nBefore connect: " << callback_variable << std::endl;
4063-
Connection fido_connection(driver->connect(opt));
4064-
std::cout << "After connect: " << callback_variable << std::endl;
4065-
ASSERT_EQUALS(3, callback_variable);
4087+
cout << endl << "Reset callback (0)" << endl;
4088+
driver->setCallBack(CB{nullptr});
4089+
test_connection(0);
40664090

4067-
// Reset callback
4068-
callback_variable = 0;
4069-
driver->setCallBack(sql::Fido_Callback(nullptr));
4070-
std::cout << "\nBefore connect: " << callback_variable << std::endl;
4071-
std::cout << "Default callback (0): ";
4072-
Connection fido_connection2(driver->connect(opt));
4073-
std::cout << "After connect: " << callback_variable << std::endl;
4074-
ASSERT_EQUALS(0, callback_variable);
4075-
}
40764091

4077-
/* Multi driver tests */
4078-
std::cout << "\nMulti driver tests: " << std::endl;
4092+
cout << endl << "Multi driver tests: " << endl;
4093+
4094+
auto multi_drv_test = [test_connection_drv]()
40794095
{
40804096
sql::Driver * driver1 = sql::mysql::get_driver_instance_by_name("drv1");
4081-
driver1->setCallBack(sql::Fido_Callback([](sql::SQLString msg) {
4082-
std::cout << "Driver 1 Callback : " << msg << std::endl;
4097+
driver1->setCallBack(CB{[](sql::SQLString msg) {
4098+
cout << "Driver 1 Callback : " << msg << endl;
40834099
callback_variable = 111;
4084-
}));
4100+
}});
40854101

40864102
sql::Driver * driver2 = sql::mysql::get_driver_instance_by_name("drv2");
4087-
driver2->setCallBack(sql::Fido_Callback([](sql::SQLString msg) {
4088-
std::cout << "Driver 2 Callback : " << msg << std::endl;
4103+
driver2->setCallBack(CB{[](sql::SQLString msg) {
4104+
cout << "Driver 2 Callback : " << msg << endl;
40894105
callback_variable = 222;
4090-
}));
4106+
}});
40914107

4092-
for (int i = 0; i < 2; ++i)
4093-
{
4094-
std::cout << "\nBefore connect: " << callback_variable << std::endl;
4095-
Connection c1(driver1->connect(opt));
4096-
std::cout << "After connect: " << callback_variable << std::endl;
4097-
ASSERT_EQUALS(111, callback_variable);
4108+
test_connection_drv(111, driver1);
4109+
test_connection_drv(222, driver2);
4110+
};
40984111

4099-
std::cout << "\nBefore connect: " << callback_variable << std::endl;
4100-
Connection c2(driver2->connect(opt));
4101-
std::cout << "After connect: " << callback_variable << std::endl;
4102-
ASSERT_EQUALS(222, callback_variable);
4103-
}
4104-
}
4112+
multi_drv_test();
4113+
4114+
cout << endl << "Multithread driver tests: " << endl;
41054115

4106-
/* Multithread driver tests */
4107-
std::cout << "Multithread driver tests: " << std::endl;
41084116
{
41094117
std::vector<std::thread> workers;
41104118

4111-
auto worker_func = [&opt]() {
4112-
sql::Driver * driver1 = sql::mysql::get_driver_instance_by_name("drv1");
4113-
driver1->setCallBack(sql::Fido_Callback([](sql::SQLString msg) {
4114-
std::cout << "Driver 1 Thread Callback : " << msg << std::endl;
4115-
callback_variable = 1001;
4116-
}));
4117-
4118-
sql::Driver * driver2 = sql::mysql::get_driver_instance_by_name("drv2");
4119-
driver2->setCallBack(sql::Fido_Callback([](sql::SQLString msg) {
4120-
std::cout << "Driver 2 Thread Callback : " << msg << std::endl;
4121-
callback_variable = 2002;
4122-
}));
4123-
4124-
for (int i = 0; i < 2; ++i)
4125-
{
4126-
std::cout << "\nBefore connect: " << callback_variable << std::endl;
4127-
Connection c1(driver1->connect(opt));
4128-
std::cout << "After connect: " << callback_variable << std::endl;
4129-
4130-
std::cout << "\nBefore connect: " << callback_variable << std::endl;
4131-
Connection c2(driver2->connect(opt));
4132-
std::cout << "After connect: " << callback_variable << std::endl;
4133-
}
4134-
};
4135-
41364119
for (int i = 0; i < 3; ++i)
41374120
{
4138-
workers.push_back(std::thread(worker_func));
4121+
workers.push_back(std::thread{multi_drv_test});
41394122
}
41404123

41414124
for (auto &w : workers)
@@ -4146,10 +4129,70 @@ void connection::fido_test()
41464129
}
41474130
catch (sql::SQLException &e)
41484131
{
4149-
std::cout << e.what() << std::endl;
4132+
cout << e.what() << endl;
41504133
FAIL("Unexpected error!");
41514134
}
4152-
std::cout << "Success\n";
4135+
4136+
cout << "Success\n";
4137+
}
4138+
4139+
4140+
/*
4141+
Note: This test is expecting account `u2` configured to use
4142+
`authentication_fido` plugin.
4143+
*/
4144+
4145+
void connection::fido_test()
4146+
{
4147+
using std::cout;
4148+
using std::endl;
4149+
4150+
if(!getenv("MYSQL_FIDO"))
4151+
return;
4152+
4153+
test_fido_webauthn<sql::Fido_Callback, MyWindowFido>();
4154+
4155+
cout << endl
4156+
<< "Check that webauthn callback is not used for fido accounts" << endl;
4157+
4158+
test_fido_webauthn<sql::WebAuthn_Callback, MyWindowWebAuthn>(true);
4159+
}
4160+
4161+
4162+
/*
4163+
Note: This test is expecting account `u2` configured to use
4164+
`authentication_webauthn` plugin.
4165+
*/
4166+
4167+
void connection::webauthn_test()
4168+
{
4169+
using std::cout;
4170+
using std::endl;
4171+
4172+
if(!getenv("MYSQL_FIDO") && !getenv("MYSQL_WEBAUTHN"))
4173+
return;
4174+
4175+
test_fido_webauthn<sql::WebAuthn_Callback, MyWindowWebAuthn>();
4176+
4177+
// Note: The fido callback should also work
4178+
4179+
cout << endl << "Running tests with Fido callbacks" << endl;
4180+
4181+
test_fido_webauthn<sql::Fido_Callback, MyWindowFido>();
4182+
4183+
cout << endl << "Overwrite WebAuthn callback with Fido one" << endl;
4184+
4185+
{
4186+
sql::Driver * driver = sql::mysql::get_driver_instance();
4187+
driver->setCallBack(sql::WebAuthn_Callback{my_callback});
4188+
try
4189+
{
4190+
driver->setCallBack(sql::Fido_Callback{my_callback});
4191+
FAIL("Expecting error but it worked!");
4192+
}
4193+
catch (sql::SQLException&)
4194+
{}
4195+
}
41534196
}
41544197

41554198

jdbc/test/unit/classes/connection.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ class connection : public unit_fixture
4747
private:
4848
typedef unit_fixture super;
4949

50+
template <class CB, class MY>
51+
void test_fido_webauthn(bool = false);
52+
5053
protected:
5154

5255
bool check_tls_ver(const char* tls_ver);
@@ -98,6 +101,7 @@ class connection : public unit_fixture
98101
TEST_CASE(mfa);
99102
TEST_CASE(tls_deprecation);
100103
TEST_CASE(fido_test);
104+
TEST_CASE(webauthn_test);
101105
TEST_CASE(normalize_ssl_options);
102106
TEST_CASE(macro_version);
103107
}
@@ -320,6 +324,7 @@ class connection : public unit_fixture
320324
*
321325
*/
322326
void fido_test();
327+
void webauthn_test();
323328

324329
/*
325330
* Test version macros.

0 commit comments

Comments
 (0)