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