2
* Drizzle Client & Protocol Library
4
* Copyright (C) 2008 Eric Day (eday@oddments.org)
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions are
11
* * Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
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
19
* * The names of its contributors may not be used to endorse or
20
* promote products derived from this software without specific prior
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.
39
* @brief Packing definitions
45
* Private declarations
49
* @addtogroup drizzle_pack_private Private Packing Functions
50
* @ingroup drizzle_pack
55
* Compute hash from password and scramble.
57
static drizzle_return_t _pack_scramble_hash(drizzle_con_st *con,
66
uint8_t *drizzle_pack_length(uint64_t number, uint8_t *ptr)
70
ptr[0]= (uint8_t)number;
73
else if (number < 65536)
77
drizzle_set_byte2(ptr, number);
80
else if (number < 16777216)
84
drizzle_set_byte3(ptr, number);
91
drizzle_set_byte8(ptr, number);
98
uint64_t drizzle_unpack_length(drizzle_con_st *con, drizzle_return_t *ret_ptr)
103
if (con->buffer_ptr[0] < 251)
105
length= (uint64_t)(con->buffer_ptr[0]);
108
else if (con->buffer_ptr[0] == 251)
114
*ret_ptr= DRIZZLE_RETURN_NULL_SIZE;
117
else if (con->buffer_ptr[0] == 252 && con->buffer_size > 2)
119
length= drizzle_get_byte2(con->buffer_ptr + 1);
122
else if (con->buffer_ptr[0] == 253 && con->buffer_size > 3)
124
length= drizzle_get_byte3(con->buffer_ptr + 1);
127
else if (con->buffer_size > 8)
129
length= drizzle_get_byte8(con->buffer_ptr + 1);
134
*ret_ptr= DRIZZLE_RETURN_IO_WAIT;
138
con->buffer_ptr+= bytes;
139
con->buffer_size-= bytes;
140
con->packet_size-= bytes;
142
*ret_ptr= DRIZZLE_RETURN_OK;
146
uint8_t *drizzle_pack_string(char *string, uint8_t *ptr)
148
uint64_t size= strlen(string);
150
ptr= drizzle_pack_length(size, ptr);
153
memcpy(ptr, string, (size_t)size);
160
drizzle_return_t drizzle_unpack_string(drizzle_con_st *con, char *buffer,
163
drizzle_return_t ret= DRIZZLE_RETURN_OK;
166
length= drizzle_unpack_length(con, &ret);
167
if (ret != DRIZZLE_RETURN_OK)
169
if (ret == DRIZZLE_RETURN_NULL_SIZE)
171
drizzle_set_error(con->drizzle, "drizzle_unpack_string",
172
"unexpected NULL length");
178
if (length < max_length)
181
memcpy(buffer, con->buffer_ptr, (size_t)length);
187
memcpy(buffer, con->buffer_ptr, (size_t)(max_length - 1));
188
buffer[max_length - 1]= 0;
191
con->buffer_ptr+= length;
192
con->buffer_size-= (size_t)length;
193
con->packet_size-= (size_t)length;
195
return DRIZZLE_RETURN_OK;
198
uint8_t *drizzle_pack_auth(drizzle_con_st *con, uint8_t *ptr,
199
drizzle_return_t *ret_ptr)
201
if (con->user[0] != 0)
203
memcpy(ptr, con->user, strlen(con->user));
204
ptr+= strlen(con->user);
210
if (con->options & DRIZZLE_CON_RAW_SCRAMBLE && con->scramble != NULL)
212
ptr[0]= DRIZZLE_MAX_SCRAMBLE_SIZE;
215
memcpy(ptr, con->scramble, DRIZZLE_MAX_SCRAMBLE_SIZE);
216
ptr+= DRIZZLE_MAX_SCRAMBLE_SIZE;
218
else if (con->password[0] == 0)
222
con->packet_size-= DRIZZLE_MAX_SCRAMBLE_SIZE;
226
ptr[0]= DRIZZLE_MAX_SCRAMBLE_SIZE;
229
if (con->options & DRIZZLE_CON_MYSQL && con->options & DRIZZLE_CON_AUTH_PLUGIN)
231
snprintf((char *)ptr, DRIZZLE_MAX_SCRAMBLE_SIZE, "%s", con->password);
233
else if (con->options & DRIZZLE_CON_MYSQL)
235
*ret_ptr= _pack_scramble_hash(con, ptr);
236
if (*ret_ptr != DRIZZLE_RETURN_OK)
239
else // We assume Drizzle
241
snprintf((char *)ptr, DRIZZLE_MAX_SCRAMBLE_SIZE, "%s", con->password);
244
ptr+= DRIZZLE_MAX_SCRAMBLE_SIZE;
249
memcpy(ptr, con->db, strlen(con->db));
250
ptr+= strlen(con->db);
256
*ret_ptr= DRIZZLE_RETURN_OK;
261
* Private definitions
264
static drizzle_return_t _pack_scramble_hash(drizzle_con_st *con,
268
uint8_t hash_tmp1[SHA1_DIGEST_LENGTH];
269
uint8_t hash_tmp2[SHA1_DIGEST_LENGTH];
271
if (SHA1_DIGEST_LENGTH != DRIZZLE_MAX_SCRAMBLE_SIZE)
273
drizzle_set_error(con->drizzle, "_pack_scramble_hash",
274
"SHA1 hash size mismatch:%u:%u", SHA1_DIGEST_LENGTH,
275
DRIZZLE_MAX_SCRAMBLE_SIZE);
276
return DRIZZLE_RETURN_INTERNAL_ERROR;
279
if (con->scramble == NULL)
281
drizzle_set_error(con->drizzle, "_pack_scramble_hash",
282
"no scramble buffer");
283
return DRIZZLE_RETURN_NO_SCRAMBLE;
286
/* First hash the password. */
288
SHA1Update(&ctx, (uint8_t *)(con->password), strlen(con->password));
289
SHA1Final(hash_tmp1, &ctx);
291
/* Second, hash the password hash. */
293
SHA1Update(&ctx, hash_tmp1, SHA1_DIGEST_LENGTH);
294
SHA1Final(hash_tmp2, &ctx);
296
/* Third, hash the scramble and the double password hash. */
298
SHA1Update(&ctx, con->scramble, SHA1_DIGEST_LENGTH);
299
SHA1Update(&ctx, hash_tmp2, SHA1_DIGEST_LENGTH);
300
SHA1Final(buffer, &ctx);
302
/* Fourth, xor the last hash against the first password hash. */
303
for (uint32_t x= 0; x < SHA1_DIGEST_LENGTH; x++)
304
buffer[x]= buffer[x] ^ hash_tmp1[x];
306
return DRIZZLE_RETURN_OK;