Authentication FAILED triggers client and backend connection close.

mysqlslap tests show some memory is nod deallocated, probably some gwbuffer incorrect use or the error handling is not triggering any consume action on buffers.
This commit is contained in:
Massimiliano Pinto 2013-06-13 18:09:14 +02:00
parent a89c2bc1c0
commit 269bef8280
2 changed files with 109 additions and 23 deletions

View File

@ -50,7 +50,7 @@
* @param packet_number
* @param in_affected_rows
* @param mysql_message
* @return
* @return packet length
*
*/
int
@ -122,6 +122,89 @@ mysql_send_ok(DCB *dcb, int packet_number, int in_affected_rows, const char* mys
return sizeof(mysql_packet_header) + mysql_payload_size;
}
/*
* mysql_send_auth_error
*
* Send a MySQL protocol ERR message, for gatewayauthentication error to the dcb
*
* @param dcb Descriptor Control Block for the connection to which the OK is sent
* @param packet_number
* @param in_affected_rows
* @param mysql_message
* @return packet lenght
*
*/
int
mysql_send_auth_error (DCB *dcb, int packet_number, int in_affected_rows, const char* mysql_message) {
uint8_t *outbuf = NULL;
uint8_t mysql_payload_size = 0;
uint8_t mysql_packet_header[4];
uint8_t *mysql_payload = NULL;
uint8_t field_count = 0;
uint8_t affected_rows = 0;
uint8_t insert_id = 0;
uint8_t mysql_err[2];
uint8_t mysql_statemsg[6];
unsigned int mysql_errno = 0;
const char *mysql_error_msg = NULL;
const char *mysql_state = NULL;
GWBUF *buf;
mysql_errno = 1045;
mysql_error_msg = "Access denied!";
mysql_state = "2800";
field_count = 0xff;
gw_mysql_set_byte2(mysql_err, mysql_errno);
mysql_statemsg[0]='#';
memcpy(mysql_statemsg+1, mysql_state, 5);
if (mysql_message != NULL) {
mysql_error_msg = mysql_message;
} else {
mysql_error_msg = "Access denied!";
}
mysql_payload_size = sizeof(field_count) + sizeof(mysql_err) + sizeof(mysql_statemsg) + strlen(mysql_error_msg);
// allocate memory for packet header + payload
if ((buf = gwbuf_alloc(sizeof(mysql_packet_header) + mysql_payload_size)) == NULL)
{
return 0;
}
outbuf = GWBUF_DATA(buf);
// write packet header with packet number
gw_mysql_set_byte3(mysql_packet_header, mysql_payload_size);
mysql_packet_header[3] = packet_number;
// write header
memcpy(outbuf, mysql_packet_header, sizeof(mysql_packet_header));
mysql_payload = outbuf + sizeof(mysql_packet_header);
// write field
memcpy(mysql_payload, &field_count, sizeof(field_count));
mysql_payload = mysql_payload + sizeof(field_count);
// write errno
memcpy(mysql_payload, mysql_err, sizeof(mysql_err));
mysql_payload = mysql_payload + sizeof(mysql_err);
// write sqlstate
memcpy(mysql_payload, mysql_statemsg, sizeof(mysql_statemsg));
mysql_payload = mysql_payload + sizeof(mysql_statemsg);
// write err messg
memcpy(mysql_payload, mysql_error_msg, strlen(mysql_error_msg));
// write data
dcb->func.write(dcb, buf);
return sizeof(mysql_packet_header) + mysql_payload_size;
}
/*
* MySQLSendHandshake
@ -304,6 +387,11 @@ int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
fprintf(stderr, "<<< Client is NOT connected with db\n");
}
if (connect_with_db) {
strncpy(database, client_auth_packet + 4 + 4 + 4 + 1 + 23 + strlen(username) + 1 + 1 + auth_token_len, 128);
}
fprintf(stderr, "<<< Client selected db is [%s]\n", database);
fprintf(stderr, "<<< Client username is [%s]\n", username);
// decode the token and check the password
@ -315,13 +403,7 @@ int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
fprintf(stderr, "<<< CLIENT AUTH FAILED\n");
}
if (connect_with_db) {
strncpy(database, client_auth_packet + 4 + 4 + 4 + 1 + 23 + strlen(username) + 1 + 1 + auth_token_len, 128);
}
fprintf(stderr, "<<< Client selected db is [%s]\n", database);
return 0;
return auth_ret;
}

View File

@ -21,7 +21,11 @@
* Revision History
*
* Date Who Description
* 10/06/13 Massimiliano Pinto Initial implementation
* 10-06-2013 Massimiliano Pinto Initial implementation
* 12-06-2013 Massimiliano Pinto Read function trought
* the gwbuff strategy
* 13-06-2013 Massimiliano Pinto Gateway local authentication
* basics
*
*/
@ -225,6 +229,7 @@ int gw_route_read_event(DCB* dcb, int epfd) {
int ret = -1;
GWBUF *queue = NULL;
GWBUF *gw_buffer = NULL;
int auth_val = -1;
//////////////////////////////////////////////////////
// read and handle errors & close, or return if busyA
// note: if b == 0 error handling is not triggered, just return
@ -240,24 +245,19 @@ int gw_route_read_event(DCB* dcb, int epfd) {
fprintf(stderr, "<<< Reading from Client %i bytes: [%s]\n", len, GWBUF_DATA(queue));
gw_mysql_do_authentication(dcb, queue);
auth_val = gw_mysql_do_authentication(dcb, queue);
// Data printed on stderr or handled withot the dcb->func.write
// Data handled withot the dcb->func.write
// so consume it now
// be sure to consume it all
queue = gwbuf_consume(queue, len);
if (auth_val == 0)
protocol->state = MYSQL_AUTH_RECV;
else
protocol->state = MYSQL_AUTH_FAILED;
}
// ToDo
// now we have the data in the buffer, do the authentication
// but don't consume the gwbuf as in the above example !!!
protocol->state = MYSQL_AUTH_RECV;
// check authentication
// if OK return mysql_ok
// else return error
//protocol->state = MYSQL_AUTH_FAILED;
break;
case MYSQL_IDLE:
@ -378,7 +378,11 @@ int gw_handle_write_event(DCB *dcb, int epfd) {
if (protocol->state == MYSQL_AUTH_FAILED) {
// still to implement
mysql_send_ok(dcb, 2, 0, NULL);
mysql_send_auth_error(dcb, 2, 0, "Authorization failed");
dcb->func.error(dcb, -1);
if (dcb->session->backends)
dcb->session->backends->func.error(dcb->session->backends, -1);
return 0;
}