Added constants to gw_decode_mysql_server_handshake

Check status of gw_read_backend_handshake and gw_send_authentication_to_backend in gw_read_backend_event
This commit is contained in:
Massimiliano Pinto
2013-09-12 16:08:31 +02:00
parent 33fc1737d5
commit 775b318889
3 changed files with 98 additions and 30 deletions

View File

@ -50,13 +50,6 @@
#include <poll.h>
#include <users.h>
#ifndef MYSQL_SCRAMBLE_LEN
#define MYSQL_SCRAMBLE_LEN GW_MYSQL_SCRAMBLE_SIZE
#endif
#define MYSQL_USER_MAXLEN 128
#define MYSQL_DATABASE_MAXLEN 128
#define GW_VERSION "0.1.0"
#define GW_MYSQL_VERSION "5.5.22-SKYSQL-" GW_VERSION
#define GW_MYSQL_LOOP_TIMEOUT 300000000
@ -70,6 +63,14 @@
#define GW_MYSQL_SERVER_LANGUAGE 0x08
#define GW_MYSQL_MAX_PACKET_LEN 0xffffffL;
#define GW_MYSQL_SCRAMBLE_SIZE 20
#define GW_SCRAMBLE_LENGTH_323 8
#ifndef MYSQL_SCRAMBLE_LEN
#define MYSQL_SCRAMBLE_LEN GW_MYSQL_SCRAMBLE_SIZE
#endif
#define MYSQL_USER_MAXLEN 128
#define MYSQL_DATABASE_MAXLEN 128
#define GW_NOINTR_CALL(A) do { errno = 0; A; } while (errno == EINTR)
// network buffer is 32K

View File

@ -39,7 +39,8 @@
* 17/07/2013 Massimiliano Pinto Added dcb->command update from gwbuf->command for proper routing
server replies to client via router->clientReply
* 04/09/2013 Massimiliano Pinto Added dcb->session and dcb->session->client checks for NULL
* in gw_read_backend_event()
* 12/09/2013 Massimiliano Pinto Added checks in gw_read_backend_event() for gw_read_backend_handshake
*
*/
static char *version_str = "V2.0.0";
@ -168,18 +169,30 @@ static int gw_read_backend_event(DCB *dcb) {
/* backend is connected:
*
* 1. read server handshake
* 2. and write auth request
* 2. if (success) write auth request
* 3. and return
*/
if (backend_protocol->state == MYSQL_CONNECTED) {
gw_read_backend_handshake(backend_protocol);
gw_send_authentication_to_backend(
if (gw_read_backend_handshake(backend_protocol) < 0) {
backend_protocol->state = MYSQL_AUTH_FAILED;
rc = 1;
goto return_rc;
}
if (gw_send_authentication_to_backend(
current_session->db,
current_session->user,
current_session->client_sha1,
backend_protocol);
rc = 1;
goto return_rc;
backend_protocol) != 0) {
backend_protocol->state = MYSQL_AUTH_FAILED;
rc = 1;
goto return_rc;
}
// the protocol state here is MYSQL_AUTH_RECV
ss_dassert(backend_protocol->state == MYSQL_AUTH_RECV);
rc = 1;
goto return_rc;
}
/* ready to check the authentication reply from backend */

View File

@ -24,6 +24,7 @@
* 17/06/2013 Massimiliano Pinto Common MySQL protocol routines
* 02/06/2013 Massimiliano Pinto MySQL connect asynchronous phases
* 04/09/2013 Massimiliano Pinto Added dcb NULL assert in mysql_send_custom_error
* 12/09/2013 Massimiliano Pinto Added checks in gw_decode_mysql_server_handshake and gw_read_backend_handshake
*
*/
@ -128,16 +129,52 @@ int gw_read_backend_handshake(MySQLProtocol *conn) {
DCB *dcb = conn->owner_dcb;
int n = -1;
uint8_t *payload = NULL;
int h_len = 0;
int success = 0;
int packet_len = 0;
if ((n = dcb_read(dcb, &head)) != -1) {
if (head) {
payload = GWBUF_DATA(head);
h_len = gwbuf_length(head);
/*
* The mysql packets content starts at byte fifth
* just return with less bytes
*/
if (h_len <= 4) {
/* log error this exit point */
conn->state = MYSQL_AUTH_FAILED;
return 1;
}
//get mysql packet size, 3 bytes
packet_len = gw_mysql_get_byte3(payload);
if (h_len < (packet_len + 4)) {
/*
* data in buffer less than expected in the packet
* log error this exit point
*/
conn->state = MYSQL_AUTH_FAILED;
return 1;
}
// skip the 4 bytes header
payload += 4;
//Now decode mysql handshake
gw_decode_mysql_server_handshake(conn, payload);
success = gw_decode_mysql_server_handshake(conn, payload);
if (success < 0) {
/* MySQL handshake has not been properly decoded
* we cannot continue
* log error this exit point
*/
conn->state = MYSQL_AUTH_FAILED;
return 1;
}
conn->state = MYSQL_AUTH_SENT;
@ -147,6 +184,8 @@ int gw_read_backend_handshake(MySQLProtocol *conn) {
return 0;
}
}
// Nothing done here, log error this
return 1;
}
@ -157,35 +196,44 @@ int gw_read_backend_handshake(MySQLProtocol *conn) {
*
* @param conn The MySQLProtocol structure
* @param payload The bytes just read from the net
* @return 0 always
* @return 0 on success, < 0 on failure
*
*/
int gw_decode_mysql_server_handshake(MySQLProtocol *conn, uint8_t *payload) {
uint8_t *server_version_end = NULL;
uint16_t mysql_server_capabilities_one;
uint16_t mysql_server_capabilities_two;
uint16_t mysql_server_capabilities_one = 0;
uint16_t mysql_server_capabilities_two = 0;
unsigned long tid =0;
uint8_t scramble_data_1[8] = "";
uint8_t scramble_data_2[12] = "";
uint8_t capab_ptr[4];
int scramble_len;
uint8_t scramble[GW_MYSQL_SCRAMBLE_SIZE];
uint8_t scramble_data_1[GW_SCRAMBLE_LENGTH_323] = "";
uint8_t scramble_data_2[GW_MYSQL_SCRAMBLE_SIZE - GW_SCRAMBLE_LENGTH_323] = "";
uint8_t capab_ptr[4] = "";
int scramble_len = 0;
uint8_t scramble[GW_MYSQL_SCRAMBLE_SIZE] = "";
int protocol_version = 0;
protocol_version = payload[0];
if (protocol_version != GW_MYSQL_PROTOCOL_VERSION) {
/* log error for this */
return -1;
}
payload++;
// Get server version (string)
server_version_end = (uint8_t *) gw_strend((char*) payload);
payload = server_version_end + 1;
// get ThreadID
// get ThreadID: 4 bytes
tid = gw_mysql_get_byte4(payload);
memcpy(&conn->tid, &tid, 4);
payload +=4;
// scramble_part 1
memcpy(scramble_data_1, payload, 8);
payload += 8;
memcpy(scramble_data_1, payload, GW_SCRAMBLE_LENGTH_323);
payload += GW_SCRAMBLE_LENGTH_323;
// 1 filler
payload++;
@ -207,16 +255,22 @@ int gw_decode_mysql_server_handshake(MySQLProtocol *conn, uint8_t *payload) {
// get scramble len
scramble_len = payload[0] -1;
ss_dassert(scramble_len > 8);
ss_dassert(scramble_len > GW_SCRAMBLE_LENGTH_323);
ss_dassert(scramble_len <= GW_MYSQL_SCRAMBLE_SIZE);
if ( (scramble_len < GW_SCRAMBLE_LENGTH_323) || scramble_len > GW_MYSQL_SCRAMBLE_SIZE) {
/* log this */
return -2;
}
// skip 10 zero bytes
payload += 11;
// copy the second part of the scramble
memcpy(scramble_data_2, payload, scramble_len - 8);
memcpy(scramble_data_2, payload, scramble_len - GW_SCRAMBLE_LENGTH_323);
memcpy(scramble, scramble_data_1, 8);
memcpy(scramble + 8, scramble_data_2, scramble_len - 8);
memcpy(scramble, scramble_data_1, GW_SCRAMBLE_LENGTH_323);
memcpy(scramble + GW_SCRAMBLE_LENGTH_323, scramble_data_2, scramble_len - GW_SCRAMBLE_LENGTH_323);
// full 20 bytes scramble is ready
memcpy(conn->scramble, scramble, GW_MYSQL_SCRAMBLE_SIZE);