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