Added database errmsg to change_user

Added database errmsg to change_user
This commit is contained in:
MassimilianoPinto
2014-10-17 19:02:19 +02:00
parent 2dfa01fccc
commit b8f590e67f
3 changed files with 119 additions and 68 deletions

View File

@ -66,7 +66,7 @@ static int backend_write_delayqueue(DCB *dcb);
static void backend_set_delayqueue(DCB *dcb, GWBUF *queue); static void backend_set_delayqueue(DCB *dcb, GWBUF *queue);
static int gw_change_user(DCB *backend_dcb, SERVER *server, SESSION *in_session, GWBUF *queue); static int gw_change_user(DCB *backend_dcb, SERVER *server, SESSION *in_session, GWBUF *queue);
static GWBUF* process_response_data (DCB* dcb, GWBUF* readbuf, int nbytes_to_process); static GWBUF* process_response_data (DCB* dcb, GWBUF* readbuf, int nbytes_to_process);
extern char* create_auth_failed_msg( GWBUF* readbuf, char* hostaddr, uint8_t* sha1, int dbmatch);
#if defined(NOT_USED) #if defined(NOT_USED)
@ -1191,6 +1191,7 @@ static int gw_change_user(
uint8_t *auth_token = NULL; uint8_t *auth_token = NULL;
int rv = -1; int rv = -1;
int auth_ret = 1; int auth_ret = 1;
int db_exists = 0;
current_session = (MYSQL_session *)in_session->client->data; current_session = (MYSQL_session *)in_session->client->data;
backend_protocol = backend->protocol; backend_protocol = backend->protocol;
@ -1217,6 +1218,10 @@ static int gw_change_user(
memcpy(auth_token, client_auth_packet, auth_token_len); memcpy(auth_token, client_auth_packet, auth_token_len);
client_auth_packet += auth_token_len; client_auth_packet += auth_token_len;
} }
// get db name
strcpy(database, (char *)client_auth_packet);
// decode the token and check the password // decode the token and check the password
// Note: if auth_token_len == 0 && auth_token == NULL, user is without password // Note: if auth_token_len == 0 && auth_token == NULL, user is without password
auth_ret = gw_check_mysql_scramble_data(backend->session->client, auth_token, auth_token_len, client_protocol->scramble, sizeof(client_protocol->scramble), username, client_sha1); auth_ret = gw_check_mysql_scramble_data(backend->session->client, auth_token, auth_token_len, client_protocol->scramble, sizeof(client_protocol->scramble), username, client_sha1);
@ -1233,17 +1238,33 @@ static int gw_change_user(
if (auth_token) if (auth_token)
free(auth_token); free(auth_token);
if (auth_ret != 0) { if (strlen(database)) {
/*< vraa : errorHandle */ int i = 0;
while(backend->session->client->service->resources[i]) {
if (strncmp(database, backend->session->client->service->resources[i], MYSQL_DATABASE_MAXLEN) == 0) {
db_exists = 1;
}
// send the error packet i++;
mysql_send_auth_error(backend->session->client, 1, 0, "Authorization failed on change_user"); }
if (!db_exists && auth_ret == 0) {
auth_ret = 2;
}
}
if (auth_ret != 0) {
char *message = create_auth_failed_msg(queue, "ipaddr", client_sha1, auth_ret);
/* send the error packet */
mysql_send_auth_error(backend->session->client, 1, 0, message);
fprintf(stderr, "ERROR change user for [%s] to [%s]\n", username, database);
//mysql_send_auth_error(backend->session->client, 1, 0, "Authorization failed on change_user");
free(message);
rv = 1; rv = 1;
} else { } else {
// get db name
strcpy(database, (char *)client_auth_packet);
rv = gw_send_change_user_to_backend(database, username, client_sha1, backend_protocol); rv = gw_send_change_user_to_backend(database, username, client_sha1, backend_protocol);
/*< /*<

View File

@ -70,7 +70,7 @@ 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* create_auth_fail_str(GWBUF* readbuf, char* hostaddr, char* sha1);
static char* get_username_from_auth(char* ptr, uint8_t* data); extern 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.
@ -394,6 +394,7 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
uint8_t *stage1_hash = NULL; uint8_t *stage1_hash = NULL;
int auth_ret = -1; int auth_ret = -1;
MYSQL_session *client_data = NULL; MYSQL_session *client_data = NULL;
int db_exists = 0;
CHK_DCB(dcb); CHK_DCB(dcb);
@ -447,11 +448,15 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
client_auth_packet + 4 + 4 + 4 + 1 + 23 + strlen(username) + 1, client_auth_packet + 4 + 4 + 4 + 1 + 23 + strlen(username) + 1,
1); 1);
/*
* Note: some clients may pass empty database, connect_with_db !=0 but database =""
*/
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);
fprintf(stderr, "---- Database name passed [%s], flag [%i]\n", database, connect_with_db);
} }
/* allocate memory for token only if auth_token_len > 0 */ /* allocate memory for token only if auth_token_len > 0 */
@ -482,13 +487,14 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
} }
} }
fprintf(stderr, "--- Authentication reply is [%i]\n", auth_ret);
/* let's free the auth_token now */ /* let's free the auth_token now */
if (auth_token) if (auth_token)
free(auth_token); free(auth_token);
if (database) { if (database && strlen(database)) {
int i = 0; int i = 0;
int db_exists = 0;
while(dcb->service->resources[i]) { while(dcb->service->resources[i]) {
if (strncmp(database, dcb->service->resources[i], MYSQL_DATABASE_MAXLEN) == 0) { if (strncmp(database, dcb->service->resources[i], MYSQL_DATABASE_MAXLEN) == 0) {
db_exists = 1; db_exists = 1;
@ -510,50 +516,6 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
return auth_ret; return auth_ret;
} }
/**
* Read username from MySQL authentication packet.
*
* @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( static char* create_auth_fail_str(
GWBUF* readbuf, GWBUF* readbuf,
char* hostaddr, char* hostaddr,
@ -757,6 +719,7 @@ int gw_read_client_event(
2, 2,
0, 0,
fail_str); fail_str);
free(fail_str);
} }
LOGIF(LD, (skygw_log_write( LOGIF(LD, (skygw_log_write(
@ -767,7 +730,6 @@ int gw_read_client_event(
protocol->owner_dcb->fd, protocol->owner_dcb->fd,
pthread_self()))); pthread_self())));
free(fail_str);
dcb_close(dcb); dcb_close(dcb);
} }
read_buffer = gwbuf_consume(read_buffer, nbytes_read); read_buffer = gwbuf_consume(read_buffer, nbytes_read);
@ -780,7 +742,8 @@ int gw_read_client_event(
uint8_t* payload = NULL; uint8_t* payload = NULL;
bool stmt_input; /*< router input type */ bool stmt_input; /*< router input type */
ss_dassert(nbytes_read >= 5); fprintf(stderr, "NBYTES %i\n", nbytes_read);
//ss_dassert(nbytes_read >= 5);
session = dcb->session; session = dcb->session;
ss_dassert( session!= NULL); ss_dassert( session!= NULL);

View File

@ -49,6 +49,7 @@ extern int gw_read_backend_event(DCB* dcb);
extern int gw_write_backend_event(DCB *dcb); extern int gw_write_backend_event(DCB *dcb);
extern int gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue); extern int gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue);
extern int gw_error_backend_event(DCB *dcb); extern int gw_error_backend_event(DCB *dcb);
char* get_username_from_auth(char* ptr, uint8_t* data);
static server_command_t* server_command_init(server_command_t* srvcmd, static server_command_t* server_command_init(server_command_t* srvcmd,
mysql_server_cmd_t cmd); mysql_server_cmd_t cmd);
@ -1117,15 +1118,15 @@ int gw_send_change_user_to_backend(
if (curr_passwd != NULL) { if (curr_passwd != NULL) {
bytes += GW_MYSQL_SCRAMBLE_SIZE; bytes += GW_MYSQL_SCRAMBLE_SIZE;
bytes++;
} else {
bytes++;
} }
// the NULL
bytes++;
if (curr_db != NULL) { if (curr_db != NULL) {
bytes += strlen(curr_db); bytes += strlen(curr_db);
bytes++;
} }
// the NULL
bytes++;
// the charset // the charset
bytes += 2; bytes += 2;
@ -1177,6 +1178,9 @@ int gw_send_change_user_to_backend(
memcpy(payload, curr_db, strlen(curr_db)); memcpy(payload, curr_db, strlen(curr_db));
payload += strlen(curr_db); payload += strlen(curr_db);
payload++; payload++;
} else {
// skip the NULL
payload++;
} }
// set the charset, 2 bytes!!!! // set the charset, 2 bytes!!!!
@ -1979,3 +1983,66 @@ void protocol_set_response_status (
spinlock_release(&p->protocol_lock); spinlock_release(&p->protocol_lock);
} }
char* create_auth_failed_msg(
GWBUF* readbuf,
char* hostaddr,
uint8_t* sha1, int dbmatch)
{
char* errstr;
char* uname=(char *)GWBUF_DATA(readbuf) + 5;
const char* ferrstr = "Access denied for user '%s'@'%s' (using password: %s)";
/** -4 comes from 2X'%s' minus terminating char */
errstr = (char *)malloc(strlen(uname)+strlen(ferrstr)+strlen(hostaddr)+strlen("YES")-6+1 + strlen(" to database ") + strlen("''") + strlen("datbase") +1);
if (errstr != NULL)
{
sprintf(errstr, ferrstr, uname, hostaddr, (*sha1 == '\0' ? "NO" : "YES"));
strcat(errstr, " to database 'database'");
}
return errstr;
}
/**
* Read username from MySQL authentication packet.
*
* @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.
*/
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;
}