diff --git a/modules/include/mysql_client_server_protocol.h b/modules/include/mysql_client_server_protocol.h index 74afa3c14..0f08a4265 100644 --- a/modules/include/mysql_client_server_protocol.h +++ b/modules/include/mysql_client_server_protocol.h @@ -224,6 +224,7 @@ int mysql_send_custom_error (DCB *dcb, int packet_number, int in_affected_rows, int gw_send_change_user_to_backend(char *dbname, char *user, uint8_t *passwd, MySQLProtocol *conn); int gw_find_mysql_user_password_sha1(char *username, uint8_t *gateway_password, void *repository); int gw_check_mysql_scramble_data(DCB *dcb, uint8_t *token, unsigned int token_len, uint8_t *scramble, unsigned int scramble_len, char *username, uint8_t *stage1_hash); +int mysql_send_auth_error (DCB *dcb, int packet_number, int in_affected_rows, const char* mysql_message); extern void gw_sha1_str(const uint8_t *in, int in_len, uint8_t *out); extern void gw_sha1_2_str(const uint8_t *in, int in_len, const uint8_t *in2, int in2_len, uint8_t *out); diff --git a/modules/protocol/mysql_backend.c b/modules/protocol/mysql_backend.c index 008600e8d..1d729c8cc 100644 --- a/modules/protocol/mysql_backend.c +++ b/modules/protocol/mysql_backend.c @@ -445,15 +445,12 @@ static int gw_change_user(DCB *backend, SERVER *server, SESSION *in_session, GWB // now get the user, after 4 bytes header and 1 byte command client_auth_packet += 5; strcpy(username, (char *)client_auth_packet); - fprintf(stderr, "<<< The NEW Client username is [%s]\n", client_auth_packet); client_auth_packet += strlen(username) + 1; // get the auth token len memcpy(&auth_token_len, client_auth_packet, 1); client_auth_packet++; - fprintf(stderr, "<<< Now decoding the NEW user %i...\n", auth_token_len); - // allocate memory for token only if auth_token_len > 0 if (auth_token_len) { auth_token = (uint8_t *)malloc(auth_token_len); @@ -461,30 +458,34 @@ static int gw_change_user(DCB *backend, SERVER *server, SESSION *in_session, GWB client_auth_packet += auth_token_len; } - fprintf(stderr, "<<< Now decoding the NEW token [%s]\n", auth_token); - // decode the token and check the 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); - fprintf(stderr, "<<< HERE after gw_check_mysql_scramble_data()\n"); - - if (auth_ret != 0) { - fprintf(stderr, "<<< CLIENT AUTH FAILED for user [%s]\n", username); - } - // let's free the auth_token now if (auth_token) free(auth_token); - // get db name - strcpy(database, (char *)client_auth_packet); - fprintf(stderr, "<<< The NEW Client selected db is [%s]\n", database); + if (auth_ret != 0) { + fprintf(stderr, "<<< CLIENT AUTH FAILED for user [%s], user session will not change!\n", username); + // send the error packet + mysql_send_auth_error(backend->session->client, 1, 0, "Authorization failed on change_user"); + } else { + // get db name + strcpy(database, (char *)client_auth_packet); - fprintf(stderr, "<<<< Backend session data is [%s],[%s],[%s]\n", current_session->user, current_session->client_sha1, current_session->db); - fprintf(stderr, "<<<< NEW Backend session data will be is [%s],[%s],[%s]\n", username, client_sha1, database); - rv = gw_send_change_user_to_backend(database, username, client_sha1, backend_protocol); + //fprintf(stderr, "<<<< Backend session data is [%s],[%s],[%s]\n", current_session->user, current_session->client_sha1, current_session->db); + rv = gw_send_change_user_to_backend(database, username, client_sha1, backend_protocol); + // Now copy new data into user session + strcpy(current_session->user, username); + strcpy(current_session->db, database); + memcpy(current_session->client_sha1, client_sha1, sizeof(current_session->client_sha1)); + + fprintf(stderr, ">>> The NEW Backend session data is [%s],[%s],[%s]\n", current_session->user, current_session->client_sha1, current_session->db); + } + + // consume all the data received from client len = GWBUF_LENGTH(queue); queue = gwbuf_consume(queue, len); diff --git a/modules/protocol/mysql_client.c b/modules/protocol/mysql_client.c index 97f3975c3..24e75280b 100644 --- a/modules/protocol/mysql_client.c +++ b/modules/protocol/mysql_client.c @@ -43,7 +43,6 @@ static int gw_client_close(DCB *dcb); static int gw_client_hangup_event(DCB *dcb); int mysql_send_ok(DCB *dcb, int packet_number, int in_affected_rows, const char* mysql_message); -int mysql_send_auth_error (DCB *dcb, int packet_number, int in_affected_rows, const char* mysql_message); int MySQLSendHandshake(DCB* dcb); static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue); @@ -179,85 +178,6 @@ 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 gateway authentication 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 length - * - */ -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 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; - } - - 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)); - - // writing data in the Client buffer queue - dcb->func.write(dcb, buf); - - return sizeof(mysql_packet_header) + mysql_payload_size; -} - /** * MySQLSendHandshake * @@ -635,7 +555,6 @@ int gw_read_client_event(DCB* dcb) { { protocol->state = MYSQL_AUTH_FAILED; - // still to implement mysql_send_auth_error(dcb, 2, 0, "Authorization failed"); dcb->func.close(dcb); diff --git a/modules/protocol/mysql_common.c b/modules/protocol/mysql_common.c index fe2d675fa..e072d1b38 100644 --- a/modules/protocol/mysql_common.c +++ b/modules/protocol/mysql_common.c @@ -625,9 +625,9 @@ int gw_send_change_user_to_backend(char *dbname, char *user, uint8_t *passwd, My dcb = conn->descriptor; -//#ifdef DEBUG_MYSQL_CONN +#ifdef DEBUG_MYSQL_CONN fprintf(stderr, ">> Sending credentials %s, %s, db %s\n", user, passwd, dbname); -//#endif +#endif // Zero the vars memset(&server_capabilities, '\0', sizeof(server_capabilities)); @@ -881,7 +881,7 @@ int gw_find_mysql_user_password_sha1(char *username, uint8_t *gateway_password, user_password = (char *)users_fetch(service->users, username); if (!user_password) { - fprintf(stderr, ">>> MYSQL user NOT FOUND: %s\n", username); + //fprintf(stderr, ">>> MYSQL user NOT FOUND: %s\n", username); return 1; } @@ -896,3 +896,81 @@ int gw_find_mysql_user_password_sha1(char *username, uint8_t *gateway_password, return 0; } +/** + * mysql_send_auth_error + * + * Send a MySQL protocol ERR message, for gateway authentication 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 length + * + */ +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 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; + } + + 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)); + + // writing data in the Client buffer queue + dcb->func.write(dcb, buf); + + return sizeof(mysql_packet_header) + mysql_payload_size; +}