Merge branch '2.2' into develop

This commit is contained in:
Johan Wikman 2018-01-29 12:59:06 +02:00
commit dccf508e54
6 changed files with 83 additions and 58 deletions

View File

@ -48,7 +48,7 @@ cp _build/*.gz .
set -x
if [ "$build_experimental" == "yes" ]
then
for component in experimental devel client
for component in experimental devel
do
cd _build
rm CMakeCache.txt

View File

@ -43,7 +43,7 @@ cp _build/*.gz .
if [ "$build_experimental" == "yes" ]
then
for component in experimental devel client
for component in experimental devel
do
cd _build
rm CMakeCache.txt

View File

@ -27,6 +27,9 @@ set(BUILD_CDC TRUE CACHE BOOL "Build Avro router")
# Build the multimaster monitor
set(BUILD_MMMON TRUE CACHE BOOL "Build multimaster monitor")
# Build MaxCtrl
set(BUILD_MAXCTRL TRUE CACHE BOOL "Build MaxCtrl")
# Build Luafilter
set(BUILD_LUAFILTER FALSE CACHE BOOL "Build Luafilter")

View File

@ -43,7 +43,7 @@
MXS_BEGIN_DECLS
#define GW_MYSQL_VERSION "5.5.5-10.0.0 " MAXSCALE_VERSION "-maxscale"
#define GW_MYSQL_VERSION "5.5.5-10.2.12 " MAXSCALE_VERSION "-maxscale"
#define GW_MYSQL_LOOP_TIMEOUT 300000000
#define GW_MYSQL_READ 0
#define GW_MYSQL_WRITE 1

View File

@ -1,20 +1,24 @@
find_package(NPM)
find_package(NodeJS)
if (BUILD_MAXCTRL)
find_package(NPM)
find_package(NodeJS)
if (NPM_FOUND AND NODEJS_FOUND AND NODEJS_VERSION VERSION_GREATER "6.0.0")
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/maxctrl/maxctrl
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build.sh ${CMAKE_SOURCE_DIR}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_custom_target(maxctrl ALL DEPENDS ${CMAKE_BINARY_DIR}/maxctrl/maxctrl)
install_script(${CMAKE_BINARY_DIR}/maxctrl/maxctrl client)
if (NPM_FOUND AND NODEJS_FOUND AND NODEJS_VERSION VERSION_GREATER "6.0.0")
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/maxctrl/maxctrl
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build.sh ${CMAKE_SOURCE_DIR}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_custom_target(maxctrl ALL DEPENDS ${CMAKE_BINARY_DIR}/maxctrl/maxctrl)
install_script(${CMAKE_BINARY_DIR}/maxctrl/maxctrl core)
add_custom_target(test_maxctrl
COMMAND ${CMAKE_SOURCE_DIR}/test/run_npm_test.sh
${CMAKE_SOURCE_DIR} # Path to MaxScale sources
${CMAKE_CURRENT_SOURCE_DIR} # Path to test sources
${CMAKE_BINARY_DIR}/maxctrl-test/ # Location where tests are built and run
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_custom_target(test_maxctrl
COMMAND ${CMAKE_SOURCE_DIR}/test/run_npm_test.sh
${CMAKE_SOURCE_DIR} # Path to MaxScale sources
${CMAKE_CURRENT_SOURCE_DIR} # Path to test sources
${CMAKE_BINARY_DIR}/maxctrl-test/ # Location where tests are built and run
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
else()
message(FATAL_ERROR "Not building MaxCtrl: npm or Node.js >= 6.0.0 not found. Add the following to skip MaxCtrl: -DBUILD_MAXCTRL=N")
endif()
else()
message(STATUS "Not building MaxCtrl: npm or Node.js >= 6.0.0 not found")
messages(STATUS "Not building MaxCtrl: BUILD_MAXCTRL=N")
endif()

View File

@ -138,15 +138,15 @@ int conversation_func(int num_msg, const struct pam_message **msg,
}
/**
* @brief Check if the client token is valid
* @brief Check if the client password is correct for the service
*
* @param token Client token
* @param len Length of the token
* @param output Pointer where the client principal name is stored
* @return True if client token is valid
* @param user Username
* @param password Password
* @param service Which PAM service is the user logging to
* @param client Client DCB
* @return True if username & password are ok
*/
bool validate_pam_password(const string& user, const string& password,
const string& service, DCB* client)
bool validate_pam_password(const string& user, const string& password, const string& service, DCB* client)
{
ConversationData appdata(client, 0, password);
pam_conv conv_struct = {conversation_func, &appdata};
@ -164,8 +164,7 @@ bool validate_pam_password(const string& user, const string& password,
MXS_DEBUG("pam_authenticate returned success.");
break;
case PAM_AUTH_ERR:
MXS_DEBUG("pam_authenticate returned authentication failure"
" (wrong password).");
MXS_DEBUG("pam_authenticate returned authentication failure (wrong password).");
// Normal failure
break;
default:
@ -223,13 +222,11 @@ PamClientSession* PamClientSession::create(const PamInstance& inst)
}
/**
* @brief Check which PAM services the session user has access to
* Check which PAM services the session user has access to.
*
* @param auth Authenticator session
* @param dcb Client DCB
* @param session MySQL session
*
* @return An array of PAM service names for the session user
* @param services_out Output for services
*/
void PamClientSession::get_pam_user_services(const DCB* dcb, const MYSQL_session* session,
StringVector* services_out)
@ -241,28 +238,14 @@ void PamClientSession::get_pam_user_services(const DCB* dcb, const MYSQL_session
"' LIKE db) ORDER BY authentication_string";
MXS_DEBUG("PAM services search sql: '%s'.", services_query.c_str());
char *err;
/**
* Try search twice: first time with the current users, second
* time with fresh users.
*/
for (int i = 0; i < 2; i++)
if (sqlite3_exec(m_dbhandle, services_query.c_str(), user_services_cb,
services_out, &err) != SQLITE_OK)
{
if (i == 0 || service_refresh_users(dcb->service) == 0)
{
if (sqlite3_exec(m_dbhandle, services_query.c_str(), user_services_cb,
services_out, &err) != SQLITE_OK)
{
MXS_ERROR("Failed to execute query: '%s'", err);
sqlite3_free(err);
}
else if (!services_out->empty())
{
MXS_DEBUG("User '%s' matched %lu rows in %s db.", session->user,
services_out->size(), m_instance.m_tablename.c_str());
break;
}
}
MXS_ERROR("Failed to execute query: '%s'", err);
sqlite3_free(err);
}
MXS_DEBUG("User '%s' matched %lu rows in %s db.", session->user,
services_out->size(), m_instance.m_tablename.c_str());
}
/**
@ -328,17 +311,52 @@ int PamClientSession::authenticate(DCB* dcb)
* responded with the password. Try to continue authentication without more
* messages to client. */
string password((char*)ses->auth_token, ses->auth_token_len);
StringVector services;
get_pam_user_services(dcb, ses, &services);
for (StringVector::const_iterator i = services.begin(); i != services.end(); i++)
/*
* Authentication may be attempted twice: first with old user account info and then with
* updated info. Updating may fail if it has been attempted too often lately. The second password
* check is useless if the user services are same as on the first attempt.
*/
bool authenticated = false;
StringVector services_old;
for (int loop = 0; loop < 2 && !authenticated; loop++)
{
if (validate_pam_password(ses->user, password, *i, dcb))
if (loop == 0 || service_refresh_users(dcb->service) == 0)
{
rval = MXS_AUTH_SUCCEEDED;
break;
bool try_validate = true;
StringVector services;
get_pam_user_services(dcb, ses, &services);
if (loop == 0)
{
services_old = services;
}
else if (services == services_old)
{
try_validate = false;
}
if (try_validate)
{
for (StringVector::iterator iter = services.begin();
iter != services.end() && !authenticated;
iter++)
{
// The server PAM plugin uses "mysql" as the default service when authenticating
// a user with no service.
if (iter->empty())
{
*iter = "mysql";
}
if (validate_pam_password(ses->user, password, *iter, dcb))
{
authenticated = true;
}
}
}
}
}
if (authenticated)
{
rval = MXS_AUTH_SUCCEEDED;
}
}
}
return rval;