Skip to content

Commit 291957d

Browse files
author
Bharathy Satish
committed
WL#14183: Support for MFA(multi factor authentication) and fido authentication.
This WL implements following: 1. Infrastructure to support multi factor authentication of mysql user accounts. a. Extend CREATE/ALTER USER syntax b. Extend SHOW CREATE USER c. Define new authentication policy for a given session d. New session tracker: SESSION_TRACK_CLIENT_PLUGIN_INFO e. Protocol changes to initiate 2nd and 3rd factor auth packet exchanges 2. Bundle open source code of cbor and libfido2 into extra folder. 3. New server side authentication plugin authentication_fido.so 4. New client side authentication plugin authentication_fido_client.so 5. Packaging related changes to bundle new libraries (libfido2.so, authentication_fido.so, authentication_fido_client.so) into rpms and debs. RB#25510
1 parent 68a368e commit 291957d

File tree

152 files changed

+7289
-1508
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

152 files changed

+7289
-1508
lines changed

CMakeLists.txt

+48-4
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,7 @@ INCLUDE(curl)
714714
INCLUDE(rapidjson)
715715
INCLUDE(fprofile)
716716
INCLUDE(gloves)
717-
717+
INCLUDE(fido2)
718718

719719
IF(UNIX)
720720
OPTION(WITH_VALGRIND "Valgrind instrumentation" OFF)
@@ -809,6 +809,16 @@ OPTION(WITH_AUTHENTICATION_CLIENT_PLUGINS
809809
"Build client-side authentication plugins, even if server-side are disabled"
810810
${WITH_AUTHENTICATION_CLIENT_PLUGINS_DEFAULT})
811811

812+
IF(WITH_INTERNAL AND (NOT SOLARIS))
813+
SET(WITH_AUTHENTICATION_FIDO_DEFAULT ON)
814+
ELSE()
815+
SET(WITH_AUTHENTICATION_FIDO_DEFAULT OFF)
816+
ENDIF()
817+
818+
OPTION(WITH_AUTHENTICATION_FIDO
819+
"Report error if the FIDO authentication plugin cannot be built."
820+
${WITH_AUTHENTICATION_FIDO_DEFAULT})
821+
812822
# On windows we need a non-standard package for CURL.
813823
IF(WITH_INTERNAL AND UNIX)
814824
SET(WITH_CURL_DEFAULT "system")
@@ -1466,6 +1476,7 @@ SET(SYSTEM_LIBRARIES
14661476
SSL
14671477
ZLIB
14681478
ZSTD
1479+
FIDO
14691480
)
14701481

14711482
SET(WITH_SYSTEM_LIBS_DEFAULT OFF)
@@ -1645,6 +1656,23 @@ ENDIF()
16451656
# Add RapidJSON library.
16461657
MYSQL_CHECK_RAPIDJSON()
16471658

1659+
IF(WITH_AUTHENTICATION_FIDO)
1660+
IF(WITH_FIDO STREQUAL "system" AND
1661+
NOT WITH_SSL STREQUAL "system")
1662+
MESSAGE(WARNING "-DWITH_AUTHENTICATION_FIDO=ON")
1663+
MESSAGE(FATAL_ERROR "Inconsistent options for FIDO/SSL")
1664+
ENDIF()
1665+
1666+
# Add fido2 library
1667+
MYSQL_CHECK_FIDO()
1668+
MYSQL_CHECK_FIDO_DLLS()
1669+
1670+
IF(NOT FIDO_FOUND)
1671+
MESSAGE(FATAL_ERROR
1672+
"-DWITH_AUTHENTICATION_FIDO=ON, but missing required libraries")
1673+
ENDIF()
1674+
ENDIF()
1675+
16481676
MACRO(MY_INCLUDE_SYSTEM_DIRECTORIES LIBRARY)
16491677
IF(${WITH_${LIBRARY}} STREQUAL "bundled")
16501678
SET(BEFORE_OR_AFTER "BEFORE")
@@ -1694,11 +1722,27 @@ IF(LINUX)
16941722
HAVE_PTHREAD_SETNAME_NP)
16951723
ENDIF()
16961724

1697-
IF(WITH_PROTOBUF STREQUAL "bundled")
1725+
IF(WITH_PROTOBUF STREQUAL "bundled" OR WITH_FIDO STREQUAL "bundled")
16981726
# Protobuf library is a target, installed to <root>/${INSTALL_PRIV_LIBDIR}
16991727
# INSTALL_RPATH must be set for all binaries linking with libprotobuf.
1700-
SET(UNIX_INSTALL_RPATH_ORIGIN_PRIV_LIBDIR 1)
1701-
ADD_SUBDIRECTORY(extra/protobuf)
1728+
IF(WITH_PROTOBUF STREQUAL "bundled")
1729+
SET(UNIX_INSTALL_RPATH_ORIGIN_PRIV_LIBDIR 1)
1730+
ADD_SUBDIRECTORY(extra/protobuf)
1731+
ENDIF()
1732+
1733+
# The Fido library is a target, installed to <root>/${INSTALL_PRIV_LIBDIR}
1734+
# INSTALL_RPATH must be set for all binaries linking with libfido2.
1735+
IF(WITH_FIDO STREQUAL "bundled")
1736+
SET(INSTALL_RPATH_FOR_FIDO2 1)
1737+
1738+
# Silence warning about CMP0075
1739+
CMAKE_PUSH_CHECK_STATE()
1740+
SET(CMAKE_REQUIRED_LIBRARIES)
1741+
ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/${CBOR_BUNDLE_SRC_PATH})
1742+
ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/${FIDO_BUNDLE_SRC_PATH})
1743+
CMAKE_POP_CHECK_STATE()
1744+
ENDIF()
1745+
17021746
IF(NOT APPLE AND NOT WIN32)
17031747
# Debug versions of plugins may be installed to <root>/lib/plugin/debug
17041748
FOREACH(LINK_FLAG

Doxyfile.in

+1
Original file line numberDiff line numberDiff line change
@@ -2278,6 +2278,7 @@ SEARCH_INCLUDES = YES
22782278
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
22792279

22802280
INCLUDE_PATH = . \
2281+
client/include \
22812282
include \
22822283
include/mysql \
22832284
sql

client/CMakeLists.txt

+12
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,19 @@ ADD_SUBDIRECTORY(dump)
3232
## Subdirectory for mysql_migrate_keyring code.
3333
ADD_SUBDIRECTORY(migrate_keyring)
3434

35+
INCLUDE_DIRECTORIES(
36+
${CMAKE_CURRENT_SOURCE_DIR}/include
37+
)
38+
3539
MYSQL_ADD_EXECUTABLE(mysql
3640
${CMAKE_SOURCE_DIR}/sql-common/net_ns.cc
3741
completion_hash.cc
3842
mysql.cc
3943
pattern_matcher.cc
4044
readline.cc
4145
client_query_attributes.cc
46+
multi_factor_passwordopt-vars.cc
47+
${CMAKE_CURRENT_SOURCE_DIR}/common/user_registration.cc
4248
LINK_LIBRARIES mysqlclient client_base ${EDITLINE_LIBRARY}
4349
)
4450

@@ -68,18 +74,22 @@ MYSQL_ADD_EXECUTABLE(mysqltest
6874
MYSQL_ADD_EXECUTABLE(mysqlcheck
6975
check/mysqlcheck.cc
7076
check/mysqlcheck_core.cc
77+
multi_factor_passwordopt-vars.cc
7178
LINK_LIBRARIES mysqlclient
7279
)
7380
MYSQL_ADD_EXECUTABLE(mysqldump
7481
mysqldump.cc
82+
multi_factor_passwordopt-vars.cc
7583
LINK_LIBRARIES mysqlclient
7684
)
7785
MYSQL_ADD_EXECUTABLE(mysqlimport
7886
mysqlimport.cc
87+
multi_factor_passwordopt-vars.cc
7988
LINK_LIBRARIES mysqlclient
8089
)
8190
MYSQL_ADD_EXECUTABLE(mysqlshow
8291
mysqlshow.cc
92+
multi_factor_passwordopt-vars.cc
8393
LINK_LIBRARIES mysqlclient
8494
)
8595

@@ -243,10 +253,12 @@ TARGET_INCLUDE_DIRECTORIES(mysqlbinlog PRIVATE ${CMAKE_SOURCE_DIR}/sql)
243253

244254
MYSQL_ADD_EXECUTABLE(mysqladmin
245255
mysqladmin.cc
256+
multi_factor_passwordopt-vars.cc
246257
LINK_LIBRARIES mysqlclient
247258
)
248259
MYSQL_ADD_EXECUTABLE(mysqlslap
249260
mysqlslap.cc
261+
multi_factor_passwordopt-vars.cc
250262
LINK_LIBRARIES mysqlclient
251263
)
252264
MYSQL_ADD_EXECUTABLE(mysql_config_editor

client/base/mysql_connection_options.cc

+13-4
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,20 @@ void Mysql_connection_options::create_options() {
100100
->set_value_step(1024)
101101
->set_value(1024 * 1024L - 1024);
102102
this->create_new_password_option(
103-
&this->m_password, "password",
103+
&this->m_password[0], "password",
104104
"Password to use when connecting to server. If password is not given,"
105105
" it's solicited on the tty.")
106106
->set_short_character('p');
107+
this->create_new_password_option(
108+
&this->m_password[0], "password1",
109+
"Password for first factor authentication plugin.");
110+
this->create_new_password_option(
111+
&this->m_password[1], "password2",
112+
"Password for second factor authentication plugin.");
113+
this->create_new_password_option(
114+
&this->m_password[2], "password3",
115+
"Password for third factor authentication plugin.");
116+
107117
#ifdef _WIN32
108118
this->create_new_option("pipe", "Use named pipes to connect to server.")
109119
->set_short_character('W')
@@ -191,9 +201,8 @@ MYSQL *Mysql_connection_options::create_connection() {
191201
&this->m_get_server_public_key);
192202

193203
if (!mysql_real_connect(connection, this->get_null_or_string(this->m_host),
194-
this->get_null_or_string(this->m_user),
195-
this->get_null_or_string(this->m_password), nullptr,
196-
this->m_mysql_port,
204+
this->get_null_or_string(this->m_user), nullptr,
205+
nullptr, this->m_mysql_port,
197206
this->get_null_or_string(this->m_mysql_unix_port),
198207
0)) {
199208
this->db_error(connection, "while connecting to the MySQL server");

client/base/mysql_connection_options.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ class Mysql_connection_options : public Composite_options_provider,
138138
uint32 m_max_allowed_packet;
139139
bool m_compress;
140140
std::optional<std::string> m_user;
141-
std::optional<std::string> m_password;
141+
std::optional<std::string> m_password[3];
142142
std::optional<std::string> m_default_charset;
143143
std::optional<std::string> m_server_public_key;
144144
bool m_get_server_public_key;

client/check/mysqlcheck.cc

+15-35
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,16 @@ static bool opt_alldbs = false, opt_check_only_changed = false,
5757
opt_extended = false, opt_compress = false, opt_databases = false,
5858
opt_fast = false, opt_medium_check = false, opt_quick = false,
5959
opt_all_in_1 = false, opt_silent = false, opt_auto_repair = false,
60-
ignore_errors = false, tty_password = false, opt_frm = false,
61-
debug_info_flag = false, debug_check_flag = false,
62-
opt_fix_table_names = false, opt_fix_db_names = false,
63-
opt_upgrade = false, opt_write_binlog = true;
60+
ignore_errors = false, opt_frm = false, debug_info_flag = false,
61+
debug_check_flag = false, opt_fix_table_names = false,
62+
opt_fix_db_names = false, opt_upgrade = false,
63+
opt_write_binlog = true;
6464
static uint verbose = 0, opt_mysql_port = 0;
6565
static uint opt_enable_cleartext_plugin = 0;
6666
static bool using_opt_enable_cleartext_plugin = false;
6767
static int my_end_arg;
6868
static char *opt_mysql_unix_port = nullptr;
69-
static char *opt_password = nullptr, *current_user = nullptr,
70-
*current_host = nullptr;
69+
static char *current_user = nullptr, *current_host = nullptr;
7170
static const char *default_charset = nullptr;
7271
static char *opt_plugin_dir = nullptr, *opt_default_auth = nullptr;
7372
static int first_error = 0;
@@ -80,6 +79,8 @@ static char *shared_memory_base_name = 0;
8079
static uint opt_protocol = 0;
8180
static char *opt_bind_addr = nullptr;
8281

82+
#include "multi_factor_passwordopt-vars.h"
83+
8384
static struct my_option my_long_options[] = {
8485
{"all-databases", 'A',
8586
"Check all the databases. This is the same as --databases with all "
@@ -183,11 +184,7 @@ static struct my_option my_long_options[] = {
183184
nullptr, 0, nullptr},
184185
{"optimize", 'o', "Optimize table.", nullptr, nullptr, nullptr, GET_NO_ARG,
185186
NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
186-
{"password", 'p',
187-
"Password to use when connecting to server. If password is not given, "
188-
"it's solicited on the tty.",
189-
nullptr, nullptr, nullptr, GET_PASSWORD, OPT_ARG, 0, 0, 0, nullptr, 0,
190-
nullptr},
187+
#include "multi_factor_passwordopt-longopts.h"
191188
#ifdef _WIN32
192189
{"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
193190
NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -267,7 +264,7 @@ static const char *load_default_groups[] = {"mysqlcheck", "client", nullptr};
267264

268265
static void usage(void);
269266
static int get_options(int *argc, char ***argv, MEM_ROOT *alloc);
270-
static int dbConnect(char *host, char *user, char *passwd);
267+
static int dbConnect(char *host, char *user);
271268
static void dbDisconnect(char *host);
272269
static void DBerror(MYSQL *mysql, const string &when);
273270
static void safe_exit(int error);
@@ -331,24 +328,7 @@ static bool get_one_option(int optid, const struct my_option *opt,
331328
case 'o':
332329
what_to_do = DO_OPTIMIZE;
333330
break;
334-
case 'p':
335-
if (argument == disabled_my_option) {
336-
// Don't require password
337-
static char empty_password[] = {'\0'};
338-
assert(empty_password[0] ==
339-
'\0'); // Check that it has not been overwritten
340-
argument = empty_password;
341-
}
342-
if (argument) {
343-
char *start = argument;
344-
my_free(opt_password);
345-
opt_password = my_strdup(PSI_NOT_INSTRUMENTED, argument, MYF(MY_FAE));
346-
while (*argument) *argument++ = 'x'; /* Destroy argument */
347-
if (*start) start[1] = 0; /* Cut length of argument */
348-
tty_password = false;
349-
} else
350-
tty_password = true;
351-
break;
331+
PARSE_COMMAND_LINE_PASSWORD_OPTION;
352332
case 'r':
353333
what_to_do = DO_REPAIR;
354334
break;
@@ -454,13 +434,12 @@ static int get_options(int *argc, char ***argv, MEM_ROOT *alloc) {
454434
printf("for more information.\n");
455435
return 1;
456436
}
457-
if (tty_password) opt_password = get_tty_password(NullS);
458437
if (debug_info_flag) my_end_arg = MY_CHECK_ERROR | MY_GIVE_INFO;
459438
if (debug_check_flag) my_end_arg = MY_CHECK_ERROR;
460439
return (0);
461440
} /* get_options */
462441

463-
static int dbConnect(char *host, char *user, char *passwd) {
442+
static int dbConnect(char *host, char *user) {
464443
DBUG_TRACE;
465444
if (verbose) {
466445
fprintf(stderr, "# Connecting to %s...\n", host ? host : "localhost");
@@ -504,8 +483,9 @@ static int dbConnect(char *host, char *user, char *passwd) {
504483
"mysqlcheck");
505484
set_server_public_key(&mysql_connection);
506485
set_get_server_public_key_option(&mysql_connection);
486+
set_password_options(&mysql_connection);
507487
if (!(sock =
508-
mysql_real_connect(&mysql_connection, host, user, passwd, nullptr,
488+
mysql_real_connect(&mysql_connection, host, user, nullptr, nullptr,
509489
opt_mysql_port, opt_mysql_unix_port, 0))) {
510490
DBerror(&mysql_connection, "when trying to connect");
511491
return 1;
@@ -544,7 +524,7 @@ int main(int argc, char **argv) {
544524
my_end(my_end_arg);
545525
exit(EX_USAGE);
546526
}
547-
if (dbConnect(current_host, current_user, opt_password)) exit(EX_MYSQLERR);
527+
if (dbConnect(current_host, current_user)) exit(EX_MYSQLERR);
548528

549529
// Sun Studio does not work with range constructor from char** to string.
550530
vector<string> conv;
@@ -559,7 +539,7 @@ int main(int argc, char **argv) {
559539
DBerror);
560540

561541
dbDisconnect(current_host);
562-
my_free(opt_password);
542+
free_passwords();
563543
#if defined(_WIN32)
564544
my_free(shared_memory_base_name);
565545
#endif

0 commit comments

Comments
 (0)