00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00016 #include "common.h"
00017
00018
00019
00020
00021
00022 drizzle_return_t drizzle_handshake_server_read(drizzle_con_st *con)
00023 {
00024 if (drizzle_state_none(con))
00025 {
00026 drizzle_state_push(con, drizzle_state_handshake_server_read);
00027 drizzle_state_push(con, drizzle_state_packet_read);
00028 }
00029
00030 return drizzle_state_loop(con);
00031 }
00032
00033 drizzle_return_t drizzle_handshake_client_write(drizzle_con_st *con)
00034 {
00035 if (drizzle_state_none(con))
00036 {
00037 drizzle_state_push(con, drizzle_state_write);
00038 drizzle_state_push(con, drizzle_state_handshake_client_write);
00039 }
00040
00041 return drizzle_state_loop(con);
00042 }
00043
00044
00045
00046
00047
00048 drizzle_return_t drizzle_handshake_server_write(drizzle_con_st *con)
00049 {
00050 if (drizzle_state_none(con))
00051 {
00052 drizzle_state_push(con, drizzle_state_write);
00053 drizzle_state_push(con, drizzle_state_handshake_server_write);
00054 }
00055
00056 return drizzle_state_loop(con);
00057 }
00058
00059 drizzle_return_t drizzle_handshake_client_read(drizzle_con_st *con)
00060 {
00061 if (drizzle_state_none(con))
00062 {
00063 drizzle_state_push(con, drizzle_state_handshake_client_read);
00064 drizzle_state_push(con, drizzle_state_packet_read);
00065 }
00066
00067 return drizzle_state_loop(con);
00068 }
00069
00070
00071
00072
00073
00074 drizzle_return_t drizzle_state_handshake_server_read(drizzle_con_st *con)
00075 {
00076 uint8_t *ptr;
00077
00078 drizzle_log_debug(con->drizzle, "drizzle_state_handshake_server_read");
00079
00080
00081 if (con->buffer_size < con->packet_size)
00082 {
00083 drizzle_state_push(con, drizzle_state_read);
00084 return DRIZZLE_RETURN_OK;
00085 }
00086
00087 if (con->packet_size < 46)
00088 {
00089 drizzle_set_error(con->drizzle, "drizzle_state_handshake_server_read",
00090 "bad packet size:>=46:%zu", con->packet_size);
00091 return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
00092 }
00093
00094 con->protocol_version= con->buffer_ptr[0];
00095 con->buffer_ptr++;
00096
00097 if (con->protocol_version != 10)
00098 {
00099
00100
00101 if (con->protocol_version == 255)
00102 {
00103 drizzle_set_error(con->drizzle, "drizzle_state_handshake_server_read",
00104 "%.*s", (int32_t)con->packet_size - 3,
00105 con->buffer_ptr + 2);
00106 return DRIZZLE_RETURN_AUTH_FAILED;
00107 }
00108
00109 drizzle_set_error(con->drizzle, "drizzle_state_handshake_server_read",
00110 "protocol version not supported:%d",
00111 con->protocol_version);
00112 return DRIZZLE_RETURN_PROTOCOL_NOT_SUPPORTED;
00113 }
00114
00115
00116 ptr= memchr(con->buffer_ptr, 0, con->buffer_size - 1);
00117 if (ptr == NULL)
00118 {
00119 drizzle_set_error(con->drizzle, "drizzle_state_handshake_server_read",
00120 "server version string not found");
00121 return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
00122 }
00123
00124 if (con->packet_size != (46 + (size_t)(ptr - con->buffer_ptr)))
00125 {
00126 drizzle_set_error(con->drizzle, "drizzle_state_handshake_server_read",
00127 "bad packet size:%zu:%zu",
00128 (46 + (size_t)(ptr - con->buffer_ptr)), con->packet_size);
00129 return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
00130 }
00131
00132 strncpy(con->server_version, (char *)con->buffer_ptr,
00133 DRIZZLE_MAX_SERVER_VERSION_SIZE);
00134 con->server_version[DRIZZLE_MAX_SERVER_VERSION_SIZE - 1]= 0;
00135 con->buffer_ptr+= ((ptr - con->buffer_ptr) + 1);
00136
00137 con->thread_id= (uint32_t)drizzle_get_byte4(con->buffer_ptr);
00138 con->buffer_ptr+= 4;
00139
00140 con->scramble= con->scramble_buffer;
00141 memcpy(con->scramble, con->buffer_ptr, 8);
00142
00143 con->buffer_ptr+= 9;
00144
00145
00146
00147
00148 con->capabilities= (drizzle_capabilities_t)drizzle_get_byte2(con->buffer_ptr);
00149 con->buffer_ptr+= 2;
00150
00151 if (con->options & DRIZZLE_CON_MYSQL &&
00152 !(con->capabilities & DRIZZLE_CAPABILITIES_PROTOCOL_41))
00153 {
00154 drizzle_set_error(con->drizzle, "drizzle_state_handshake_server_read",
00155 "protocol version not supported, must be MySQL 4.1+");
00156 return DRIZZLE_RETURN_PROTOCOL_NOT_SUPPORTED;
00157 }
00158
00159 con->charset= con->buffer_ptr[0];
00160 con->buffer_ptr+= 1;
00161
00162 con->status= drizzle_get_byte2(con->buffer_ptr);
00163
00164 con->buffer_ptr+= 15;
00165
00166 memcpy(con->scramble + 8, con->buffer_ptr, 12);
00167 con->buffer_ptr+= 13;
00168
00169 con->buffer_size-= con->packet_size;
00170 if (con->buffer_size != 0)
00171 {
00172 drizzle_set_error(con->drizzle, "drizzle_state_handshake_server_read",
00173 "unexpected data after packet:%zu", con->buffer_size);
00174 return DRIZZLE_RETURN_UNEXPECTED_DATA;
00175 }
00176
00177 con->buffer_ptr= con->buffer;
00178
00179 drizzle_state_pop(con);
00180
00181 if (!(con->options & DRIZZLE_CON_RAW_PACKET))
00182 {
00183 drizzle_state_push(con, drizzle_state_handshake_result_read);
00184 drizzle_state_push(con, drizzle_state_packet_read);
00185 drizzle_state_push(con, drizzle_state_write);
00186 drizzle_state_push(con, drizzle_state_handshake_client_write);
00187 }
00188
00189 return DRIZZLE_RETURN_OK;
00190 }
00191
00192 drizzle_return_t drizzle_state_handshake_server_write(drizzle_con_st *con)
00193 {
00194 uint8_t *ptr;
00195
00196 drizzle_log_debug(con->drizzle, "drizzle_state_handshake_server_write");
00197
00198
00199 con->packet_size= 1
00200 + strlen(con->server_version) + 1
00201 + 4
00202 + 8
00203 + 1
00204 + 2
00205 + 1
00206 + 2
00207 + 13
00208 + 12
00209 + 1;
00210
00211
00212 if ((con->packet_size + 4) > DRIZZLE_MAX_BUFFER_SIZE)
00213 {
00214 drizzle_set_error(con->drizzle, "drizzle_state_handshake_server_write",
00215 "buffer too small:%zu", con->packet_size + 4);
00216 return DRIZZLE_RETURN_INTERNAL_ERROR;
00217 }
00218
00219 ptr= con->buffer_ptr;
00220
00221
00222 drizzle_set_byte3(ptr, con->packet_size);
00223 ptr[3]= 0;
00224 con->packet_number= 1;
00225 ptr+= 4;
00226
00227 ptr[0]= con->protocol_version;
00228 ptr++;
00229
00230 memcpy(ptr, con->server_version, strlen(con->server_version));
00231 ptr+= strlen(con->server_version);
00232
00233 ptr[0]= 0;
00234 ptr++;
00235
00236 drizzle_set_byte4(ptr, con->thread_id);
00237 ptr+= 4;
00238
00239 if (con->scramble == NULL)
00240 memset(ptr, 0, 8);
00241 else
00242 memcpy(ptr, con->scramble, 8);
00243 ptr+= 8;
00244
00245 ptr[0]= 0;
00246 ptr++;
00247
00248 if (con->options & DRIZZLE_CON_MYSQL)
00249 con->capabilities|= DRIZZLE_CAPABILITIES_PROTOCOL_41;
00250
00251
00252 drizzle_set_byte2(ptr, con->capabilities);
00253 ptr+= 2;
00254
00255 ptr[0]= con->charset;
00256 ptr++;
00257
00258 drizzle_set_byte2(ptr, con->status);
00259 ptr+= 2;
00260
00261 memset(ptr, 0, 13);
00262 ptr+= 13;
00263
00264 if (con->scramble == NULL)
00265 memset(ptr, 0, 12);
00266 else
00267 memcpy(ptr, con->scramble + 8, 12);
00268 ptr+= 12;
00269
00270 ptr[0]= 0;
00271 ptr++;
00272
00273 con->buffer_size+= (4 + con->packet_size);
00274
00275
00276 if ((size_t)(ptr - con->buffer_ptr) != (4 + con->packet_size))
00277 {
00278 drizzle_set_error(con->drizzle, "drizzle_state_handshake_server_write",
00279 "error packing server handshake:%zu:%zu",
00280 (size_t)(ptr - con->buffer_ptr), 4 + con->packet_size);
00281 return DRIZZLE_RETURN_INTERNAL_ERROR;
00282 }
00283
00284 drizzle_state_pop(con);
00285 return DRIZZLE_RETURN_OK;
00286 }
00287
00288 drizzle_return_t drizzle_state_handshake_client_read(drizzle_con_st *con)
00289 {
00290 size_t real_size;
00291 uint8_t *ptr;
00292 uint8_t scramble_size;
00293
00294 drizzle_log_debug(con->drizzle, "drizzle_state_handshake_client_read");
00295
00296
00297 if (con->buffer_size < con->packet_size)
00298 {
00299 drizzle_state_push(con, drizzle_state_read);
00300 return DRIZZLE_RETURN_OK;
00301 }
00302
00303
00304 if (con->packet_size < 34)
00305 {
00306 drizzle_set_error(con->drizzle, "drizzle_state_handshake_client_read",
00307 "bad packet size:>=34:%zu", con->packet_size);
00308 return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
00309 }
00310
00311 real_size= 34;
00312
00313 con->capabilities= drizzle_get_byte4(con->buffer_ptr);
00314 con->buffer_ptr+= 4;
00315
00316 if (con->options & DRIZZLE_CON_MYSQL &&
00317 !(con->capabilities & DRIZZLE_CAPABILITIES_PROTOCOL_41))
00318 {
00319 drizzle_set_error(con->drizzle, "drizzle_state_handshake_client_read",
00320 "protocol version not supported, must be MySQL 4.1+");
00321 return DRIZZLE_RETURN_PROTOCOL_NOT_SUPPORTED;
00322 }
00323
00324 con->max_packet_size= (uint32_t)drizzle_get_byte4(con->buffer_ptr);
00325 con->buffer_ptr+= 4;
00326
00327 con->charset= con->buffer_ptr[0];
00328 con->buffer_ptr+= 1;
00329
00330
00331 con->buffer_ptr+= 23;
00332
00333
00334 ptr= memchr(con->buffer_ptr, 0, con->buffer_size - 32);
00335 if (ptr == NULL)
00336 {
00337 drizzle_set_error(con->drizzle, "drizzle_state_handshake_client_read",
00338 "user string not found");
00339 return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
00340 }
00341
00342 if (con->buffer_ptr == ptr)
00343 {
00344 con->user[0]= 0;
00345 con->buffer_ptr++;
00346 }
00347 else
00348 {
00349 real_size+= (size_t)(ptr - con->buffer_ptr);
00350 if (con->packet_size < real_size)
00351 {
00352 drizzle_set_error(con->drizzle, "drizzle_state_handshake_client_read",
00353 "bad packet size:>=%zu:%zu", real_size,
00354 con->packet_size);
00355 return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
00356 }
00357
00358 strncpy(con->user, (char *)con->buffer_ptr, DRIZZLE_MAX_USER_SIZE);
00359 con->user[DRIZZLE_MAX_USER_SIZE - 1]= 0;
00360 con->buffer_ptr+= ((ptr - con->buffer_ptr) + 1);
00361 }
00362
00363 scramble_size= con->buffer_ptr[0];
00364 con->buffer_ptr+= 1;
00365
00366 if (scramble_size == 0)
00367 con->scramble= NULL;
00368 else
00369 {
00370 if (scramble_size != DRIZZLE_MAX_SCRAMBLE_SIZE)
00371 {
00372 drizzle_set_error(con->drizzle, "drizzle_state_handshake_client_read",
00373 "wrong scramble size");
00374 return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
00375 }
00376
00377 real_size+= scramble_size;
00378 con->scramble= con->scramble_buffer;
00379 memcpy(con->scramble, con->buffer_ptr, DRIZZLE_MAX_SCRAMBLE_SIZE);
00380
00381 con->buffer_ptr+= DRIZZLE_MAX_SCRAMBLE_SIZE;
00382 }
00383
00384
00385 if ((34 + strlen(con->user) + scramble_size) == con->packet_size)
00386 con->db[0]= 0;
00387 else
00388 {
00389 ptr= memchr(con->buffer_ptr, 0, con->buffer_size -
00390 (34 + strlen(con->user) + scramble_size));
00391 if (ptr == NULL)
00392 {
00393 drizzle_set_error(con->drizzle, "drizzle_state_handshake_client_read",
00394 "db string not found");
00395 return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
00396 }
00397
00398 real_size+= ((size_t)(ptr - con->buffer_ptr) + 1);
00399 if (con->packet_size != real_size)
00400 {
00401 drizzle_set_error(con->drizzle, "drizzle_state_handshake_client_read",
00402 "bad packet size:%zu:%zu", real_size, con->packet_size);
00403 return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
00404 }
00405
00406 if (con->buffer_ptr == ptr)
00407 {
00408 con->db[0]= 0;
00409 con->buffer_ptr++;
00410 }
00411 else
00412 {
00413 strncpy(con->db, (char *)con->buffer_ptr, DRIZZLE_MAX_DB_SIZE);
00414 con->db[DRIZZLE_MAX_DB_SIZE - 1]= 0;
00415 con->buffer_ptr+= ((ptr - con->buffer_ptr) + 1);
00416 }
00417 }
00418
00419 con->buffer_size-= con->packet_size;
00420 if (con->buffer_size != 0)
00421 {
00422 drizzle_set_error(con->drizzle, "drizzle_state_handshake_client_read",
00423 "unexpected data after packet:%zu", con->buffer_size);
00424 return DRIZZLE_RETURN_UNEXPECTED_DATA;
00425 }
00426
00427 con->buffer_ptr= con->buffer;
00428
00429 drizzle_state_pop(con);
00430 return DRIZZLE_RETURN_OK;
00431 }
00432
00433 drizzle_return_t drizzle_state_handshake_client_write(drizzle_con_st *con)
00434 {
00435 uint8_t *ptr;
00436 drizzle_capabilities_t capabilities;
00437 drizzle_return_t ret;
00438
00439 drizzle_log_debug(con->drizzle, "drizzle_state_handshake_client_write");
00440
00441
00442 con->packet_size= 4
00443 + 4
00444 + 1
00445 + 23
00446 + strlen(con->user) + 1
00447 + 1
00448 + DRIZZLE_MAX_SCRAMBLE_SIZE
00449 + strlen(con->db) + 1;
00450
00451
00452 if ((con->packet_size + 4) > DRIZZLE_MAX_BUFFER_SIZE)
00453 {
00454 drizzle_set_error(con->drizzle, "drizzle_state_handshake_client_write",
00455 "buffer too small:%zu", con->packet_size + 4);
00456 return DRIZZLE_RETURN_INTERNAL_ERROR;
00457 }
00458
00459 ptr= con->buffer_ptr;
00460
00461
00462 ptr[3]= con->packet_number;
00463 con->packet_number++;
00464 ptr+= 4;
00465
00466 if (con->options & DRIZZLE_CON_MYSQL)
00467 con->capabilities|= DRIZZLE_CAPABILITIES_PROTOCOL_41;
00468
00469 capabilities= con->capabilities & DRIZZLE_CAPABILITIES_CLIENT;
00470 capabilities&= ~(DRIZZLE_CAPABILITIES_COMPRESS | DRIZZLE_CAPABILITIES_SSL);
00471 if (con->db[0] == 0)
00472 capabilities&= ~DRIZZLE_CAPABILITIES_CONNECT_WITH_DB;
00473
00474 drizzle_set_byte4(ptr, capabilities);
00475 ptr+= 4;
00476
00477 drizzle_set_byte4(ptr, con->max_packet_size);
00478 ptr+= 4;
00479
00480 ptr[0]= con->charset;
00481 ptr++;
00482
00483 memset(ptr, 0, 23);
00484 ptr+= 23;
00485
00486 ptr= drizzle_pack_auth(con, ptr, &ret);
00487 if (ret != DRIZZLE_RETURN_OK)
00488 return ret;
00489
00490 con->buffer_size+= (4 + con->packet_size);
00491
00492
00493 if ((size_t)(ptr - con->buffer_ptr) != (4 + con->packet_size))
00494 {
00495 drizzle_set_error(con->drizzle, "drizzle_state_handshake_client_write",
00496 "error packing client handshake:%zu:%zu",
00497 (size_t)(ptr - con->buffer_ptr), 4 + con->packet_size);
00498 return DRIZZLE_RETURN_INTERNAL_ERROR;
00499 }
00500
00501
00502 drizzle_set_byte3(con->buffer_ptr, con->packet_size);
00503
00504 drizzle_state_pop(con);
00505 return DRIZZLE_RETURN_OK;
00506 }
00507
00508 drizzle_return_t drizzle_state_handshake_result_read(drizzle_con_st *con)
00509 {
00510 drizzle_return_t ret;
00511 drizzle_result_st result;
00512
00513 drizzle_log_debug(con->drizzle, "drizzle_state_handshake_result_read");
00514
00515 if (drizzle_result_create(con, &result) == NULL)
00516 return DRIZZLE_RETURN_MEMORY;
00517
00518 con->result= &result;
00519
00520 ret= drizzle_state_result_read(con);
00521 if (drizzle_state_none(con))
00522 {
00523 if (ret == DRIZZLE_RETURN_OK)
00524 {
00525 if (drizzle_result_eof(&result))
00526 {
00527 drizzle_set_error(con->drizzle, "drizzle_state_handshake_result_read",
00528 "old insecure authentication mechanism not supported");
00529 ret= DRIZZLE_RETURN_AUTH_FAILED;
00530 }
00531 else
00532 con->options|= DRIZZLE_CON_READY;
00533 }
00534 }
00535
00536 drizzle_result_free(&result);
00537
00538 if (ret == DRIZZLE_RETURN_ERROR_CODE)
00539 return DRIZZLE_RETURN_HANDSHAKE_FAILED;
00540
00541 return ret;
00542 }