libdrizzle Developer Documentation
Main Page
Related Pages
Modules
Data Structures
Files
File List
Globals
libdrizzle
pack.c
Go to the documentation of this file.
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
16
#include "
common.h
"
17
18
/*
19
* Private declarations
20
*/
21
31
static
drizzle_return_t
_pack_scramble_hash
(
drizzle_con_st
*con,
32
uint8_t *buffer);
33
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
}
Generated by
1.8.1.1