39
39
#include < algorithm>
40
40
#include < random>
41
41
#include < mutex>
42
+ #include < unordered_set>
42
43
#ifdef HAVE_STDINT_H
43
44
#include < stdint.h>
44
45
#endif
@@ -318,6 +319,16 @@ static const String2IntMap stringOptions[]=
318
319
{OPT_LOAD_DATA_LOCAL_DIR, MYSQL_OPT_LOAD_DATA_LOCAL_DIR, false }
319
320
};
320
321
322
+ static const std::unordered_set<std::string> stringPluginOptions = {
323
+ OPT_OCI_CONFIG_FILE,
324
+ OPT_AUTHENTICATION_KERBEROS_CLIENT_MODE,
325
+ OPT_OCI_CLIENT_CONFIG_PROFILE,
326
+ OPT_OPENID_TOKEN_FILE
327
+ };
328
+
329
+ static const std::unordered_set<std::string> intPluginOptions = {
330
+ OPT_WEBAUTHN_DEVICE_NUMBER
331
+ };
321
332
322
333
// Option conversion for libmysqlclient < 80011
323
334
@@ -1335,12 +1346,12 @@ void MySQL_Connection::init(ConnectOptionsMap & properties)
1335
1346
options are set here, before making a connection, to the values specified
1336
1347
by this connection and driver.
1337
1348
1338
- The guard is needed to prevent overwritting plugin options by another
1349
+ The guard is needed to prevent overwriting plugin options by another
1339
1350
connection while this connection is being established.
1340
1351
1341
1352
Note: If connection options do not specify a value for a plugin option that
1342
1353
plugin option is set to null which resets it to its default value (which
1343
- could be overwriten by other connections).
1354
+ could be overwritten by other connections).
1344
1355
1345
1356
TODO: Move setting of plugin options later in the connection process, after
1346
1357
any other options which can take long time to set (e.g. OpenSSL options or
@@ -1351,44 +1362,105 @@ void MySQL_Connection::init(ConnectOptionsMap & properties)
1351
1362
1352
1363
MySQL_Connection::PluginGuard guard{this };
1353
1364
1365
+ /*
1366
+ Set option `option` of plugin `plugin_name` of type `plugin_type` to
1367
+ the value given by connection option `con_opt_name` if it is specified.
1368
+ Otherwise (if the connection option is not specified) reset plugin option
1369
+ value to the default value given by `default_val`.
1370
+
1371
+ If plugin option value could not be set throw error with description given
1372
+ by `err_msg` (not if the plugin option is set to its default value).
1373
+
1374
+ Note that for most plugin options the default value is restored when
1375
+ the option is set to null.
1376
+ */
1377
+
1354
1378
auto set_plugin_option = [this , &properties] (
1355
1379
const ::sql::SQLString con_opt_name,
1356
1380
int plugin_type,
1357
1381
const ::sql::SQLString & plugin_name,
1358
1382
const ::sql::SQLString & option,
1359
- const char * err_msg)
1383
+ const char * err_msg,
1384
+ const void * default_val = nullptr
1385
+ )
1360
1386
{
1361
1387
sql::SQLString *p_s = nullptr ;
1388
+ const void * val = nullptr ;
1362
1389
1363
1390
auto opt = properties.find (con_opt_name);
1364
1391
if (opt != properties.end ())
1365
1392
{
1366
- try {
1367
- p_s = (opt->second ).get <sql::SQLString>();
1368
- } catch (sql::InvalidArgumentException&) {
1369
- throw sql::InvalidArgumentException (
1370
- " Wrong type passed for " + con_opt_name +
1371
- " . Expected sql::SQLString." );
1393
+ if (stringPluginOptions.count (con_opt_name))
1394
+ {
1395
+ try
1396
+ {
1397
+ p_s = (opt->second ).get <sql::SQLString>();
1398
+ if (!p_s)
1399
+ throw sql::InvalidArgumentException{
1400
+ " No string value passed for " + con_opt_name
1401
+ };
1402
+ val = p_s->c_str ();
1403
+ }
1404
+ catch (sql::InvalidArgumentException&)
1405
+ {
1406
+ throw sql::InvalidArgumentException (
1407
+ " Wrong type passed for " + con_opt_name +
1408
+ " . Expected sql::SQLString." );
1409
+ }
1410
+ }
1411
+ else if (intPluginOptions.count (con_opt_name))
1412
+ {
1413
+ try
1414
+ {
1415
+ val = (opt->second ).get <int >();
1416
+ if (!val)
1417
+ throw sql::InvalidArgumentException{
1418
+ " No int value passed for " + con_opt_name
1419
+ };
1420
+ }
1421
+ catch (sql::InvalidArgumentException&)
1422
+ {
1423
+ throw sql::InvalidArgumentException (
1424
+ " Wrong type passed for " + con_opt_name +
1425
+ " . Expected int." );
1426
+ }
1427
+ }
1428
+ else
1429
+ {
1430
+ /*
1431
+ We end up here only if below this lambda is called with connection
1432
+ option that is not a plugin option (not listed in
1433
+ `stringPluginOptions` or `intPluginOptions` -- that should never
1434
+ happen.
1435
+ */
1436
+ assert (false );
1372
1437
}
1373
1438
}
1374
1439
1375
- /*
1376
- Note: the plugin option will be set to nullptr if the corresponding
1377
- connection option was not set. This has the effect of re-setting plugin
1378
- option to its default value (if it was changed).
1379
- */
1440
+ try
1441
+ {
1442
+ /*
1443
+ Note: `val` is null if the connection option was not set. In that case
1444
+ we reset plugin option to the default value as given by `default_val`
1445
+ parameter. The last argument of `plugin_option()` informs that the
1446
+ option set is the default one which is the case when `val` is null.
1447
+ */
1380
1448
1381
- const void * val = p_s ? p_s->c_str () : nullptr ;
1382
- try {
1383
- proxy->plugin_option (plugin_type, plugin_name, option, val);
1384
- } catch (sql::InvalidArgumentException &e) {
1449
+ proxy->plugin_option (
1450
+ plugin_type, plugin_name, option,
1451
+ val ? val : default_val, val == nullptr
1452
+ );
1453
+ }
1454
+ catch (sql::InvalidArgumentException &e)
1455
+ {
1385
1456
if (val)
1386
- // Throw only when setting a non-null value
1457
+ // Throw only when setting to a non-default value
1387
1458
throw ::sql::SQLUnsupportedOptionException (err_msg,
1388
1459
con_opt_name.asStdString ());
1389
1460
}
1390
1461
};
1391
1462
1463
+
1392
1464
set_plugin_option (OPT_OCI_CONFIG_FILE,
1393
1465
MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
1394
1466
" authentication_oci_client" ,
@@ -1419,18 +1491,30 @@ void MySQL_Connection::init(ConnectOptionsMap & properties)
1419
1491
" Failed to set token file for authentication_openid_connect_client plugin"
1420
1492
);
1421
1493
1494
+ // Note: The default value for WebAuthN "device" option is 0.
1495
+
1496
+ const int webauthn_device_default_val = 0 ;
1497
+
1498
+ set_plugin_option (OPT_WEBAUTHN_DEVICE_NUMBER,
1499
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
1500
+ " authentication_webauthn_client" ,
1501
+ " device" ,
1502
+ " Failed to set a WebAuthn authentication device" ,
1503
+ &webauthn_device_default_val
1504
+ );
1505
+
1422
1506
/*
1423
1507
Setting webauthn callback functions.
1424
1508
1425
1509
The callback is an option of the webauthn authentication plugin that
1426
1510
is configured on the driver level (as opposed to plugin options above,
1427
1511
which are configured on per-connection basis). Correctly setting the option
1428
- based on driver configuration is handled by register_webauthn_callback() function
1429
- of PluginGuard class. The option will be set only if needed.
1512
+ based on driver configuration is handled by register_webauthn_callback()
1513
+ function of PluginGuard class. The option will be set only if needed.
1430
1514
1431
- Note: If register_webauthn_callback() sets a callback then the plugin options guard
1432
- ensures that this callback function is not modified by other connections
1433
- while being used.
1515
+ Note: If register_webauthn_callback() sets a callback then the plugin
1516
+ options guard ensures that this callback function is not modified by other
1517
+ connections while being used.
1434
1518
*/
1435
1519
1436
1520
guard.register_webauthn_callback (*static_cast <MySQL_Driver*>(driver));
0 commit comments