Skip to content

Commit

Permalink
Bug #30956106: LIBMYSQLCLIENT DEPENDS ON THE KERBEROS LIBRARY
Browse files Browse the repository at this point in the history
RB: 24006
  • Loading branch information
Yashwant Sahu committed Mar 5, 2020
1 parent 58e1560 commit 49844e1
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 42 deletions.
19 changes: 0 additions & 19 deletions libmysql/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -187,21 +187,6 @@ SET(CLIENT_SOURCES
../sql/auth/sha2_password_common.cc
)

IF (KERBEROS_FOUND)
LIST(APPEND CLIENT_SOURCES
authentication_ldap/log_client.cc
authentication_ldap/auth_ldap_kerberos.cc
)
# Kerberos is deprecated in macOS.
IF(APPLE)
ADD_COMPILE_FLAGS(authentication_ldap/auth_ldap_kerberos.cc
COMPILE_FLAGS "-Wno-deprecated-declarations")
ENDIF()
IF(FREEBSD AND KERBEROS_SYSTEM_LIBRARY)
INCLUDE_DIRECTORIES(SYSTEM /usr/local/include)
ENDIF()
ENDIF()

IF (WIN32 AND OPENSSL_APPLINK_C)
ADD_COMPILE_DEFINITIONS(
../sql-common/client_authentication.cc
Expand Down Expand Up @@ -245,10 +230,6 @@ ELSE()
LIST(APPEND LIBS_TO_LINK ${ZSTD_LIBRARY})
ENDIF()

IF (KERBEROS_FOUND)
LIST(APPEND LIBS_TO_LINK ${KERBEROS_LIBRARY_PATH})
ENDIF()

LIST(APPEND LIBS_TO_LINK ${SSL_LIBRARIES})

#
Expand Down
4 changes: 4 additions & 0 deletions libmysql/authentication_ldap/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ IF (KERBEROS_FOUND)
ELSE()
MESSAGE(STATUS "KERBEROS_LIBRARY_PATH = ${KERBEROS_LIBRARY_PATH}")
SET(AUTH_LDAP_KERBEROS_CC auth_ldap_kerberos.cc)
# mysys is required to use my_free and my_strdup when getting Kerberos user name.
# Adding mysys only when build has Kerberos support
SET(MY_SYS "mysys")
ENDIF()
ELSE()
MESSAGE(STATUS "Without Kerberos")
Expand All @@ -71,6 +74,7 @@ MYSQL_ADD_PLUGIN(authentication_ldap_sasl_client
${KERBEROS_LIBRARY_PATH}
${SSL_LIBRARIES}
${LIBDL}
${MY_SYS}
CLIENT_ONLY
MODULE_ONLY
MODULE_OUTPUT_NAME "authentication_ldap_sasl_client")
Expand Down
9 changes: 7 additions & 2 deletions libmysql/authentication_ldap/auth_ldap_kerberos.cc
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ void Kerberos::destroy_credentials() {
}
}

bool Kerberos::get_user_name(char *name) {
bool Kerberos::get_user_name(std::string *name) {
krb5_error_code res_kerberos = 0;
krb5_principal principal = nullptr;
krb5_context context = nullptr;
Expand All @@ -508,6 +508,11 @@ bool Kerberos::get_user_name(char *name) {
log_dbg("Kerberos object is not initialized.");
goto EXIT;
}
if (!name) {
log_dbg("Failed to get Kerberos user name");
goto EXIT;
}
*name = "";
if (m_krb_credentials_cache == nullptr) {
res_kerberos = krb5_cc_default(m_context, &m_krb_credentials_cache);
if (res_kerberos) {
Expand Down Expand Up @@ -536,7 +541,7 @@ bool Kerberos::get_user_name(char *name) {
log_stream << "SASL get user name: ";
log_stream << user_name;
log_info(log_stream.str());
strcpy(name, user_name);
*name = user_name;
}

EXIT:
Expand Down
2 changes: 1 addition & 1 deletion libmysql/authentication_ldap/auth_ldap_kerberos.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class Kerberos {
@retval true, If function is successfully able to get user name.
@retval false, If function is failed to get user name.
*/
bool get_user_name(char *name);
bool get_user_name(std::string *name);
void destroy_credentials();
/**
This function gets LDAP host from krb5.conf file.
Expand Down
62 changes: 60 additions & 2 deletions libmysql/authentication_ldap/auth_ldap_sasl_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,33 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */

#include "auth_ldap_sasl_client.h"
/*
In case of Kerberos authentication we need to fill user name as Kerberos user
name if it is empty. We need to fill user name inside mysql->user, client’s
uses my_strdup directly to create new string. To use MySQL alloc functions we
need to include "/mysql/service_mysql_alloc.h". Inside “service_mysql_alloc.h”
there is #define which forces all dynamic plugins to use MySQL malloc function
via services. Client side plugin can’t use any services as of now. Code
check in “service_mysql_alloc.h” #ifdef MYSQL_DYNAMIC_PLUGIN #define my_strdup
mysql_malloc_service->my_strdup #else extern char *my_strdup(PSI_memory_key
key, const char *from, myf_t flags); #endif Client authentication plugin
defines MYSQL_DYNAMIC_PLUGIN. And this forces to use always my_strdup via
services. To use native direct my_strdup, we need to undefine
MYSQL_DYNAMIC_PLUGIN. And again define MYSQL_DYNAMIC_PLUGIN once correct
my_strdup are declared. “service_mysql_alloc.h” should provide proper fix like
Instead of #ifdef MYSQL_DYNAMIC_PLUGIN
#ifdef MYSQL_DYNAMIC_PLUGIN && ! MYSQL_CLIENT_PLUGIN
*/
#if defined(KERBEROS_LIB_CONFIGURED)
#undef MYSQL_DYNAMIC_PLUGIN
#include <mysql/service_mysql_alloc.h>
#define MYSQL_DYNAMIC_PLUGIN
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "auth_ldap_sasl_client.h"
#ifndef _WIN32
#include <lber.h>
#include <sasl/sasl.h>
Expand Down Expand Up @@ -290,6 +313,28 @@ int Sasl_client::sasl_step(char *server_in, int server_in_length,

std::string Sasl_client::get_method() { return m_mechanism; }

#if defined(KERBEROS_LIB_CONFIGURED)
void Sasl_client::read_kerberos_user_name() {
std::string user_name = "";
bool ret_kerberos = false;
auth_ldap_client_kerberos_context::Kerberos kerberos("", "");
ret_kerberos = kerberos.get_user_name(&user_name);
if (m_mysql && ret_kerberos && (!user_name.empty())) {
/*
MySQL clients/lib uses my_free, my_strdup my_* string function for string
management. We also need to use same methods as these are used/free inside
libmysqlclient
*/
if (m_mysql->user) {
my_free(m_mysql->user);
m_mysql->user = nullptr;
}
m_mysql->user =
my_strdup(PSI_NOT_INSTRUMENTED, user_name.c_str(), MYF(MY_WME));
}
}
#endif

void Sasl_client::set_user_info(std::string name, std::string pwd) {
strncpy(m_user_name, name.c_str(), sizeof(m_user_name) - 1);
m_user_name[sizeof(m_user_name) - 1] = '\0';
Expand All @@ -315,8 +360,20 @@ static int sasl_authenticate(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql) {
int sasl_client_output_len = 0;
std::stringstream log_stream;
Sasl_client sasl_client;
sasl_client.set_user_info(mysql->user, mysql->passwd);

sasl_client.set_plugin_info(vio, mysql);

#if defined(KERBEROS_LIB_CONFIGURED)
/*
For some cases MySQL user name will be empty as user name is supposed to
come from kerberos TGT. Get kerberos user name from TGT and assign this as
MySQL user name.
*/
if (!mysql->user || mysql->user[0] == '\0') {
sasl_client.read_kerberos_user_name();
}
#endif

server_packet_len = sasl_client.read_method_name_from_server();
if (server_packet_len < 0) {
// Callee has already logged the messages.
Expand All @@ -333,6 +390,7 @@ static int sasl_authenticate(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql) {
}
#endif

sasl_client.set_user_info(mysql->user, mysql->passwd);
rc_sasl = sasl_client.initilize();
if (rc_sasl != SASL_OK) {
log_error("sasl_authenticate: initialize failed");
Expand Down
3 changes: 3 additions & 0 deletions libmysql/authentication_ldap/auth_ldap_sasl_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ class Sasl_client {
void set_user_info(std::string name, std::string pwd);
static void sasl_client_done_wrapper();
std::string get_method();
#if defined(KERBEROS_LIB_CONFIGURED)
void read_kerberos_user_name();
#endif

protected:
char m_user_name[SASL_MAX_STR_SIZE];
Expand Down
1 change: 0 additions & 1 deletion libmysql/client_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ extern char *mysql_unix_port;
CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA | CLIENT_CONNECT_ATTRS | \
CLIENT_SESSION_TRACK | CLIENT_DEPRECATE_EOF)

bool read_kerberos_user_name(char *name);
void read_user_name(char *name);
bool handle_local_infile(MYSQL *mysql, const char *net_filename);

Expand Down
16 changes: 0 additions & 16 deletions libmysql/libmysql.cc
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,6 @@
#include "client_settings.h"
#include "mysql_trace.h"
#include "sql_common.h"
#ifdef KERBEROS_LIB_CONFIGURED
#include "authentication_ldap/auth_ldap_kerberos.h"
#endif

/*
Temporary replacement for COM_SHUTDOWN. This will be removed once
Expand Down Expand Up @@ -330,19 +327,6 @@ struct passwd *getpwuid(uid_t);
char *getlogin(void);
#endif

#if defined(KERBEROS_LIB_CONFIGURED)
bool read_kerberos_user_name(char *name) {
bool ret_kerberos = false;
auth_ldap_client_kerberos_context::Kerberos kerberos("", "");
ret_kerberos = kerberos.get_user_name(name);
if (ret_kerberos && (strcmp(name, "") != 0)) {
return true;
} else {
return false;
}
}
#endif

#if !defined(_WIN32)

void read_user_name(char *name) {
Expand Down
6 changes: 5 additions & 1 deletion sql-common/client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4755,8 +4755,12 @@ static bool prep_client_reply_packet(MCPVIO_EXT *mpvio, const uchar *data,
strmake(end, mysql->user, USERNAME_LENGTH);
else {
#if defined(KERBEROS_LIB_CONFIGURED)
/*
Kerberos user name should have already read inside LDAP SASL client
plugin. If it is still empty we should return error.
*/
if (strcmp(mpvio->plugin->name, "authentication_ldap_sasl_client") == 0) {
if (!read_kerberos_user_name(end)) {
if (!mysql->user[0]) {
set_mysql_error(mysql, CR_KERBEROS_USER_NOT_FOUND, unknown_sqlstate);
return true;
}
Expand Down

0 comments on commit 49844e1

Please sign in to comment.