~drizzle-trunk/drizzle/development

1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1
/*
2
 * Drizzle Client & Protocol Library
3
 *
4
 * Copyright (C) 2008 Eric Day (eday@oddments.org)
5
 * All rights reserved.
6
 *
7
 * Use and distribution licensed under the BSD license.  See
8
 * the COPYING file in this directory for full text.
9
 */
10
11
/**
12
 * @file
13
 * @brief Packing definitions
14
 */
15
16
#include "common.h"
17
18
/*
19
 * Private declarations
20
 */
21
22
/**
23
 * @addtogroup drizzle_pack_private Private Packing Functions
24
 * @ingroup drizzle_pack
25
 * @{
26
 */
27
28
/**
29
 * Compute hash from password and scramble.
30
 */
31
static drizzle_return_t _pack_scramble_hash(drizzle_con_st *con,
32
                                            uint8_t *buffer);
33
34
/** @} */
35
36
/*
37
 * Public definitions
38
 */
39
40
uint8_t *drizzle_pack_length(uint64_t number, uint8_t *ptr)
41
{
42
  if (number < 251)
43
  {
44
    ptr[0]= (uint8_t)number;
45
    ptr++;
46
  }
47
  else if (number < 65536)
48
  {
49
    ptr[0]= 252;
50
    ptr++;
51
    drizzle_set_byte2(ptr, number);
52
    ptr+= 2;
53
  }
54
  else if (number < 16777216)
55
  {
56
    ptr[0]= 253;
57
    ptr++;
58
    drizzle_set_byte3(ptr, number);
59
    ptr+= 3;
60
  }
61
  else
62
  {
63
    ptr[0]= 254;
64
    ptr++;
65
    drizzle_set_byte8(ptr, number);
66
    ptr+= 8;
67
  }
68
69
  return ptr;
70
}
71
72
uint64_t drizzle_unpack_length(drizzle_con_st *con, drizzle_return_t *ret_ptr)
73
{
74
  uint64_t length;
75
  uint8_t bytes;
76
77
  if (con->buffer_ptr[0] < 251)
78
  {
79
    length= (uint64_t)(con->buffer_ptr[0]);
80
    bytes= 1;
81
  }
82
  else if (con->buffer_ptr[0] == 251)
83
  {
84
    con->buffer_ptr++;
85
    con->buffer_size--;
86
    con->packet_size--;
87
88
    *ret_ptr= DRIZZLE_RETURN_NULL_SIZE;
89
    return 0;
90
  }
91
  else if (con->buffer_ptr[0] == 252 && con->buffer_size > 2)
92
  {
93
    length= drizzle_get_byte2(con->buffer_ptr + 1);
94
    bytes= 3;
95
  }
96
  else if (con->buffer_ptr[0] == 253 && con->buffer_size > 3)
97
  {
98
    length= drizzle_get_byte3(con->buffer_ptr + 1);
99
    bytes= 4;
100
  }
101
  else if (con->buffer_size > 8)
102
  {
103
    length= drizzle_get_byte8(con->buffer_ptr + 1);
104
    bytes= 9;
105
  }
106
  else
107
  {
108
    *ret_ptr= DRIZZLE_RETURN_IO_WAIT;
109
    return 0;
110
  }
111
112
  con->buffer_ptr+= bytes;
113
  con->buffer_size-= bytes;
114
  con->packet_size-= bytes;
115
116
  *ret_ptr= DRIZZLE_RETURN_OK;
117
  return length;
118
}
119
120
uint8_t *drizzle_pack_string(char *string, uint8_t *ptr)
121
{
122
  uint64_t size= strlen(string);
123
124
  ptr= drizzle_pack_length(size, ptr);
125
  if (size > 0)
126
  {
127
    memcpy(ptr, string, (size_t)size);
128
    ptr+= size;
129
  }
130
131
  return ptr;
132
}
133
134
drizzle_return_t drizzle_unpack_string(drizzle_con_st *con, char *buffer,
135
                                       uint64_t max_length)
136
{
137
  drizzle_return_t ret= DRIZZLE_RETURN_OK;
138
  uint64_t length;
139
140
  length= drizzle_unpack_length(con, &ret);
141
  if (ret != DRIZZLE_RETURN_OK)
142
  {
143
    if (ret == DRIZZLE_RETURN_NULL_SIZE)
144
    {
145
      drizzle_set_error(con->drizzle, "drizzle_unpack_string",
146
                        "unexpected NULL length");
147
    }
148
149
    return ret;
150
  }
151
152
  if (length < max_length)
153
  {
154
    if (length > 0)
155
      memcpy(buffer, con->buffer_ptr, (size_t)length);
156
157
    buffer[length]= 0;
158
  }
159
  else
160
  {
161
    memcpy(buffer, con->buffer_ptr, (size_t)(max_length - 1));
162
    buffer[max_length - 1]= 0;
163
  }
164
  
165
  con->buffer_ptr+= length;
166
  con->buffer_size-= (size_t)length;
167
  con->packet_size-= (size_t)length;
168
169
  return DRIZZLE_RETURN_OK;
170
}
171
172
uint8_t *drizzle_pack_auth(drizzle_con_st *con, uint8_t *ptr,
173
                           drizzle_return_t *ret_ptr)
174
{
175
  if (con->user[0] != 0)
176
  {
177
    memcpy(ptr, con->user, strlen(con->user));
178
    ptr+= strlen(con->user);
179
  }
180
181
  ptr[0]= 0;
182
  ptr++;
183
184
  if (con->options & DRIZZLE_CON_RAW_SCRAMBLE && con->scramble != NULL)
185
  {
186
    ptr[0]= DRIZZLE_MAX_SCRAMBLE_SIZE;
187
    ptr++;
188
189
    memcpy(ptr, con->scramble, DRIZZLE_MAX_SCRAMBLE_SIZE);
190
    ptr+= DRIZZLE_MAX_SCRAMBLE_SIZE;
191
  }
192
  else if (con->password[0] == 0)
193
  {
194
    ptr[0]= 0;
195
    ptr++;
196
    con->packet_size-= DRIZZLE_MAX_SCRAMBLE_SIZE;
197
  }
198
  else
199
  {
200
    ptr[0]= DRIZZLE_MAX_SCRAMBLE_SIZE;
201
    ptr++;
202
203
    if (con->options & DRIZZLE_CON_MYSQL)
204
    {
205
      *ret_ptr= _pack_scramble_hash(con, ptr);
206
      if (*ret_ptr != DRIZZLE_RETURN_OK)
207
        return ptr;
208
    }
209
    else
210
      snprintf((char *)ptr, DRIZZLE_MAX_SCRAMBLE_SIZE, "%s", con->password);
211
212
    ptr+= DRIZZLE_MAX_SCRAMBLE_SIZE;
213
  }
214
215
  if (con->db[0] != 0)
216
  {
217
    memcpy(ptr, con->db, strlen(con->db));
218
    ptr+= strlen(con->db);
219
  }
220
221
  ptr[0]= 0;
222
  ptr++;
223
224
  *ret_ptr= DRIZZLE_RETURN_OK;
225
  return ptr;
226
}
227
228
/*
229
 * Private definitions
230
 */
231
232
static drizzle_return_t _pack_scramble_hash(drizzle_con_st *con,
233
                                            uint8_t *buffer)
234
{
235
  SHA1_CTX ctx;
236
  uint8_t hash_tmp1[SHA1_DIGEST_LENGTH];
237
  uint8_t hash_tmp2[SHA1_DIGEST_LENGTH];
238
  uint32_t x;
239
240
  if (SHA1_DIGEST_LENGTH != DRIZZLE_MAX_SCRAMBLE_SIZE)
241
  {
242
    drizzle_set_error(con->drizzle, "_pack_scramble_hash",
243
                      "SHA1 hash size mismatch:%u:%u", SHA1_DIGEST_LENGTH,
244
                      DRIZZLE_MAX_SCRAMBLE_SIZE);
245
    return DRIZZLE_RETURN_INTERNAL_ERROR;
246
  }
247
248
  if (con->scramble == NULL)
249
  {
250
    drizzle_set_error(con->drizzle, "_pack_scramble_hash",
251
                      "no scramble buffer");
252
    return DRIZZLE_RETURN_NO_SCRAMBLE;
253
  }
254
255
  /* First hash the password. */
256
  SHA1Init(&ctx);
257
  SHA1Update(&ctx, (uint8_t *)(con->password), strlen(con->password));
258
  SHA1Final(hash_tmp1, &ctx);
259
260
  /* Second, hash the password hash. */
261
  SHA1Init(&ctx);
262
  SHA1Update(&ctx, hash_tmp1, SHA1_DIGEST_LENGTH);
263
  SHA1Final(hash_tmp2, &ctx);
264
265
  /* Third, hash the scramble and the double password hash. */
266
  SHA1Init(&ctx);
267
  SHA1Update(&ctx, con->scramble, SHA1_DIGEST_LENGTH);
268
  SHA1Update(&ctx, hash_tmp2, SHA1_DIGEST_LENGTH);
269
  SHA1Final(buffer, &ctx);
270
271
  /* Fourth, xor the last hash against the first password hash. */
272
  for (x= 0; x < SHA1_DIGEST_LENGTH; x++)
273
    buffer[x]= buffer[x] ^ hash_tmp1[x];
274
275
  return DRIZZLE_RETURN_OK;
276
}