Commit 4dbde7f5 4dbde7f53b025eb6704ea5b55c8f5bc91a832bea by Sergey Poznyakoff

Implement verification against mysql v4 passwords

1 parent 3b373a64
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) = {
......