~patrick-crews/drizzle/dbqp_server_setup

« back to all changes in this revision

Viewing changes to libdrizzle-2.0/libdrizzle/handshake.cc

  • Committer: Lee Bieber
  • Date: 2011-03-23 14:44:31 UTC
  • mfrom: (2244.1.2 libdrizzle-2.0)
  • mto: This revision was merged to the branch mainline in revision 2247.
  • Revision ID: kalebral@gmail.com-20110323144431-i07xlqna63deaxaj
Merge Monty - Splits out libdrizzle-1.0 and libdrizzle-2.0.

Show diffs side-by-side

added added

removed removed

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