From 2dfa01fccc43337d328893cd7115e383dd939cf2 Mon Sep 17 00:00:00 2001 From: MassimilianoPinto Date: Thu, 16 Oct 2014 19:17:15 +0200 Subject: [PATCH] MySQL Auth with dbname check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MySQL Auth with dbname check Unknown database ‘xxxxx’ is returned to client Proper error number is still missing and also com_change_user need to be fixed --- server/core/dbusers.c | 17 ++++--- server/core/service.c | 6 +-- server/core/test/test_mysql_users.c | 67 +++++++++++++++++--------- server/include/dbusers.h | 2 +- server/modules/protocol/mysql_client.c | 16 ++++-- 5 files changed, 69 insertions(+), 39 deletions(-) diff --git a/server/core/dbusers.c b/server/core/dbusers.c index 685c7aa39..a355e85f0 100644 --- a/server/core/dbusers.c +++ b/server/core/dbusers.c @@ -64,7 +64,7 @@ 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); -void *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key); +char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key); char *mysql_format_user_entry(void *data); int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *passwd, char *anydb, char *db); static int getDatabases(SERVICE *); @@ -188,7 +188,11 @@ int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *p 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); + //fprintf(stderr, "Current %s@%s has anydb access %s OR specific db %s\n", user, host, anydb, db); + + if (users == NULL || user == NULL || host == NULL) { + return ret; + } /* prepare the user@host data struct */ memset(&serv_addr, 0, sizeof(serv_addr)); @@ -219,10 +223,11 @@ int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *p found_any = 1; } else { char *tmp; - strcpy(ret_ip, host); + strncpy(ret_ip, host, INET_ADDRSTRLEN); tmp = ret_ip+strlen(ret_ip)-1; /* start from Class C */ + while(tmp > ret_ip) { if (*tmp == '%') { /* set only the last IPv4 byte to 1 @@ -254,10 +259,10 @@ int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *p } /* add user@host as key and passwd as value in the MySQL users hash table */ - if (mysql_users_add(users, &key, passwd)) + 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); @@ -698,7 +703,7 @@ int add; * @param key The key with user@host * @return The authentication data or NULL on error */ -void *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key) { +char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key) { MYSQL_USER_HOST *entry; if (key == NULL) return NULL; diff --git a/server/core/service.c b/server/core/service.c index d8472818f..e2cb8dd9d 100644 --- a/server/core/service.c +++ b/server/core/service.c @@ -220,9 +220,9 @@ GWPROTOCOL *funcs; dbnames_loaded = mysql_users_load_dbs(service); LOGIF(LM, (skygw_log_write( - LOGFILE_MESSAGE, - "Loaded %d MySQL Databases.", - dbnames_loaded))); + LOGFILE_MESSAGE, + "Loaded %d MySQL Databases.", + dbnames_loaded))); } else { /* Generic users table */ service->users = users_alloc(); diff --git a/server/core/test/test_mysql_users.c b/server/core/test/test_mysql_users.c index 7f72496cc..e2d15a960 100644 --- a/server/core/test/test_mysql_users.c +++ b/server/core/test/test_mysql_users.c @@ -54,9 +54,23 @@ int set_and_get_single_mysql_users_ipv4(char *username, unsigned long ipv4, char char ret_ip[200]=""; char *fetch_data; char *db=""; + DCB *dcb; + SERVICE *service; unsigned long fix_ipv4; + dcb = dcb_alloc(DCB_ROLE_INTERNAL); + + if (dcb == NULL) { + fprintf(stderr, "dcb_alloc() failed\n"); + return 1; + } + if ((service = (SERVICE *)calloc(1, sizeof(SERVICE))) == NULL) { + fprintf(stderr, "service_alloc() failed\n"); + dcb_free(dcb); + return 1; + } + if (ipv4 > UINT_MAX) { fix_ipv4 = UINT_MAX; } else { @@ -82,6 +96,8 @@ int set_and_get_single_mysql_users_ipv4(char *username, unsigned long ipv4, char if (!mysql_users_add(mysql_users, &key, password)) { fprintf(stderr, "Failed adding %s@%s(%lu)\n", username, ret_ip, fix_ipv4); users_free(mysql_users); + free(service); + dcb_free(dcb); return 1; } @@ -97,6 +113,8 @@ int set_and_get_single_mysql_users_ipv4(char *username, unsigned long ipv4, char fetch_data = mysql_users_fetch(mysql_users, &find_key); users_free(mysql_users); + free(service); + dcb_free(dcb); if (!fetch_data) return 1; @@ -166,22 +184,23 @@ int set_and_get_single_mysql_users(char *username, char *hostname, char *passwor 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; + int ret = -1; + int rc = -1; struct sockaddr_in client_addr; DCB *dcb; SERVICE *service; - MYSQL_session data; + MYSQL_session *data; dcb = dcb_alloc(DCB_ROLE_INTERNAL); if (dcb == NULL) { fprintf(stderr, "dcb_alloc() failed\n"); - return 1; + return ret; } if ((service = (SERVICE *)calloc(1, sizeof(SERVICE))) == NULL) { fprintf(stderr, "service_alloc() failed\n"); dcb_free(dcb); - return 1; + return ret; } memset(&client_addr, 0, sizeof(client_addr)); @@ -191,10 +210,18 @@ int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *pass fprintf(stderr, "setipaddress failed for host [%s]\n", from); free(service); dcb_free(dcb); - return 1; + return ret; } } + if ((data = (MYSQL_session *) calloc(1, sizeof(MYSQL_session))) == NULL) { + fprintf(stderr, "MYSQL_session alloc failed\n"); + free(service); + dcb_free(dcb); + return ret; + } + + /* client IPv4 in raw data*/ memcpy(&dcb->ipv4, (struct sockaddr_in *)&client_addr, sizeof(struct sockaddr_in)); @@ -205,14 +232,15 @@ int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *pass service->users = mysql_users; if (db_from != NULL) - strcpy(data.db, db_from); + strcpy(data->db, db_from); else - strcpy(data.db, ""); + strcpy(data->db, ""); - dcb->data = &data; + /* freed by dcb_free(dcb) */ + dcb->data = data; // the routine returns 1 on success - if (anydb) { + if (anydb != NULL) { 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) { @@ -223,25 +251,19 @@ int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *pass } else { ret = add_mysql_users_with_host_ipv4(mysql_users, username, hostname, password, "N", NULL); } - - - if (!ret) { + + if (ret == 0) { fprintf(stderr, "add_mysql_users_with_host_ipv4 (%s@%s, %s) FAILED\n", username, hostname, password); - users_free(mysql_users); - free(service); - dcb_free(dcb); - - return 1; } else { - char db_passwd[100]=""; + unsigned 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); + //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); + ret = gw_find_mysql_user_password_sha1(username, db_passwd, dcb); } users_free(mysql_users); @@ -309,7 +331,7 @@ int main() { 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); + ret = set_and_get_mysql_users_wildcards("pippo", "192.168.4.%", "ffoo", "192.168.2.2", NULL, NULL, NULL); if (ret) fprintf(stderr, "\t-- Expecting no match\n"); assert(ret == 1); @@ -321,7 +343,6 @@ int main() { 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); @@ -383,8 +404,6 @@ int main() { if (!ret) fprintf(stderr, "\t-- Expecting ok\n"); assert(ret == 0); - - fprintf(stderr, "----------------\n"); fprintf(stderr, "<<< Test completed\n"); diff --git a/server/include/dbusers.h b/server/include/dbusers.h index 57b205333..7b7fb03dd 100644 --- a/server/include/dbusers.h +++ b/server/include/dbusers.h @@ -63,6 +63,6 @@ extern int reload_mysql_users(SERVICE *service); extern int mysql_users_add(USERS *users, MYSQL_USER_HOST *key, char *auth); extern int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *passwd, char *anydb, char *db); extern USERS *mysql_users_alloc(); -extern void *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key); +extern char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key); extern int replace_mysql_users(SERVICE *service); #endif diff --git a/server/modules/protocol/mysql_client.c b/server/modules/protocol/mysql_client.c index 43baf02f0..54d577d4d 100644 --- a/server/modules/protocol/mysql_client.c +++ b/server/modules/protocol/mysql_client.c @@ -497,7 +497,7 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) { i++; } - if (!db_exists) { + if (!db_exists && auth_ret == 0) { auth_ret = 2; } } @@ -735,18 +735,23 @@ int gw_read_client_event( 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); if (auth_val == 2) { + char *dberr; + dberr= calloc(1, 100); + sprintf(dberr, "Unknown database '%s'", (char*)((MYSQL_session *)dcb->data)->db); + mysql_send_auth_error( dcb, 2, 0, - "Database not existent"); + dberr); + free(dberr); } else { /** Send error 1045 to client */ + fail_str = create_auth_fail_str(read_buffer, + dcb->remote, + (char*)((MYSQL_session *)dcb->data)->client_sha1); mysql_send_auth_error( dcb, 2, @@ -761,6 +766,7 @@ int gw_read_client_event( "state = MYSQL_AUTH_FAILED.", protocol->owner_dcb->fd, pthread_self()))); + free(fail_str); dcb_close(dcb); }