From 72e7f011b29998d8a3e15eb5b381ef962af5fe5b Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 5 Apr 2019 10:30:58 +0300 Subject: Upgrade to 8.0.15 --- mysql/libmysql/authentication_win/common.cpp | 510 --------------------- mysql/libmysql/authentication_win/common.h | 324 ------------- mysql/libmysql/authentication_win/handshake.cpp | 288 ------------ mysql/libmysql/authentication_win/handshake.h | 181 -------- .../authentication_win/handshake_client.cpp | 393 ---------------- mysql/libmysql/authentication_win/log_client.cpp | 65 --- .../libmysql/authentication_win/plugin_client.cpp | 67 --- 7 files changed, 1828 deletions(-) delete mode 100644 mysql/libmysql/authentication_win/common.cpp delete mode 100644 mysql/libmysql/authentication_win/common.h delete mode 100644 mysql/libmysql/authentication_win/handshake.cpp delete mode 100644 mysql/libmysql/authentication_win/handshake.h delete mode 100644 mysql/libmysql/authentication_win/handshake_client.cpp delete mode 100644 mysql/libmysql/authentication_win/log_client.cpp delete mode 100644 mysql/libmysql/authentication_win/plugin_client.cpp (limited to 'mysql/libmysql/authentication_win') diff --git a/mysql/libmysql/authentication_win/common.cpp b/mysql/libmysql/authentication_win/common.cpp deleted file mode 100644 index 48c400d..0000000 --- a/mysql/libmysql/authentication_win/common.cpp +++ /dev/null @@ -1,510 +0,0 @@ -/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ - -#include "common.h" -#include // for ConvertSidToStringSid() -#include // for GetUserNameEx() - - -template <> void error_log_print(const char *fmt, ...); -template <> void error_log_print(const char *fmt, ...); -template <> void error_log_print(const char *fmt, ...); - -/** - Option indicating desired level of logging. Values: - - 0 - no logging - 1 - log only error messages - 2 - additionally log warnings - 3 - additionally log info notes - 4 - also log debug messages - - Value of this option should be taken into account in the - implementation of error_log_vprint() function (see - log_client.cc). - - Note: No error or debug messages are logged in production code - (see logging macros in common.h). -*/ -int opt_auth_win_log_level= 2; - - -/** Connection class **************************************************/ - -/** - Create connection out of an active MYSQL_PLUGIN_VIO object. - - @param[in] vio pointer to a @c MYSQL_PLUGIN_VIO object used for - connection - it can not be NULL -*/ - -Connection::Connection(MYSQL_PLUGIN_VIO *vio): m_vio(vio), m_error(0) -{ - DBUG_ASSERT(vio); -} - - -/** - Write data to the connection. - - @param[in] blob data to be written - - @return 0 on success, VIO error code on failure. - - @note In case of error, VIO error code is stored in the connection object - and can be obtained with @c error() method. -*/ - -int Connection::write(const Blob &blob) -{ - m_error= m_vio->write_packet(m_vio, blob.ptr(), static_cast(blob.len())); - -#ifndef DBUG_OFF - if (m_error) - DBUG_PRINT("error", ("vio write error %d", m_error)); -#endif - - return m_error; -} - - -/** - Read data from connection. - - @return A Blob containing read packet or null Blob in case of error. - - @note In case of error, VIO error code is stored in the connection object - and can be obtained with @c error() method. -*/ - -Blob Connection::read() -{ - unsigned char *ptr; - int len= m_vio->read_packet(m_vio, &ptr); - - if (len < 0) - { - m_error= true; - return Blob(); - } - - return Blob(ptr, len); -} - - -/** Sid class *****************************************************/ - - -/** - Create Sid object corresponding to a given account name. - - @param[in] account_name name of a Windows account - - The account name can be in any form accepted by @c LookupAccountName() - function. - - @note In case of errors created object is invalid and its @c is_valid() - method returns @c false. -*/ - -Sid::Sid(const wchar_t *account_name): m_data(NULL) -#ifndef DBUG_OFF -, m_as_string(NULL) -#endif -{ - DWORD sid_size= 0, domain_size= 0; - bool success; - - // Determine required buffer sizes - - success= LookupAccountNameW(NULL, account_name, NULL, &sid_size, - NULL, &domain_size, &m_type); - - if (!success && GetLastError() != ERROR_INSUFFICIENT_BUFFER) - { -#ifndef DBUG_OFF - Error_message_buf error_buf; - DBUG_PRINT("error", ("Could not determine SID buffer size, " - "LookupAccountName() failed with error %X (%s)", - GetLastError(), get_last_error_message(error_buf))); -#endif - return; - } - - // Query for SID (domain is ignored) - - wchar_t *domain= new wchar_t[domain_size]; - m_data= (TOKEN_USER*) new BYTE[sid_size + sizeof(TOKEN_USER)]; - m_data->User.Sid= (BYTE*)m_data + sizeof(TOKEN_USER); - - success= LookupAccountNameW(NULL, account_name, - m_data->User.Sid, &sid_size, - domain, &domain_size, - &m_type); - - if (!success || !is_valid()) - { -#ifndef DBUG_OFF - Error_message_buf error_buf; - DBUG_PRINT("error", ("Could not determine SID of '%S', " - "LookupAccountName() failed with error %X (%s)", - account_name, GetLastError(), - get_last_error_message(error_buf))); -#endif - goto fail; - } - - goto end; - -fail: - if (m_data) - delete [] m_data; - m_data= NULL; - -end: - if (domain) - delete [] domain; -} - - -/** - Create Sid object corresponding to a given security token. - - @param[in] token security token of a Windows account - - @note In case of errors created object is invalid and its @c is_valid() - method returns @c false. -*/ - -Sid::Sid(HANDLE token): m_data(NULL) -#ifndef DBUG_OFF -, m_as_string(NULL) -#endif -{ - DWORD req_size= 0; - bool success; - - // Determine required buffer size - - success= GetTokenInformation(token, TokenUser, NULL, 0, &req_size); - if (!success && GetLastError() != ERROR_INSUFFICIENT_BUFFER) - { -#ifndef DBUG_OFF - Error_message_buf error_buf; - DBUG_PRINT("error", ("Could not determine SID buffer size, " - "GetTokenInformation() failed with error %X (%s)", - GetLastError(), get_last_error_message(error_buf))); -#endif - return; - } - - m_data= (TOKEN_USER*) new BYTE[req_size]; - success= GetTokenInformation(token, TokenUser, m_data, req_size, &req_size); - - if (!success || !is_valid()) - { - delete [] m_data; - m_data= NULL; -#ifndef DBUG_OFF - if (!success) - { - Error_message_buf error_buf; - DBUG_PRINT("error", ("Could not read SID from security token, " - "GetTokenInformation() failed with error %X (%s)", - GetLastError(), get_last_error_message(error_buf))); - } -#endif - } -} - - -Sid::~Sid() -{ - if (m_data) - delete [] m_data; -#ifndef DBUG_OFF - if (m_as_string) - LocalFree(m_as_string); -#endif -} - -/// Check if Sid object is valid. -bool Sid::is_valid(void) const -{ - return m_data && m_data->User.Sid && IsValidSid(m_data->User.Sid); -} - - -#ifndef DBUG_OFF - -/** - Produces string representation of the SID. - - @return String representation of the SID or NULL in case of errors. - - @note Memory allocated for the string is automatically freed in Sid's - destructor. -*/ - -const char* Sid::as_string() -{ - if (!m_data) - return NULL; - - if (!m_as_string) - { - bool success= ConvertSidToStringSid(m_data->User.Sid, &m_as_string); - - if (!success) - { -#ifndef DBUG_OFF - Error_message_buf error_buf; - DBUG_PRINT("error", ("Could not get textual representation of a SID, " - "ConvertSidToStringSid() failed with error %X (%s)", - GetLastError(), get_last_error_message(error_buf))); -#endif - m_as_string= NULL; - return NULL; - } - } - - return m_as_string; -} - -#endif - - -bool Sid::operator ==(const Sid &other) -{ - if (!is_valid() || !other.is_valid()) - return false; - - return EqualSid(m_data->User.Sid, other.m_data->User.Sid); -} - - -/** Generating User Principal Name *************************/ - -/** - Call Windows API functions to get UPN of the current user and store it - in internal buffer. -*/ - -UPN::UPN(): m_buf(NULL) -{ - wchar_t buf1[MAX_SERVICE_NAME_LENGTH]; - - // First we try to use GetUserNameEx. - - m_len= sizeof(buf1)/sizeof(wchar_t); - - if (!GetUserNameExW(NameUserPrincipal, buf1, (PULONG)&m_len)) - { - if (GetLastError()) - { -#ifndef DBUG_OFF - Error_message_buf error_buf; - DBUG_PRINT("note", ("When determining UPN" - ", GetUserNameEx() failed with error %X (%s)", - GetLastError(), get_last_error_message(error_buf))); -#endif - if (ERROR_MORE_DATA == GetLastError()) - ERROR_LOG(INFO, ("Buffer overrun when determining UPN:" - " need %ul characters but have %ul", - m_len, sizeof(buf1)/sizeof(WCHAR))); - } - - m_len= 0; // m_len == 0 indicates invalid UPN - return; - } - - /* - UPN is stored in buf1 in wide-char format - convert it to utf8 - for sending over network. - */ - - m_buf= wchar_to_utf8(buf1, &m_len); - - if(!m_buf) - ERROR_LOG(ERROR, ("Failed to convert UPN to utf8")); - - // Note: possible error would be indicated by the fact that m_buf is NULL. - return; -} - - -UPN::~UPN() -{ - if (m_buf) - free(m_buf); -} - - -/** - Convert a wide-char string to utf8 representation. - - @param[in] string null-terminated wide-char string to be converted - @param[in,out] len length of the string to be converted or 0; on - return length (in bytes, excluding terminating - null character) of the converted string - - If len is 0 then the length of the string will be computed by this function. - - @return Pointer to a buffer containing utf8 representation or NULL in - case of error. - - @note The returned buffer must be freed with @c free() call. -*/ - -char* wchar_to_utf8(const wchar_t *string, size_t *len) -{ - char *buf= NULL; - size_t str_len= len && *len ? *len : wcslen(string); - - /* - A conversion from utf8 to wchar_t will never take more than 3 bytes per - character, so a buffer of length 3 * str_len schould be sufficient. - We check that assumption with an assertion later. - */ - - size_t buf_len= 3 * str_len; - - buf= (char*)malloc(buf_len + 1); - if (!buf) - { - DBUG_PRINT("error",("Out of memory when converting string '%S' to utf8", - string)); - return NULL; - } - - int res= WideCharToMultiByte(CP_UTF8, // convert to UTF-8 - 0, // conversion flags - string, // input buffer - str_len, // its length - buf, buf_len, // output buffer and its size - NULL, NULL); // default character (not used) - - if (res) - { - buf[res]= '\0'; - if (len) - *len= res; - return buf; - } - - // res is 0 which indicates error - -#ifndef DBUG_OFF - Error_message_buf error_buf; - DBUG_PRINT("error", ("Could not convert string '%S' to utf8" - ", WideCharToMultiByte() failed with error %X (%s)", - string, GetLastError(), - get_last_error_message(error_buf))); -#endif - - // Let's check our assumption about sufficient buffer size - DBUG_ASSERT(ERROR_INSUFFICIENT_BUFFER != GetLastError()); - - return NULL; -} - - -/** - Convert an utf8 string to a wide-char string. - - @param[in] string null-terminated utf8 string to be converted - @param[in,out] len length of the string to be converted or 0; on - return length (in chars) of the converted string - - If len is 0 then the length of the string will be computed by this function. - - @return Pointer to a buffer containing wide-char representation or NULL in - case of error. - - @note The returned buffer must be freed with @c free() call. -*/ - -wchar_t* utf8_to_wchar(const char *string, size_t *len) -{ - size_t buf_len; - - /* - Note: length (in bytes) of an utf8 string is always bigger than the - number of characters in this string. Hence a buffer of size len will - be sufficient. We add 1 for the terminating null character. - */ - - buf_len= len && *len ? *len : strlen(string); - wchar_t *buf= (wchar_t*)malloc((buf_len+1)*sizeof(wchar_t)); - - if (!buf) - { - DBUG_PRINT("error",("Out of memory when converting utf8 string '%s'" - " to wide-char representation", string)); - return NULL; - } - - size_t res; - res= MultiByteToWideChar(CP_UTF8, // convert from UTF-8 - 0, // conversion flags - string, // input buffer - buf_len, // its size - buf, buf_len); // output buffer and its size - if (res) - { - buf[res]= '\0'; - if (len) - *len= res; - return buf; - } - - // error in MultiByteToWideChar() - -#ifndef DBUG_OFF - Error_message_buf error_buf; - DBUG_PRINT("error", ("Could not convert UPN from UTF-8" - ", MultiByteToWideChar() failed with error %X (%s)", - GetLastError(), get_last_error_message(error_buf))); -#endif - - // Let's check our assumption about sufficient buffer size - DBUG_ASSERT(ERROR_INSUFFICIENT_BUFFER != GetLastError()); - - return NULL; -} - - -/** Error handling ****************************************************/ - - -/** - Returns error message corresponding to the last Windows error given - by GetLastError(). - - @note Error message is overwritten by next call to - @c get_last_error_message(). -*/ - -const char* get_last_error_message(Error_message_buf buf) -{ - int error= GetLastError(); - - buf[0]= '\0'; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, - NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)buf, sizeof(buf), NULL ); - - return buf; -} diff --git a/mysql/libmysql/authentication_win/common.h b/mysql/libmysql/authentication_win/common.h deleted file mode 100644 index b7525fb..0000000 --- a/mysql/libmysql/authentication_win/common.h +++ /dev/null @@ -1,324 +0,0 @@ -/* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ - -#ifndef COMMON_H -#define COMMON_H - -#include -#include -#include // for CtxtHandle -#include // for MYSQL_PLUGIN_VIO - -/// Maximum length of the target service name. -#define MAX_SERVICE_NAME_LENGTH 1024 - - -/** Debugging and error reporting infrastructure ***************************/ - -/* - Note: We use plugin local logging and error reporting mechanisms until - WL#2940 (plugin service: error reporting) is available. -*/ - -#undef INFO -#undef WARNING -#undef ERROR - -struct error_log_level -{ - typedef enum {INFO, WARNING, ERROR} type; -}; - -extern "C" int opt_auth_win_log_level; -unsigned int get_log_level(void); -void set_log_level(unsigned int); - - -/* - If DEBUG_ERROR_LOG is defined then error logging happens only - in debug-copiled code. Otherwise ERROR_LOG() expands to - error_log_print() even in production code. - - Note: Macro ERROR_LOG() can use printf-like format string like this: - - ERROR_LOG(Level, ("format string", args)); - - The implementation should handle it correctly. Currently it is passed - to fprintf() (see error_log_vprint() function). -*/ - -#if defined(DEBUG_ERROR_LOG) && defined(DBUG_OFF) -#define ERROR_LOG(Level, Msg) do {} while (0) -#else -#define ERROR_LOG(Level, Msg) error_log_print< error_log_level::Level > Msg -#endif - - -void error_log_vprint(error_log_level::type level, - const char *fmt, va_list args); - -template -void error_log_print(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - error_log_vprint(Level, fmt, args); - va_end(args); -} - -typedef char Error_message_buf[1024]; -const char* get_last_error_message(Error_message_buf); - - -/* - Internal implementation of debug message printing which does not use - dbug library. This is invoked via macro: - - DBUG_PRINT_DO(Keyword, ("format string", args)); - - This is supposed to be used as an implementation of DBUG_PRINT() macro, - unless the dbug library implementation is used or debug messages are disabled. -*/ - -#ifndef DBUG_OFF - -#define DBUG_PRINT_DO(Keyword, Msg) \ - do { \ - if (4 > get_log_level()) break; \ - fprintf(stderr, "winauth: %s: ", Keyword); \ - debug_msg Msg; \ - } while (0) - -inline -void debug_msg(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - vfprintf(stderr, fmt, args); - fputc('\n', stderr); - fflush(stderr); - va_end(args); -} - -#else -#define DBUG_PRINT_DO(K, M) do {} while (0) -#endif - - -#ifndef WINAUTH_USE_DBUG_LIB - -#undef DBUG_PRINT -#define DBUG_PRINT(Keyword, Msg) DBUG_PRINT_DO(Keyword, Msg) - -/* - Redefine few more debug macros to make sure that no symbols from - dbug library are used. -*/ - -#undef DBUG_ENTER -#define DBUG_ENTER(X) do {} while (0) - -#undef DBUG_RETURN -#define DBUG_RETURN(X) return (X) - -#undef DBUG_ASSERT -#ifndef DBUG_OFF -#define DBUG_ASSERT(X) assert (X) -#else -#define DBUG_ASSERT(X) do {} while (0) -#endif - -#undef DBUG_DUMP -#define DBUG_DUMP(A,B,C) do {} while (0) - -#endif - - -/** Blob class *************************************************************/ - -typedef unsigned char byte; - -/** - Class representing a region of memory (e.g., a string or binary buffer). - - @note This class does not allocate memory. It merely describes a region - of memory which must be allocated externally (if it is dynamic memory). -*/ - -class Blob -{ - byte *m_ptr; ///< Pointer to the first byte of the memory region. - size_t m_len; ///< Length of the memory region. - -public: - - Blob(): m_ptr(NULL), m_len(0) - {} - - Blob(const byte *ptr, const size_t len) - : m_ptr(const_cast(ptr)), m_len(len) - {} - - Blob(const char *str): m_ptr((byte*)str) - { - m_len= strlen(str); - } - - byte* ptr() const - { - return m_ptr; - } - - size_t len() const - { - return m_len; - } - - byte& operator[](unsigned pos) const - { - static byte out_of_range= 0; // alas, no exceptions... - return pos < len() ? m_ptr[pos] : out_of_range; - } - - bool is_null() const - { - return m_ptr == NULL; - } - - void trim(size_t l) - { - m_len= l; - } -}; - - -/** Connection class *******************************************************/ - -/** - Convenience wrapper around MYSQL_PLUGIN_VIO object providing basic - read/write operations. -*/ - -class Connection -{ - MYSQL_PLUGIN_VIO *m_vio; ///< Pointer to @c MYSQL_PLUGIN_VIO structure. - - /** - If non-zero, indicates that connection is broken. If this has happened - because of failed operation, stores non-zero error code from that failure. - */ - int m_error; - -public: - - Connection(MYSQL_PLUGIN_VIO *vio); - int write(const Blob&); - Blob read(); - - int error() const - { - return m_error; - } -}; - - -/** Sid class **************************************************************/ - -/** - Class for storing and manipulating Windows security identifiers (SIDs). -*/ - -class Sid -{ - TOKEN_USER *m_data; ///< Pointer to structure holding identifier's data. - SID_NAME_USE m_type; ///< Type of identified entity. - -public: - - Sid(const wchar_t*); - Sid(HANDLE sec_token); - ~Sid(); - - bool is_valid(void) const; - - bool is_group(void) const - { - return m_type == SidTypeGroup - || m_type == SidTypeWellKnownGroup - || m_type == SidTypeAlias; - } - - bool is_user(void) const - { - return m_type == SidTypeUser; - } - - bool operator==(const Sid&); - - operator PSID() const - { - return (PSID)m_data->User.Sid; - } - -#ifndef DBUG_OFF - -private: - char *m_as_string; ///< Cached string representation of the SID. -public: - const char* as_string(); - -#endif -}; - - -/** UPN class **************************************************************/ - -/** - An object of this class obtains and stores User Principal Name of the - account under which current process is running. -*/ - -class UPN -{ - char *m_buf; ///< Pointer to UPN in utf8 representation. - size_t m_len; ///< Length of the name. - -public: - - UPN(); - ~UPN(); - - bool is_valid() const - { - return m_len > 0; - } - - const Blob as_blob() const - { - return m_len ? Blob((byte*)m_buf, m_len) : Blob(); - } - - const char* as_string() const - { - return (const char*)m_buf; - } - -}; - - -char* wchar_to_utf8(const wchar_t*, size_t*); -wchar_t* utf8_to_wchar(const char*, size_t*); - -#endif diff --git a/mysql/libmysql/authentication_win/handshake.cpp b/mysql/libmysql/authentication_win/handshake.cpp deleted file mode 100644 index 7801bb0..0000000 --- a/mysql/libmysql/authentication_win/handshake.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ - -#include "handshake.h" - - -/** Handshake class implementation **********************************/ - -/** - Create common part of handshake context. - - @param[in] ssp name of the SSP (Security Service Provider) to - be used for authentication - @param[in] side is this handshake object used for server- or - client-side handshake - - Prepare for handshake using the @c ssp security module. We use - "Negotiate" which picks best available module. Parameter @c side - tells if this is preparing for server or client side authentication - and is used to prepare appropriate credentials. -*/ - -Handshake::Handshake(const char *ssp, side_t side) -: m_atts(0L), m_error(0), m_complete(FALSE), - m_have_credentials(false), m_have_sec_context(false) -#ifndef DBUG_OFF - , m_ssp_info(NULL) -#endif -{ - SECURITY_STATUS ret; - - // Obtain credentials for the authentication handshake. - - ret= AcquireCredentialsHandle(NULL, (SEC_CHAR*)ssp, - side == SERVER ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND, - NULL, NULL, NULL, NULL, &m_cred, &m_expire); - - if (ret != SEC_E_OK) - { - DBUG_PRINT("error", ("AcqireCredentialsHandle() failed" - " with error %X", ret)); - ERROR_LOG(ERROR, ("Could not obtain local credentials" - " required for authentication")); - m_error= ret; - } - - m_have_credentials= true; -} - - -Handshake::~Handshake() -{ - if (m_have_credentials) - FreeCredentialsHandle(&m_cred); - if (m_have_sec_context) - DeleteSecurityContext(&m_sctx); - m_output.mem_free(); - -#ifndef DBUG_OFF - if (m_ssp_info) - FreeContextBuffer(m_ssp_info); -#endif -} - - -/** - Read and process data packets from the other end of a connection. - - @param[IN] con a connection to read packets from - - Packets are read and processed until authentication handshake is - complete. It is assumed that the peer will send at least one packet. - Packets are processed with @c process_data() method. If new data is - generated during packet processing, this data is sent to the peer and - another round of packet exchange starts. - - @return 0 on success. - - @note In case of error, appropriate error message is logged. -*/ -int Handshake::packet_processing_loop() -{ - m_round= 0; - - do { - ++m_round; - // Read packet send by the peer - - DBUG_PRINT("info", ("Waiting for packet")); - Blob packet= read_packet(); - if (error()) - { - ERROR_LOG(ERROR, ("Error reading packet in round %d", m_round)); - return 1; - } - DBUG_PRINT("info", ("Got packet of length %d", packet.len())); - - /* - Process received data, possibly generating new data to be sent. - */ - - Blob new_data= process_data(packet); - - if (error()) - { - ERROR_LOG(ERROR, ("Error processing packet in round %d", m_round)); - return 1; - } - - /* - If new data has been generated, send it to the peer. Otherwise - handshake must be completed. - */ - - if (!new_data.is_null()) - { - DBUG_PRINT("info", ("Round %d started", m_round)); - - DBUG_PRINT("info", ("Sending packet of length %d", new_data.len())); - int ret= write_packet(new_data); - if (ret) - { - ERROR_LOG(ERROR, ("Error writing packet in round %d", m_round)); - return 1; - } - DBUG_PRINT("info", ("Data sent")); - } - else if (!is_complete()) - { - ERROR_LOG(ERROR, ("No data to send in round %d" - " but handshake is not complete", m_round)); - return 1; - } - - /* - To protect against malicious clients, break handshake exchange if - too many rounds. - */ - - if (m_round > MAX_HANDSHAKE_ROUNDS) - { - ERROR_LOG(ERROR, ("Authentication handshake could not be completed" - " after %d rounds", m_round)); - return 1; - } - - } while(!is_complete()); - - ERROR_LOG(INFO, ("Handshake completed after %d rounds", m_round)); - return 0; -} - - -#ifndef DBUG_OFF - -/** - Get name of the security package which was used in authentication. - - This method should be called only after handshake was completed. It is - available only in debug builds. - - @return Name of security package or NULL if it can not be obtained. -*/ - -const char* Handshake::ssp_name() -{ - if (!m_ssp_info && m_complete) - { - SecPkgContext_PackageInfo pinfo; - - int ret= QueryContextAttributes(&m_sctx, SECPKG_ATTR_PACKAGE_INFO, &pinfo); - - if (SEC_E_OK == ret) - { - m_ssp_info= pinfo.PackageInfo; - } - else - DBUG_PRINT("error", - ("Could not obtain SSP info from authentication context" - ", QueryContextAttributes() failed with error %X", ret)); - } - - return m_ssp_info ? m_ssp_info->Name : NULL; -} - -#endif - - -/** - Process result of @c {Initialize,Accept}SecurityContext() function. - - @param[in] ret return code from @c {Initialize,Accept}SecurityContext() - function - - This function analyses return value of Windows - @c {Initialize,Accept}SecurityContext() function. A call to - @c CompleteAuthToken() is done if requested. If authentication is complete, - this fact is marked in the internal state of the Handshake object. - If errors are detected the object is moved to error state. - - @return True if error has been detected. -*/ - -bool Handshake::process_result(int ret) -{ - /* - First check for errors and set the m_complete flag if the result - indicates that handshake is complete. - */ - - switch (ret) - { - case SEC_E_OK: - case SEC_I_COMPLETE_NEEDED: - // Handshake completed - m_complete= true; - break; - - case SEC_I_CONTINUE_NEEDED: - case SEC_I_COMPLETE_AND_CONTINUE: - break; - - default: - m_error= ret; - return true; - } - - m_have_sec_context= true; - - /* - If the result indicates a need for this, complete the authentication - token. - */ - - switch (ret) - { - case SEC_I_COMPLETE_NEEDED: - case SEC_I_COMPLETE_AND_CONTINUE: - ret= CompleteAuthToken(&m_sctx, &m_output); - if (ret != 0) - { - DBUG_PRINT("error", ("CompleteAuthToken() failed with error %X", ret)); - m_error= ret; - return true; - } - default: - break; - } - - return false; -} - - -/** Security_buffer class implementation **********************************/ - - -Security_buffer::Security_buffer(const Blob &blob): m_allocated(false) -{ - init(blob.ptr(), blob.len()); -} - - -Security_buffer::Security_buffer(): m_allocated(true) -{ - init(NULL, 0); -} - - -void Security_buffer::mem_free(void) -{ - if (m_allocated && NULL != ptr()) - { - FreeContextBuffer(ptr()); - init(NULL, 0); - } -} diff --git a/mysql/libmysql/authentication_win/handshake.h b/mysql/libmysql/authentication_win/handshake.h deleted file mode 100644 index 14b1386..0000000 --- a/mysql/libmysql/authentication_win/handshake.h +++ /dev/null @@ -1,181 +0,0 @@ -/* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ - -#ifndef HANDSHAKE_H -#define HANDSHAKE_H - -#include "common.h" - -/** - Name of the SSP (Security Support Provider) to be used for authentication. - - We use "Negotiate" which will find the most secure SSP which can be used - and redirect to that SSP. -*/ -#define SSP_NAME "Negotiate" - -/** - Maximal number of rounds in authentication handshake. - - Server will interrupt authentication handshake with error if client's - identity can not be determined within this many rounds. -*/ -#define MAX_HANDSHAKE_ROUNDS 50 - - -/// Convenience wrapper around @c SecBufferDesc. - -class Security_buffer: public SecBufferDesc -{ - SecBuffer m_buf; ///< A @c SecBuffer instance. - - void init(byte *ptr, size_t len) - { - ulVersion= 0; - cBuffers= 1; - pBuffers= &m_buf; - - m_buf.BufferType= SECBUFFER_TOKEN; - m_buf.pvBuffer= ptr; - m_buf.cbBuffer= (ulong)len; - } - - /// If @c false, no deallocation will be done in the destructor. - const bool m_allocated; - - // Copying/assignment is not supported and can lead to memory leaks - // So declaring copy constructor and assignment operator as private - Security_buffer( const Security_buffer& ); - const Security_buffer& operator=( const Security_buffer& ); - - public: - - Security_buffer(const Blob&); - Security_buffer(); - - ~Security_buffer() - { - mem_free(); - } - - byte* ptr() const - { - return (byte*)m_buf.pvBuffer; - } - - size_t len() const - { - return m_buf.cbBuffer; - } - - const Blob as_blob() const - { - return Blob(ptr(), len()); - } - - void mem_free(void); -}; - - -/// Common base for Handshake_{server,client}. - -class Handshake -{ -public: - - typedef enum {CLIENT, SERVER} side_t; - - Handshake(const char *ssp, side_t side); - virtual ~Handshake(); - - int Handshake::packet_processing_loop(); - - bool virtual is_complete() const - { - return m_complete; - } - - int error() const - { - return m_error; - } - -protected: - - /// Security context object created during the handshake. - CtxtHandle m_sctx; - - /// Credentials of the principal performing this handshake. - CredHandle m_cred; - - /// Stores expiry date of the created security context. - TimeStamp m_expire; - - /// Stores attributes of the created security context. - ULONG m_atts; - - /** - Round of the handshake (starting from round 1). One round - consist of reading packet from the other side, processing it and - optionally sending a reply (see @c packet_processing_loop()). - */ - unsigned int m_round; - - /// If non-zero, stores error code of the last failed operation. - int m_error; - - /// @c true when handshake is complete. - bool m_complete; - - /// @c true when the principal credentials has been determined. - bool m_have_credentials; - - /// @c true when the security context has been created. - bool m_have_sec_context; - - /// Buffer for data to be send to the other side. - Security_buffer m_output; - - bool process_result(int); - - /** - This method is used inside @c packet_processing_loop to process - data packets received from the other end. - - @param[IN] data data to be processed - - @return A blob with data to be sent to the other end or null blob if - no more data needs to be exchanged. - */ - virtual Blob process_data(const Blob &data) =0; - - /// Read packet from the other end. - virtual Blob read_packet() =0; - - /// Write packet to the other end. - virtual int write_packet(Blob &data) =0; - -#ifndef DBUG_OFF - -private: - SecPkgInfo *m_ssp_info; -public: - const char* ssp_name(); - -#endif -}; - - -#endif diff --git a/mysql/libmysql/authentication_win/handshake_client.cpp b/mysql/libmysql/authentication_win/handshake_client.cpp deleted file mode 100644 index 4cf6219..0000000 --- a/mysql/libmysql/authentication_win/handshake_client.cpp +++ /dev/null @@ -1,393 +0,0 @@ -/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ - -#include "handshake.h" - -#include // for MYSQL structure - - -/// Client-side context for authentication handshake - -class Handshake_client: public Handshake -{ - /** - Name of the server's service for which we authenticate. - - The service name is sent by server in the initial packet. If no - service name is used, this member is @c NULL. - */ - SEC_WCHAR *m_service_name; - - /// Buffer for storing service name obtained from server. - SEC_WCHAR m_service_name_buf[MAX_SERVICE_NAME_LENGTH]; - - Connection &m_con; - -public: - - Handshake_client(Connection &con, const char *target, size_t len); - ~Handshake_client(); - - Blob first_packet(); - Blob process_data(const Blob&); - - Blob read_packet(); - int write_packet(Blob &data); -}; - - -/** - Create authentication handshake context for client. - - @param con connection for communication with the peer - @param target name of the target service with which we will authenticate - (can be NULL if not used) - - Some security packages (like Kerberos) require providing explicit name - of the service with which a client wants to authenticate. The server-side - authentication plugin sends this name in the greeting packet - (see @c win_auth_handshake_{server,client}() functions). -*/ - -Handshake_client::Handshake_client(Connection &con, - const char *target, size_t len) -: Handshake(SSP_NAME, CLIENT), m_service_name(NULL), m_con(con) -{ - if (!target || 0 == len) - return; - - // Convert received UPN to internal WCHAR representation. - - m_service_name= utf8_to_wchar(target, &len); - - if (m_service_name) - DBUG_PRINT("info", ("Using target service: %S\n", m_service_name)); - else - { - /* - Note: we ignore errors here - m_target will be NULL, the target name - will not be used and system will fall-back to NTLM authentication. But - we leave trace in error log. - */ - ERROR_LOG(WARNING, ("Could not decode UPN sent by the server" - "; target service name will not be used" - " and Kerberos authentication will not work")); - } -} - - -Handshake_client::~Handshake_client() -{ - if (m_service_name) - free(m_service_name); -} - - -Blob Handshake_client::read_packet() -{ - /* - We do a fake read in the first round because first - packet from the server containing UPN must be read - before the handshake context is created and the packet - processing loop starts. We return an empty blob here - and process_data() function will ignore it. - */ - if (m_round == 1) - return Blob(); - - // Otherwise we read packet from the connection. - - Blob packet= m_con.read(); - m_error= m_con.error(); - if (!m_error && packet.is_null()) - m_error= true; // (no specific error code assigned) - - if (m_error) - return Blob(); - - DBUG_PRINT("dump", ("Got the following bytes")); - DBUG_DUMP("dump", packet.ptr(), packet.len()); - return packet; -} - - - -int Handshake_client::write_packet(Blob &data) -{ - /* - Length of the first data payload send by client authentication plugin is - limited to 255 bytes (because it is wrapped inside client authentication - packet and is length-encoded with 1 byte for the length). - - If the data payload is longer than 254 bytes, then it is sent in two parts: - first part of length 255 will be embedded in the authentication packet, - second part will be sent in the following packet. Byte 255 of the first - part contains information about the total length of the payload. It is a - number of blocks of size 512 bytes which is sufficient to store the - combined packets. - - Server's logic for reading first client's payload is as follows - (see Handshake_server::read_packet()): - 1. Read data from the authentication packet, if it is shorter than 255 bytes - then that is all data sent by client. - 2. If there is 255 bytes of data in the authentication packet, read another - packet and append it to the data, skipping byte 255 of the first packet - which can be used to allocate buffer of appropriate size. - */ - - size_t len2= 0; // length of the second part of first data payload - byte saved_byte; // for saving byte 255 in which data length is stored - - if (m_round == 1 && data.len() > 254) - { - len2= data.len() - 254; - DBUG_PRINT("info", ("Splitting first packet of length %lu" - ", %lu bytes will be sent in a second part", - data.len(), len2)); - /* - Store in byte 255 the number of 512b blocks that are needed to - keep all the data. - */ - unsigned block_count= data.len()/512 + ((data.len() % 512) ? 1 : 0); - -#if !defined(DBUG_OFF) && defined(WINAUTH_USE_DBUG_LIB) - - /* - For testing purposes, use wrong block count to see how server - handles this. - */ - DBUG_EXECUTE_IF("winauth_first_packet_test",{ - block_count= data.len() == 601 ? 0 : - data.len() == 602 ? 1 : - block_count; - }); - -#endif - - DBUG_ASSERT(block_count < (unsigned)0x100); - saved_byte= data[254]; - data[254] = block_count; - - data.trim(255); - } - - DBUG_PRINT("dump", ("Sending the following data")); - DBUG_DUMP("dump", data.ptr(), data.len()); - int ret= m_con.write(data); - - if (ret) - return ret; - - // Write second part if it is present. - if (len2) - { - data[254]= saved_byte; - Blob data2(data.ptr() + 254, len2); - DBUG_PRINT("info", ("Sending second part of data")); - DBUG_DUMP("info", data2.ptr(), data2.len()); - ret= m_con.write(data2); - } - - return ret; -} - - -/** - Process data sent by server. - - @param[in] data blob with data from server - - This method analyses data sent by server during authentication handshake. - If client should continue packet exchange, this method returns data to - be sent to the server next. If no more data needs to be exchanged, an - empty blob is returned and @c is_complete() is @c true. In case of error - an empty blob is returned and @c error() gives non-zero error code. - - When invoked for the first time (in the first round of the handshake) - there is no data from the server (data blob is null) and the intial - packet is generated without an input. - - @return Data to be sent to the server next or null blob if no more data - needs to be exchanged or in case of error. -*/ - -Blob Handshake_client::process_data(const Blob &data) -{ -#if !defined(DBUG_OFF) && defined(WINAUTH_USE_DBUG_LIB) - /* - Code for testing the logic for sending the first client payload. - - A fake data of length given by environment variable TEST_PACKET_LENGTH - (or default 255 bytes) is sent to the server. First 2 bytes of the - payload contain its total length (LSB first). The length of test data - is limited to 2048 bytes. - - Upon receiving test data, server will check that data is correct and - refuse connection. If server detects data errors it will crash on - assertion. - - This code is executed if debug flag "winauth_first_packet_test" is - set, e.g. using client option: - - --debug="d,winauth_first_packet_test" - - The same debug flag must be enabled in the server, e.g. using - statement: - - SET GLOBAL debug= '+d,winauth_first_packet_test'; - */ - - static byte test_buf[2048]; - - if (m_round == 1 - && DBUG_EVALUATE_IF("winauth_first_packet_test", true, false)) - { - const char *env= getenv("TEST_PACKET_LENGTH"); - size_t len= env ? atoi(env) : 0; - if (!len) - len= 255; - if (len > sizeof(test_buf)) - len= sizeof(test_buf); - - // Store data length in first 2 bytes. - byte *ptr= test_buf; - *ptr++= len & 0xFF; - *ptr++= len >> 8; - - // Fill remaining bytes with known values. - for (byte b= 0; ptr < test_buf + len; ++ptr, ++b) - *ptr= b; - - return Blob(test_buf, len); - }; - -#endif - - Security_buffer input(data); - SECURITY_STATUS ret; - - m_output.mem_free(); - - ret= InitializeSecurityContextW( - &m_cred, - m_round == 1 ? NULL : &m_sctx, // partial context - m_service_name, // service name - ASC_REQ_ALLOCATE_MEMORY, // requested attributes - 0, // reserved - SECURITY_NETWORK_DREP, // data representation - m_round == 1 ? NULL : &input, // input data - 0, // reserved - &m_sctx, // context - &m_output, // output data - &m_atts, // attributes - &m_expire); // expire date - - if (process_result(ret)) - { - DBUG_PRINT("error", - ("InitializeSecurityContext() failed with error %X", ret)); - return Blob(); - } - - return m_output.as_blob(); -} - - -/**********************************************************************/ - - -/** - Perform authentication handshake from client side. - - @param[in] vio pointer to @c MYSQL_PLUGIN_VIO instance to be used - for communication with the server - @param[in] mysql pointer to a MySQL connection for which we authenticate - - After reading the initial packet from server, containing its UPN to be - used as service name, client starts packet exchange by sending the first - packet in this exchange. While handshake is not yet completed, client - reads packets sent by the server and process them, possibly generating new - data to be sent to the server. - - This function reports errors. - - @return 0 on success. -*/ - -int win_auth_handshake_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql) -{ - DBUG_ENTER("win_auth_handshake_client"); - - /* - Check if we should enable logging. - */ - { - const char *opt= getenv("AUTHENTICATION_WIN_LOG"); - int opt_val= opt ? atoi(opt) : 0; - if (opt && !opt_val) - { - if (!_strnicmp("on", opt, 2)) opt_val= 2; - if (!_strnicmp("yes", opt, 3)) opt_val= 2; - if (!_strnicmp("true", opt, 4)) opt_val= 2; - if (!_strnicmp("debug", opt, 5)) opt_val= 4; - if (!_strnicmp("dbug", opt, 4)) opt_val= 4; - } - set_log_level(opt_val); - } - - ERROR_LOG(INFO, ("Authentication handshake for account %s", mysql->user)); - - // Create connection object. - - Connection con(vio); - DBUG_ASSERT(!con.error()); - - // Read initial packet from server containing service name. - - Blob service_name= con.read(); - - if (con.error() || service_name.is_null()) - { - ERROR_LOG(ERROR, ("Error reading initial packet")); - DBUG_RETURN(CR_ERROR); - } - DBUG_PRINT("info", ("Got initial packet of length %d", service_name.len())); - - // Create authentication handshake context using the given service name. - - Handshake_client hndshk(con, - service_name[0] ? (char *)service_name.ptr() : NULL, - service_name.len()); - if (hndshk.error()) - { - ERROR_LOG(ERROR, ("Could not create authentication handshake context")); - DBUG_RETURN(CR_ERROR); - } - - DBUG_ASSERT(!hndshk.error()); - - /* - Read and process packets from server until handshake is complete. - Note that the first read from server is dummy - (see Handshake_client::read_packet()) as we already have read the - first packet to establish service name. - */ - if (hndshk.packet_processing_loop()) - DBUG_RETURN(CR_ERROR); - - DBUG_ASSERT(!hndshk.error() && hndshk.is_complete()); - - DBUG_RETURN(CR_OK); -} diff --git a/mysql/libmysql/authentication_win/log_client.cpp b/mysql/libmysql/authentication_win/log_client.cpp deleted file mode 100644 index 6973c95..0000000 --- a/mysql/libmysql/authentication_win/log_client.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ - -#include -#include "common.h" - - -// Client-side logging function - -void error_log_vprint(error_log_level::type level, - const char *fmt, va_list args) -{ - const char *level_string= ""; - int log_level= get_log_level(); - - switch (level) - { - case error_log_level::INFO: - if (3 > log_level) - return; - level_string= "Note"; - break; - case error_log_level::WARNING: - if (2 > log_level) - return; - level_string= "Warning"; - break; - case error_log_level::ERROR: - if (1 > log_level) - return; - level_string= "ERROR"; - break; - } - - fprintf(stderr, "Windows Authentication Plugin %s: ", level_string); - vfprintf(stderr, fmt, args); - fputc('\n', stderr); - fflush(stderr); -} - - -// Trivial implementation of log-level setting storage. - -void set_log_level(unsigned int level) -{ - opt_auth_win_log_level= level; -} - - -unsigned int get_log_level(void) -{ - return opt_auth_win_log_level; -} diff --git a/mysql/libmysql/authentication_win/plugin_client.cpp b/mysql/libmysql/authentication_win/plugin_client.cpp deleted file mode 100644 index d25aae8..0000000 --- a/mysql/libmysql/authentication_win/plugin_client.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ - -#include -#include -#include - -#include "common.h" - -/* - The following MS C++ specific pragma embeds a comment in the resulting - object file. A "lib" comment tells the linker to use the specified - library, thus the dependency is handled automagically. -*/ - -#ifdef _MSC_VER -#pragma comment(lib, "Secur32") -#endif - -static int win_auth_client_plugin_init(char*, size_t, int, va_list) -{ - return 0; -} - - -static int win_auth_client_plugin_deinit() -{ - return 0; -} - - -int win_auth_handshake_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql); - - -/* - Client plugin declaration. This is added to mysql_client_builtins[] - in sql-common/client.c -*/ - -extern "C" -st_mysql_client_plugin_AUTHENTICATION win_auth_client_plugin= -{ - MYSQL_CLIENT_AUTHENTICATION_PLUGIN, - MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION, - "authentication_windows_client", - "Rafal Somla", - "Windows Authentication Plugin - client side", - {0,1,0}, - "GPL", - NULL, - win_auth_client_plugin_init, - win_auth_client_plugin_deinit, - NULL, // option handling - win_auth_handshake_client -}; -- cgit v1.1