@@ -3962,6 +3962,29 @@ void connection::tls_deprecation()
3962
3962
3963
3963
}
3964
3964
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
+
3965
3988
/* Variable value will be changed by callbacks */
3966
3989
int callback_variable = -1 ;
3967
3990
@@ -3971,171 +3994,131 @@ void my_callback(sql::SQLString s)
3971
3994
callback_variable = 1 ;
3972
3995
}
3973
3996
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
3994
3998
{
3995
- if (!getenv (" MYSQL_FIDO" ))
3996
- return ;
3999
+ public:
3997
4000
3998
- class MyWindow : public sql ::Fido_Callback
4001
+ virtual void FidoActionRequested ( sql::SQLString msg) override
3999
4002
{
4000
- public:
4003
+ std::cout << " Method Override (3): " << msg << std::endl;
4004
+ callback_variable = 3 ;
4005
+ }
4006
+ };
4001
4007
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);
4007
4050
};
4008
4051
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
+ };
4011
4056
4012
4057
try
4013
4058
{
4014
- sql::ConnectOptionsMap opt;
4015
- opt[OPT_HOSTNAME] = url;
4016
- opt[OPT_USERNAME] = fido_user;
4017
- opt[OPT_PASSWORD] = fido_pwd;
4018
4059
4019
- /* No callback */
4020
- {
4021
- callback_variable = 0 ;
4022
- sql::Driver * driver = sql::mysql::get_driver_instance ();
4023
- std::cout << " \n Before 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
- }
4029
4060
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 );
4034
4063
4035
- std::cout << " \n Before 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 );
4040
4067
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 ;
4048
4070
4049
- std::cout << " \n Before 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 );
4054
4077
4055
- /* Callback class */
4078
+ cout << endl << " Callback Class (3) " << endl;
4056
4079
{
4057
- MyWindow window;
4080
+ MY window;
4058
4081
4059
4082
sql::Driver * driver = sql::mysql::get_driver_instance ();
4060
4083
driver->setCallBack (window);
4084
+ test_connection (3 );
4085
+ }
4061
4086
4062
- std::cout << " \n Before 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 );
4066
4090
4067
- // Reset callback
4068
- callback_variable = 0 ;
4069
- driver->setCallBack (sql::Fido_Callback (nullptr ));
4070
- std::cout << " \n Before 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
- }
4076
4091
4077
- /* Multi driver tests */
4078
- std::cout << " \n Multi driver tests: " << std::endl;
4092
+ cout << endl << " Multi driver tests: " << endl;
4093
+
4094
+ auto multi_drv_test = [test_connection_drv]()
4079
4095
{
4080
4096
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;
4083
4099
callback_variable = 111 ;
4084
- }) );
4100
+ }} );
4085
4101
4086
4102
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;
4089
4105
callback_variable = 222 ;
4090
- }) );
4106
+ }} );
4091
4107
4092
- for (int i = 0 ; i < 2 ; ++i)
4093
- {
4094
- std::cout << " \n Before 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
+ };
4098
4111
4099
- std::cout << " \n Before 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;
4105
4115
4106
- /* Multithread driver tests */
4107
- std::cout << " Multithread driver tests: " << std::endl;
4108
4116
{
4109
4117
std::vector<std::thread> workers;
4110
4118
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 << " \n Before connect: " << callback_variable << std::endl;
4127
- Connection c1 (driver1->connect (opt));
4128
- std::cout << " After connect: " << callback_variable << std::endl;
4129
-
4130
- std::cout << " \n Before connect: " << callback_variable << std::endl;
4131
- Connection c2 (driver2->connect (opt));
4132
- std::cout << " After connect: " << callback_variable << std::endl;
4133
- }
4134
- };
4135
-
4136
4119
for (int i = 0 ; i < 3 ; ++i)
4137
4120
{
4138
- workers.push_back (std::thread (worker_func) );
4121
+ workers.push_back (std::thread{multi_drv_test} );
4139
4122
}
4140
4123
4141
4124
for (auto &w : workers)
@@ -4146,10 +4129,70 @@ void connection::fido_test()
4146
4129
}
4147
4130
catch (sql::SQLException &e)
4148
4131
{
4149
- std:: cout << e.what () << std:: endl;
4132
+ cout << e.what () << endl;
4150
4133
FAIL (" Unexpected error!" );
4151
4134
}
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
+ }
4153
4196
}
4154
4197
4155
4198
0 commit comments