Implement verification against mysql v4 passwords
Showing
1 changed file
with
30 additions
and
27 deletions
... | @@ -25,6 +25,7 @@ | ... | @@ -25,6 +25,7 @@ |
25 | 25 | ||
26 | #include <mysql/mysql.h> | 26 | #include <mysql/mysql.h> |
27 | #include <mysql/errmsg.h> | 27 | #include <mysql/errmsg.h> |
28 | #include <sha1.h> | ||
28 | 29 | ||
29 | struct mu_mysql_data | 30 | struct mu_mysql_data |
30 | { | 31 | { |
... | @@ -250,11 +251,10 @@ scramble_password (unsigned long *result, const char *password) | ... | @@ -250,11 +251,10 @@ scramble_password (unsigned long *result, const char *password) |
250 | result[1] = nr2 & (((unsigned long) 1L << 31) -1L); | 251 | result[1] = nr2 & (((unsigned long) 1L << 31) -1L); |
251 | } | 252 | } |
252 | 253 | ||
253 | #if 0 | ||
254 | static void | 254 | static void |
255 | octet2hex (char *to, const unsigned char *str, unsigned len) | 255 | octet2hex (char *to, const unsigned char *str, unsigned len) |
256 | { | 256 | { |
257 | const char *str_end= str + len; | 257 | const unsigned char *str_end= str + len; |
258 | static char d[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | 258 | static char d[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
259 | 259 | ||
260 | for ( ; str != str_end; ++str) | 260 | for ( ; str != str_end; ++str) |
... | @@ -266,16 +266,13 @@ octet2hex (char *to, const unsigned char *str, unsigned len) | ... | @@ -266,16 +266,13 @@ octet2hex (char *to, const unsigned char *str, unsigned len) |
266 | } | 266 | } |
267 | 267 | ||
268 | #define SHA1_HASH_SIZE 20 | 268 | #define SHA1_HASH_SIZE 20 |
269 | int | 269 | static int |
270 | mu_check_mysql_4x_password (const char *scrambled, const char *message) | 270 | mu_check_mysql_4x_password (const char *scrambled, const char *message) |
271 | { | 271 | { |
272 | struct sha1_ctx sha1_context; | 272 | struct sha1_ctx sha1_context; |
273 | uint8 hash_stage2[SHA1_HASH_SIZE]; | 273 | unsigned char hash_stage2[SHA1_HASH_SIZE]; |
274 | char to[2*SHA1_HASH_SIZE + 2]; | 274 | char to[2*SHA1_HASH_SIZE + 2]; |
275 | 275 | ||
276 | if (!to) | ||
277 | return 1; | ||
278 | |||
279 | /* stage 1: hash password */ | 276 | /* stage 1: hash password */ |
280 | sha1_init_ctx (&sha1_context); | 277 | sha1_init_ctx (&sha1_context); |
281 | sha1_process_bytes (message, strlen (message), &sha1_context); | 278 | sha1_process_bytes (message, strlen (message), &sha1_context); |
... | @@ -287,37 +284,22 @@ mu_check_mysql_4x_password (const char *scrambled, const char *message) | ... | @@ -287,37 +284,22 @@ mu_check_mysql_4x_password (const char *scrambled, const char *message) |
287 | sha1_finish_ctx (&sha1_context, hash_stage2); | 284 | sha1_finish_ctx (&sha1_context, hash_stage2); |
288 | 285 | ||
289 | /* convert hash_stage2 to hex string */ | 286 | /* convert hash_stage2 to hex string */ |
290 | *to++= '*'; | 287 | to[0] = '*'; |
291 | octet2hex (to, hash_stage2, SHA1_HASH_SIZE); | 288 | octet2hex (to + 1, hash_stage2, SHA1_HASH_SIZE); |
292 | 289 | ||
293 | /* Compare both strings */ | 290 | /* Compare both strings */ |
294 | return memcmp (to, scrambled, strlen (scrambled)); | 291 | return memcmp (to, scrambled, strlen (scrambled)); |
295 | } | 292 | } |
296 | #endif | ||
297 | 293 | ||
298 | /* Check whether a plaintext password MESSAGE matches MySQL scrambled password | 294 | static int |
299 | PASSWORD */ | 295 | mu_check_mysql_3x_password (const char *scrambled, const char *message) |
300 | int | ||
301 | mu_check_mysql_scrambled_password (const char *scrambled, const char *message) | ||
302 | { | 296 | { |
303 | unsigned long hash_pass[2], hash_message[2]; | 297 | unsigned long hash_pass[2], hash_message[2]; |
304 | char buf[17]; | 298 | char buf[17]; |
305 | 299 | ||
306 | if (strlen (scrambled) < 16) | ||
307 | return 1; | ||
308 | if (strlen (scrambled) > 16) | ||
309 | { | ||
310 | const char *p; | ||
311 | /* Try to normalize it by cutting off trailing whitespace */ | ||
312 | for (p = scrambled + strlen (scrambled) - 1; | ||
313 | p > scrambled && isspace (*p); p--) | ||
314 | ; | ||
315 | if (p - scrambled != 15) | ||
316 | return 1; | ||
317 | memcpy (buf, scrambled, 16); | 300 | memcpy (buf, scrambled, 16); |
318 | buf[17] = 0; | 301 | buf[16] = 0; |
319 | scrambled = buf; | 302 | scrambled = buf; |
320 | } | ||
321 | 303 | ||
322 | get_salt_from_scrambled (hash_pass, scrambled); | 304 | get_salt_from_scrambled (hash_pass, scrambled); |
323 | scramble_password (hash_message, message); | 305 | scramble_password (hash_message, message); |
... | @@ -325,6 +307,27 @@ mu_check_mysql_scrambled_password (const char *scrambled, const char *message) | ... | @@ -325,6 +307,27 @@ mu_check_mysql_scrambled_password (const char *scrambled, const char *message) |
325 | && hash_message[1] == hash_pass[1]); | 307 | && hash_message[1] == hash_pass[1]); |
326 | } | 308 | } |
327 | 309 | ||
310 | /* Check whether a plaintext password MESSAGE matches MySQL scrambled password | ||
311 | PASSWORD */ | ||
312 | int | ||
313 | mu_check_mysql_scrambled_password (const char *scrambled, const char *message) | ||
314 | { | ||
315 | const char *p; | ||
316 | |||
317 | /* Try to normalize it by cutting off trailing whitespace */ | ||
318 | for (p = scrambled + strlen (scrambled) - 1; | ||
319 | p > scrambled && isspace (*p); p--) | ||
320 | ; | ||
321 | switch (p - scrambled) | ||
322 | { | ||
323 | case 15: | ||
324 | return mu_check_mysql_3x_password (scrambled, message); | ||
325 | case 40: | ||
326 | return mu_check_mysql_4x_password (scrambled, message); | ||
327 | } | ||
328 | return 1; | ||
329 | } | ||
330 | |||
328 | 331 | ||
329 | /* Register module */ | 332 | /* Register module */ |
330 | MU_DECL_SQL_DISPATCH_T(mysql) = { | 333 | MU_DECL_SQL_DISPATCH_T(mysql) = { | ... | ... |
-
Please register or sign in to post a comment