1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2  *
3  * Drizzle Client & Protocol Library
4  *
5  * Copyright (C) 2008-2013 Drizzle Developer Group
6  * Copyright (C) 2008 Eric Day (eday@oddments.org)
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are
11  * met:
12  *
13  *     * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  *     * Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following disclaimer
18  * in the documentation and/or other materials provided with the
19  * distribution.
20  *
21  *     * The names of its contributors may not be used to endorse or
22  * promote products derived from this software without specific prior
23  * written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *
37  */
38 
39 /**
40  * @file
41  * @brief Handshake Definitions
42  */
43 
44 #include "config.h"
45 #include "libdrizzle/common.h"
46 
47 /*
48  * Client Definitions
49  */
50 
drizzle_handshake_server_read(drizzle_st * con)51 drizzle_return_t drizzle_handshake_server_read(drizzle_st *con)
52 {
53   if (con->has_state())
54   {
55     con->push_state(drizzle_state_handshake_server_read);
56     con->push_state(drizzle_state_packet_read);
57   }
58 
59   return drizzle_state_loop(con);
60 }
61 
drizzle_handshake_client_write(drizzle_st * con)62 drizzle_return_t drizzle_handshake_client_write(drizzle_st *con)
63 {
64   if (con->has_state())
65   {
66     con->push_state(drizzle_state_write);
67     con->push_state(drizzle_state_handshake_client_write);
68 
69     if (con->ssl)
70     {
71       con->push_state(drizzle_state_write);
72       con->push_state(drizzle_state_handshake_ssl_client_write);
73     }
74   }
75 
76   return drizzle_state_loop(con);
77 }
78 
79 /*
80  * State Definitions
81  */
82 
drizzle_state_handshake_server_read(drizzle_st * con)83 drizzle_return_t drizzle_state_handshake_server_read(drizzle_st *con)
84 {
85   unsigned char *ptr;
86   ptrdiff_t extra_length;
87   unsigned char* packet_end;
88 
89   if (con == NULL)
90   {
91     return DRIZZLE_RETURN_INVALID_ARGUMENT;
92   }
93   drizzle_log_debug(con, "drizzle_state_handshake_server_read");
94 
95   /* Assume the entire handshake packet will fit in the buffer. */
96   if (con->buffer_size < con->packet_size)
97   {
98     con->push_state(drizzle_state_read);
99     return DRIZZLE_RETURN_OK;
100   }
101 
102   if (con->packet_size < 46)
103   {
104     drizzle_set_error(con, "drizzle_state_handshake_server_read",
105                       "bad packet size:>=46:%zu", con->packet_size);
106     return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
107   }
108 
109   packet_end= con->buffer_ptr + con->packet_size;
110   con->protocol_version= con->buffer_ptr[0];
111   con->buffer_ptr++;
112 
113   if (con->protocol_version != 10)
114   {
115     /* This is a special case where the server determines that authentication
116        will be impossible and denies any attempt right away. */
117     if (con->protocol_version == 255)
118     {
119       drizzle_set_error(con, "drizzle_state_handshake_server_read",
120                         "%.*s", (int)con->packet_size - 3,
121                         con->buffer_ptr + 2);
122       return DRIZZLE_RETURN_AUTH_FAILED;
123     }
124 
125     drizzle_set_error(con, "drizzle_state_handshake_server_read",
126                       "protocol version not supported:%d",
127                       con->protocol_version);
128     return DRIZZLE_RETURN_PROTOCOL_NOT_SUPPORTED;
129   }
130 
131   /* Look for null-terminated server version string. */
132   ptr= (unsigned char*)memchr(con->buffer_ptr, 0, con->buffer_size - 1);
133   if (ptr == NULL)
134   {
135     drizzle_set_error(con, "drizzle_state_handshake_server_read",
136                       "server version string not found");
137     return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
138   }
139 
140   if (con->packet_size < (46 + (size_t)(ptr - con->buffer_ptr)))
141   {
142     drizzle_set_error(con, "drizzle_state_handshake_server_read",
143                       "bad packet size:%zu:%zu",
144                       (46 + (size_t)(ptr - con->buffer_ptr)), con->packet_size);
145     return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
146   }
147 
148   strncpy(con->server_version, (char *)con->buffer_ptr,
149           DRIZZLE_MAX_SERVER_VERSION_SIZE);
150   con->server_version[DRIZZLE_MAX_SERVER_VERSION_SIZE - 1]= 0;
151   con->buffer_ptr+= ((ptr - con->buffer_ptr) + 1);
152 
153   con->thread_id= (uint32_t)drizzle_get_byte4(con->buffer_ptr);
154   con->buffer_ptr+= 4;
155 
156   con->scramble= con->scramble_buffer;
157   memcpy(con->scramble, con->buffer_ptr, 8);
158   /* Skip scramble and filler. */
159   con->buffer_ptr+= 9;
160 
161   /* Even though drizzle_capabilities is more than 2 bytes, the protocol only
162      allows for 2. This means some capabilities are not possible during this
163      handshake step. The options beyond 2 bytes are for client response only. */
164   con->capabilities= (drizzle_capabilities_t)drizzle_get_byte2(con->buffer_ptr);
165   con->buffer_ptr+= 2;
166 
167   if (!(con->capabilities & DRIZZLE_CAPABILITIES_PROTOCOL_41))
168   {
169     drizzle_set_error(con, "drizzle_state_handshake_server_read",
170                       "protocol version not supported, must be MySQL 4.1+");
171     return DRIZZLE_RETURN_PROTOCOL_NOT_SUPPORTED;
172   }
173 
174   con->charset= (drizzle_charset_t)con->buffer_ptr[0];
175   con->buffer_ptr+= 1;
176 
177   con->status= (drizzle_status_t)drizzle_get_byte2(con->buffer_ptr);
178   /* Skip status and filler. */
179   con->buffer_ptr+= 15;
180 
181   memcpy(con->scramble + 8, con->buffer_ptr, 12);
182   con->buffer_ptr+= 13;
183 
184   /* MySQL 5.5 adds "mysql_native_password" after the server greeting. */
185   extra_length= packet_end - con->buffer_ptr;
186   assert(extra_length >= 0);
187   if (extra_length > DRIZZLE_MAX_SERVER_EXTRA_SIZE - 1)
188     extra_length= DRIZZLE_MAX_SERVER_EXTRA_SIZE - 1;
189   memcpy(con->server_extra, (char *)con->buffer_ptr, extra_length);
190   con->server_extra[extra_length]= 0;
191 
192   con->buffer_size-= con->packet_size;
193   if (con->buffer_size != 0)
194   {
195     drizzle_set_error(con, "drizzle_state_handshake_server_read",
196                       "unexpected data after packet:%zu", con->buffer_size);
197     return DRIZZLE_RETURN_UNEXPECTED_DATA;
198   }
199 
200   con->buffer_ptr= con->buffer;
201 
202   con->pop_state();
203 
204   if (con->state.raw_packet == false)
205   {
206     con->push_state(drizzle_state_handshake_result_read);
207     con->push_state(drizzle_state_packet_read);
208     con->push_state(drizzle_state_write);
209     con->push_state(drizzle_state_handshake_client_write);
210     if (con->ssl)
211     {
212       con->push_state(drizzle_state_write);
213       con->push_state(drizzle_state_handshake_ssl_client_write);
214     }
215   }
216 
217   return DRIZZLE_RETURN_OK;
218 }
219 
drizzle_state_handshake_server_write(drizzle_st * con)220 drizzle_return_t drizzle_state_handshake_server_write(drizzle_st *con)
221 {
222   unsigned char *ptr;
223 
224   if (con == NULL)
225   {
226     return DRIZZLE_RETURN_INVALID_ARGUMENT;
227   }
228   drizzle_log_debug(con, "drizzle_state_handshake_server_write");
229 
230   /* Calculate max packet size. */
231   con->packet_size= 1   /* Protocol version */
232                   + strlen(con->server_version) + 1
233                   + 4   /* Thread ID */
234                   + 8   /* Scramble */
235                   + 1   /* NULL */
236                   + 2   /* Capabilities */
237                   + 1   /* Language */
238                   + 2   /* Status */
239                   + 13  /* Unused */
240                   + 12  /* Scramble */
241                   + 1;  /* NULL */
242 
243   /* Assume the entire handshake packet will fit in the buffer. */
244   if ((con->packet_size + 4) > con->buffer_allocation)
245   {
246     drizzle_set_error(con, "drizzle_state_handshake_server_write",
247                       "buffer too small:%zu", con->packet_size + 4);
248     return DRIZZLE_RETURN_INTERNAL_ERROR;
249   }
250 
251   ptr= con->buffer_ptr;
252 
253   /* Store packet size and packet number first. */
254   drizzle_set_byte3(ptr, con->packet_size);
255   ptr[3]= 0;
256   con->packet_number= 1;
257   ptr+= 4;
258 
259   ptr[0]= con->protocol_version;
260   ptr++;
261 
262   memcpy(ptr, con->server_version, strlen(con->server_version));
263   ptr+= strlen(con->server_version);
264 
265   ptr[0]= 0;
266   ptr++;
267 
268   drizzle_set_byte4(ptr, con->thread_id);
269   ptr+= 4;
270 
271   if (con->scramble == NULL)
272   {
273     memset(ptr, 0, 8);
274   }
275   else
276   {
277     memcpy(ptr, con->scramble, 8);
278   }
279   ptr+= 8;
280 
281   ptr[0]= 0;
282   ptr++;
283 
284   con->capabilities = (drizzle_capabilities_t)((int) con->capabilities | (int)DRIZZLE_CAPABILITIES_PROTOCOL_41);
285 
286   /* We can only send two bytes worth, this is a protocol limitation. */
287   drizzle_set_byte2(ptr, con->capabilities);
288   ptr+= 2;
289 
290   ptr[0]= con->charset;
291   ptr++;
292 
293   drizzle_set_byte2(ptr, con->status);
294   ptr+= 2;
295 
296   memset(ptr, 0, 13);
297   ptr+= 13;
298 
299   if (con->scramble == NULL)
300   {
301     memset(ptr, 0, 12);
302   }
303   else
304   {
305     memcpy(ptr, con->scramble + 8, 12);
306   }
307   ptr+= 12;
308 
309   ptr[0]= 0;
310   ptr++;
311 
312   con->buffer_size+= (4 + con->packet_size);
313 
314   /* Make sure we packed it correctly. */
315   if ((size_t)(ptr - con->buffer_ptr) != (4 + con->packet_size))
316   {
317     drizzle_set_error(con, "drizzle_state_handshake_server_write",
318                       "error packing server handshake:%zu:%zu",
319                       (size_t)(ptr - con->buffer_ptr), 4 + con->packet_size);
320     return DRIZZLE_RETURN_INTERNAL_ERROR;
321   }
322 
323   con->pop_state();
324   return DRIZZLE_RETURN_OK;
325 }
326 
drizzle_state_handshake_client_read(drizzle_st * con)327 drizzle_return_t drizzle_state_handshake_client_read(drizzle_st *con)
328 {
329   size_t real_size;
330   uint8_t scramble_size;
331 
332   if (con == NULL)
333   {
334     return DRIZZLE_RETURN_INVALID_ARGUMENT;
335   }
336   drizzle_log_debug(con, "drizzle_state_handshake_client_read");
337 
338   /* Assume the entire handshake packet will fit in the buffer. */
339   if (con->buffer_size < con->packet_size)
340   {
341     con->push_state(drizzle_state_read);
342     return DRIZZLE_RETURN_OK;
343   }
344 
345   /* This is the minimum packet size. */
346   if (con->packet_size < 34)
347   {
348     drizzle_set_error(con, "drizzle_state_handshake_client_read",
349                       "bad packet size:>=34:%zu", con->packet_size);
350     return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
351   }
352 
353   real_size= 34;
354 
355   con->capabilities= (drizzle_capabilities_t) drizzle_get_byte4(con->buffer_ptr);
356   con->buffer_ptr+= 4;
357 
358   if (!(con->capabilities & DRIZZLE_CAPABILITIES_PROTOCOL_41))
359   {
360     drizzle_set_error(con, "drizzle_state_handshake_client_read",
361                       "protocol version not supported, must be MySQL 4.1+");
362     return DRIZZLE_RETURN_PROTOCOL_NOT_SUPPORTED;
363   }
364 
365   con->max_packet_size= (uint32_t)drizzle_get_byte4(con->buffer_ptr);
366   con->buffer_ptr+= 4;
367 
368   con->charset= (drizzle_charset_t)con->buffer_ptr[0];
369   con->buffer_ptr+= 1;
370 
371   /* Skip unused. */
372   con->buffer_ptr+= 23;
373 
374   /* Look for null-terminated user string. */
375   unsigned char *ptr= (unsigned char*)memchr(con->buffer_ptr, 0, con->buffer_size - 32);
376   if (ptr == NULL)
377   {
378     drizzle_set_error(con, "drizzle_state_handshake_client_read",
379                       "user string not found");
380     return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
381   }
382 
383   if (con->buffer_ptr == ptr)
384   {
385     con->user[0]= 0;
386     con->buffer_ptr++;
387   }
388   else
389   {
390     real_size+= (size_t)(ptr - con->buffer_ptr);
391     if (con->packet_size < real_size)
392     {
393       drizzle_set_error(con, "drizzle_state_handshake_client_read",
394                         "bad packet size:>=%zu:%zu", real_size,
395                         con->packet_size);
396       return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
397     }
398 
399     strncpy(con->user, (char *)con->buffer_ptr, DRIZZLE_MAX_USER_SIZE);
400     con->user[DRIZZLE_MAX_USER_SIZE - 1]= 0;
401     con->buffer_ptr+= ((ptr - con->buffer_ptr) + 1);
402   }
403 
404   scramble_size= con->buffer_ptr[0];
405   con->buffer_ptr+= 1;
406 
407   if (scramble_size == 0)
408   {
409     con->scramble= NULL;
410   }
411   else
412   {
413     if (scramble_size != DRIZZLE_MAX_SCRAMBLE_SIZE)
414     {
415       drizzle_set_error(con, "drizzle_state_handshake_client_read",
416                         "wrong scramble size");
417       return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
418     }
419 
420     real_size+= scramble_size;
421     con->scramble= con->scramble_buffer;
422     memcpy(con->scramble, con->buffer_ptr, DRIZZLE_MAX_SCRAMBLE_SIZE);
423 
424     con->buffer_ptr+= DRIZZLE_MAX_SCRAMBLE_SIZE;
425   }
426 
427   /* Look for null-terminated db string. */
428   if ((34 + strlen(con->user) + scramble_size) == con->packet_size)
429   {
430     con->db[0]= 0;
431   }
432   else
433   {
434     ptr= (unsigned char*)memchr(con->buffer_ptr, 0, con->buffer_size -
435                                     (34 + strlen(con->user) + scramble_size));
436     if (ptr == NULL)
437     {
438       drizzle_set_error(con, "drizzle_state_handshake_client_read",
439                         "db string not found");
440       return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
441     }
442 
443     real_size+= ((size_t)(ptr - con->buffer_ptr) + 1);
444     if (con->packet_size != real_size)
445     {
446       drizzle_set_error(con, "drizzle_state_handshake_client_read",
447                         "bad packet size:%zu:%zu", real_size, con->packet_size);
448       return DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET;
449     }
450 
451     if (con->buffer_ptr == ptr)
452     {
453       con->db[0]= 0;
454       con->buffer_ptr++;
455     }
456     else
457     {
458       strncpy(con->db, (char *)con->buffer_ptr, DRIZZLE_MAX_DB_SIZE);
459       con->db[DRIZZLE_MAX_DB_SIZE - 1]= 0;
460       con->buffer_ptr+= ((ptr - con->buffer_ptr) + 1);
461     }
462   }
463 
464   con->buffer_size-= con->packet_size;
465   if (con->buffer_size != 0)
466   {
467     drizzle_set_error(con, "drizzle_state_handshake_client_read",
468                       "unexpected data after packet:%zu", con->buffer_size);
469     return DRIZZLE_RETURN_UNEXPECTED_DATA;
470   }
471 
472   con->buffer_ptr= con->buffer;
473 
474   con->pop_state();
475   return DRIZZLE_RETURN_OK;
476 }
477 
drizzle_compile_capabilities(drizzle_st * con)478 int drizzle_compile_capabilities(drizzle_st *con)
479 {
480   int capabilities;
481 
482   con->capabilities = (drizzle_capabilities_t)((int)con->capabilities | (int)DRIZZLE_CAPABILITIES_PROTOCOL_41);
483 
484   capabilities= con->capabilities & DRIZZLE_CAPABILITIES_CLIENT;
485   if (con->options.found_rows == false)
486   {
487     capabilities&= ~DRIZZLE_CAPABILITIES_FOUND_ROWS;
488   }
489 
490   if (con->options.interactive)
491   {
492     capabilities|= DRIZZLE_CAPABILITIES_INTERACTIVE;
493   }
494 
495   if (con->options.multi_statements)
496   {
497     capabilities|= DRIZZLE_CAPABILITIES_MULTI_STATEMENTS;
498   }
499 
500   if (con->options.auth_plugin)
501   {
502     capabilities|= DRIZZLE_CAPABILITIES_PLUGIN_AUTH;
503   }
504 #ifdef USE_OPENSSL
505   if (con->ssl)
506   {
507     capabilities|= DRIZZLE_CAPABILITIES_SSL;
508   }
509 #endif
510   capabilities&= ~DRIZZLE_CAPABILITIES_COMPRESS;
511   if (con->db[0] == 0)
512     capabilities&= ~DRIZZLE_CAPABILITIES_CONNECT_WITH_DB;
513 
514   return capabilities;
515 }
516 
drizzle_state_handshake_client_write(drizzle_st * con)517 drizzle_return_t drizzle_state_handshake_client_write(drizzle_st *con)
518 {
519   unsigned char *ptr;
520   int capabilities;
521 #ifdef USE_OPENSSL
522   int ssl_ret;
523 #endif
524   drizzle_return_t ret;
525 
526   if (con == NULL)
527   {
528     return DRIZZLE_RETURN_INVALID_ARGUMENT;
529   }
530   drizzle_log_debug(con, "drizzle_state_handshake_client_write");
531 #ifdef USE_OPENSSL
532   if (con->ssl)
533   {
534     ssl_ret= SSL_connect(con->ssl);
535     if (ssl_ret != 1)
536     {
537       drizzle_set_error(con, "drizzle_state_handshake_client_write", "SSL error: %d", SSL_get_error(con->ssl, ssl_ret));
538       return DRIZZLE_RETURN_SSL_ERROR;
539     }
540     con->ssl_state= DRIZZLE_SSL_STATE_HANDSHAKE_COMPLETE;
541   }
542 #endif
543   /* Calculate max packet size. */
544   con->packet_size= 4   /* Capabilities */
545                   + 4   /* Max packet size */
546                   + 1   /* Charset */
547                   + 23  /* Unused */
548                   + strlen(con->user) + 1
549                   + 1   /* Scramble size */
550                   + DRIZZLE_MAX_SCRAMBLE_SIZE
551                   + strlen(con->db) + 1;
552 
553   /* Assume the entire handshake packet will fit in the buffer. */
554   if ((con->packet_size + 4) > con->buffer_allocation)
555   {
556     drizzle_set_error(con, "drizzle_state_handshake_client_write",
557                       "buffer too small:%zu", con->packet_size + 4);
558     return DRIZZLE_RETURN_INTERNAL_ERROR;
559   }
560 
561   ptr= con->buffer_ptr;
562 
563   /* Store packet size at the end since it may change. */
564   ptr[3]= con->packet_number;
565   con->packet_number++;
566   ptr+= 4;
567 
568   capabilities= drizzle_compile_capabilities(con);
569 
570   drizzle_set_byte4(ptr, capabilities);
571   ptr+= 4;
572 
573   drizzle_set_byte4(ptr, con->max_packet_size);
574   ptr+= 4;
575 
576   ptr[0]= con->charset;
577   ptr++;
578 
579   memset(ptr, 0, 23);
580   ptr+= 23;
581 
582   ptr= drizzle_pack_auth(con, ptr, &ret);
583   if (ret != DRIZZLE_RETURN_OK)
584     return ret;
585 
586   con->buffer_size+= (4 + con->packet_size);
587 
588   /* Make sure we packed it correctly. */
589   if ((size_t)(ptr - con->buffer_ptr) != (4 + con->packet_size))
590   {
591     drizzle_set_error(con, "drizzle_state_handshake_client_write",
592                       "error packing client handshake:%zu:%zu",
593                       (size_t)(ptr - con->buffer_ptr), 4 + con->packet_size);
594     return DRIZZLE_RETURN_INTERNAL_ERROR;
595   }
596 
597   /* Store packet size now. */
598   drizzle_set_byte3(con->buffer_ptr, con->packet_size);
599 
600   con->pop_state();
601   return DRIZZLE_RETURN_OK;
602 }
603 
drizzle_state_handshake_ssl_client_write(drizzle_st * con)604 drizzle_return_t drizzle_state_handshake_ssl_client_write(drizzle_st *con)
605 {
606   unsigned char *ptr;
607   int capabilities;
608 
609   drizzle_log_debug(con, "drizzle_state_handshake_ssl_client_write");
610 
611   /* SSL handshake packet structure */
612   con->packet_size= 4   /* Capabilities */
613                   + 4   /* Max packet size */
614                   + 1   /* Charset */
615                   + 23; /* Padding unused bytes */
616 
617   ptr= con->buffer_ptr;
618   drizzle_set_byte3(ptr, con->packet_size);
619   ptr[3]= con->packet_number;
620   con->packet_number++;
621   ptr+= 4;
622 
623   capabilities= drizzle_compile_capabilities(con);
624   drizzle_set_byte4(ptr, capabilities);
625   ptr+= 4;
626   drizzle_set_byte4(ptr, con->max_packet_size);
627   ptr+= 4;
628 
629   ptr[0]= con->charset;
630 
631   con->buffer_size+= con->packet_size + 4;
632   ptr++;
633 
634   memset(ptr, 0, 23);
635 
636   con->pop_state();
637   return DRIZZLE_RETURN_OK;
638 }
639 
drizzle_state_handshake_result_read(drizzle_st * con)640 drizzle_return_t drizzle_state_handshake_result_read(drizzle_st *con)
641 {
642   if (con == NULL)
643   {
644     return DRIZZLE_RETURN_INVALID_ARGUMENT;
645   }
646   drizzle_log_debug(con, "drizzle_state_handshake_result_read");
647 
648   drizzle_result_st *result = drizzle_result_create(con);
649 
650   if (result == NULL)
651   {
652     return DRIZZLE_RETURN_MEMORY;
653   }
654 
655   con->result= result;
656 
657   drizzle_return_t ret= drizzle_state_result_read(con);
658   if (con->has_state())
659   {
660     if (ret == DRIZZLE_RETURN_OK)
661     {
662       if (drizzle_result_eof(result))
663       {
664         drizzle_set_error(con, "drizzle_state_handshake_result_read",
665                          "old insecure authentication mechanism not supported");
666         ret= DRIZZLE_RETURN_AUTH_FAILED;
667       }
668       else
669       {
670         con->state.ready= true;
671       }
672     }
673   }
674 
675   drizzle_result_free(result);
676 
677   if (ret == DRIZZLE_RETURN_ERROR_CODE)
678   {
679     return DRIZZLE_RETURN_HANDSHAKE_FAILED;
680   }
681 
682   return ret;
683 }
684