00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00016 #include "common.h"
00017
00018
00019
00020
00021
00022 drizzle_return_t drizzle_server_handshake_read(drizzle_con_st *con)
00023 {
00024 if (DRIZZLE_STATE_NONE(con))
00025 {
00026 DRIZZLE_STATE_PUSH(con, drizzle_state_server_handshake_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_client_handshake_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_client_handshake_write)
00039 }
00040
00041 return drizzle_state_loop(con);
00042 }
00043
00044
00045
00046
00047
00048 drizzle_return_t drizzle_server_handshake_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_server_handshake_write)
00054 }
00055
00056 return drizzle_state_loop(con);
00057 }
00058
00059 drizzle_return_t drizzle_client_handshake_read(drizzle_con_st *con)
00060 {
00061 if (DRIZZLE_STATE_NONE(con))
00062 {
00063 DRIZZLE_STATE_PUSH(con, drizzle_state_client_handshake_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_server_handshake_read(drizzle_con_st *con)
00075 {
00076 uint8_t *ptr;
00077
00078 PDEBUG("drizzle_state_server_handshake_read", "%5zu %5zu", con->buffer_size,
00079 con->packet_size)
00080
00081
00082 if (con->buffer_size < con->packet_size)
00083 {
00084 DRIZZLE_STATE_PUSH(con, drizzle_state_read)
00085 return DRIZZLE_RETURN_OK;
00086 }
00087
00088 if (con->packet_size < 46)
00089 {
00090 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_server_handshake_read",
00091 "bad packet size:>=46:%zu", con->packet_size)
00092 return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
00093 }
00094
00095 con->protocol_version= con->buffer_ptr[0];
00096 con->buffer_ptr++;
00097
00098 if (con->protocol_version != 10)
00099 {
00100
00101
00102 if (con->protocol_version == 255)
00103 {
00104 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_server_handshake_read",
00105 "%.*s", (int32_t)con->packet_size - 3,
00106 con->buffer_ptr + 2)
00107 return DRIZZLE_RETURN_AUTH_FAILED;
00108 }
00109
00110 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_server_handshake_read",
00111 "protocol version not supported:%d",
00112 con->protocol_version)
00113 return DRIZZLE_RETURN_PROTOCOL_NOT_SUPPORTED;
00114 }
00115
00116
00117 ptr= memchr(con->buffer_ptr, 0, con->buffer_size - 1);
00118 if (ptr == NULL)
00119 {
00120 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_server_handshake_read",
00121 "server version string not found")
00122 return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
00123 }
00124
00125 if (con->packet_size != (46 + (size_t)(ptr - con->buffer_ptr)))
00126 {
00127 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_server_handshake_read",
00128 "bad packet size:%zu:%zu",
00129 (46 + (size_t)(ptr - con->buffer_ptr)), con->packet_size)
00130 return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
00131 }
00132
00133 strncpy(con->server_version, (char *)con->buffer_ptr,
00134 DRIZZLE_MAX_SERVER_VERSION_SIZE);
00135 con->server_version[DRIZZLE_MAX_SERVER_VERSION_SIZE - 1]= 0;
00136 con->buffer_ptr+= ((ptr - con->buffer_ptr) + 1);
00137
00138 con->thread_id= (uint32_t)DRIZZLE_GET_BYTE4(con->buffer_ptr);
00139 con->buffer_ptr+= 4;
00140
00141 con->scramble= con->scramble_buffer;
00142 memcpy(con->scramble, con->buffer_ptr, 8);
00143
00144 con->buffer_ptr+= 9;
00145
00146
00147
00148
00149 con->capabilities= (drizzle_capabilities_t)DRIZZLE_GET_BYTE2(con->buffer_ptr);
00150 con->buffer_ptr+= 2;
00151
00152 if (con->options & DRIZZLE_CON_MYSQL &&
00153 !(con->capabilities & DRIZZLE_CAPABILITIES_PROTOCOL_41))
00154 {
00155 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_server_handshake_read",
00156 "protocol version not supported, must be MySQL 4.1+")
00157 return DRIZZLE_RETURN_PROTOCOL_NOT_SUPPORTED;
00158 }
00159
00160 con->charset= con->buffer_ptr[0];
00161 con->buffer_ptr+= 1;
00162
00163 con->status= DRIZZLE_GET_BYTE2(con->buffer_ptr);
00164
00165 con->buffer_ptr+= 15;
00166
00167 memcpy(con->scramble + 8, con->buffer_ptr, 12);
00168 con->buffer_ptr+= 13;
00169
00170 con->buffer_size-= con->packet_size;
00171 if (con->buffer_size != 0)
00172 {
00173 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_server_handshake_read",
00174 "unexpected data after packet:%zu", con->buffer_size)
00175 return DRIZZLE_RETURN_UNEXPECTED_DATA;
00176 }
00177
00178 con->buffer_ptr= con->buffer;
00179
00180 DRIZZLE_STATE_POP(con)
00181
00182 if (!(con->options & DRIZZLE_CON_RAW_PACKET))
00183 {
00184 DRIZZLE_STATE_PUSH(con, drizzle_state_handshake_result_read)
00185 DRIZZLE_STATE_PUSH(con, drizzle_state_packet_read)
00186 DRIZZLE_STATE_PUSH(con, drizzle_state_write)
00187 DRIZZLE_STATE_PUSH(con, drizzle_state_client_handshake_write)
00188 }
00189
00190 return DRIZZLE_RETURN_OK;
00191 }
00192
00193 drizzle_return_t drizzle_state_server_handshake_write(drizzle_con_st *con)
00194 {
00195 uint8_t *ptr;
00196
00197
00198 con->packet_size= 1
00199 + strlen(con->server_version) + 1
00200 + 4
00201 + 8
00202 + 1
00203 + 2
00204 + 1
00205 + 2
00206 + 13
00207 + 12
00208 + 1;
00209
00210
00211 if ((con->packet_size + 4) > DRIZZLE_MAX_BUFFER_SIZE)
00212 {
00213 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_server_handshake_write",
00214 "buffer too small:%zu", con->packet_size + 4)
00215 return DRIZZLE_RETURN_INTERNAL_ERROR;
00216 }
00217
00218 ptr= con->buffer_ptr;
00219
00220
00221 DRIZZLE_SET_BYTE3(ptr, con->packet_size)
00222 ptr[3]= 0;
00223 con->packet_number= 1;
00224 ptr+= 4;
00225
00226 ptr[0]= con->protocol_version;
00227 ptr++;
00228
00229 memcpy(ptr, con->server_version, strlen(con->server_version));
00230 ptr+= strlen(con->server_version);
00231
00232 ptr[0]= 0;
00233 ptr++;
00234
00235 DRIZZLE_SET_BYTE4(ptr, con->thread_id)
00236 ptr+= 4;
00237
00238 if (con->scramble == NULL)
00239 memset(ptr, 0, 8);
00240 else
00241 memcpy(ptr, con->scramble, 8);
00242 ptr+= 8;
00243
00244 ptr[0]= 0;
00245 ptr++;
00246
00247 if (con->options & DRIZZLE_CON_MYSQL)
00248 con->capabilities|= DRIZZLE_CAPABILITIES_PROTOCOL_41;
00249
00250
00251 DRIZZLE_SET_BYTE2(ptr, con->capabilities)
00252 ptr+= 2;
00253
00254 ptr[0]= con->charset;
00255 ptr++;
00256
00257 DRIZZLE_SET_BYTE2(ptr, con->status)
00258 ptr+= 2;
00259
00260 memset(ptr, 0, 13);
00261 ptr+= 13;
00262
00263 if (con->scramble == NULL)
00264 memset(ptr, 0, 12);
00265 else
00266 memcpy(ptr, con->scramble + 8, 12);
00267 ptr+= 12;
00268
00269 ptr[0]= 0;
00270 ptr++;
00271
00272 con->buffer_size+= (4 + con->packet_size);
00273
00274
00275 if ((size_t)(ptr - con->buffer_ptr) != (4 + con->packet_size))
00276 {
00277 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_server_handshake_write",
00278 "error packing server handshake:%zu:%zu",
00279 (size_t)(ptr - con->buffer_ptr), 4 + con->packet_size)
00280 return DRIZZLE_RETURN_INTERNAL_ERROR;
00281 }
00282
00283 DRIZZLE_STATE_POP(con)
00284 return DRIZZLE_RETURN_OK;
00285 }
00286
00287 drizzle_return_t drizzle_state_client_handshake_read(drizzle_con_st *con)
00288 {
00289 size_t real_size;
00290 uint8_t *ptr;
00291 uint8_t scramble_size;
00292
00293 PDEBUG("drizzle_state_client_handshake_read", "%5zu %5zu", con->buffer_size,
00294 con->packet_size)
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_ERROR_SET(con->drizzle, "drizzle_state_client_handshake_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_ERROR_SET(con->drizzle, "drizzle_state_client_handshake_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_ERROR_SET(con->drizzle, "drizzle_state_client_handshake_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_ERROR_SET(con->drizzle, "drizzle_state_client_handshake_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_ERROR_SET(con->drizzle, "drizzle_state_client_handshake_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_ERROR_SET(con->drizzle, "drizzle_state_client_handshake_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_ERROR_SET(con->drizzle, "drizzle_state_client_handshake_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_ERROR_SET(con->drizzle, "drizzle_state_client_handshake_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_client_handshake_write(drizzle_con_st *con)
00434 {
00435 uint8_t *ptr;
00436 drizzle_capabilities_t capabilities;
00437 drizzle_return_t ret;
00438
00439
00440 con->packet_size= 4
00441 + 4
00442 + 1
00443 + 23
00444 + strlen(con->user) + 1
00445 + 1
00446 + DRIZZLE_MAX_SCRAMBLE_SIZE
00447 + strlen(con->db) + 1;
00448
00449
00450 if ((con->packet_size + 4) > DRIZZLE_MAX_BUFFER_SIZE)
00451 {
00452 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_client_handshake_write",
00453 "buffer too small:%zu", con->packet_size + 4)
00454 return DRIZZLE_RETURN_INTERNAL_ERROR;
00455 }
00456
00457 ptr= con->buffer_ptr;
00458
00459
00460 ptr[3]= con->packet_number;
00461 con->packet_number++;
00462 ptr+= 4;
00463
00464 if (con->options & DRIZZLE_CON_MYSQL)
00465 con->capabilities|= DRIZZLE_CAPABILITIES_PROTOCOL_41;
00466
00467 capabilities= con->capabilities & DRIZZLE_CAPABILITIES_CLIENT;
00468 capabilities&= ~(DRIZZLE_CAPABILITIES_COMPRESS | DRIZZLE_CAPABILITIES_SSL);
00469 if (con->db[0] == 0)
00470 capabilities&= ~DRIZZLE_CAPABILITIES_CONNECT_WITH_DB;
00471
00472 DRIZZLE_SET_BYTE4(ptr, capabilities)
00473 ptr+= 4;
00474
00475 DRIZZLE_SET_BYTE4(ptr, con->max_packet_size)
00476 ptr+= 4;
00477
00478 ptr[0]= con->charset;
00479 ptr++;
00480
00481 memset(ptr, 0, 23);
00482 ptr+= 23;
00483
00484 ptr= drizzle_pack_auth(con, ptr, &ret);
00485 if (ret != DRIZZLE_RETURN_OK)
00486 return ret;
00487
00488 con->buffer_size+= (4 + con->packet_size);
00489
00490
00491 if ((size_t)(ptr - con->buffer_ptr) != (4 + con->packet_size))
00492 {
00493 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_client_handshake_write",
00494 "error packing client handshake:%zu:%zu",
00495 (size_t)(ptr - con->buffer_ptr), 4 + con->packet_size)
00496 return DRIZZLE_RETURN_INTERNAL_ERROR;
00497 }
00498
00499
00500 DRIZZLE_SET_BYTE3(con->buffer_ptr, con->packet_size)
00501
00502 DRIZZLE_STATE_POP(con)
00503 return DRIZZLE_RETURN_OK;
00504 }
00505
00506 drizzle_return_t drizzle_state_handshake_result_read(drizzle_con_st *con)
00507 {
00508 drizzle_return_t ret;
00509 drizzle_result_st result;
00510
00511 if (drizzle_result_create(con, &result) == NULL)
00512 return DRIZZLE_RETURN_MEMORY;
00513
00514 con->result= &result;
00515
00516 ret= drizzle_state_result_read(con);
00517 if (DRIZZLE_STATE_NONE(con))
00518 {
00519 if (ret == DRIZZLE_RETURN_OK)
00520 {
00521 if (drizzle_result_eof(&result))
00522 {
00523 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_handshake_result_read",
00524 "old insecure authentication mechanism not supported")
00525 ret= DRIZZLE_RETURN_AUTH_FAILED;
00526 }
00527 else
00528 con->options|= DRIZZLE_CON_READY;
00529 }
00530 }
00531
00532 drizzle_result_free(&result);
00533
00534 if (ret == DRIZZLE_RETURN_ERROR_CODE)
00535 return DRIZZLE_RETURN_HANDSHAKE_FAILED;
00536
00537 return ret;
00538 }