Implementation of db auth
Implementation of db auth
This commit is contained in:
@ -28,6 +28,9 @@
|
|||||||
* 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
|
||||||
* 26/02/2014 Massimiliano Pinto Addd: replace_mysql_users() routine may replace users' table based on a checksum
|
* 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
|
* 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
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -45,18 +48,25 @@
|
|||||||
#include <mysql_client_server_protocol.h>
|
#include <mysql_client_server_protocol.h>
|
||||||
|
|
||||||
#define USERS_QUERY_NO_ROOT " AND user NOT IN ('root')"
|
#define USERS_QUERY_NO_ROOT " AND user NOT IN ('root')"
|
||||||
#define LOAD_MYSQL_USERS_QUERY "SELECT user, host, password, concat(user,host,password) AS userdata FROM mysql.user WHERE user IS NOT NULL AND user <> ''"
|
#define LOAD_MYSQL_USERS_QUERY "SELECT user, host, password, concat(user,host,password,Select_priv) AS userdata, Select_priv AS anydb FROM mysql.user WHERE user IS NOT NULL AND user <> ''"
|
||||||
#define MYSQL_USERS_COUNT "SELECT COUNT(1) AS nusers FROM mysql.user"
|
#define MYSQL_USERS_COUNT "SELECT COUNT(1) AS nusers FROM mysql.user"
|
||||||
|
|
||||||
|
#define MYSQL_USERS_WITH_DB_ORDER " ORDER BY host DESC"
|
||||||
|
#define LOAD_MYSQL_USERS_WITH_DB_QUERY "SELECT user.user AS user,user.host AS host,user.password AS password,concat(user.user,user.host,user.password,user.Select_priv) AS userdata, user.Select_priv AS anydb,db.db AS db FROM mysql.user LEFT JOIN mysql.db ON user.user=db.user AND user.host=db.host WHERE user.user IS NOT NULL AND user.user <> ''" MYSQL_USERS_WITH_DB_ORDER
|
||||||
|
|
||||||
|
#define LOAD_MYSQL_USERS_WITH_DB_QUERY_NO_ROOT "SELECT * FROM (" LOAD_MYSQL_USERS_WITH_DB_QUERY ") AS t1 WHERE user NOT IN ('root')" MYSQL_USERS_WITH_DB_ORDER
|
||||||
|
|
||||||
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, USERS *users);
|
||||||
static int uh_cmpfun( void* v1, void* v2);
|
static int uh_cmpfun( void* v1, void* v2);
|
||||||
static void *uh_keydup(void* key);
|
static void *uh_keydup(void* key);
|
||||||
static void uh_keyfree( void* key);
|
static void uh_keyfree( void* key);
|
||||||
static int uh_hfun( void* key);
|
static int uh_hfun( void* key);
|
||||||
char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key);
|
void *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key);
|
||||||
char *mysql_format_user_entry(void *data);
|
char *mysql_format_user_entry(void *data);
|
||||||
|
int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *passwd, char *anydb, char *db);
|
||||||
|
static int getDatabases(SERVICE *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
@ -71,6 +81,10 @@ load_mysql_users(SERVICE *service)
|
|||||||
return getUsers(service, service->users);
|
return getUsers(service, service->users);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mysql_users_load_dbs(SERVICE *service) {
|
||||||
|
return getDatabases(service);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reload the user/passwd form mysql.user table into the service users' hashtable
|
* Reload the user/passwd form mysql.user table into the service users' hashtable
|
||||||
* environment.
|
* environment.
|
||||||
@ -82,7 +96,7 @@ int
|
|||||||
reload_mysql_users(SERVICE *service)
|
reload_mysql_users(SERVICE *service)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct users *newusers, *oldusers;
|
USERS *newusers, *oldusers;
|
||||||
|
|
||||||
if ((newusers = mysql_users_alloc()) == NULL)
|
if ((newusers = mysql_users_alloc()) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
@ -108,7 +122,7 @@ int
|
|||||||
replace_mysql_users(SERVICE *service)
|
replace_mysql_users(SERVICE *service)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct users *newusers, *oldusers;
|
USERS *newusers, *oldusers;
|
||||||
|
|
||||||
if ((newusers = mysql_users_alloc()) == NULL)
|
if ((newusers = mysql_users_alloc()) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
@ -148,6 +162,108 @@ struct users *newusers, *oldusers;
|
|||||||
return i;
|
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, char *anydb, char *db) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
fprintf(stderr, "Current %s@%s has anydb access %s OR specific db %s\n", user, host, anydb, db);
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for anydb == Y key.resource is '\0' as set by memset */
|
||||||
|
if (strcmp(anydb, "N") == 0) {
|
||||||
|
if (db)
|
||||||
|
key.resource = strdup(db);
|
||||||
|
else
|
||||||
|
key.resource = NULL;
|
||||||
|
} else {
|
||||||
|
key.resource = strdup("");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
if (ret == 1)
|
||||||
|
fprintf(stderr, "Added user %s@%i with db [%s]\n", key.user, key.ipv4.sin_addr.s_addr, key.resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(key.user);
|
||||||
|
if (key.resource)
|
||||||
|
free(key.resource);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
* environment.
|
* environment.
|
||||||
@ -157,7 +273,7 @@ struct users *newusers, *oldusers;
|
|||||||
* @return -1 on any error or the number of users inserted (0 means no users at all)
|
* @return -1 on any error or the number of users inserted (0 means no users at all)
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
getUsers(SERVICE *service, struct users *users)
|
getDatabases(SERVICE *service)
|
||||||
{
|
{
|
||||||
MYSQL *con = NULL;
|
MYSQL *con = NULL;
|
||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
@ -171,17 +287,188 @@ getUsers(SERVICE *service, struct users *users)
|
|||||||
char *users_query;
|
char *users_query;
|
||||||
unsigned char hash[SHA_DIGEST_LENGTH]="";
|
unsigned char hash[SHA_DIGEST_LENGTH]="";
|
||||||
char *users_data = NULL;
|
char *users_data = NULL;
|
||||||
|
int ndbs = 0;
|
||||||
|
/* last byte is for Select_priv=Y|N */
|
||||||
|
int users_data_row_len = MYSQL_USER_MAXLEN + MYSQL_HOST_MAXLEN + MYSQL_PASSWORD_LEN + sizeof(char);
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
serviceGetUser(service, &service_user, &service_passwd);
|
||||||
|
if (service_user == NULL || service_passwd == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
con = mysql_init(NULL);
|
||||||
|
|
||||||
|
if (con == NULL) {
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error : mysql_init: %s",
|
||||||
|
mysql_error(con))));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mysql_options(con, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL)) {
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error : failed to set external connection. "
|
||||||
|
"It is needed for backend server connections. "
|
||||||
|
"Exiting.")));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Attempt to connect to one of the databases database or until we run
|
||||||
|
* out of databases
|
||||||
|
* to try
|
||||||
|
*/
|
||||||
|
server = service->databases;
|
||||||
|
dpwd = decryptPassword(service_passwd);
|
||||||
|
while (server != NULL && (mysql_real_connect(con,
|
||||||
|
server->name,
|
||||||
|
service_user,
|
||||||
|
dpwd,
|
||||||
|
NULL,
|
||||||
|
server->port,
|
||||||
|
NULL,
|
||||||
|
0) == NULL))
|
||||||
|
{
|
||||||
|
server = server->nextdb;
|
||||||
|
}
|
||||||
|
free(dpwd);
|
||||||
|
|
||||||
|
if (server == NULL)
|
||||||
|
{
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error : Unable to get user data from backend database "
|
||||||
|
"for service %s. Missing server information.",
|
||||||
|
service->name)));
|
||||||
|
mysql_close(con);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mysql_query(con, "select count(1) from information_schema.SCHEMATA")) {
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error : Loading database names for service %s encountered "
|
||||||
|
"error: %s.",
|
||||||
|
service->name,
|
||||||
|
mysql_error(con))));
|
||||||
|
mysql_close(con);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
result = mysql_store_result(con);
|
||||||
|
|
||||||
|
if (result == NULL) {
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error : Loading database names for service %s encountered "
|
||||||
|
"error: %s.",
|
||||||
|
service->name,
|
||||||
|
mysql_error(con))));
|
||||||
|
mysql_close(con);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
num_fields = mysql_num_fields(result);
|
||||||
|
row = mysql_fetch_row(result);
|
||||||
|
|
||||||
|
ndbs = atoi(row[0]);
|
||||||
|
|
||||||
|
mysql_free_result(result);
|
||||||
|
|
||||||
|
fprintf(stderr, "Found %i schemas\n", ndbs);
|
||||||
|
|
||||||
|
if (!ndbs) {
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error : Counting users for service %s returned 0",
|
||||||
|
service->name)));
|
||||||
|
mysql_close(con);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
service->resources = (char **) calloc(ndbs+1, sizeof(char *));
|
||||||
|
for (i = 0; i < ndbs; i++) {
|
||||||
|
service->resources[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
service->resources[i] = NULL;
|
||||||
|
|
||||||
|
if (mysql_query(con, "SHOW DATABASES")) {
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error : Loading database names for service %s encountered "
|
||||||
|
"error: %s.",
|
||||||
|
service->name,
|
||||||
|
mysql_error(con))));
|
||||||
|
mysql_close(con);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = mysql_store_result(con);
|
||||||
|
|
||||||
|
if (result == NULL) {
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error : Loading database names for service %s encountered "
|
||||||
|
"error: %s.",
|
||||||
|
service->name,
|
||||||
|
mysql_error(con))));
|
||||||
|
mysql_close(con);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
num_fields = mysql_num_fields(result);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while ((row = mysql_fetch_row(result))) {
|
||||||
|
service->resources[i] = strndup(row[0], MYSQL_DATABASE_MAXLEN);
|
||||||
|
fprintf(stderr, "Found a Database[%i]:[%s]\n", i, service->resources[i]);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ndbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the user/passwd form mysql.user table into the service users' hashtable
|
||||||
|
* environment.
|
||||||
|
*
|
||||||
|
* @param service The current service
|
||||||
|
* @param users The users table into which to load the users
|
||||||
|
* @return -1 on any error or the number of users inserted (0 means no users at all)
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
getUsers(SERVICE *service, USERS *users)
|
||||||
|
{
|
||||||
|
MYSQL *con = NULL;
|
||||||
|
MYSQL_ROW row;
|
||||||
|
MYSQL_RES *result = NULL;
|
||||||
|
int num_fields = 0;
|
||||||
|
char *service_user = NULL;
|
||||||
|
char *service_passwd = NULL;
|
||||||
|
char *dpwd;
|
||||||
|
int total_users = 0;
|
||||||
|
SERVER *server;
|
||||||
|
char *users_query;
|
||||||
|
char *dbs_query;
|
||||||
|
unsigned char hash[SHA_DIGEST_LENGTH]="";
|
||||||
|
char *users_data = NULL;
|
||||||
int nusers = 0;
|
int nusers = 0;
|
||||||
int users_data_row_len = MYSQL_USER_MAXLEN + MYSQL_HOST_MAXLEN + MYSQL_PASSWORD_LEN;
|
/* last byte is for Select_priv=Y|N */
|
||||||
struct sockaddr_in serv_addr;
|
int users_data_row_len = MYSQL_USER_MAXLEN + MYSQL_HOST_MAXLEN + MYSQL_PASSWORD_LEN + sizeof(char);
|
||||||
MYSQL_USER_HOST key;
|
|
||||||
|
|
||||||
/* enable_root for MySQL protocol module means load the root user credentials from backend databases */
|
/* enable_root for MySQL protocol module means load the root user credentials from backend databases */
|
||||||
|
/*
|
||||||
if(service->enable_root) {
|
if(service->enable_root) {
|
||||||
users_query = LOAD_MYSQL_USERS_QUERY " ORDER BY HOST DESC";
|
users_query = LOAD_MYSQL_USERS_QUERY " ORDER BY HOST DESC";
|
||||||
} else {
|
} else {
|
||||||
users_query = LOAD_MYSQL_USERS_QUERY USERS_QUERY_NO_ROOT " ORDER BY HOST DESC";
|
users_query = LOAD_MYSQL_USERS_QUERY USERS_QUERY_NO_ROOT " ORDER BY HOST DESC";
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
if(service->enable_root) {
|
||||||
|
users_query = LOAD_MYSQL_USERS_WITH_DB_QUERY;
|
||||||
|
} else {
|
||||||
|
users_query = LOAD_MYSQL_USERS_WITH_DB_QUERY_NO_ROOT;
|
||||||
|
}
|
||||||
|
|
||||||
serviceGetUser(service, &service_user, &service_passwd);
|
serviceGetUser(service, &service_user, &service_passwd);
|
||||||
if (service_user == NULL || service_passwd == NULL)
|
if (service_user == NULL || service_passwd == NULL)
|
||||||
@ -306,68 +593,31 @@ getUsers(SERVICE *service, struct users *users)
|
|||||||
|
|
||||||
while ((row = mysql_fetch_row(result))) {
|
while ((row = mysql_fetch_row(result))) {
|
||||||
/**
|
/**
|
||||||
* Four fields should be returned.
|
* Six fields should be returned.
|
||||||
* user and passwd+1 (escaping the first byte that is '*') are
|
* user,host,passwd,concat(),anydb,db
|
||||||
* added to hashtable.
|
* passwd+1 (escaping the first byte that is '*')
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char ret_ip[INET_ADDRSTRLEN + 1]="";
|
int rc = 0;
|
||||||
const char *rc;
|
|
||||||
|
|
||||||
/* prepare the user@host data struct */
|
rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], strlen(row[2]) ? row[2]+1 : row[2], row[4], row[5]);
|
||||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
|
||||||
memset(&key, 0, sizeof(key));
|
|
||||||
|
|
||||||
/* if host == '%', 0 is passed */
|
if (rc == 1) {
|
||||||
if (setipaddress(&serv_addr.sin_addr, strcmp(row[1], "%") ? row[1] : "0.0.0.0")) {
|
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]);
|
/* Append data in the memory area for SHA1 digest */
|
||||||
|
strncat(users_data, row[3], users_data_row_len);
|
||||||
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);
|
|
||||||
|
|
||||||
|
total_users++;
|
||||||
} else {
|
} else {
|
||||||
/* setipaddress() failed, skip user add and log this*/
|
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
LOGFILE_ERROR,
|
LOGFILE_ERROR,
|
||||||
"%lu [getUsers()] setipaddress failed: user %s@%s not added",
|
"%lu [mysql_users_add()] Failed adding user %s@%s",
|
||||||
pthread_self(),
|
pthread_self(),
|
||||||
row[0],
|
row[0],
|
||||||
row[1])));
|
row[1])));
|
||||||
@ -445,11 +695,23 @@ int add;
|
|||||||
* @param key The key with user@host
|
* @param key The key with user@host
|
||||||
* @return The authentication data or NULL on error
|
* @return The authentication data or NULL on error
|
||||||
*/
|
*/
|
||||||
char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key) {
|
void *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key) {
|
||||||
|
HASHENTRIES *matched;
|
||||||
|
MYSQL_USER_HOST *entry;
|
||||||
if (key == NULL)
|
if (key == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
atomic_add(&users->stats.n_fetches, 1);
|
atomic_add(&users->stats.n_fetches, 1);
|
||||||
return hashtable_fetch(users->data, key);
|
|
||||||
|
fprintf(stderr, "-- fetching %s@%i db=[%s]\n", key->user, key->ipv4.sin_addr.s_addr, key->resource);
|
||||||
|
|
||||||
|
matched = (HASHENTRIES *)hashtable_fetch_key(users->data, key);
|
||||||
|
if (matched) {
|
||||||
|
entry = (MYSQL_USER_HOST *)matched->key;
|
||||||
|
fprintf(stderr, "+++++++ Hash match for %s, db %s\n", entry->user, entry->resource);
|
||||||
|
return matched->value;
|
||||||
|
} else
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -475,7 +737,7 @@ static int uh_hfun( void* key) {
|
|||||||
* Currently only IPv4 addresses are supported
|
* 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 key1 The key value, i.e. username@host (IPv4)
|
* @param key2 The key value, i.e. username@host (IPv4)
|
||||||
* @return The compare value
|
* @return The compare value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -486,8 +748,28 @@ static int uh_cmpfun( void* v1, void* v2) {
|
|||||||
if (v1 == NULL || v2 == NULL || hu1 == NULL || hu2 == NULL || hu1->user == NULL || hu2->user == NULL)
|
if (v1 == NULL || v2 == NULL || hu1 == NULL || hu2 == NULL || hu1->user == NULL || hu2->user == NULL)
|
||||||
return 0;
|
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;
|
|
||||||
|
/* if no database name was passed, auth is ok */
|
||||||
|
if (hu1->resource == NULL || (hu1->resource && !strlen(hu1->resource))) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
/* (1) check for no database grants at all and deny auth*/
|
||||||
|
if (hu2->resource == NULL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* (2) check for ANY database grant and allow auth*/
|
||||||
|
if (!strlen(hu2->resource)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* (3) check for database name specific grant and allow auth*/
|
||||||
|
if (hu1->resource && hu2->resource && strcmp(hu1->resource,hu2->resource) == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no matches, deny auth */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -513,6 +795,10 @@ static void *uh_keydup(void* key) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
memcpy(&rval->ipv4, ¤t_key->ipv4, sizeof(struct sockaddr_in));
|
memcpy(&rval->ipv4, ¤t_key->ipv4, sizeof(struct sockaddr_in));
|
||||||
|
memcpy(&rval->netmask, ¤t_key->netmask, sizeof(int));
|
||||||
|
|
||||||
|
if (current_key->resource)
|
||||||
|
rval->resource = strdup(current_key->resource);
|
||||||
|
|
||||||
return (void *) rval;
|
return (void *) rval;
|
||||||
}
|
}
|
||||||
@ -531,6 +817,9 @@ static void uh_keyfree( void* key) {
|
|||||||
if (current_key && current_key->user)
|
if (current_key && current_key->user)
|
||||||
free(current_key->user);
|
free(current_key->user);
|
||||||
|
|
||||||
|
if (current_key && current_key->resource)
|
||||||
|
free(current_key->resource);
|
||||||
|
|
||||||
free(key);
|
free(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -546,7 +835,7 @@ char *mysql_format_user_entry(void *data)
|
|||||||
MYSQL_USER_HOST *entry;
|
MYSQL_USER_HOST *entry;
|
||||||
char *mysql_user;
|
char *mysql_user;
|
||||||
/* the returned user string is "USER" + "@" + "HOST" + '\0' */
|
/* the returned user string is "USER" + "@" + "HOST" + '\0' */
|
||||||
int mysql_user_len = MYSQL_USER_MAXLEN + 1 + INET_ADDRSTRLEN + 1;
|
int mysql_user_len = MYSQL_USER_MAXLEN + 1 + INET_ADDRSTRLEN + 10 + MYSQL_USER_MAXLEN + 1;
|
||||||
|
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -561,13 +850,37 @@ char *mysql_format_user_entry(void *data)
|
|||||||
if (mysql_user == NULL)
|
if (mysql_user == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (entry->ipv4.sin_addr.s_addr == INADDR_ANY) {
|
/* format user@host based on wildcards */
|
||||||
snprintf(mysql_user, mysql_user_len, "%s@%%", entry->user);
|
if (entry->ipv4.sin_addr.s_addr == INADDR_ANY && entry->netmask == 0) {
|
||||||
} else {
|
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);
|
strncpy(mysql_user, entry->user, MYSQL_USER_MAXLEN);
|
||||||
strcat(mysql_user, "@");
|
strcat(mysql_user, "@");
|
||||||
inet_ntop(AF_INET, &(entry->ipv4).sin_addr, mysql_user+strlen(mysql_user), INET_ADDRSTRLEN);
|
inet_ntop(AF_INET, &(entry->ipv4).sin_addr, mysql_user+strlen(mysql_user), INET_ADDRSTRLEN);
|
||||||
|
} else {
|
||||||
|
snprintf(mysql_user, MYSQL_USER_MAXLEN-5, "Err: %s", entry->user);
|
||||||
|
strcat(mysql_user, "@");
|
||||||
|
inet_ntop(AF_INET, &(entry->ipv4).sin_addr, mysql_user+strlen(mysql_user), INET_ADDRSTRLEN);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->resource) {
|
||||||
|
if (strlen(entry->resource)) {
|
||||||
|
strcat(mysql_user, " db: ");
|
||||||
|
strcat(mysql_user, entry->resource);
|
||||||
|
} else {
|
||||||
|
strcat(mysql_user, " db: ANY");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strcat(mysql_user, " no db");
|
||||||
}
|
}
|
||||||
|
|
||||||
return mysql_user;
|
return mysql_user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,37 +1,16 @@
|
|||||||
|
add_executable(test_mysql_users test_mysql_users.c)
|
||||||
add_executable(test_hash testhash.c)
|
add_executable(test_hash testhash.c)
|
||||||
add_executable(test_hint testhint.c)
|
|
||||||
add_executable(test_spinlock testspinlock.c)
|
add_executable(test_spinlock testspinlock.c)
|
||||||
add_executable(test_filter testfilter.c)
|
add_executable(test_filter testfilter.c)
|
||||||
add_executable(test_buffer testbuffer.c)
|
|
||||||
add_executable(test_dcb testdcb.c)
|
|
||||||
add_executable(test_modutil testmodutil.c)
|
|
||||||
add_executable(test_poll testpoll.c)
|
|
||||||
add_executable(test_service testservice.c)
|
|
||||||
add_executable(test_server testserver.c)
|
|
||||||
add_executable(test_users testusers.c)
|
|
||||||
add_executable(test_adminusers testadminusers.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_hash fullcore)
|
||||||
target_link_libraries(test_hint fullcore)
|
|
||||||
target_link_libraries(test_spinlock fullcore)
|
target_link_libraries(test_spinlock fullcore)
|
||||||
target_link_libraries(test_filter fullcore)
|
target_link_libraries(test_filter fullcore)
|
||||||
target_link_libraries(test_buffer fullcore)
|
|
||||||
target_link_libraries(test_dcb fullcore)
|
|
||||||
target_link_libraries(test_modutil fullcore)
|
|
||||||
target_link_libraries(test_poll fullcore)
|
|
||||||
target_link_libraries(test_service fullcore)
|
|
||||||
target_link_libraries(test_server fullcore)
|
|
||||||
target_link_libraries(test_users fullcore)
|
|
||||||
target_link_libraries(test_adminusers fullcore)
|
target_link_libraries(test_adminusers fullcore)
|
||||||
|
add_test(testMySQLUsers test_mysql_users)
|
||||||
add_test(TestHash test_hash)
|
add_test(TestHash test_hash)
|
||||||
add_test(TestHint test_hint)
|
|
||||||
add_test(TestSpinlock test_spinlock)
|
add_test(TestSpinlock test_spinlock)
|
||||||
add_test(TestFilter test_filter)
|
add_test(TestFilter test_filter)
|
||||||
add_test(TestBuffer test_buffer)
|
|
||||||
add_test(TestDCB test_dcb)
|
|
||||||
add_test(TestModutil test_modutil)
|
|
||||||
add_test(TestPoll test_poll)
|
|
||||||
add_test(TestService test_service)
|
|
||||||
add_test(TestServer test_server)
|
|
||||||
add_test(TestUsers test_users)
|
|
||||||
add_test(TestAdminUsers test_adminusers)
|
add_test(TestAdminUsers test_adminusers)
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
* Date Who Description
|
* Date Who Description
|
||||||
* 14/02/2014 Massimiliano Pinto Initial implementation
|
* 14/02/2014 Massimiliano Pinto Initial implementation
|
||||||
* 17/02/2014 Massimiliano Pinto Added check ipv4
|
* 17/02/2014 Massimiliano Pinto Added check ipv4
|
||||||
|
* 03/10/2014 Massimiliano Pinto Added check for wildcard hosts
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -39,6 +40,7 @@
|
|||||||
#include <log_manager.h>
|
#include <log_manager.h>
|
||||||
#include <secrets.h>
|
#include <secrets.h>
|
||||||
#include <dbusers.h>
|
#include <dbusers.h>
|
||||||
|
#include <mysql_client_server_protocol.h>
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
@ -51,6 +53,7 @@ int set_and_get_single_mysql_users_ipv4(char *username, unsigned long ipv4, char
|
|||||||
USERS *mysql_users;
|
USERS *mysql_users;
|
||||||
char ret_ip[200]="";
|
char ret_ip[200]="";
|
||||||
char *fetch_data;
|
char *fetch_data;
|
||||||
|
char *db="";
|
||||||
|
|
||||||
unsigned long fix_ipv4;
|
unsigned long fix_ipv4;
|
||||||
|
|
||||||
@ -69,6 +72,7 @@ int set_and_get_single_mysql_users_ipv4(char *username, unsigned long ipv4, char
|
|||||||
|
|
||||||
key.user = username;
|
key.user = username;
|
||||||
memcpy(&key.ipv4, &serv_addr, sizeof(serv_addr));
|
memcpy(&key.ipv4, &serv_addr, sizeof(serv_addr));
|
||||||
|
key.resource = db;
|
||||||
|
|
||||||
inet_ntop(AF_INET, &(serv_addr).sin_addr, ret_ip, INET_ADDRSTRLEN);
|
inet_ntop(AF_INET, &(serv_addr).sin_addr, ret_ip, INET_ADDRSTRLEN);
|
||||||
|
|
||||||
@ -85,6 +89,7 @@ int set_and_get_single_mysql_users_ipv4(char *username, unsigned long ipv4, char
|
|||||||
|
|
||||||
find_key.user = username;
|
find_key.user = username;
|
||||||
memcpy(&(serv_addr).sin_addr.s_addr, &ipv4, sizeof(ipv4));
|
memcpy(&(serv_addr).sin_addr.s_addr, &ipv4, sizeof(ipv4));
|
||||||
|
find_key.resource = db;
|
||||||
|
|
||||||
memcpy(&find_key.ipv4, &serv_addr, sizeof(serv_addr));
|
memcpy(&find_key.ipv4, &serv_addr, sizeof(serv_addr));
|
||||||
|
|
||||||
@ -101,10 +106,10 @@ int set_and_get_single_mysql_users_ipv4(char *username, unsigned long ipv4, char
|
|||||||
int set_and_get_single_mysql_users(char *username, char *hostname, char *password) {
|
int set_and_get_single_mysql_users(char *username, char *hostname, char *password) {
|
||||||
struct sockaddr_in serv_addr;
|
struct sockaddr_in serv_addr;
|
||||||
MYSQL_USER_HOST key;
|
MYSQL_USER_HOST key;
|
||||||
MYSQL_USER_HOST find_key;
|
|
||||||
USERS *mysql_users;
|
USERS *mysql_users;
|
||||||
char ret_ip[200]="";
|
char ret_ip[200]="";
|
||||||
char *fetch_data;
|
char *fetch_data;
|
||||||
|
char *db="";
|
||||||
|
|
||||||
mysql_users = mysql_users_alloc();
|
mysql_users = mysql_users_alloc();
|
||||||
/* prepare the user@host data struct */
|
/* prepare the user@host data struct */
|
||||||
@ -121,6 +126,7 @@ int set_and_get_single_mysql_users(char *username, char *hostname, char *passwor
|
|||||||
key.user = username;
|
key.user = username;
|
||||||
|
|
||||||
memcpy(&key.ipv4, &serv_addr, sizeof(serv_addr));
|
memcpy(&key.ipv4, &serv_addr, sizeof(serv_addr));
|
||||||
|
key.resource = db;
|
||||||
|
|
||||||
inet_ntop(AF_INET, &(serv_addr).sin_addr, ret_ip, INET_ADDRSTRLEN);
|
inet_ntop(AF_INET, &(serv_addr).sin_addr, ret_ip, INET_ADDRSTRLEN);
|
||||||
|
|
||||||
@ -133,7 +139,6 @@ int set_and_get_single_mysql_users(char *username, char *hostname, char *passwor
|
|||||||
}
|
}
|
||||||
|
|
||||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||||
memset(&find_key, 0, sizeof(key));
|
|
||||||
|
|
||||||
if (hostname)
|
if (hostname)
|
||||||
if(!setipaddress(&serv_addr.sin_addr, hostname)) {
|
if(!setipaddress(&serv_addr.sin_addr, hostname)) {
|
||||||
@ -142,6 +147,7 @@ int set_and_get_single_mysql_users(char *username, char *hostname, char *passwor
|
|||||||
}
|
}
|
||||||
key.user = username;
|
key.user = username;
|
||||||
memcpy(&key.ipv4, &serv_addr, sizeof(serv_addr));
|
memcpy(&key.ipv4, &serv_addr, sizeof(serv_addr));
|
||||||
|
key.resource = db;
|
||||||
|
|
||||||
fetch_data = mysql_users_fetch(mysql_users, &key);
|
fetch_data = mysql_users_fetch(mysql_users, &key);
|
||||||
|
|
||||||
@ -153,6 +159,81 @@ int set_and_get_single_mysql_users(char *username, char *hostname, char *passwor
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *password, char *from, char *anydb, char *db, char *db_from) {
|
||||||
|
USERS *mysql_users;
|
||||||
|
int ret;
|
||||||
|
struct sockaddr_in client_addr;
|
||||||
|
DCB *dcb;
|
||||||
|
SERVICE *service;
|
||||||
|
MYSQL_session data;
|
||||||
|
|
||||||
|
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");
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (db_from != NULL)
|
||||||
|
strcpy(data.db, db_from);
|
||||||
|
else
|
||||||
|
strcpy(data.db, "");
|
||||||
|
|
||||||
|
dcb->data = &data;
|
||||||
|
|
||||||
|
// the routine returns 1 on success
|
||||||
|
if (anydb) {
|
||||||
|
if (strcmp(anydb, "N") == 0) {
|
||||||
|
ret = add_mysql_users_with_host_ipv4(mysql_users, username, hostname, password, anydb, db);
|
||||||
|
} else if (strcmp(anydb, "Y") == 0) {
|
||||||
|
ret = add_mysql_users_with_host_ipv4(mysql_users, username, hostname, password, "Y", "");
|
||||||
|
} else {
|
||||||
|
ret = add_mysql_users_with_host_ipv4(mysql_users, username, hostname, password, "N", NULL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = add_mysql_users_with_host_ipv4(mysql_users, username, hostname, password, "N", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
fprintf(stderr, "add_mysql_users_with_host_ipv4 (%s@%s, %s) FAILED\n", username, hostname, password);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
int ret;
|
int ret;
|
||||||
@ -166,6 +247,7 @@ int main() {
|
|||||||
fprintf(stderr, "%s\n", asctime(localtime(&t)));
|
fprintf(stderr, "%s\n", asctime(localtime(&t)));
|
||||||
fprintf(stderr, ">>> Started MySQL load, set & get users@host\n");
|
fprintf(stderr, ">>> Started MySQL load, set & get users@host\n");
|
||||||
|
|
||||||
|
|
||||||
ret = set_and_get_single_mysql_users("pippo", "localhost", "xyz");
|
ret = set_and_get_single_mysql_users("pippo", "localhost", "xyz");
|
||||||
assert(ret == 0);
|
assert(ret == 0);
|
||||||
ret = set_and_get_single_mysql_users("pippo", "127.0.0.2", "xyz");
|
ret = set_and_get_single_mysql_users("pippo", "127.0.0.2", "xyz");
|
||||||
@ -193,15 +275,102 @@ int main() {
|
|||||||
char user[129] = "";
|
char user[129] = "";
|
||||||
snprintf(user, 128, "user_%i", k);
|
snprintf(user, 128, "user_%i", k);
|
||||||
ret = set_and_get_single_mysql_users_ipv4(user, i, "JJcd");
|
ret = set_and_get_single_mysql_users_ipv4(user, i, "JJcd");
|
||||||
|
assert(ret == 0);
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = set_and_get_mysql_users_wildcards("pippo", "%", "one", "127.0.0.1", NULL, NULL, NULL);
|
||||||
|
if (ret) fprintf(stderr, "\t-- Expecting no match\n");
|
||||||
|
assert(ret == 1);
|
||||||
|
|
||||||
|
ret = set_and_get_mysql_users_wildcards("pippo", "%", "", "127.0.0.1", NULL, NULL, NULL);
|
||||||
|
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", NULL, NULL, NULL);
|
||||||
|
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", NULL, NULL, NULL);
|
||||||
|
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", NULL, NULL, NULL);
|
||||||
|
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", NULL, NULL, NULL);
|
||||||
|
if (!ret) fprintf(stderr, "\t-- Expecting ok\n");
|
||||||
|
assert(ret == 0);
|
||||||
|
|
||||||
|
fprintf(stderr, "Adding pippo, 192.%%.%%.%%, foo, 192.0.0.2, Y, NULL, cossa\n");
|
||||||
|
ret = set_and_get_mysql_users_wildcards("pippo", "192.%.%.%", "foo", "192.0.0.2", "Y", NULL, "cossa");
|
||||||
|
if (!ret) fprintf(stderr, "\t-- Expecting ok\n");
|
||||||
|
assert(ret == 0);
|
||||||
|
|
||||||
|
fprintf(stderr, "Adding pippo, 192.%%.%%.%%, foo, 192.0.0.2, N, NULL, ragione\n");
|
||||||
|
ret = set_and_get_mysql_users_wildcards("pippo", "192.%.%.%", "foo", "192.0.0.2", "N", NULL, "ragione");
|
||||||
|
if (!ret) fprintf(stderr, "\t-- Expecting no match\n");
|
||||||
|
assert(ret == 1);
|
||||||
|
|
||||||
|
ret = set_and_get_mysql_users_wildcards("pippo", "192.0.%.%", "foo", "192.2.0.2", NULL, NULL, NULL);
|
||||||
|
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", NULL, NULL, NULL);
|
||||||
|
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", NULL, NULL, NULL);
|
||||||
|
if (ret) fprintf(stderr, "\t-- Expecting no match\n");
|
||||||
|
assert(ret == 1);
|
||||||
|
|
||||||
|
ret = set_and_get_mysql_users_wildcards("pippo", "192.0.0.%", "foo", "192.3.2.1", NULL, NULL, NULL);
|
||||||
|
if (ret) fprintf(stderr, "\t-- Expecting no match\n");
|
||||||
|
assert(ret == 1);
|
||||||
|
|
||||||
|
ret = set_and_get_mysql_users_wildcards("pippo", "192.0.%.%", "foo", "192.3.2.1", NULL, NULL, NULL);
|
||||||
|
if (ret) fprintf(stderr, "\t-- Expecting no match\n");
|
||||||
|
assert(ret == 1);
|
||||||
|
|
||||||
|
ret = set_and_get_mysql_users_wildcards("pippo", "192.%.%.%", "foo", "192.254.254.245", "N", "matto", "matto");
|
||||||
|
if (!ret) fprintf(stderr, "\t-- Expecting ok\n");
|
||||||
|
assert(ret == 0);
|
||||||
|
|
||||||
|
ret = set_and_get_mysql_users_wildcards("pippo", "192.%.%.%", "foo", "192.254.254.245", "N", "matto", "fatto");
|
||||||
|
if (!ret) fprintf(stderr, "\t-- Expecting no match\n");
|
||||||
|
assert(ret == 1);
|
||||||
|
|
||||||
|
ret = set_and_get_mysql_users_wildcards("pippo", "192.%.%.%", "foo", "192.254.254.245", "Y", "matto", "fatto");
|
||||||
|
if (!ret) fprintf(stderr, "\t-- Expecting ok\n");
|
||||||
|
assert(ret == 0);
|
||||||
|
|
||||||
|
ret = set_and_get_mysql_users_wildcards("pippo", "192.%.%.%", "foo", "192.254.254.245", "Y", "", "fto");
|
||||||
|
if (!ret) fprintf(stderr, "\t-- Expecting ok\n");
|
||||||
|
assert(ret == 0);
|
||||||
|
|
||||||
|
ret = set_and_get_mysql_users_wildcards("pippo", "192.%.%.%", "foo", "192.254.254.245", "Y", NULL, "grewao");
|
||||||
|
if (!ret) fprintf(stderr, "\t-- Expecting ok\n");
|
||||||
|
assert(ret == 0);
|
||||||
|
|
||||||
|
ret = set_and_get_mysql_users_wildcards("pippo", "192.%.%.%", "foo", "192.254.254.242", NULL, NULL, NULL);
|
||||||
|
if (!ret) fprintf(stderr, "\t-- Expecting ok\n");
|
||||||
|
assert(ret == 0);
|
||||||
|
|
||||||
|
ret = set_and_get_mysql_users_wildcards("riccio", "192.0.0.%", "foo", "192.134.0.2", NULL, NULL, NULL);
|
||||||
|
if (ret) fprintf(stderr, "\t-- Expecting no match\n");
|
||||||
|
assert(ret == 1);
|
||||||
|
|
||||||
|
ret = set_and_get_mysql_users_wildcards("pippo", "192.%.%.%", "foo", "192.254.254.245", "Y", NULL, NULL);
|
||||||
|
if (!ret) fprintf(stderr, "\t-- Expecting ok\n");
|
||||||
|
assert(ret == 0);
|
||||||
|
|
||||||
fprintf(stderr, "----------------\n");
|
fprintf(stderr, "----------------\n");
|
||||||
fprintf(stderr, "<<< Test completed\n");
|
fprintf(stderr, "<<< Test completed\n");
|
||||||
|
|
||||||
time(&t);
|
time(&t);
|
||||||
fprintf(stderr, "%s\n", asctime(localtime(&t)));
|
fprintf(stderr, "%s\n", asctime(localtime(&t)));
|
||||||
|
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
* 25/06/13 Mark Riddoch Initial implementation
|
* 25/06/13 Mark Riddoch Initial implementation
|
||||||
* 25/02/13 Massimiliano Pinto Added users table refresh rate default values
|
* 25/02/13 Massimiliano Pinto Added users table refresh rate default values
|
||||||
* 28/02/14 Massimiliano Pinto Added MySQL user and host data structure
|
* 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
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -52,12 +53,15 @@
|
|||||||
typedef struct mysql_user_host_key {
|
typedef struct mysql_user_host_key {
|
||||||
char *user;
|
char *user;
|
||||||
struct sockaddr_in ipv4;
|
struct sockaddr_in ipv4;
|
||||||
|
int netmask;
|
||||||
|
char *resource;
|
||||||
} MYSQL_USER_HOST;
|
} 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 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, char *anydb, char *db);
|
||||||
extern USERS *mysql_users_alloc();
|
extern USERS *mysql_users_alloc();
|
||||||
extern char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key);
|
extern void *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key);
|
||||||
extern int replace_mysql_users(SERVICE *service);
|
extern int replace_mysql_users(SERVICE *service);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
|
* This file is distributed as part of the SkySQL Gateway. It is free
|
||||||
* software: you can redistribute it and/or modify it under the terms of the
|
* 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,
|
* GNU General Public License as published by the Free Software Foundation,
|
||||||
* version 2.
|
* version 2.
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* this program; if not, write to the Free Software Foundation, Inc., 51
|
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*
|
*
|
||||||
* Copyright MariaDB Corporation Ab 2013-2014
|
* Copyright SkySQL Ab 2013
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mysql_client_server_protocol.h"
|
#include "mysql_client_server_protocol.h"
|
||||||
@ -27,7 +27,7 @@
|
|||||||
* Revision History
|
* Revision History
|
||||||
* Date Who Description
|
* Date Who Description
|
||||||
* 14/06/2013 Mark Riddoch Initial version
|
* 14/06/2013 Mark Riddoch Initial version
|
||||||
* 17/06/2013 Massimiliano Pinto Added MaxScale To Backends routines
|
* 17/06/2013 Massimiliano Pinto Added Gateway To Backends routines
|
||||||
* 27/06/2013 Vilho Raatikka Added skygw_log_write command as an example
|
* 27/06/2013 Vilho Raatikka Added skygw_log_write command as an example
|
||||||
* and necessary headers.
|
* and necessary headers.
|
||||||
* 01/07/2013 Massimiliano Pinto Put Log Manager example code behind SS_DEBUG macros.
|
* 01/07/2013 Massimiliano Pinto Put Log Manager example code behind SS_DEBUG macros.
|
||||||
@ -199,7 +199,6 @@ static int gw_read_backend_event(DCB *dcb) {
|
|||||||
|
|
||||||
if (backend_protocol->protocol_auth_state == MYSQL_CONNECTED)
|
if (backend_protocol->protocol_auth_state == MYSQL_CONNECTED)
|
||||||
{
|
{
|
||||||
/** Read cached backend handshake */
|
|
||||||
if (gw_read_backend_handshake(backend_protocol) != 0)
|
if (gw_read_backend_handshake(backend_protocol) != 0)
|
||||||
{
|
{
|
||||||
backend_protocol->protocol_auth_state = MYSQL_AUTH_FAILED;
|
backend_protocol->protocol_auth_state = MYSQL_AUTH_FAILED;
|
||||||
@ -210,13 +209,11 @@ static int gw_read_backend_event(DCB *dcb) {
|
|||||||
"state = MYSQL_AUTH_FAILED.",
|
"state = MYSQL_AUTH_FAILED.",
|
||||||
pthread_self(),
|
pthread_self(),
|
||||||
backend_protocol->owner_dcb->fd)));
|
backend_protocol->owner_dcb->fd)));
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/**
|
/* handshake decoded, send the auth credentials */
|
||||||
* Decode password and send the auth credentials
|
|
||||||
* to backend.
|
|
||||||
*/
|
|
||||||
if (gw_send_authentication_to_backend(
|
if (gw_send_authentication_to_backend(
|
||||||
current_session->db,
|
current_session->db,
|
||||||
current_session->user,
|
current_session->user,
|
||||||
@ -239,7 +236,7 @@ static int gw_read_backend_event(DCB *dcb) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
spinlock_release(&dcb->authlock);
|
spinlock_release(&dcb->authlock);
|
||||||
} /*< backend_protocol->protocol_auth_state == MYSQL_CONNECTED */
|
}
|
||||||
/*
|
/*
|
||||||
* Now:
|
* Now:
|
||||||
* -- check the authentication reply from backend
|
* -- check the authentication reply from backend
|
||||||
@ -269,10 +266,9 @@ static int gw_read_backend_event(DCB *dcb) {
|
|||||||
router_instance = session->service->router_instance;
|
router_instance = session->service->router_instance;
|
||||||
rsession = session->router_session;
|
rsession = session->router_session;
|
||||||
|
|
||||||
if (backend_protocol->protocol_auth_state == MYSQL_AUTH_RECV)
|
if (backend_protocol->protocol_auth_state == MYSQL_AUTH_RECV) {
|
||||||
{
|
/*<
|
||||||
/**
|
* Read backed auth reply
|
||||||
* Read backed's reply to authentication message
|
|
||||||
*/
|
*/
|
||||||
receive_rc =
|
receive_rc =
|
||||||
gw_receive_backend_auth(backend_protocol);
|
gw_receive_backend_auth(backend_protocol);
|
||||||
@ -288,6 +284,7 @@ static int gw_read_backend_event(DCB *dcb) {
|
|||||||
pthread_self(),
|
pthread_self(),
|
||||||
backend_protocol->owner_dcb->fd)));
|
backend_protocol->owner_dcb->fd)));
|
||||||
|
|
||||||
|
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
LOGFILE_ERROR,
|
LOGFILE_ERROR,
|
||||||
"Error : Backend server didn't "
|
"Error : Backend server didn't "
|
||||||
@ -374,6 +371,7 @@ static int gw_read_backend_event(DCB *dcb) {
|
|||||||
&succp);
|
&succp);
|
||||||
|
|
||||||
ss_dassert(!succp);
|
ss_dassert(!succp);
|
||||||
|
|
||||||
LOGIF(LD, (skygw_log_write(
|
LOGIF(LD, (skygw_log_write(
|
||||||
LOGFILE_DEBUG,
|
LOGFILE_DEBUG,
|
||||||
"%lu [gw_read_backend_event] "
|
"%lu [gw_read_backend_event] "
|
||||||
@ -880,10 +878,6 @@ static int gw_create_backend_connection(
|
|||||||
goto return_fd;
|
goto return_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Copy client flags to backend protocol */
|
|
||||||
protocol->client_capabilities =
|
|
||||||
((MySQLProtocol *)(backend_dcb->session->client->protocol))->client_capabilities;
|
|
||||||
|
|
||||||
/*< if succeed, fd > 0, -1 otherwise */
|
/*< if succeed, fd > 0, -1 otherwise */
|
||||||
rv = gw_do_connect_to_backend(server->name, server->port, &fd);
|
rv = gw_do_connect_to_backend(server->name, server->port, &fd);
|
||||||
/*< Assign protocol with backend_dcb */
|
/*< Assign protocol with backend_dcb */
|
||||||
@ -1054,10 +1048,6 @@ gw_backend_close(DCB *dcb)
|
|||||||
|
|
||||||
mysql_protocol_done(dcb);
|
mysql_protocol_done(dcb);
|
||||||
|
|
||||||
/**
|
|
||||||
* If session->state is set to STOPPING the client and the session must
|
|
||||||
* be closed too.
|
|
||||||
*/
|
|
||||||
if (session != NULL && session->state == SESSION_STATE_STOPPING)
|
if (session != NULL && session->state == SESSION_STATE_STOPPING)
|
||||||
{
|
{
|
||||||
client_dcb = session->client;
|
client_dcb = session->client;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
|
* This file is distributed as part of the SkySQL Gateway. It is free
|
||||||
* software: you can redistribute it and/or modify it under the terms of the
|
* 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,
|
* GNU General Public License as published by the Free Software Foundation,
|
||||||
* version 2.
|
* version 2.
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* this program; if not, write to the Free Software Foundation, Inc., 51
|
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*
|
*
|
||||||
* Copyright MariaDB Corporation Ab 2013-2014
|
* Copyright SkySQL Ab 2013
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,7 +25,7 @@
|
|||||||
* Revision History
|
* Revision History
|
||||||
* Date Who Description
|
* Date Who Description
|
||||||
* 14/06/2013 Mark Riddoch Initial version
|
* 14/06/2013 Mark Riddoch Initial version
|
||||||
* 17/06/2013 Massimiliano Pinto Added Client To MaxScale routines
|
* 17/06/2013 Massimiliano Pinto Added Client To Gateway routines
|
||||||
* 24/06/2013 Massimiliano Pinto Added: fetch passwords from service users' hashtable
|
* 24/06/2013 Massimiliano Pinto Added: fetch passwords from service users' hashtable
|
||||||
* 02/09/2013 Massimiliano Pinto Added: session refcount
|
* 02/09/2013 Massimiliano Pinto Added: session refcount
|
||||||
* 16/12/2013 Massimiliano Pinto Added: client closed socket detection with recv(..., MSG_PEEK)
|
* 16/12/2013 Massimiliano Pinto Added: client closed socket detection with recv(..., MSG_PEEK)
|
||||||
@ -68,8 +68,6 @@ int mysql_send_ok(DCB *dcb, int packet_number, int in_affected_rows, const char*
|
|||||||
int MySQLSendHandshake(DCB* dcb);
|
int MySQLSendHandshake(DCB* dcb);
|
||||||
static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue);
|
static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue);
|
||||||
static int route_by_statement(SESSION *, GWBUF **);
|
static int route_by_statement(SESSION *, GWBUF **);
|
||||||
static char* create_auth_fail_str(GWBUF* readbuf, char* hostaddr, char* sha1);
|
|
||||||
static char* get_username_from_auth(char* ptr, uint8_t* data);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The "module object" for the mysqld client protocol module.
|
* The "module object" for the mysqld client protocol module.
|
||||||
@ -374,9 +372,9 @@ MySQLSendHandshake(DCB* dcb)
|
|||||||
* The useful data: user, db, client_sha1 are copied into the MYSQL_session * dcb->session->data
|
* The useful data: user, db, client_sha1 are copied into the MYSQL_session * dcb->session->data
|
||||||
* client_capabilitiesa are copied into the dcb->protocol
|
* client_capabilitiesa are copied into the dcb->protocol
|
||||||
*
|
*
|
||||||
* @param dcb Descriptor Control Block of the client
|
* @param dcb Descriptor Control Block of the client
|
||||||
* @param queue The GWBUF with data from client
|
* @param queue The GWBUF with data from client
|
||||||
* @return 0 If succeed, otherwise non-zero value
|
* @return 0 for Authentication ok, !=0 for failed autht
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -434,10 +432,12 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
|
|||||||
&protocol->client_capabilities);
|
&protocol->client_capabilities);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
username = get_username_from_auth(username, client_auth_packet);
|
/* now get the user */
|
||||||
|
strncpy(username, (char *)(client_auth_packet + 4 + 4 + 4 + 1 + 23), MYSQL_USER_MAXLEN);
|
||||||
|
|
||||||
if (username == NULL)
|
|
||||||
{
|
/* the empty username field is not allowed */
|
||||||
|
if (!strlen(username)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,9 +448,9 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
|
|||||||
|
|
||||||
if (connect_with_db) {
|
if (connect_with_db) {
|
||||||
database = client_data->db;
|
database = client_data->db;
|
||||||
strncpy(database,
|
strncpy(database,
|
||||||
(char *)(client_auth_packet + 4 + 4 + 4 + 1 + 23 + strlen(username) +
|
(char *)(client_auth_packet + 4 + 4 + 4 + 1 + 23 + strlen(username) +
|
||||||
1 + 1 + auth_token_len), MYSQL_DATABASE_MAXLEN);
|
1 + 1 + auth_token_len), MYSQL_DATABASE_MAXLEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate memory for token only if auth_token_len > 0 */
|
/* allocate memory for token only if auth_token_len > 0 */
|
||||||
@ -485,6 +485,23 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
|
|||||||
if (auth_token)
|
if (auth_token)
|
||||||
free(auth_token);
|
free(auth_token);
|
||||||
|
|
||||||
|
|
||||||
|
if (database) {
|
||||||
|
int i = 0;
|
||||||
|
int db_exists = 0;
|
||||||
|
while(dcb->service->resources[i]) {
|
||||||
|
if (strncmp(database, dcb->service->resources[i], MYSQL_DATABASE_MAXLEN) == 0) {
|
||||||
|
db_exists = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!db_exists) {
|
||||||
|
auth_ret = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (auth_ret == 0)
|
if (auth_ret == 0)
|
||||||
{
|
{
|
||||||
dcb->user = strdup(client_data->user);
|
dcb->user = strdup(client_data->user);
|
||||||
@ -494,77 +511,7 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read username from MySQL authentication packet.
|
* Write function for client DCB: writes data from Gateway to Client
|
||||||
*
|
|
||||||
* @param ptr address where to write the result or NULL if memory
|
|
||||||
* is allocated here.
|
|
||||||
* @param data Address of MySQL packet.
|
|
||||||
*
|
|
||||||
* @return Pointer to a copy of the username. NULL if memory allocation
|
|
||||||
* failed or if username was empty.
|
|
||||||
*/
|
|
||||||
static char* get_username_from_auth(
|
|
||||||
char* ptr,
|
|
||||||
uint8_t* data)
|
|
||||||
{
|
|
||||||
char* first_letter;
|
|
||||||
char* rval;
|
|
||||||
|
|
||||||
first_letter = (char *)(data + 4 + 4 + 4 + 1 + 23);
|
|
||||||
|
|
||||||
if (first_letter == '\0')
|
|
||||||
{
|
|
||||||
rval = NULL;
|
|
||||||
goto retblock;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ptr == NULL)
|
|
||||||
{
|
|
||||||
if ((rval = (char *)malloc(MYSQL_USER_MAXLEN+1)) == NULL)
|
|
||||||
{
|
|
||||||
goto retblock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rval = ptr;
|
|
||||||
}
|
|
||||||
snprintf(rval, MYSQL_USER_MAXLEN+1, "%s", first_letter);
|
|
||||||
|
|
||||||
retblock:
|
|
||||||
|
|
||||||
return rval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static char* create_auth_fail_str(
|
|
||||||
GWBUF* readbuf,
|
|
||||||
char* hostaddr,
|
|
||||||
char* sha1)
|
|
||||||
{
|
|
||||||
char* errstr;
|
|
||||||
char* uname;
|
|
||||||
const char* ferrstr = "Access denied for user '%s'@'%s' (using password: %s)";
|
|
||||||
|
|
||||||
if ( (uname = get_username_from_auth(NULL, (uint8_t *)GWBUF_DATA(readbuf))) == NULL)
|
|
||||||
{
|
|
||||||
errstr = NULL;
|
|
||||||
goto retblock;
|
|
||||||
}
|
|
||||||
/** -4 comes from 2X'%s' minus terminating char */
|
|
||||||
errstr = (char *)malloc(strlen(uname)+strlen(ferrstr)+strlen(hostaddr)+strlen("YES")-6+1);
|
|
||||||
|
|
||||||
if (errstr != NULL)
|
|
||||||
{
|
|
||||||
sprintf(errstr, ferrstr, uname, hostaddr, (*sha1 == '\0' ? "NO" : "YES"));
|
|
||||||
}
|
|
||||||
|
|
||||||
retblock:
|
|
||||||
return errstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write function for client DCB: writes data from MaxScale to Client
|
|
||||||
*
|
*
|
||||||
* @param dcb The DCB of the client
|
* @param dcb The DCB of the client
|
||||||
* @param queue Queue of buffers to write
|
* @param queue Queue of buffers to write
|
||||||
@ -663,83 +610,85 @@ int gw_read_client_event(
|
|||||||
|
|
||||||
case MYSQL_AUTH_SENT:
|
case MYSQL_AUTH_SENT:
|
||||||
{
|
{
|
||||||
int auth_val;
|
int auth_val = -1;
|
||||||
|
|
||||||
auth_val = gw_mysql_do_authentication(dcb, read_buffer);
|
auth_val = gw_mysql_do_authentication(dcb, read_buffer);
|
||||||
|
read_buffer = gwbuf_consume(read_buffer, nbytes_read);
|
||||||
|
ss_dassert(read_buffer == NULL || GWBUF_EMPTY(read_buffer));
|
||||||
|
|
||||||
if (auth_val == 0)
|
if (auth_val == 0)
|
||||||
{
|
{
|
||||||
SESSION *session;
|
SESSION *session = NULL;
|
||||||
|
protocol->protocol_auth_state = MYSQL_AUTH_RECV;
|
||||||
|
/**
|
||||||
|
* Create session, and a router session for it.
|
||||||
|
* If successful, there will be backend connection(s)
|
||||||
|
* after this point.
|
||||||
|
*/
|
||||||
|
session = session_alloc(dcb->service, dcb);
|
||||||
|
|
||||||
protocol->protocol_auth_state = MYSQL_AUTH_RECV;
|
if (session != NULL)
|
||||||
/**
|
{
|
||||||
* Create session, and a router session for it.
|
CHK_SESSION(session);
|
||||||
* If successful, there will be backend connection(s)
|
ss_dassert(session->state != SESSION_STATE_ALLOC);
|
||||||
* after this point.
|
|
||||||
*/
|
|
||||||
session = session_alloc(dcb->service, dcb);
|
|
||||||
|
|
||||||
if (session != NULL)
|
protocol->protocol_auth_state = MYSQL_IDLE;
|
||||||
{
|
/**
|
||||||
CHK_SESSION(session);
|
* Send an AUTH_OK packet to the client,
|
||||||
ss_dassert(session->state != SESSION_STATE_ALLOC);
|
* packet sequence is # 2
|
||||||
|
*/
|
||||||
|
mysql_send_ok(dcb, 2, 0, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
protocol->protocol_auth_state = MYSQL_AUTH_FAILED;
|
||||||
|
LOGIF(LD, (skygw_log_write(
|
||||||
|
LOGFILE_DEBUG,
|
||||||
|
"%lu [gw_read_client_event] session "
|
||||||
|
"creation failed. fd %d, "
|
||||||
|
"state = MYSQL_AUTH_FAILED.",
|
||||||
|
protocol->owner_dcb->fd,
|
||||||
|
pthread_self())));
|
||||||
|
|
||||||
protocol->protocol_auth_state = MYSQL_IDLE;
|
/** Send ERR 1045 to client */
|
||||||
/**
|
mysql_send_auth_error(
|
||||||
* Send an AUTH_OK packet to the client,
|
dcb,
|
||||||
* packet sequence is # 2
|
2,
|
||||||
*/
|
0,
|
||||||
mysql_send_ok(dcb, 2, 0, NULL);
|
"failed to create new session");
|
||||||
|
|
||||||
|
dcb_close(dcb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
protocol->protocol_auth_state = MYSQL_AUTH_FAILED;
|
||||||
|
LOGIF(LD, (skygw_log_write(
|
||||||
|
LOGFILE_DEBUG,
|
||||||
|
"%lu [gw_read_client_event] after "
|
||||||
|
"gw_mysql_do_authentication, fd %d, "
|
||||||
|
"state = MYSQL_AUTH_FAILED.",
|
||||||
|
protocol->owner_dcb->fd,
|
||||||
|
pthread_self())));
|
||||||
|
|
||||||
|
/** Send ERR 1045 to client */
|
||||||
|
if (auth_val == 2) {
|
||||||
|
mysql_send_auth_error(
|
||||||
|
dcb,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
"Database not existent");
|
||||||
|
} else {
|
||||||
|
mysql_send_auth_error(
|
||||||
|
dcb,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
"Authorization failed");
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
protocol->protocol_auth_state = MYSQL_AUTH_FAILED;
|
|
||||||
LOGIF(LD, (skygw_log_write(
|
|
||||||
LOGFILE_DEBUG,
|
|
||||||
"%lu [gw_read_client_event] session "
|
|
||||||
"creation failed. fd %d, "
|
|
||||||
"state = MYSQL_AUTH_FAILED.",
|
|
||||||
protocol->owner_dcb->fd,
|
|
||||||
pthread_self())));
|
|
||||||
|
|
||||||
/** Send ERR 1045 to client */
|
dcb_close(dcb);
|
||||||
mysql_send_auth_error(
|
}
|
||||||
dcb,
|
}
|
||||||
2,
|
|
||||||
0,
|
|
||||||
"failed to create new session");
|
|
||||||
|
|
||||||
dcb_close(dcb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char* fail_str;
|
|
||||||
|
|
||||||
protocol->protocol_auth_state = MYSQL_AUTH_FAILED;
|
|
||||||
fail_str = create_auth_fail_str(read_buffer,
|
|
||||||
dcb->remote,
|
|
||||||
(char*)((MYSQL_session *)dcb->data)->client_sha1);
|
|
||||||
|
|
||||||
/** Send error 1045 to client */
|
|
||||||
mysql_send_auth_error(
|
|
||||||
dcb,
|
|
||||||
2,
|
|
||||||
0,
|
|
||||||
fail_str);
|
|
||||||
|
|
||||||
LOGIF(LD, (skygw_log_write(
|
|
||||||
LOGFILE_DEBUG,
|
|
||||||
"%lu [gw_read_client_event] after "
|
|
||||||
"gw_mysql_do_authentication, fd %d, "
|
|
||||||
"state = MYSQL_AUTH_FAILED.",
|
|
||||||
protocol->owner_dcb->fd,
|
|
||||||
pthread_self())));
|
|
||||||
free(fail_str);
|
|
||||||
dcb_close(dcb);
|
|
||||||
}
|
|
||||||
read_buffer = gwbuf_consume(read_buffer, nbytes_read);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MYSQL_IDLE:
|
case MYSQL_IDLE:
|
||||||
@ -877,12 +826,9 @@ int gw_read_client_event(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** succeed */
|
/** succeed */
|
||||||
if (rc)
|
if (rc) {
|
||||||
{
|
|
||||||
rc = 0; /**< here '0' means success */
|
rc = 0; /**< here '0' means success */
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
GWBUF* errbuf;
|
GWBUF* errbuf;
|
||||||
bool succp;
|
bool succp;
|
||||||
|
|
||||||
@ -1439,12 +1385,20 @@ gw_client_close(DCB *dcb)
|
|||||||
CHK_SESSION(session);
|
CHK_SESSION(session);
|
||||||
spinlock_acquire(&session->ses_lock);
|
spinlock_acquire(&session->ses_lock);
|
||||||
|
|
||||||
if (session->state != SESSION_STATE_STOPPING)
|
if (session->state == SESSION_STATE_STOPPING)
|
||||||
{
|
{
|
||||||
session->state = SESSION_STATE_STOPPING;
|
/**
|
||||||
}
|
* Session is already getting closed so avoid
|
||||||
spinlock_release(&session->ses_lock);
|
* redundant calls
|
||||||
|
*/
|
||||||
|
spinlock_release(&session->ses_lock);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
session->state = SESSION_STATE_STOPPING;
|
||||||
|
spinlock_release(&session->ses_lock);
|
||||||
|
}
|
||||||
router = session->service->router;
|
router = session->service->router;
|
||||||
router_instance = session->service->router_instance;
|
router_instance = session->service->router_instance;
|
||||||
rsession = session->router_session;
|
rsession = session->router_session;
|
||||||
|
@ -31,6 +31,9 @@
|
|||||||
* localhost entry should be added for the selected user in the backends.
|
* 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
|
* Setting to 1 allow localhost (127.0.0.1 or socket) to match the any host grant via
|
||||||
* user@%
|
* 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.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -463,7 +466,6 @@ int gw_receive_backend_auth(
|
|||||||
bufstr)));
|
bufstr)));
|
||||||
|
|
||||||
free(bufstr);
|
free(bufstr);
|
||||||
free(err);
|
|
||||||
rc = -1;
|
rc = -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -538,9 +540,9 @@ int gw_receive_backend_auth(
|
|||||||
* @return 0 on success, 1 on failure
|
* @return 0 on success, 1 on failure
|
||||||
*/
|
*/
|
||||||
int gw_send_authentication_to_backend(
|
int gw_send_authentication_to_backend(
|
||||||
char *dbname,
|
char *dbname,
|
||||||
char *user,
|
char *user,
|
||||||
uint8_t *passwd,
|
uint8_t *passwd,
|
||||||
MySQLProtocol *conn)
|
MySQLProtocol *conn)
|
||||||
{
|
{
|
||||||
int compress = 0;
|
int compress = 0;
|
||||||
@ -550,8 +552,8 @@ int gw_send_authentication_to_backend(
|
|||||||
long bytes;
|
long bytes;
|
||||||
uint8_t client_scramble[GW_MYSQL_SCRAMBLE_SIZE];
|
uint8_t client_scramble[GW_MYSQL_SCRAMBLE_SIZE];
|
||||||
uint8_t client_capabilities[4];
|
uint8_t client_capabilities[4];
|
||||||
uint32_t server_capabilities = 0;
|
uint32_t server_capabilities;
|
||||||
uint32_t final_capabilities = 0;
|
uint32_t final_capabilities;
|
||||||
char dbpass[MYSQL_USER_MAXLEN + 1]="";
|
char dbpass[MYSQL_USER_MAXLEN + 1]="";
|
||||||
GWBUF *buffer;
|
GWBUF *buffer;
|
||||||
DCB *dcb;
|
DCB *dcb;
|
||||||
@ -566,12 +568,17 @@ int gw_send_authentication_to_backend(
|
|||||||
curr_passwd = passwd;
|
curr_passwd = passwd;
|
||||||
|
|
||||||
dcb = conn->owner_dcb;
|
dcb = conn->owner_dcb;
|
||||||
|
|
||||||
|
// Zero the vars
|
||||||
|
memset(&server_capabilities, '\0', sizeof(server_capabilities));
|
||||||
|
memset(&final_capabilities, '\0', sizeof(final_capabilities));
|
||||||
|
|
||||||
final_capabilities = gw_mysql_get_byte4((uint8_t *)&server_capabilities);
|
final_capabilities = gw_mysql_get_byte4((uint8_t *)&server_capabilities);
|
||||||
|
|
||||||
/** Copy client's flags to backend */
|
final_capabilities |= GW_MYSQL_CAPABILITIES_PROTOCOL_41;
|
||||||
final_capabilities |= conn->client_capabilities;;
|
final_capabilities |= GW_MYSQL_CAPABILITIES_CLIENT;
|
||||||
|
|
||||||
if (compress) {
|
if (compress) {
|
||||||
final_capabilities |= GW_MYSQL_CAPABILITIES_COMPRESS;
|
final_capabilities |= GW_MYSQL_CAPABILITIES_COMPRESS;
|
||||||
#ifdef DEBUG_MYSQL_CONN
|
#ifdef DEBUG_MYSQL_CONN
|
||||||
fprintf(stderr, ">>>> Backend Connection with compression\n");
|
fprintf(stderr, ">>>> Backend Connection with compression\n");
|
||||||
@ -1026,24 +1033,19 @@ int mysql_send_custom_error (
|
|||||||
* @param passwd The SHA1(real_password): Note real_password is unknown
|
* @param passwd The SHA1(real_password): Note real_password is unknown
|
||||||
* @return 1 on success, 0 on failure
|
* @return 1 on success, 0 on failure
|
||||||
*/
|
*/
|
||||||
int gw_send_change_user_to_backend(
|
int gw_send_change_user_to_backend(char *dbname, char *user, uint8_t *passwd, MySQLProtocol *conn) {
|
||||||
char *dbname,
|
int compress = 0;
|
||||||
char *user,
|
int rv;
|
||||||
uint8_t *passwd,
|
uint8_t *payload = NULL;
|
||||||
MySQLProtocol *conn)
|
uint8_t *payload_start = NULL;
|
||||||
{
|
long bytes;
|
||||||
int compress = 0;
|
uint8_t client_scramble[GW_MYSQL_SCRAMBLE_SIZE];
|
||||||
int rv;
|
uint8_t client_capabilities[4];
|
||||||
uint8_t *payload = NULL;
|
uint32_t server_capabilities;
|
||||||
uint8_t *payload_start = NULL;
|
uint32_t final_capabilities;
|
||||||
long bytes;
|
char dbpass[MYSQL_USER_MAXLEN + 1]="";
|
||||||
uint8_t client_scramble[GW_MYSQL_SCRAMBLE_SIZE];
|
GWBUF *buffer;
|
||||||
uint8_t client_capabilities[4];
|
DCB *dcb;
|
||||||
uint32_t server_capabilities = 0;
|
|
||||||
uint32_t final_capabilities = 0;
|
|
||||||
char dbpass[MYSQL_USER_MAXLEN + 1]="";
|
|
||||||
GWBUF *buffer;
|
|
||||||
DCB *dcb;
|
|
||||||
|
|
||||||
char *curr_db = NULL;
|
char *curr_db = NULL;
|
||||||
uint8_t *curr_passwd = NULL;
|
uint8_t *curr_passwd = NULL;
|
||||||
@ -1056,10 +1058,14 @@ int gw_send_change_user_to_backend(
|
|||||||
|
|
||||||
dcb = conn->owner_dcb;
|
dcb = conn->owner_dcb;
|
||||||
|
|
||||||
final_capabilities = gw_mysql_get_byte4((uint8_t *)&server_capabilities);
|
// Zero the vars
|
||||||
|
memset(&server_capabilities, '\0', sizeof(server_capabilities));
|
||||||
|
memset(&final_capabilities, '\0', sizeof(final_capabilities));
|
||||||
|
|
||||||
/** Copy client's flags to backend */
|
final_capabilities = gw_mysql_get_byte4((uint8_t *)&server_capabilities);
|
||||||
final_capabilities |= conn->client_capabilities;;
|
|
||||||
|
final_capabilities |= GW_MYSQL_CAPABILITIES_PROTOCOL_41;
|
||||||
|
final_capabilities |= GW_MYSQL_CAPABILITIES_CLIENT;
|
||||||
|
|
||||||
if (compress) {
|
if (compress) {
|
||||||
final_capabilities |= GW_MYSQL_CAPABILITIES_COMPRESS;
|
final_capabilities |= GW_MYSQL_CAPABILITIES_COMPRESS;
|
||||||
@ -1310,7 +1316,7 @@ int gw_check_mysql_scramble_data(DCB *dcb, uint8_t *token, unsigned int token_le
|
|||||||
/**
|
/**
|
||||||
* gw_find_mysql_user_password_sha1
|
* 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
|
* 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
|
* If found the HEX password, representing sha1(sha1(password)), is converted in binary data and
|
||||||
@ -1328,12 +1334,18 @@ int gw_find_mysql_user_password_sha1(char *username, uint8_t *gateway_password,
|
|||||||
struct sockaddr_in *client;
|
struct sockaddr_in *client;
|
||||||
char *user_password = NULL;
|
char *user_password = NULL;
|
||||||
MYSQL_USER_HOST key;
|
MYSQL_USER_HOST key;
|
||||||
|
MYSQL_session *client_data = NULL;
|
||||||
|
|
||||||
|
client_data = dcb->data;
|
||||||
|
|
||||||
service = (SERVICE *) dcb->service;
|
service = (SERVICE *) dcb->service;
|
||||||
client = (struct sockaddr_in *) &dcb->ipv4;
|
client = (struct sockaddr_in *) &dcb->ipv4;
|
||||||
|
|
||||||
key.user = username;
|
key.user = username;
|
||||||
|
key.resource = client_data->db;
|
||||||
|
|
||||||
memcpy(&key.ipv4, client, sizeof(struct sockaddr_in));
|
memcpy(&key.ipv4, client, sizeof(struct sockaddr_in));
|
||||||
|
key.netmask = 32;
|
||||||
|
|
||||||
LOGIF(LD,
|
LOGIF(LD,
|
||||||
(skygw_log_write_flush(
|
(skygw_log_write_flush(
|
||||||
@ -1343,73 +1355,118 @@ int gw_find_mysql_user_password_sha1(char *username, uint8_t *gateway_password,
|
|||||||
key.user,
|
key.user,
|
||||||
dcb->remote)));
|
dcb->remote)));
|
||||||
|
|
||||||
/* look for user@current_host now */
|
/* look for user@current_ipv4 now */
|
||||||
user_password = mysql_users_fetch(service->users, &key);
|
user_password = mysql_users_fetch(service->users, &key);
|
||||||
|
|
||||||
if (!user_password) {
|
if (!user_password) {
|
||||||
/* The user is not authenticated @ current host */
|
/* The user is not authenticated @ current IPv4 */
|
||||||
|
|
||||||
/* 1) Check for localhost first.
|
while (1) {
|
||||||
* The check for localhost is 127.0.0.1 (IPv4 only)
|
/*
|
||||||
*/
|
* (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)));
|
|
||||||
|
|
||||||
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
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
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,
|
||||||
|
"%lu [MySQL Client Auth], user [%s@%s] not found, please try with 'localhost_match_wildcard_host=1' in service definition",
|
||||||
|
pthread_self(),
|
||||||
|
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,
|
LOGIF(LD,
|
||||||
(skygw_log_write_flush(
|
(skygw_log_write_flush(
|
||||||
LOGFILE_DEBUG,
|
LOGFILE_DEBUG,
|
||||||
"%lu [MySQL Client Auth], user [%s@%s] not existent",
|
"%lu [MySQL Client Auth], checking user [%s@%s] with wildcard host [%%]",
|
||||||
pthread_self(),
|
pthread_self(),
|
||||||
key.user,
|
key.user,
|
||||||
dcb->remote)));
|
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
|
/* 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)).
|
* Convert the hex data (40 bytes) to binary (20 bytes).
|
||||||
* Please note: the real_password is unknown and SHA1(real_password) is unknown as well
|
* The gateway_password represents the SHA1(SHA1(real_password)).
|
||||||
*/
|
* Please note: the real_password is unknown and SHA1(real_password) is unknown as well
|
||||||
|
*/
|
||||||
|
//char *the_password = user_password->value;
|
||||||
|
//MYSQL_USER_HOST *matched_key = (MYSQL_USER_HOST *)user_password->key;
|
||||||
|
|
||||||
if (strlen(user_password))
|
|
||||||
gw_hex2bin(gateway_password, user_password, SHA_DIGEST_LENGTH * 2);
|
|
||||||
|
|
||||||
return 0;
|
if (strlen(user_password))
|
||||||
|
gw_hex2bin(gateway_password, user_password, SHA_DIGEST_LENGTH * 2);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1457,7 +1514,7 @@ mysql_send_auth_error (
|
|||||||
}
|
}
|
||||||
mysql_errno = 1045;
|
mysql_errno = 1045;
|
||||||
mysql_error_msg = "Access denied!";
|
mysql_error_msg = "Access denied!";
|
||||||
mysql_state = "28000";
|
mysql_state = "2800";
|
||||||
|
|
||||||
field_count = 0xff;
|
field_count = 0xff;
|
||||||
gw_mysql_set_byte2(mysql_err, mysql_errno);
|
gw_mysql_set_byte2(mysql_err, mysql_errno);
|
||||||
@ -1652,11 +1709,9 @@ void protocol_archive_srv_command(
|
|||||||
|
|
||||||
s1 = &p->protocol_command;
|
s1 = &p->protocol_command;
|
||||||
|
|
||||||
LOGIF(LD, (skygw_log_write(
|
LOGIF(LT, (skygw_log_write(
|
||||||
LOGFILE_DEBUG,
|
LOGFILE_TRACE,
|
||||||
"%lu [protocol_archive_srv_command] Move command %s from fd %d "
|
"Move command %s from fd %d to command history.",
|
||||||
"to command history.",
|
|
||||||
pthread_self(),
|
|
||||||
STRPACKETTYPE(s1->scom_cmd),
|
STRPACKETTYPE(s1->scom_cmd),
|
||||||
p->owner_dcb->fd)));
|
p->owner_dcb->fd)));
|
||||||
|
|
||||||
@ -1728,8 +1783,8 @@ void protocol_add_srv_command(
|
|||||||
p->protocol_command.scom_next = server_command_init(NULL, cmd);
|
p->protocol_command.scom_next = server_command_init(NULL, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGIF(LD, (skygw_log_write(
|
LOGIF(LT, (skygw_log_write(
|
||||||
LOGFILE_DEBUG,
|
LOGFILE_TRACE,
|
||||||
"Added command %s to fd %d.",
|
"Added command %s to fd %d.",
|
||||||
STRPACKETTYPE(cmd),
|
STRPACKETTYPE(cmd),
|
||||||
p->owner_dcb->fd)));
|
p->owner_dcb->fd)));
|
||||||
@ -1739,8 +1794,8 @@ void protocol_add_srv_command(
|
|||||||
|
|
||||||
while (c != NULL && c->scom_cmd != MYSQL_COM_UNDEFINED)
|
while (c != NULL && c->scom_cmd != MYSQL_COM_UNDEFINED)
|
||||||
{
|
{
|
||||||
LOGIF(LD, (skygw_log_write(
|
LOGIF(LT, (skygw_log_write(
|
||||||
LOGFILE_DEBUG,
|
LOGFILE_TRACE,
|
||||||
"fd %d : %d %s",
|
"fd %d : %d %s",
|
||||||
p->owner_dcb->fd,
|
p->owner_dcb->fd,
|
||||||
c->scom_cmd,
|
c->scom_cmd,
|
||||||
|
Reference in New Issue
Block a user