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:
@ -50,13 +50,6 @@
|
|||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <users.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_VERSION "0.1.0"
|
||||||
#define GW_MYSQL_VERSION "5.5.22-SKYSQL-" GW_VERSION
|
#define GW_MYSQL_VERSION "5.5.22-SKYSQL-" GW_VERSION
|
||||||
#define GW_MYSQL_LOOP_TIMEOUT 300000000
|
#define GW_MYSQL_LOOP_TIMEOUT 300000000
|
||||||
@ -70,6 +63,14 @@
|
|||||||
#define GW_MYSQL_SERVER_LANGUAGE 0x08
|
#define GW_MYSQL_SERVER_LANGUAGE 0x08
|
||||||
#define GW_MYSQL_MAX_PACKET_LEN 0xffffffL;
|
#define GW_MYSQL_MAX_PACKET_LEN 0xffffffL;
|
||||||
#define GW_MYSQL_SCRAMBLE_SIZE 20
|
#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)
|
#define GW_NOINTR_CALL(A) do { errno = 0; A; } while (errno == EINTR)
|
||||||
// network buffer is 32K
|
// network buffer is 32K
|
||||||
|
@ -39,7 +39,8 @@
|
|||||||
* 17/07/2013 Massimiliano Pinto Added dcb->command update from gwbuf->command for proper routing
|
* 17/07/2013 Massimiliano Pinto Added dcb->command update from gwbuf->command for proper routing
|
||||||
server replies to client via router->clientReply
|
server replies to client via router->clientReply
|
||||||
* 04/09/2013 Massimiliano Pinto Added dcb->session and dcb->session->client checks for NULL
|
* 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";
|
static char *version_str = "V2.0.0";
|
||||||
@ -168,18 +169,30 @@ static int gw_read_backend_event(DCB *dcb) {
|
|||||||
/* backend is connected:
|
/* backend is connected:
|
||||||
*
|
*
|
||||||
* 1. read server handshake
|
* 1. read server handshake
|
||||||
* 2. and write auth request
|
* 2. if (success) write auth request
|
||||||
* 3. and return
|
* 3. and return
|
||||||
*/
|
*/
|
||||||
if (backend_protocol->state == MYSQL_CONNECTED) {
|
if (backend_protocol->state == MYSQL_CONNECTED) {
|
||||||
gw_read_backend_handshake(backend_protocol);
|
if (gw_read_backend_handshake(backend_protocol) < 0) {
|
||||||
gw_send_authentication_to_backend(
|
backend_protocol->state = MYSQL_AUTH_FAILED;
|
||||||
|
rc = 1;
|
||||||
|
goto return_rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gw_send_authentication_to_backend(
|
||||||
current_session->db,
|
current_session->db,
|
||||||
current_session->user,
|
current_session->user,
|
||||||
current_session->client_sha1,
|
current_session->client_sha1,
|
||||||
backend_protocol);
|
backend_protocol) != 0) {
|
||||||
rc = 1;
|
backend_protocol->state = MYSQL_AUTH_FAILED;
|
||||||
goto return_rc;
|
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 */
|
/* ready to check the authentication reply from backend */
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
* 17/06/2013 Massimiliano Pinto Common MySQL protocol routines
|
* 17/06/2013 Massimiliano Pinto Common MySQL protocol routines
|
||||||
* 02/06/2013 Massimiliano Pinto MySQL connect asynchronous phases
|
* 02/06/2013 Massimiliano Pinto MySQL connect asynchronous phases
|
||||||
* 04/09/2013 Massimiliano Pinto Added dcb NULL assert in mysql_send_custom_error
|
* 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;
|
DCB *dcb = conn->owner_dcb;
|
||||||
int n = -1;
|
int n = -1;
|
||||||
uint8_t *payload = NULL;
|
uint8_t *payload = NULL;
|
||||||
|
int h_len = 0;
|
||||||
|
int success = 0;
|
||||||
|
int packet_len = 0;
|
||||||
|
|
||||||
if ((n = dcb_read(dcb, &head)) != -1) {
|
if ((n = dcb_read(dcb, &head)) != -1) {
|
||||||
if (head) {
|
if (head) {
|
||||||
payload = GWBUF_DATA(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
|
// skip the 4 bytes header
|
||||||
payload += 4;
|
payload += 4;
|
||||||
|
|
||||||
//Now decode mysql handshake
|
//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;
|
conn->state = MYSQL_AUTH_SENT;
|
||||||
|
|
||||||
@ -147,6 +184,8 @@ int gw_read_backend_handshake(MySQLProtocol *conn) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Nothing done here, log error this
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,35 +196,44 @@ int gw_read_backend_handshake(MySQLProtocol *conn) {
|
|||||||
*
|
*
|
||||||
* @param conn The MySQLProtocol structure
|
* @param conn The MySQLProtocol structure
|
||||||
* @param payload The bytes just read from the net
|
* @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) {
|
int gw_decode_mysql_server_handshake(MySQLProtocol *conn, uint8_t *payload) {
|
||||||
uint8_t *server_version_end = NULL;
|
uint8_t *server_version_end = NULL;
|
||||||
uint16_t mysql_server_capabilities_one;
|
uint16_t mysql_server_capabilities_one = 0;
|
||||||
uint16_t mysql_server_capabilities_two;
|
uint16_t mysql_server_capabilities_two = 0;
|
||||||
unsigned long tid =0;
|
unsigned long tid =0;
|
||||||
uint8_t scramble_data_1[8] = "";
|
uint8_t scramble_data_1[GW_SCRAMBLE_LENGTH_323] = "";
|
||||||
uint8_t scramble_data_2[12] = "";
|
uint8_t scramble_data_2[GW_MYSQL_SCRAMBLE_SIZE - GW_SCRAMBLE_LENGTH_323] = "";
|
||||||
uint8_t capab_ptr[4];
|
uint8_t capab_ptr[4] = "";
|
||||||
int scramble_len;
|
int scramble_len = 0;
|
||||||
uint8_t scramble[GW_MYSQL_SCRAMBLE_SIZE];
|
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++;
|
payload++;
|
||||||
|
|
||||||
// Get server version (string)
|
// Get server version (string)
|
||||||
server_version_end = (uint8_t *) gw_strend((char*) payload);
|
server_version_end = (uint8_t *) gw_strend((char*) payload);
|
||||||
|
|
||||||
payload = server_version_end + 1;
|
payload = server_version_end + 1;
|
||||||
|
|
||||||
// get ThreadID
|
// get ThreadID: 4 bytes
|
||||||
tid = gw_mysql_get_byte4(payload);
|
tid = gw_mysql_get_byte4(payload);
|
||||||
memcpy(&conn->tid, &tid, 4);
|
memcpy(&conn->tid, &tid, 4);
|
||||||
|
|
||||||
payload +=4;
|
payload +=4;
|
||||||
|
|
||||||
// scramble_part 1
|
// scramble_part 1
|
||||||
memcpy(scramble_data_1, payload, 8);
|
memcpy(scramble_data_1, payload, GW_SCRAMBLE_LENGTH_323);
|
||||||
payload += 8;
|
payload += GW_SCRAMBLE_LENGTH_323;
|
||||||
|
|
||||||
// 1 filler
|
// 1 filler
|
||||||
payload++;
|
payload++;
|
||||||
@ -207,16 +255,22 @@ int gw_decode_mysql_server_handshake(MySQLProtocol *conn, uint8_t *payload) {
|
|||||||
|
|
||||||
// get scramble len
|
// get scramble len
|
||||||
scramble_len = payload[0] -1;
|
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
|
// skip 10 zero bytes
|
||||||
payload += 11;
|
payload += 11;
|
||||||
|
|
||||||
// copy the second part of the scramble
|
// 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, scramble_data_1, GW_SCRAMBLE_LENGTH_323);
|
||||||
memcpy(scramble + 8, scramble_data_2, scramble_len - 8);
|
memcpy(scramble + GW_SCRAMBLE_LENGTH_323, scramble_data_2, scramble_len - GW_SCRAMBLE_LENGTH_323);
|
||||||
|
|
||||||
// full 20 bytes scramble is ready
|
// full 20 bytes scramble is ready
|
||||||
memcpy(conn->scramble, scramble, GW_MYSQL_SCRAMBLE_SIZE);
|
memcpy(conn->scramble, scramble, GW_MYSQL_SCRAMBLE_SIZE);
|
||||||
|
Reference in New Issue
Block a user