Merge branch 'develop' of github.com:skysql/MaxScale into develop
This commit is contained in:
commit
0cd97ea482
@ -144,6 +144,7 @@ add_custom_target(buildtests
|
||||
add_custom_target(testall
|
||||
COMMAND ${CMAKE_COMMAND} -DDEPS_OK=Y -DBUILD_TESTS=Y -DBUILD_TYPE=Debug -DINSTALL_DIR=${CMAKE_BINARY_DIR} -DINSTALL_SYSTEM_FILES=N ${CMAKE_SOURCE_DIR}
|
||||
COMMAND make install
|
||||
COMMAND cp -vn ${CMAKE_SOURCE_DIR}/server/test/MaxScale_test.cnf ${CMAKE_BINARY_DIR}/etc/MaxScale.cnf
|
||||
COMMAND /bin/sh -c "${CMAKE_BINARY_DIR}/bin/maxscale -c ${CMAKE_BINARY_DIR} &>/dev/null"
|
||||
COMMAND /bin/sh -c "make test || echo \"Test results written to: ${CMAKE_BINARY_DIR}/Testing/Temporary/\""
|
||||
COMMAND killall maxscale
|
||||
|
16
macros.cmake
16
macros.cmake
@ -127,13 +127,17 @@ debugmsg("Search returned: ${MYSQL_DIR_LOC}")
|
||||
# Find the embedded mysql library
|
||||
|
||||
if (DEFINED EMBEDDED_LIB)
|
||||
debugmsg("Searching for the embedded library at: ${EMBEDDED_LIB}")
|
||||
if(${CMAKE_VERSION} VERSION_LESS 2.12 )
|
||||
set(COMP_VAR PATH)
|
||||
else()
|
||||
set(COMP_VAR DIRECTORY)
|
||||
if( NOT (IS_DIRECTORY ${EMBEDDED_LIB}) )
|
||||
debugmsg("EMBEDDED_LIB is not a directory: ${EMBEDDED_LIB}")
|
||||
if(${CMAKE_VERSION} VERSION_LESS 2.12 )
|
||||
set(COMP_VAR PATH)
|
||||
else()
|
||||
set(COMP_VAR DIRECTORY)
|
||||
endif()
|
||||
get_filename_component(EMBEDDED_LIB ${EMBEDDED_LIB} ${COMP_VAR})
|
||||
debugmsg("EMBEDDED_LIB directory component: ${EMBEDDED_LIB}")
|
||||
endif()
|
||||
get_filename_component(EMBEDDED_LIB ${EMBEDDED_LIB} ${COMP_VAR})
|
||||
debugmsg("Searching for the embedded library at: ${EMBEDDED_LIB}")
|
||||
endif()
|
||||
|
||||
if(STATIC_EMBEDDED)
|
||||
|
@ -1,6 +1,3 @@
|
||||
add_subdirectory(core)
|
||||
add_subdirectory(modules)
|
||||
add_subdirectory(inih)
|
||||
if(BUILD_TESTS)
|
||||
add_subdirectory(test)
|
||||
endif()
|
@ -28,6 +28,9 @@
|
||||
* 06/02/2014 Massimiliano Pinto Mysql user root selected based on configuration flag
|
||||
* 26/02/2014 Massimiliano Pinto Addd: replace_mysql_users() routine may replace users' table based on a checksum
|
||||
* 28/02/2014 Massimiliano Pinto Added Mysql user@host authentication
|
||||
* 29/09/2014 Massimiliano Pinto Added Mysql user@host authentication with wildcard in IPv4 hosts:
|
||||
* x.y.z.%, x.y.%.%, x.%.%.%
|
||||
* 03/10/14 Massimiliano Pinto Added netmask to user@host authentication for wildcard in IPv4 hosts
|
||||
*
|
||||
* @endverbatim
|
||||
*/
|
||||
@ -50,13 +53,14 @@
|
||||
|
||||
extern int lm_enabled_logfiles_bitmask;
|
||||
|
||||
static int getUsers(SERVICE *service, struct users *users);
|
||||
static int getUsers(SERVICE *service, USERS *users);
|
||||
static int uh_cmpfun( void* v1, void* v2);
|
||||
static void *uh_keydup(void* key);
|
||||
static void uh_keyfree( void* key);
|
||||
static int uh_hfun( void* key);
|
||||
char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key);
|
||||
char *mysql_format_user_entry(void *data);
|
||||
int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *passwd);
|
||||
|
||||
/**
|
||||
* Load the user/passwd form mysql.user table into the service users' hashtable
|
||||
@ -82,7 +86,7 @@ int
|
||||
reload_mysql_users(SERVICE *service)
|
||||
{
|
||||
int i;
|
||||
struct users *newusers, *oldusers;
|
||||
USERS *newusers, *oldusers;
|
||||
|
||||
if ((newusers = mysql_users_alloc()) == NULL)
|
||||
return 0;
|
||||
@ -108,15 +112,17 @@ int
|
||||
replace_mysql_users(SERVICE *service)
|
||||
{
|
||||
int i;
|
||||
struct users *newusers, *oldusers;
|
||||
USERS *newusers, *oldusers;
|
||||
|
||||
if ((newusers = mysql_users_alloc()) == NULL)
|
||||
return -1;
|
||||
|
||||
i = getUsers(service, newusers);
|
||||
|
||||
if (i <= 0)
|
||||
if (i <= 0) {
|
||||
users_free(newusers);
|
||||
return i;
|
||||
}
|
||||
|
||||
spinlock_acquire(&service->spin);
|
||||
oldusers = service->users;
|
||||
@ -148,6 +154,92 @@ struct users *newusers, *oldusers;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a new MySQL user with host, password and netmask into the service users table
|
||||
*
|
||||
* The netmask values are:
|
||||
* 0 for any, 32 for single IPv4
|
||||
* 24 for a class C from a.b.c.%, 16 for a Class B from a.b.%.% and 8 for a Class A from a.%.%.%
|
||||
*
|
||||
* @param users The users table
|
||||
* @param user The user name
|
||||
* @param host The host to add, with possible wildcards
|
||||
* @param passwd The sha1(sha1(passoword)) to add
|
||||
* @return 1 on success, 0 on failure
|
||||
*/
|
||||
|
||||
int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *passwd) {
|
||||
struct sockaddr_in serv_addr;
|
||||
MYSQL_USER_HOST key;
|
||||
char ret_ip[INET_ADDRSTRLEN + 1]="";
|
||||
int found_range=0;
|
||||
int found_any=0;
|
||||
int ret = 0;
|
||||
|
||||
/* prepare the user@host data struct */
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
memset(&key, 0, sizeof(key));
|
||||
|
||||
/* set user */
|
||||
key.user = strdup(user);
|
||||
|
||||
if(key.user == NULL) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* handle ANY, Class C,B,A */
|
||||
|
||||
/* ANY */
|
||||
if (strcmp(host, "%") == 0) {
|
||||
strcpy(ret_ip, "0.0.0.0");
|
||||
found_any = 1;
|
||||
} else {
|
||||
char *tmp;
|
||||
strcpy(ret_ip, host);
|
||||
tmp = ret_ip+strlen(ret_ip)-1;
|
||||
|
||||
/* start from Class C */
|
||||
while(*tmp) {
|
||||
if (*tmp == '%') {
|
||||
/* set only the last IPv4 byte to 1
|
||||
* avoiding setipadress() failure
|
||||
* for Class C address
|
||||
*/
|
||||
found_range++;
|
||||
if (found_range == 1)
|
||||
*tmp = '1';
|
||||
else
|
||||
*tmp = '0';
|
||||
}
|
||||
tmp--;
|
||||
}
|
||||
}
|
||||
|
||||
/* fill IPv4 data struct */
|
||||
if (setipaddress(&serv_addr.sin_addr, ret_ip)) {
|
||||
|
||||
/* copy IPv4 data into key.ipv4 */
|
||||
memcpy(&key.ipv4, &serv_addr, sizeof(serv_addr));
|
||||
|
||||
if (found_range) {
|
||||
/* let's zero the last IP byte: a.b.c.0 we set above to 1*/
|
||||
key.ipv4.sin_addr.s_addr &= 0x00FFFFFF;
|
||||
key.netmask = 32 - (found_range * 8);
|
||||
} else {
|
||||
key.netmask = 32 - (found_any * 32);
|
||||
}
|
||||
|
||||
/* add user@host as key and passwd as value in the MySQL users hash table */
|
||||
if (mysql_users_add(users, &key, passwd))
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
free(key.user);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the user/passwd form mysql.user table into the service users' hashtable
|
||||
* environment.
|
||||
@ -157,7 +249,7 @@ struct users *newusers, *oldusers;
|
||||
* @return -1 on any error or the number of users inserted (0 means no users at all)
|
||||
*/
|
||||
static int
|
||||
getUsers(SERVICE *service, struct users *users)
|
||||
getUsers(SERVICE *service, USERS *users)
|
||||
{
|
||||
MYSQL *con = NULL;
|
||||
MYSQL_ROW row;
|
||||
@ -173,8 +265,6 @@ getUsers(SERVICE *service, struct users *users)
|
||||
char *users_data = NULL;
|
||||
int nusers = 0;
|
||||
int users_data_row_len = MYSQL_USER_MAXLEN + MYSQL_HOST_MAXLEN + MYSQL_PASSWORD_LEN;
|
||||
struct sockaddr_in serv_addr;
|
||||
MYSQL_USER_HOST key;
|
||||
|
||||
/* enable_root for MySQL protocol module means load the root user credentials from backend databases */
|
||||
if(service->enable_root) {
|
||||
@ -311,63 +401,26 @@ getUsers(SERVICE *service, struct users *users)
|
||||
* added to hashtable.
|
||||
*/
|
||||
|
||||
char ret_ip[INET_ADDRSTRLEN + 1]="";
|
||||
const char *rc;
|
||||
int rc = 0;
|
||||
|
||||
/* prepare the user@host data struct */
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
memset(&key, 0, sizeof(key));
|
||||
rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], strlen(row[2]) ? row[2]+1 : row[2]);
|
||||
|
||||
/* if host == '%', 0 is passed */
|
||||
if (setipaddress(&serv_addr.sin_addr, strcmp(row[1], "%") ? row[1] : "0.0.0.0")) {
|
||||
if (rc == 1) {
|
||||
LOGIF(LD, (skygw_log_write_flush(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [mysql_users_add()] Added user %s@%s",
|
||||
pthread_self(),
|
||||
row[0],
|
||||
row[1])));
|
||||
|
||||
key.user = strdup(row[0]);
|
||||
|
||||
if(key.user == NULL) {
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"%lu [getUsers()] strdup() failed for user %s",
|
||||
pthread_self(),
|
||||
row[0])));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(&key.ipv4, &serv_addr, sizeof(serv_addr));
|
||||
|
||||
rc = inet_ntop(AF_INET, &(serv_addr).sin_addr, ret_ip, INET_ADDRSTRLEN);
|
||||
|
||||
/* add user@host as key and passwd as value in the MySQL users hash table */
|
||||
if (mysql_users_add(users, &key, strlen(row[2]) ? row[2]+1 : row[2])) {
|
||||
LOGIF(LD, (skygw_log_write_flush(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [mysql_users_add()] Added user %s@%s(%s)",
|
||||
pthread_self(),
|
||||
row[0],
|
||||
row[1],
|
||||
rc == NULL ? "NULL" : ret_ip)));
|
||||
|
||||
/* Append data in the memory area for SHA1 digest */
|
||||
strncat(users_data, row[3], users_data_row_len);
|
||||
|
||||
total_users++;
|
||||
} else {
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"%lu [mysql_users_add()] Failed adding user %s@%s(%s)",
|
||||
pthread_self(),
|
||||
row[0],
|
||||
row[1],
|
||||
rc == NULL ? "NULL" : ret_ip)));
|
||||
}
|
||||
|
||||
free(key.user);
|
||||
/* Append data in the memory area for SHA1 digest */
|
||||
strncat(users_data, row[3], users_data_row_len);
|
||||
|
||||
total_users++;
|
||||
} else {
|
||||
/* setipaddress() failed, skip user add and log this*/
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"%lu [getUsers()] setipaddress failed: user %s@%s not added",
|
||||
"%lu [mysql_users_add()] Failed adding user %s@%s",
|
||||
pthread_self(),
|
||||
row[0],
|
||||
row[1])));
|
||||
@ -475,7 +528,7 @@ static int uh_hfun( void* key) {
|
||||
* Currently only IPv4 addresses are supported
|
||||
*
|
||||
* @param key1 The key value, i.e. username@host (IPv4)
|
||||
* @param key1 The key value, i.e. username@host (IPv4)
|
||||
* @param key2 The key value, i.e. username@host (IPv4)
|
||||
* @return The compare value
|
||||
*/
|
||||
|
||||
@ -486,7 +539,7 @@ static int uh_cmpfun( void* v1, void* v2) {
|
||||
if (v1 == NULL || v2 == NULL || hu1 == NULL || hu2 == NULL || hu1->user == NULL || hu2->user == NULL)
|
||||
return 0;
|
||||
|
||||
if (strcmp(hu1->user, hu2->user) == 0 && (hu1->ipv4.sin_addr.s_addr == hu2->ipv4.sin_addr.s_addr)) {
|
||||
if (strcmp(hu1->user, hu2->user) == 0 && (hu1->ipv4.sin_addr.s_addr == hu2->ipv4.sin_addr.s_addr) && (hu1->netmask >= hu2->netmask)) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
@ -513,6 +566,7 @@ static void *uh_keydup(void* key) {
|
||||
return NULL;
|
||||
|
||||
memcpy(&rval->ipv4, ¤t_key->ipv4, sizeof(struct sockaddr_in));
|
||||
memcpy(&rval->netmask, ¤t_key->netmask, sizeof(int));
|
||||
|
||||
return (void *) rval;
|
||||
}
|
||||
@ -561,13 +615,25 @@ char *mysql_format_user_entry(void *data)
|
||||
if (mysql_user == NULL)
|
||||
return NULL;
|
||||
|
||||
if (entry->ipv4.sin_addr.s_addr == INADDR_ANY) {
|
||||
snprintf(mysql_user, mysql_user_len, "%s@%%", entry->user);
|
||||
} else {
|
||||
if (entry->ipv4.sin_addr.s_addr == INADDR_ANY && entry->netmask == 0) {
|
||||
snprintf(mysql_user, mysql_user_len-1, "%s@%%", entry->user);
|
||||
} else if ( (entry->ipv4.sin_addr.s_addr & 0xFF000000) == 0 && entry->netmask == 24) {
|
||||
snprintf(mysql_user, mysql_user_len-1, "%s@%i.%i.%i.%%", entry->user, entry->ipv4.sin_addr.s_addr & 0x000000FF, (entry->ipv4.sin_addr.s_addr & 0x0000FF00) / (256), (entry->ipv4.sin_addr.s_addr & 0x00FF0000) / (256 * 256));
|
||||
} else if ( (entry->ipv4.sin_addr.s_addr & 0xFFFF0000) == 0 && entry->netmask == 16) {
|
||||
snprintf(mysql_user, mysql_user_len-1, "%s@%i.%i.%%.%%", entry->user, entry->ipv4.sin_addr.s_addr & 0x000000FF, (entry->ipv4.sin_addr.s_addr & 0x0000FF00) / (256));
|
||||
} else if ( (entry->ipv4.sin_addr.s_addr & 0xFFFFFF00) == 0 && entry->netmask == 8) {
|
||||
snprintf(mysql_user, mysql_user_len-1, "%s@%i.%%.%%.%%", entry->user, entry->ipv4.sin_addr.s_addr & 0x000000FF);
|
||||
} else if (entry->netmask == 32) {
|
||||
strncpy(mysql_user, entry->user, MYSQL_USER_MAXLEN);
|
||||
strcat(mysql_user, "@");
|
||||
inet_ntop(AF_INET, &(entry->ipv4).sin_addr, mysql_user+strlen(mysql_user), INET_ADDRSTRLEN);
|
||||
} else {
|
||||
snprintf(mysql_user, MYSQL_USER_MAXLEN-6, "warn: %s", entry->user);
|
||||
strcat(mysql_user, "@");
|
||||
inet_ntop(AF_INET, &(entry->ipv4).sin_addr, mysql_user+strlen(mysql_user), INET_ADDRSTRLEN);
|
||||
|
||||
}
|
||||
|
||||
return mysql_user;
|
||||
}
|
||||
|
||||
|
@ -539,7 +539,7 @@ return_succp:
|
||||
static bool resolve_maxscale_homedir(
|
||||
char** p_home_dir)
|
||||
{
|
||||
bool succp = false;
|
||||
bool succp;
|
||||
char* tmp;
|
||||
char* log_context = NULL;
|
||||
|
||||
@ -627,15 +627,25 @@ check_home_dir:
|
||||
|
||||
free(errstr);
|
||||
free(logstr);
|
||||
succp = false;
|
||||
}
|
||||
else if (!daemon_mode)
|
||||
else
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Using %s as MAXSCALE_HOME = %s\n",
|
||||
log_context,
|
||||
tmp);
|
||||
succp = true;
|
||||
|
||||
if (!daemon_mode)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Using %s as MAXSCALE_HOME = %s\n",
|
||||
log_context,
|
||||
tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
succp = false;
|
||||
}
|
||||
free (tmp);
|
||||
|
||||
if (log_context != NULL)
|
||||
@ -1392,7 +1402,7 @@ int main(int argc, char **argv)
|
||||
{
|
||||
if (!resolve_maxscale_homedir(&home_dir))
|
||||
{
|
||||
ss_dassert(home_dir == NULL);
|
||||
ss_dassert(home_dir != NULL);
|
||||
rc = MAXSCALE_HOMELESS;
|
||||
goto return_main;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
add_executable(test_mysql_users test_mysql_users.c)
|
||||
add_executable(test_hash testhash.c)
|
||||
add_executable(test_hint testhint.c)
|
||||
add_executable(test_spinlock testspinlock.c)
|
||||
@ -10,6 +11,7 @@ add_executable(test_service testservice.c)
|
||||
add_executable(test_server testserver.c)
|
||||
add_executable(test_users testusers.c)
|
||||
add_executable(test_adminusers testadminusers.c)
|
||||
target_link_libraries(test_mysql_users fullcore MySQLClient)
|
||||
target_link_libraries(test_hash fullcore)
|
||||
target_link_libraries(test_hint fullcore)
|
||||
target_link_libraries(test_spinlock fullcore)
|
||||
@ -22,6 +24,7 @@ target_link_libraries(test_service fullcore)
|
||||
target_link_libraries(test_server fullcore)
|
||||
target_link_libraries(test_users fullcore)
|
||||
target_link_libraries(test_adminusers fullcore)
|
||||
add_test(testMySQLUsers test_mysql_users)
|
||||
add_test(TestHash test_hash)
|
||||
add_test(TestHint test_hint)
|
||||
add_test(TestSpinlock test_spinlock)
|
||||
|
@ -1,32 +0,0 @@
|
||||
# cleantests - clean local and subdirectories' tests
|
||||
# buildtests - build all local and subdirectories' tests
|
||||
# runtests - run all local tests
|
||||
# testall - clean, build and run local and subdirectories' tests
|
||||
|
||||
include ../../../build_gateway.inc
|
||||
include ../../../makefile.inc
|
||||
|
||||
CC=cc
|
||||
DEBUG=Y
|
||||
cleantests:
|
||||
- $(DEL) *.o
|
||||
- $(DEL) test_mysql_users
|
||||
- $(DEL) *~
|
||||
|
||||
testall: cleantests buildtests runtests
|
||||
|
||||
buildtests :
|
||||
$(CC) $(CFLAGS) \
|
||||
-I$(ROOT_PATH)/server/include \
|
||||
-I$(ROOT_PATH)/utils \
|
||||
-I$(ROOT_PATH)/log_manager \
|
||||
test_mysql_users.c ../secrets.o ../service.o ../gwbitmask.o ../load_utils.o ../session.o ../poll.o ../dcb.o ../utils.o ../buffer.o ../gw_utils.o ../hashtable.o ../atomic.o ../spinlock.o ../users.o ../dbusers.o ../../../utils/skygw_utils.o ../../../log_manager/log_manager.o -o test_mysql_users -L$(EMBEDDED_LIB) -lmysqlclient -lpthread -lssl -lz -lm -lcrypt -lcrypto -ldl -laio -lrt -lstdc++
|
||||
runtests:
|
||||
@echo ""
|
||||
@echo "-------------------------------"
|
||||
@echo $(shell date)
|
||||
@echo "Test MaxScale core"
|
||||
@echo "-------------------------------"
|
||||
@echo ""
|
||||
@echo "MaxSclale Load MySQL users"
|
||||
@./test_mysql_users
|
@ -24,6 +24,7 @@
|
||||
* Date Who Description
|
||||
* 14/02/2014 Massimiliano Pinto Initial implementation
|
||||
* 17/02/2014 Massimiliano Pinto Added check ipv4
|
||||
* 03/10/2014 Massimiliano Pinto Added check for wildcard hosts
|
||||
*
|
||||
* @endverbatim
|
||||
*/
|
||||
@ -77,6 +78,7 @@ int set_and_get_single_mysql_users_ipv4(char *username, unsigned long ipv4, char
|
||||
/* add user@host as key and passwd as value in the MySQL users hash table */
|
||||
if (!mysql_users_add(mysql_users, &key, password)) {
|
||||
fprintf(stderr, "Failed adding %s@%s(%lu)\n", username, ret_ip, fix_ipv4);
|
||||
users_free(mysql_users);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -107,6 +109,7 @@ int set_and_get_single_mysql_users(char *username, char *hostname, char *passwor
|
||||
char *fetch_data;
|
||||
|
||||
mysql_users = mysql_users_alloc();
|
||||
|
||||
/* prepare the user@host data struct */
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
memset(&key, 0, sizeof(key));
|
||||
@ -115,6 +118,7 @@ int set_and_get_single_mysql_users(char *username, char *hostname, char *passwor
|
||||
if (hostname)
|
||||
if(!setipaddress(&serv_addr.sin_addr, hostname)) {
|
||||
fprintf(stderr, "setipaddress failed for host [%s]\n", hostname);
|
||||
users_free(mysql_users);
|
||||
return 1;
|
||||
}
|
||||
if (username)
|
||||
@ -129,6 +133,7 @@ int set_and_get_single_mysql_users(char *username, char *hostname, char *passwor
|
||||
/* add user@host as key and passwd as value in the MySQL users hash table */
|
||||
if (!mysql_users_add(mysql_users, &key, password)) {
|
||||
fprintf(stderr, "mysql_users_add() failed for %s@%s\n", username, hostname);
|
||||
users_free(mysql_users);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -138,6 +143,7 @@ int set_and_get_single_mysql_users(char *username, char *hostname, char *passwor
|
||||
if (hostname)
|
||||
if(!setipaddress(&serv_addr.sin_addr, hostname)) {
|
||||
fprintf(stderr, "setipaddress failed for host [%s]\n", hostname);
|
||||
users_free(mysql_users);
|
||||
return 1;
|
||||
}
|
||||
key.user = username;
|
||||
@ -153,6 +159,73 @@ int set_and_get_single_mysql_users(char *username, char *hostname, char *passwor
|
||||
return 0;
|
||||
}
|
||||
|
||||
int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *password, char *from) {
|
||||
USERS *mysql_users;
|
||||
int ret;
|
||||
struct sockaddr_in client_addr;
|
||||
DCB *dcb;
|
||||
SERVICE *service;
|
||||
|
||||
dcb = dcb_alloc(DCB_ROLE_INTERNAL);
|
||||
|
||||
if (dcb == NULL) {
|
||||
fprintf(stderr, "dcb_alloc() failed\n");
|
||||
return 1;
|
||||
}
|
||||
if ((service = (SERVICE *)calloc(1, sizeof(SERVICE))) == NULL) {
|
||||
fprintf(stderr, "service_alloc() failed\n");
|
||||
dcb_free(dcb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(&client_addr, 0, sizeof(client_addr));
|
||||
|
||||
if (hostname) {
|
||||
if(!setipaddress(&client_addr.sin_addr, from)) {
|
||||
fprintf(stderr, "setipaddress failed for host [%s]\n", from);
|
||||
free(service);
|
||||
dcb_free(dcb);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* client IPv4 in raw data*/
|
||||
memcpy(&dcb->ipv4, (struct sockaddr_in *)&client_addr, sizeof(struct sockaddr_in));
|
||||
|
||||
dcb->service = service;
|
||||
|
||||
mysql_users = mysql_users_alloc();
|
||||
|
||||
service->users = mysql_users;
|
||||
|
||||
|
||||
// the routine returns 1 on success
|
||||
ret = add_mysql_users_with_host_ipv4(mysql_users, username, hostname, password);
|
||||
if (!ret) {
|
||||
fprintf(stderr, "add_mysql_users_with_host_ipv4 passed(%s@%s, %s) FAILED\n", username, hostname, password);
|
||||
users_free(mysql_users);
|
||||
free(service);
|
||||
dcb_free(dcb);
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
char db_passwd[100]="";
|
||||
|
||||
dcb->remote=strdup(from);
|
||||
//fprintf(stderr, "add_mysql_users_with_host_ipv4 passed(%s@%s, %s) OK\n", username, hostname, password);
|
||||
|
||||
fprintf(stderr, "Checking '%s' @ '%s' against (%s@%s)\n", username, from, username, hostname);
|
||||
|
||||
// returns 0 on success
|
||||
ret = gw_find_mysql_user_password_sha1(username, db_passwd, dcb);
|
||||
}
|
||||
|
||||
users_free(mysql_users);
|
||||
free(service);
|
||||
dcb_free(dcb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int ret;
|
||||
@ -180,6 +253,7 @@ int main() {
|
||||
assert(ret == 1);
|
||||
ret = set_and_get_single_mysql_users(NULL, NULL, NULL);
|
||||
assert(ret == 1);
|
||||
|
||||
ret = set_and_get_single_mysql_users_ipv4("negative", -467295, "_ncd");
|
||||
assert(ret == 1);
|
||||
ret = set_and_get_single_mysql_users_ipv4("extra", 0xFFFFFFFFFUL * 100, "JJcd");
|
||||
@ -189,19 +263,77 @@ int main() {
|
||||
ret = set_and_get_single_mysql_users_ipv4(NULL, '\0', "JJcd");
|
||||
assert(ret == 1);
|
||||
|
||||
|
||||
for (i = 256*256*256; i <= 256*256*256 + 5; i++) {
|
||||
char user[129] = "";
|
||||
snprintf(user, 128, "user_%i", k);
|
||||
ret = set_and_get_single_mysql_users_ipv4(user, i, "JJcd");
|
||||
assert(ret == 0);
|
||||
k++;
|
||||
}
|
||||
|
||||
ret = set_and_get_mysql_users_wildcards("pippo", "%", "one", "127.0.0.1");
|
||||
if (ret) fprintf(stderr, "\t-- Expecting no match\n");
|
||||
assert(ret == 1);
|
||||
|
||||
ret = set_and_get_mysql_users_wildcards("pippo", "%", "", "127.0.0.1");
|
||||
if (ret) fprintf(stderr, "\t-- Expecting no match\n");
|
||||
assert(ret == 1);
|
||||
|
||||
ret = set_and_get_mysql_users_wildcards("pippo", "%", "two", "192.168.2.2");
|
||||
if (!ret) fprintf(stderr, "\t-- Expecting ok\n");
|
||||
assert(ret == 0);
|
||||
|
||||
ret = set_and_get_mysql_users_wildcards("pippo", "192.168.1.%", "foo", "192.168.2.2");
|
||||
if (ret) fprintf(stderr, "\t-- Expecting no match\n");
|
||||
assert(ret == 1);
|
||||
|
||||
ret = set_and_get_mysql_users_wildcards("pippo", "192.168.%.%", "foo", "192.168.2.2");
|
||||
if (!ret) fprintf(stderr, "\t-- Expecting ok\n");
|
||||
assert(ret == 0);
|
||||
|
||||
ret = set_and_get_mysql_users_wildcards("pippo", "192.%.%.%", "foo", "192.68.0.2");
|
||||
if (!ret) fprintf(stderr, "\t-- Expecting ok\n");
|
||||
assert(ret == 0);
|
||||
|
||||
ret = set_and_get_mysql_users_wildcards("pippo", "192.%.%.%", "foo", "192.0.0.2");
|
||||
if (!ret) fprintf(stderr, "\t-- Expecting ok\n");
|
||||
assert(ret == 0);
|
||||
|
||||
ret = set_and_get_mysql_users_wildcards("pippo", "192.0.%.%", "foo", "192.2.0.2");
|
||||
if (ret) fprintf(stderr, "\t-- Expecting no match\n");
|
||||
assert(ret == 1);
|
||||
|
||||
ret = set_and_get_mysql_users_wildcards("pippo", "192.0.0.1", "foo", "192.0.0.2");
|
||||
if (ret) fprintf(stderr, "\t-- Expecting no match\n");
|
||||
assert(ret == 1);
|
||||
|
||||
ret = set_and_get_mysql_users_wildcards("pippo", "192.0.%.%", "foo", "192.1.0.2");
|
||||
if (ret) fprintf(stderr, "\t-- Expecting no match\n");
|
||||
assert(ret == 1);
|
||||
|
||||
ret = set_and_get_mysql_users_wildcards("pippo", "192.0.0.%", "y78764o", "192.3.2.1");
|
||||
if (ret) fprintf(stderr, "\t-- Expecting no match\n");
|
||||
assert(ret == 1);
|
||||
|
||||
ret = set_and_get_mysql_users_wildcards("pippo", "192.0.%.%", "1234567890123456789012345678901234567890", "192.3.2.1");
|
||||
if (ret) fprintf(stderr, "\t-- Expecting no match\n");
|
||||
assert(ret == 1);
|
||||
|
||||
ret = set_and_get_mysql_users_wildcards("pippo", "192.%.%.%", "1234567890123456789012345678901234567890f8__uuo5", "192.3.2.1");
|
||||
if (!ret) fprintf(stderr, "\t-- Expecting ok\n");
|
||||
assert(ret == 0);
|
||||
|
||||
ret = set_and_get_mysql_users_wildcards("pippo", "192.0.0.%", "fo887778o", "192.134.0.2");
|
||||
if (ret) fprintf(stderr, "\t-- Expecting no match\n");
|
||||
assert(ret == 1);
|
||||
|
||||
fprintf(stderr, "----------------\n");
|
||||
fprintf(stderr, "<<< Test completed\n");
|
||||
|
||||
time(&t);
|
||||
fprintf(stderr, "%s\n", asctime(localtime(&t)));
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
* 25/06/13 Mark Riddoch Initial implementation
|
||||
* 25/02/13 Massimiliano Pinto Added users table refresh rate default values
|
||||
* 28/02/14 Massimiliano Pinto Added MySQL user and host data structure
|
||||
* 03/10/14 Massimiliano Pinto Added netmask to MySQL user and host data structure
|
||||
*
|
||||
* @endverbatim
|
||||
*/
|
||||
@ -52,11 +53,13 @@
|
||||
typedef struct mysql_user_host_key {
|
||||
char *user;
|
||||
struct sockaddr_in ipv4;
|
||||
int netmask;
|
||||
} MYSQL_USER_HOST;
|
||||
|
||||
extern int load_mysql_users(SERVICE *service);
|
||||
extern int reload_mysql_users(SERVICE *service);
|
||||
extern int mysql_users_add(USERS *users, MYSQL_USER_HOST *key, char *auth);
|
||||
extern int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *passwd);
|
||||
extern USERS *mysql_users_alloc();
|
||||
extern char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key);
|
||||
extern int replace_mysql_users(SERVICE *service);
|
||||
|
@ -558,6 +558,7 @@ static char* create_auth_fail_str(
|
||||
{
|
||||
sprintf(errstr, ferrstr, uname, hostaddr, (*sha1 == '\0' ? "NO" : "YES"));
|
||||
}
|
||||
free(uname);
|
||||
|
||||
retblock:
|
||||
return errstr;
|
||||
|
@ -31,6 +31,9 @@
|
||||
* localhost entry should be added for the selected user in the backends.
|
||||
* Setting to 1 allow localhost (127.0.0.1 or socket) to match the any host grant via
|
||||
* user@%
|
||||
* 29/09/2014 Massimiliano Pinto Added Mysql user@host authentication with wildcard in IPv4 hosts:
|
||||
* x.y.z.%, x.y.%.%, x.%.%.%
|
||||
* 03/10/2014 Massimiliano Pinto Added netmask for wildcard in IPv4 hosts.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -1310,7 +1313,7 @@ int gw_check_mysql_scramble_data(DCB *dcb, uint8_t *token, unsigned int token_le
|
||||
/**
|
||||
* gw_find_mysql_user_password_sha1
|
||||
*
|
||||
* The routine fetches look for an user int he MaxScale users' table
|
||||
* The routine fetches look for an user int the MaxScale users' table
|
||||
* The users' table is dcb->service->users or a different one specified with void *repository
|
||||
*
|
||||
* If found the HEX password, representing sha1(sha1(password)), is converted in binary data and
|
||||
@ -1334,6 +1337,7 @@ int gw_find_mysql_user_password_sha1(char *username, uint8_t *gateway_password,
|
||||
|
||||
key.user = username;
|
||||
memcpy(&key.ipv4, client, sizeof(struct sockaddr_in));
|
||||
key.netmask = 32;
|
||||
|
||||
LOGIF(LD,
|
||||
(skygw_log_write_flush(
|
||||
@ -1343,73 +1347,119 @@ int gw_find_mysql_user_password_sha1(char *username, uint8_t *gateway_password,
|
||||
key.user,
|
||||
dcb->remote)));
|
||||
|
||||
/* look for user@current_host now */
|
||||
/* look for user@current_ipv4 now */
|
||||
user_password = mysql_users_fetch(service->users, &key);
|
||||
|
||||
if (!user_password) {
|
||||
/* The user is not authenticated @ current host */
|
||||
/* The user is not authenticated @ current IPv4 */
|
||||
|
||||
/* 1) Check for localhost first.
|
||||
* The check for localhost is 127.0.0.1 (IPv4 only)
|
||||
*/
|
||||
|
||||
if ((key.ipv4.sin_addr.s_addr == 0x0100007F) && !dcb->service->localhost_match_wildcard_host) {
|
||||
/* Skip the wildcard check and return 1 */
|
||||
LOGIF(LE,
|
||||
(skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : user %s@%s not found, try set "
|
||||
"'localhost_match_wildcard_host=1' in "
|
||||
"service definition of the configuration "
|
||||
"file.",
|
||||
key.user,
|
||||
dcb->remote)));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 2) Continue and check for wildcard host, user@%
|
||||
* Return 1 if no match
|
||||
*/
|
||||
|
||||
memset(&key.ipv4, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
LOGIF(LD,
|
||||
(skygw_log_write_flush(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [MySQL Client Auth], checking user [%s@%s] with wildcard host [%%]",
|
||||
pthread_self(),
|
||||
key.user,
|
||||
dcb->remote)));
|
||||
|
||||
user_password = mysql_users_fetch(service->users, &key);
|
||||
|
||||
if (!user_password) {
|
||||
/* the user@% was not found.
|
||||
* Return 1
|
||||
while (1) {
|
||||
/*
|
||||
* (1) Check for localhost first: 127.0.0.1 (IPv4 only)
|
||||
*/
|
||||
|
||||
if ((key.ipv4.sin_addr.s_addr == 0x0100007F) && !dcb->service->localhost_match_wildcard_host) {
|
||||
/* Skip the wildcard check and return 1 */
|
||||
LOGIF(LE,
|
||||
(skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : user %s@%s not found, try set "
|
||||
"'localhost_match_wildcard_host=1' in "
|
||||
"service definition of the configuration "
|
||||
"file.",
|
||||
key.user,
|
||||
dcb->remote)));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* (2) check for possible IPv4 class C,B,A networks
|
||||
*/
|
||||
|
||||
/* Class C check */
|
||||
key.ipv4.sin_addr.s_addr &= 0x00FFFFFF;
|
||||
key.netmask -= 8;
|
||||
|
||||
user_password = mysql_users_fetch(service->users, &key);
|
||||
|
||||
if (user_password) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Class B check */
|
||||
key.ipv4.sin_addr.s_addr &= 0x0000FFFF;
|
||||
key.netmask -= 8;
|
||||
|
||||
user_password = mysql_users_fetch(service->users, &key);
|
||||
|
||||
if (user_password) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Class A check */
|
||||
key.ipv4.sin_addr.s_addr &= 0x000000FF;
|
||||
key.netmask -= 8;
|
||||
|
||||
user_password = mysql_users_fetch(service->users, &key);
|
||||
|
||||
if (user_password) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* (3) Continue check for wildcard host, user@%
|
||||
*/
|
||||
|
||||
memset(&key.ipv4, 0, sizeof(struct sockaddr_in));
|
||||
key.netmask = 0;
|
||||
|
||||
LOGIF(LD,
|
||||
(skygw_log_write_flush(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [MySQL Client Auth], user [%s@%s] not existent",
|
||||
"%lu [MySQL Client Auth], checking user [%s@%s] with wildcard host [%%]",
|
||||
pthread_self(),
|
||||
key.user,
|
||||
dcb->remote)));
|
||||
return 1;
|
||||
|
||||
user_password = mysql_users_fetch(service->users, &key);
|
||||
|
||||
if (!user_password) {
|
||||
/*
|
||||
* the user@% has not been found.
|
||||
*/
|
||||
|
||||
LOGIF(LD,
|
||||
(skygw_log_write_flush(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [MySQL Client Auth], user [%s@%s] not existent",
|
||||
pthread_self(),
|
||||
key.user,
|
||||
dcb->remote)));
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* user@host found: now check the password
|
||||
*
|
||||
* Convert the hex data (40 bytes) to binary (20 bytes).
|
||||
* The gateway_password represents the SHA1(SHA1(real_password)).
|
||||
* Please note: the real_password is unknown and SHA1(real_password) is unknown as well
|
||||
*/
|
||||
/* If user@host has been found we get the the password in binary format*/
|
||||
if (user_password) {
|
||||
/*
|
||||
* Convert the hex data (40 bytes) to binary (20 bytes).
|
||||
* The gateway_password represents the SHA1(SHA1(real_password)).
|
||||
* Please note: the real_password is unknown and SHA1(real_password) is unknown as well
|
||||
*/
|
||||
int passwd_len=strlen(user_password);
|
||||
if (passwd_len) {
|
||||
passwd_len = (passwd_len <= (SHA_DIGEST_LENGTH * 2)) ? passwd_len : (SHA_DIGEST_LENGTH * 2);
|
||||
gw_hex2bin(gateway_password, user_password, passwd_len);
|
||||
}
|
||||
|
||||
if (strlen(user_password))
|
||||
gw_hex2bin(gateway_password, user_password, SHA_DIGEST_LENGTH * 2);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1652,11 +1702,9 @@ void protocol_archive_srv_command(
|
||||
|
||||
s1 = &p->protocol_command;
|
||||
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [protocol_archive_srv_command] Move command %s from fd %d "
|
||||
"to command history.",
|
||||
pthread_self(),
|
||||
LOGIF(LT, (skygw_log_write(
|
||||
LOGFILE_TRACE,
|
||||
"Move command %s from fd %d to command history.",
|
||||
STRPACKETTYPE(s1->scom_cmd),
|
||||
p->owner_dcb->fd)));
|
||||
|
||||
@ -1728,8 +1776,8 @@ void protocol_add_srv_command(
|
||||
p->protocol_command.scom_next = server_command_init(NULL, cmd);
|
||||
}
|
||||
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
LOGIF(LT, (skygw_log_write(
|
||||
LOGFILE_TRACE,
|
||||
"Added command %s to fd %d.",
|
||||
STRPACKETTYPE(cmd),
|
||||
p->owner_dcb->fd)));
|
||||
@ -1739,8 +1787,8 @@ void protocol_add_srv_command(
|
||||
|
||||
while (c != NULL && c->scom_cmd != MYSQL_COM_UNDEFINED)
|
||||
{
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
LOGIF(LT, (skygw_log_write(
|
||||
LOGFILE_TRACE,
|
||||
"fd %d : %d %s",
|
||||
p->owner_dcb->fd,
|
||||
c->scom_cmd,
|
||||
|
@ -1708,6 +1708,12 @@ static int routeQuery(
|
||||
}
|
||||
goto retblock;
|
||||
}
|
||||
/** If buffer is not contiguous, make it such */
|
||||
if (querybuf->next != NULL)
|
||||
{
|
||||
querybuf = gwbuf_make_contiguous(querybuf);
|
||||
}
|
||||
|
||||
master_dcb = router_cli_ses->rses_master_ref->bref_dcb;
|
||||
CHK_DCB(master_dcb);
|
||||
|
||||
|
@ -1,3 +0,0 @@
|
||||
if(BUILD_TESTS)
|
||||
install(FILES MaxScale_test.cnf DESTINATION etc RENAME MaxScale.cnf)
|
||||
endif()
|
Loading…
x
Reference in New Issue
Block a user