Drizzled Public API Documentation

handshake.cc
Go to the documentation of this file.
00001 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00002  *
00003  * Drizzle Client & Protocol Library
00004  *
00005  * Copyright (C) 2008 Eric Day (eday@oddments.org)
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are
00010  * met:
00011  *
00012  *     * Redistributions of source code must retain the above copyright
00013  * notice, this list of conditions and the following disclaimer.
00014  *
00015  *     * Redistributions in binary form must reproduce the above
00016  * copyright notice, this list of conditions and the following disclaimer
00017  * in the documentation and/or other materials provided with the
00018  * distribution.
00019  *
00020  *     * The names of its contributors may not be used to endorse or
00021  * promote products derived from this software without specific prior
00022  * written permission.
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00026  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00027  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00028  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00029  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00030  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00031  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00032  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  */
00037 
00043 #include <libdrizzle/common.h>
00044 
00045 /*
00046  * Client Definitions
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  * Server Definitions
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  * State Definitions
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   /* Assume the entire handshake packet will fit in the buffer. */
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     /* This is a special case where the server determines that authentication
00134        will be impossible and denies any attempt right away. */
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   /* Look for null-terminated server version string. */
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   /* Skip scramble and filler. */
00177   con->buffer_ptr+= 9;
00178 
00179   /* Even though drizzle_capabilities is more than 2 bytes, the protocol only
00180      allows for 2. This means some capabilities are not possible during this
00181      handshake step. The options beyond 2 bytes are for client response only. */
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   /* Skip status and filler. */
00198   con->buffer_ptr+= 15;
00199 
00200   memcpy(con->scramble + 8, con->buffer_ptr, 12);
00201   con->buffer_ptr+= 13;
00202 
00203   /* MySQL 5.5 adds "mysql_native_password" after the server greeting. */
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   /* Calculate max packet size. */
00245   con->packet_size= 1   /* Protocol version */
00246                   + strlen(con->server_version) + 1
00247                   + 4   /* Thread ID */
00248                   + 8   /* Scramble */
00249                   + 1   /* NULL */
00250                   + 2   /* Capabilities */
00251                   + 1   /* Language */
00252                   + 2   /* Status */
00253                   + 13  /* Unused */
00254                   + 12  /* Scramble */
00255                   + 1;  /* NULL */
00256 
00257   /* Assume the entire handshake packet will fit in the buffer. */
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   /* Store packet size and packet number first. */
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   /* We can only send two bytes worth, this is a protocol limitation. */
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   /* Make sure we packed it correctly. */
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   /* Assume the entire handshake packet will fit in the buffer. */
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   /* This is the minimum packet size. */
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   /* Skip unused. */
00388   con->buffer_ptr+= 23;
00389 
00390   /* Look for null-terminated user string. */
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   /* Look for null-terminated db string. */
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   /* Calculate max packet size. */
00507   con->packet_size= 4   /* Capabilities */
00508                   + 4   /* Max packet size */
00509                   + 1   /* Charset */
00510                   + 23  /* Unused */
00511                   + strlen(con->user) + 1
00512                   + 1   /* Scramble size */
00513                   + DRIZZLE_MAX_SCRAMBLE_SIZE
00514                   + strlen(con->db) + 1;
00515 
00516   /* Assume the entire handshake packet will fit in the buffer. */
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   /* Store packet size at the end since it may change. */
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   /* Make sure we packed it correctly. */
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   /* Store packet size now. */
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 }