MySQL authentication with user@host
MySQL authentication with user@host: user, host and pass word are loaded from backend servers. Host is currently handled as IPv4 address
This commit is contained in:
@ -26,6 +26,7 @@
|
|||||||
* 24/06/2013 Massimiliano Pinto Initial implementation
|
* 24/06/2013 Massimiliano Pinto Initial implementation
|
||||||
* 08/08/2013 Massimiliano Pinto Fixed bug for invalid memory access in row[1]+1 when row[1] is ""
|
* 08/08/2013 Massimiliano Pinto Fixed bug for invalid memory access in row[1]+1 when row[1] is ""
|
||||||
* 06/02/2014 Massimiliano Pinto Mysql user root selected based on configuration flag
|
* 06/02/2014 Massimiliano Pinto Mysql user root selected based on configuration flag
|
||||||
|
* 07/02/2014 Massimiliano Pinto Added Mysql user@host authentication
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -39,13 +40,20 @@
|
|||||||
#include <skygw_utils.h>
|
#include <skygw_utils.h>
|
||||||
#include <log_manager.h>
|
#include <log_manager.h>
|
||||||
#include <secrets.h>
|
#include <secrets.h>
|
||||||
|
#include <dbusers.h>
|
||||||
|
|
||||||
#define USERS_QUERY_NO_ROOT " WHERE user NOT IN ('root')"
|
#define USERS_QUERY_NO_ROOT " AND user NOT IN ('root')"
|
||||||
#define LOAD_MYSQL_USERS_QUERY "SELECT user, password FROM mysql.user"
|
#define LOAD_MYSQL_USERS_QUERY "SELECT user, host, password FROM mysql.user WHERE user IS NOT NULL AND user <> ''"
|
||||||
|
|
||||||
extern int lm_enabled_logfiles_bitmask;
|
extern int lm_enabled_logfiles_bitmask;
|
||||||
|
|
||||||
static int getUsers(SERVICE *service, struct users *users);
|
static int getUsers(SERVICE *service, struct 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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the user/passwd form mysql.user table into the service users' hashtable
|
* Load the user/passwd form mysql.user table into the service users' hashtable
|
||||||
@ -73,7 +81,7 @@ reload_mysql_users(SERVICE *service)
|
|||||||
int i;
|
int i;
|
||||||
struct users *newusers, *oldusers;
|
struct users *newusers, *oldusers;
|
||||||
|
|
||||||
if ((newusers = users_alloc()) == NULL)
|
if ((newusers = mysql_users_alloc()) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
i = getUsers(service, newusers);
|
i = getUsers(service, newusers);
|
||||||
spinlock_acquire(&service->spin);
|
spinlock_acquire(&service->spin);
|
||||||
@ -105,14 +113,19 @@ getUsers(SERVICE *service, struct users *users)
|
|||||||
char *dpwd;
|
char *dpwd;
|
||||||
int total_users = 0;
|
int total_users = 0;
|
||||||
SERVER *server;
|
SERVER *server;
|
||||||
|
struct sockaddr_in serv_addr;
|
||||||
|
MYSQL_USER_HOST key;
|
||||||
char *users_query;
|
char *users_query;
|
||||||
|
|
||||||
if(service->enable_root)
|
/* enable_root for MySQL protocol module means load the root user credentials from backend databases */
|
||||||
users_query = LOAD_MYSQL_USERS_QUERY;
|
if(service->enable_root) {
|
||||||
else
|
users_query = LOAD_MYSQL_USERS_QUERY " ORDER BY HOST DESC";
|
||||||
users_query = LOAD_MYSQL_USERS_QUERY USERS_QUERY_NO_ROOT;
|
} else {
|
||||||
|
users_query = LOAD_MYSQL_USERS_QUERY USERS_QUERY_NO_ROOT " ORDER BY HOST DESC";
|
||||||
|
}
|
||||||
|
|
||||||
serviceGetUser(service, &service_user, &service_passwd);
|
serviceGetUser(service, &service_user, &service_passwd);
|
||||||
|
|
||||||
/** multi-thread environment requires that thread init succeeds. */
|
/** multi-thread environment requires that thread init succeeds. */
|
||||||
if (mysql_thread_init()) {
|
if (mysql_thread_init()) {
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
@ -158,6 +171,7 @@ getUsers(SERVICE *service, struct users *users)
|
|||||||
server = server->nextdb;
|
server = server->nextdb;
|
||||||
}
|
}
|
||||||
free(dpwd);
|
free(dpwd);
|
||||||
|
|
||||||
if (server == NULL)
|
if (server == NULL)
|
||||||
{
|
{
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
@ -194,16 +208,259 @@ getUsers(SERVICE *service, struct users *users)
|
|||||||
num_fields = mysql_num_fields(result);
|
num_fields = mysql_num_fields(result);
|
||||||
|
|
||||||
while ((row = mysql_fetch_row(result))) {
|
while ((row = mysql_fetch_row(result))) {
|
||||||
|
char ret_ip[INET_ADDRSTRLEN + 1]="";
|
||||||
|
const char *rc;
|
||||||
/**
|
/**
|
||||||
* Two fields should be returned.
|
* Two fields should be returned.
|
||||||
* user and passwd+1 (escaping the first byte that is '*') are
|
* user and passwd+1 (escaping the first byte that is '*') are
|
||||||
* added to hashtable.
|
* added to hashtable.
|
||||||
*/
|
*/
|
||||||
users_add(users, row[0], strlen(row[1]) ? row[1]+1 : row[1]);
|
|
||||||
total_users++;
|
/* prepare the user@host data struct */
|
||||||
|
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||||
|
memset(&key, 0, sizeof(key));
|
||||||
|
|
||||||
|
/* if host == '%', 0 is passed */
|
||||||
|
if (setipaddress(&serv_addr.sin_addr, strcmp(row[1], "%") ? row[1] : "0.0.0.0")) {
|
||||||
|
|
||||||
|
key.user = strdup(row[0]);
|
||||||
|
|
||||||
|
if(key.user == NULL) {
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"%lu [getUsers()] strdup() failed for user %s\n",
|
||||||
|
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)\n",
|
||||||
|
pthread_self(),
|
||||||
|
row[0],
|
||||||
|
row[1],
|
||||||
|
rc == NULL ? "NULL" : ret_ip)));
|
||||||
|
|
||||||
|
total_users++;
|
||||||
|
} else {
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"%lu [mysql_users_add()] Failed adding user user %s@%s(%s)\n",
|
||||||
|
pthread_self(),
|
||||||
|
row[0],
|
||||||
|
row[1],
|
||||||
|
rc == NULL ? "NULL" : ret_ip)));
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* setipaddress() failed, skip user add and log this*/
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"%lu [getUsers()] setipaddress failed: user NOT added %s@%s\n",
|
||||||
|
pthread_self(),
|
||||||
|
row[0],
|
||||||
|
row[1])));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mysql_free_result(result);
|
mysql_free_result(result);
|
||||||
mysql_close(con);
|
mysql_close(con);
|
||||||
mysql_thread_end();
|
mysql_thread_end();
|
||||||
|
|
||||||
return total_users;
|
return total_users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate a new MySQL users table for mysql specific users@host as key
|
||||||
|
*
|
||||||
|
* @return The users table
|
||||||
|
*/
|
||||||
|
USERS *
|
||||||
|
mysql_users_alloc()
|
||||||
|
{
|
||||||
|
USERS *rval;
|
||||||
|
|
||||||
|
if ((rval = calloc(1, sizeof(USERS))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if ((rval->data = hashtable_alloc(52, uh_hfun, uh_cmpfun)) == NULL) {
|
||||||
|
free(rval);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the MySQL user@host print routine for the debug interface */
|
||||||
|
rval->usersCustomUserFormat = mysql_format_user_entry;
|
||||||
|
|
||||||
|
/* the key is handled by uh_keydup/uh_keyfree.
|
||||||
|
* the value is a (char *): it's handled by strdup/free
|
||||||
|
*/
|
||||||
|
hashtable_memory_fns(rval->data, (HASHMEMORYFN)uh_keydup, (HASHMEMORYFN) strdup, (HASHMEMORYFN)uh_keyfree, (HASHMEMORYFN)free);
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new MySQL user to the user table. The user name must be unique
|
||||||
|
*
|
||||||
|
* @param users The users table
|
||||||
|
* @param user The user name
|
||||||
|
* @param auth The authentication data
|
||||||
|
* @return The number of users added to the table
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
mysql_users_add(USERS *users, MYSQL_USER_HOST *key, char *auth)
|
||||||
|
{
|
||||||
|
int add;
|
||||||
|
|
||||||
|
if (key == NULL || key->user == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
atomic_add(&users->stats.n_adds, 1);
|
||||||
|
add = hashtable_add(users->data, key, auth);
|
||||||
|
atomic_add(&users->stats.n_entries, add);
|
||||||
|
|
||||||
|
return add;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the authentication data for a particular user from the users table
|
||||||
|
*
|
||||||
|
* @param users The MySQL users table
|
||||||
|
* @param key The key with user@host
|
||||||
|
* @return The authentication data or NULL on error
|
||||||
|
*/
|
||||||
|
char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key) {
|
||||||
|
if (key == NULL)
|
||||||
|
return NULL;
|
||||||
|
atomic_add(&users->stats.n_fetches, 1);
|
||||||
|
return hashtable_fetch(users->data, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hash function we use for storing MySQL users as: users@hosts.
|
||||||
|
* Currently only IPv4 addresses are supported
|
||||||
|
*
|
||||||
|
* @param key The key value, i.e. username@host (IPv4)
|
||||||
|
* @return The hash key
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int uh_hfun( void* key) {
|
||||||
|
MYSQL_USER_HOST *hu = (MYSQL_USER_HOST *) key;
|
||||||
|
|
||||||
|
if (key == NULL || hu == NULL || hu->user == NULL) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return (*hu->user + *(hu->user + 1) + (unsigned int) (hu->ipv4.sin_addr.s_addr & 0xFF000000 / (256 * 256 * 256)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The compare function we use for compare MySQL users as: users@hosts.
|
||||||
|
* 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)
|
||||||
|
* @return The compare value
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int uh_cmpfun( void* v1, void* v2) {
|
||||||
|
MYSQL_USER_HOST *hu1 = (MYSQL_USER_HOST *) v1;
|
||||||
|
MYSQL_USER_HOST *hu2 = (MYSQL_USER_HOST *) v2;
|
||||||
|
|
||||||
|
if (v1 == NULL || v2 == NULL || hu1 == NULL || hu2 == NULL || hu1->user == NULL || hu2->user)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (strcmp(hu1->user, hu2->user) == 0 && (hu1->ipv4.sin_addr.s_addr == hu2->ipv4.sin_addr.s_addr)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*The key dup function we use for duplicate the users@hosts.
|
||||||
|
*
|
||||||
|
* @param key The key value, i.e. username@host ip4/ip6 data
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void *uh_keydup(void* key) {
|
||||||
|
MYSQL_USER_HOST *rval = (MYSQL_USER_HOST *) calloc(1, sizeof(MYSQL_USER_HOST));
|
||||||
|
MYSQL_USER_HOST *current_key = (MYSQL_USER_HOST *)key;
|
||||||
|
|
||||||
|
if (key == NULL || rval == NULL || current_key == NULL || current_key->user == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rval->user = strdup(current_key->user);
|
||||||
|
|
||||||
|
if (rval->user == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
memcpy(&rval->ipv4, ¤t_key->ipv4, sizeof(struct sockaddr_in));
|
||||||
|
|
||||||
|
return (void *) rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The key free function we use for freeing the users@hosts data
|
||||||
|
*
|
||||||
|
* @param key The key value, i.e. username@host ip4 data
|
||||||
|
*/
|
||||||
|
static void uh_keyfree( void* key) {
|
||||||
|
MYSQL_USER_HOST *current_key = (MYSQL_USER_HOST *)key;
|
||||||
|
|
||||||
|
if (key == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (current_key && current_key->user)
|
||||||
|
free(current_key->user);
|
||||||
|
|
||||||
|
free(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format the mysql user as user@host
|
||||||
|
* The returned memory must be freed by the caller
|
||||||
|
*
|
||||||
|
* @param data Input data
|
||||||
|
* @return the MySQL user@host
|
||||||
|
*/
|
||||||
|
char *mysql_format_user_entry(void *data)
|
||||||
|
{
|
||||||
|
MYSQL_USER_HOST *entry;
|
||||||
|
char *mysql_user;
|
||||||
|
/* the returned user string is "USER@HOST" */
|
||||||
|
int mysql_user_len = 128 + 1 + INET_ADDRSTRLEN + 1;
|
||||||
|
|
||||||
|
if (data == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
entry = (MYSQL_USER_HOST *) data;
|
||||||
|
|
||||||
|
if (entry == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
mysql_user = (char *) calloc(mysql_user_len, sizeof(char));
|
||||||
|
|
||||||
|
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 {
|
||||||
|
snprintf(mysql_user, 128, entry->user);
|
||||||
|
strcat(mysql_user, "@");
|
||||||
|
inet_ntop(AF_INET, &(entry->ipv4).sin_addr, mysql_user+strlen(mysql_user), INET_ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mysql_user;
|
||||||
|
}
|
||||||
|
|||||||
@ -26,6 +26,8 @@
|
|||||||
* 18/06/13 Mark Riddoch Initial implementation
|
* 18/06/13 Mark Riddoch Initial implementation
|
||||||
* 24/06/13 Massimiliano Pinto Added: Loading users from mysql backend in serviceStart
|
* 24/06/13 Massimiliano Pinto Added: Loading users from mysql backend in serviceStart
|
||||||
* 06/02/14 Massimiliano Pinto Added: serviceEnableRootUser routine
|
* 06/02/14 Massimiliano Pinto Added: serviceEnableRootUser routine
|
||||||
|
* 14/02/14 Massimiliano Pinto users_alloc moved from service_alloc to serviceStartPort (generic hashable for services)
|
||||||
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -78,7 +80,6 @@ SERVICE *service;
|
|||||||
service->state = SERVICE_STATE_ALLOC;
|
service->state = SERVICE_STATE_ALLOC;
|
||||||
service->credentials.name = NULL;
|
service->credentials.name = NULL;
|
||||||
service->credentials.authdata = NULL;
|
service->credentials.authdata = NULL;
|
||||||
service->users = users_alloc();
|
|
||||||
service->enable_root = 0;
|
service->enable_root = 0;
|
||||||
service->routerOptions = NULL;
|
service->routerOptions = NULL;
|
||||||
service->databases = NULL;
|
service->databases = NULL;
|
||||||
@ -113,11 +114,17 @@ GWPROTOCOL *funcs;
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (strcmp(port->protocol, "MySQLClient") == 0) {
|
if (strcmp(port->protocol, "MySQLClient") == 0) {
|
||||||
int loaded = load_mysql_users(service);
|
int loaded;
|
||||||
|
/* Allocate specific data for MySQL users */
|
||||||
|
service->users = mysql_users_alloc();
|
||||||
|
loaded = load_mysql_users(service);
|
||||||
LOGIF(LM, (skygw_log_write(
|
LOGIF(LM, (skygw_log_write(
|
||||||
LOGFILE_MESSAGE,
|
LOGFILE_MESSAGE,
|
||||||
"Loaded %d MySQL Users.",
|
"Loaded %d MySQL Users.",
|
||||||
loaded)));
|
loaded)));
|
||||||
|
} else {
|
||||||
|
/* Generic users table */
|
||||||
|
service->users = users_alloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((funcs =
|
if ((funcs =
|
||||||
|
|||||||
@ -177,7 +177,8 @@ void
|
|||||||
dcb_usersPrint(DCB *dcb, USERS *users)
|
dcb_usersPrint(DCB *dcb, USERS *users)
|
||||||
{
|
{
|
||||||
HASHITERATOR *iter;
|
HASHITERATOR *iter;
|
||||||
char *sep, *user;
|
char *sep;
|
||||||
|
void *user;
|
||||||
|
|
||||||
dcb_printf(dcb, "Users table data\n");
|
dcb_printf(dcb, "Users table data\n");
|
||||||
dcb_hashtable_stats(dcb, users->data);
|
dcb_hashtable_stats(dcb, users->data);
|
||||||
@ -185,11 +186,26 @@ char *sep, *user;
|
|||||||
{
|
{
|
||||||
dcb_printf(dcb, "User names: ");
|
dcb_printf(dcb, "User names: ");
|
||||||
sep = "";
|
sep = "";
|
||||||
while ((user = hashtable_next(iter)) != NULL)
|
|
||||||
{
|
if (users->usersCustomUserFormat != NULL) {
|
||||||
dcb_printf(dcb, "%s%s", sep, user);
|
while ((user = hashtable_next(iter)) != NULL)
|
||||||
sep = ", ";
|
{
|
||||||
|
char *custom_user;
|
||||||
|
custom_user = users->usersCustomUserFormat(user);
|
||||||
|
if (custom_user) {
|
||||||
|
dcb_printf(dcb, "%s%s", sep, custom_user);
|
||||||
|
free(custom_user);
|
||||||
|
sep = ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while ((user = hashtable_next(iter)) != NULL)
|
||||||
|
{
|
||||||
|
dcb_printf(dcb, "%s%s", sep, (char *)user);
|
||||||
|
sep = ", ";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dcb_printf(dcb, "\n");
|
dcb_printf(dcb, "\n");
|
||||||
hashtable_iterator_free(iter);
|
hashtable_iterator_free(iter);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,8 @@
|
|||||||
* Copyright SkySQL Ab 2013
|
* Copyright SkySQL Ab 2013
|
||||||
*/
|
*/
|
||||||
#include <service.h>
|
#include <service.h>
|
||||||
|
#include <gw.h>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file dbusers.h Extarct user information form the backend database
|
* @file dbusers.h Extarct user information form the backend database
|
||||||
@ -25,12 +27,24 @@
|
|||||||
* @verbatim
|
* @verbatim
|
||||||
* Revision History
|
* Revision History
|
||||||
*
|
*
|
||||||
* Date Who Description
|
* Date Who Description
|
||||||
* 25/06/13 Mark Riddoch Initial implementation
|
* 25/06/13 Mark Riddoch Initial implementation
|
||||||
|
* 07/02/14 Massimiliano Pinto Added MySQL user and host data structure
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MySQL user and host data structure
|
||||||
|
*/
|
||||||
|
typedef struct mysql_user_host_key {
|
||||||
|
char *user;
|
||||||
|
struct sockaddr_in ipv4;
|
||||||
|
} MYSQL_USER_HOST;
|
||||||
|
|
||||||
extern int load_mysql_users(SERVICE *service);
|
extern int load_mysql_users(SERVICE *service);
|
||||||
extern int reload_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 USERS *mysql_users_alloc();
|
||||||
|
extern char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -27,8 +27,9 @@
|
|||||||
* @verbatim
|
* @verbatim
|
||||||
* Revision History
|
* Revision History
|
||||||
*
|
*
|
||||||
* Date Who Description
|
* Date Who Description
|
||||||
* 23/06/13 Mark Riddoch Initial implementation
|
* 23/06/13 Mark Riddoch Initial implementation
|
||||||
|
* 14/02/14 Massimiliano Pinto Added usersCustomUserFormat, optional username format routine
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -48,8 +49,9 @@ typedef struct {
|
|||||||
* for the authentication implementation within the gateway.
|
* for the authentication implementation within the gateway.
|
||||||
*/
|
*/
|
||||||
typedef struct users {
|
typedef struct users {
|
||||||
HASHTABLE *data; /**< The hashtable containing the actual data */
|
HASHTABLE *data; /**< The hashtable containing the actual data */
|
||||||
USERS_STATS stats; /**< The statistics for the users table */
|
char *(*usersCustomUserFormat)(void *); /**< Optional username format routine */
|
||||||
|
USERS_STATS stats; /**< The statistics for the users table */
|
||||||
} USERS;
|
} USERS;
|
||||||
|
|
||||||
extern USERS *users_alloc(); /**< Allocate a users table */
|
extern USERS *users_alloc(); /**< Allocate a users table */
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
* 02/06/2013 Massimiliano Pinto MySQL connect asynchronous phases
|
* 02/06/2013 Massimiliano Pinto MySQL connect asynchronous phases
|
||||||
* 04/09/2013 Massimiliano Pinto Added dcb NULL assert in mysql_send_custom_error
|
* 04/09/2013 Massimiliano Pinto Added dcb NULL assert in mysql_send_custom_error
|
||||||
* 12/09/2013 Massimiliano Pinto Added checks in gw_decode_mysql_server_handshake and gw_read_backend_handshake
|
* 12/09/2013 Massimiliano Pinto Added checks in gw_decode_mysql_server_handshake and gw_read_backend_handshake
|
||||||
|
* 10/02/2014 Massimiliano Pinto Added MySQL Authentication with user@host
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -1099,15 +1100,53 @@ int gw_check_mysql_scramble_data(DCB *dcb, uint8_t *token, unsigned int token_le
|
|||||||
|
|
||||||
int gw_find_mysql_user_password_sha1(char *username, uint8_t *gateway_password, void *repository) {
|
int gw_find_mysql_user_password_sha1(char *username, uint8_t *gateway_password, void *repository) {
|
||||||
SERVICE *service = NULL;
|
SERVICE *service = NULL;
|
||||||
|
struct sockaddr_in *client;
|
||||||
char *user_password = NULL;
|
char *user_password = NULL;
|
||||||
|
DCB *dcb = (DCB *)repository;
|
||||||
|
MYSQL_USER_HOST key;
|
||||||
|
|
||||||
service = (SERVICE *) ((DCB *)repository)->service;
|
service = (SERVICE *) ((DCB *)repository)->service;
|
||||||
|
client = (struct sockaddr_in *) &dcb->ipv4;
|
||||||
|
|
||||||
user_password = (char *)users_fetch(service->users, username);
|
key.user = username;
|
||||||
|
memcpy(&key.ipv4, client, sizeof(struct sockaddr_in));
|
||||||
|
|
||||||
|
LOGIF(LD,
|
||||||
|
(skygw_log_write_flush(
|
||||||
|
LOGFILE_DEBUG,
|
||||||
|
"%lu [MySQL Client Auth], checking user [%s@%s]",
|
||||||
|
pthread_self(),
|
||||||
|
key.user,
|
||||||
|
dcb->remote)));
|
||||||
|
|
||||||
|
/* lookk for user@current_host now */
|
||||||
|
user_password = mysql_users_fetch(service->users, &key);
|
||||||
|
|
||||||
if (!user_password) {
|
if (!user_password) {
|
||||||
return 1;
|
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)));
|
||||||
|
|
||||||
|
/* look for wildcard user@%, and then fail if no match */
|
||||||
|
user_password = mysql_users_fetch(service->users, &key);
|
||||||
|
|
||||||
|
if (!user_password) {
|
||||||
|
LOGIF(LD,
|
||||||
|
(skygw_log_write_flush(
|
||||||
|
LOGFILE_DEBUG,
|
||||||
|
"%lu [MySQL Client Auth], user [%s@%s] not existent",
|
||||||
|
pthread_self(),
|
||||||
|
key.user,
|
||||||
|
dcb->remote)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*<
|
/*<
|
||||||
* Convert now the hex data (40 bytes) to binary (20 bytes).
|
* Convert now the hex data (40 bytes) to binary (20 bytes).
|
||||||
|
|||||||
Reference in New Issue
Block a user