~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to libmysql/password.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000-2006 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
/* password checking routines */
 
17
/*****************************************************************************
 
18
  The main idea is that no password are sent between client & server on
 
19
  connection and that no password are saved in mysql in a decodable form.
 
20
 
 
21
  On connection a random string is generated and sent to the client.
 
22
  The client generates a new string with a random generator inited with
 
23
  the hash values from the password and the sent string.
 
24
  This 'check' string is sent to the server where it is compared with
 
25
  a string generated from the stored hash_value of the password and the
 
26
  random string.
 
27
 
 
28
  The password is saved (in user.password) by using the PASSWORD() function in
 
29
  mysql.
 
30
 
 
31
  This is .c file because it's used in libmysqlclient, which is entirely in C.
 
32
  (we need it to be portable to a variety of systems).
 
33
  Example:
 
34
    update user set password=PASSWORD("hello") where user="test"
 
35
  This saves a hashed number as a string in the password field.
 
36
 
 
37
  The new authentication is performed in following manner:
 
38
 
 
39
  SERVER:  public_seed=create_random_string()
 
40
           send(public_seed)
 
41
 
 
42
  CLIENT:  recv(public_seed)
 
43
           hash_stage1=sha1("password")
 
44
           hash_stage2=sha1(hash_stage1)
 
45
           reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
 
46
 
 
47
           // this three steps are done in scramble() 
 
48
 
 
49
           send(reply)
 
50
 
 
51
     
 
52
  SERVER:  recv(reply)
 
53
           hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
 
54
           candidate_hash2=sha1(hash_stage1)
 
55
           check(candidate_hash2==hash_stage2)
 
56
 
 
57
           // this three steps are done in check_scramble()
 
58
 
 
59
*****************************************************************************/
 
60
 
 
61
#include <my_global.h>
 
62
#include <my_sys.h>
 
63
#include <m_string.h>
 
64
#include <sha1.h>
 
65
#include "mysql.h"
 
66
 
 
67
/************ MySQL 3.23-4.0 authentication routines: untouched ***********/
 
68
 
 
69
/*
 
70
  New (MySQL 3.21+) random generation structure initialization
 
71
  SYNOPSIS
 
72
    randominit()
 
73
    rand_st    OUT  Structure to initialize
 
74
    seed1      IN   First initialization parameter
 
75
    seed2      IN   Second initialization parameter
 
76
*/
 
77
 
 
78
void randominit(struct rand_struct *rand_st, ulong seed1, ulong seed2)
 
79
{                                               /* For mysql 3.21.# */
 
80
#ifdef HAVE_purify
 
81
  bzero((char*) rand_st,sizeof(*rand_st));      /* Avoid UMC varnings */
 
82
#endif
 
83
  rand_st->max_value= 0x3FFFFFFFL;
 
84
  rand_st->max_value_dbl=(double) rand_st->max_value;
 
85
  rand_st->seed1=seed1%rand_st->max_value ;
 
86
  rand_st->seed2=seed2%rand_st->max_value;
 
87
}
 
88
 
 
89
 
 
90
/*
 
91
    Generate random number.
 
92
  SYNOPSIS
 
93
    my_rnd()
 
94
    rand_st    INOUT  Structure used for number generation
 
95
  RETURN VALUE
 
96
    generated pseudo random number
 
97
*/
 
98
 
 
99
double my_rnd(struct rand_struct *rand_st)
 
100
{
 
101
  rand_st->seed1=(rand_st->seed1*3+rand_st->seed2) % rand_st->max_value;
 
102
  rand_st->seed2=(rand_st->seed1+rand_st->seed2+33) % rand_st->max_value;
 
103
  return (((double) rand_st->seed1)/rand_st->max_value_dbl);
 
104
}
 
105
 
 
106
 
 
107
/*
 
108
    Generate binary hash from raw text string 
 
109
    Used for Pre-4.1 password handling
 
110
  SYNOPSIS
 
111
    hash_password()
 
112
    result       OUT store hash in this location
 
113
    password     IN  plain text password to build hash
 
114
    password_len IN  password length (password may be not null-terminated)
 
115
*/
 
116
 
 
117
void hash_password(ulong *result, const char *password, uint password_len)
 
118
{
 
119
  register ulong nr=1345345333L, add=7, nr2=0x12345671L;
 
120
  ulong tmp;
 
121
  const char *password_end= password + password_len;
 
122
  for (; password < password_end; password++)
 
123
  {
 
124
    if (*password == ' ' || *password == '\t')
 
125
      continue;                                 /* skip space in password */
 
126
    tmp= (ulong) (uchar) *password;
 
127
    nr^= (((nr & 63)+add)*tmp)+ (nr << 8);
 
128
    nr2+=(nr2 << 8) ^ nr;
 
129
    add+=tmp;
 
130
  }
 
131
  result[0]=nr & (((ulong) 1L << 31) -1L); /* Don't use sign bit (str2int) */;
 
132
  result[1]=nr2 & (((ulong) 1L << 31) -1L);
 
133
}
 
134
 
 
135
 
 
136
/*
 
137
    Create password to be stored in user database from raw string
 
138
    Used for pre-4.1 password handling
 
139
  SYNOPSIS
 
140
    my_make_scrambled_password_323()
 
141
    to        OUT store scrambled password here
 
142
    password  IN  user-supplied password
 
143
    pass_len  IN  length of password string
 
144
*/
 
145
 
 
146
void my_make_scrambled_password_323(char *to, const char *password,
 
147
                                    size_t pass_len)
 
148
{
 
149
  ulong hash_res[2];
 
150
  hash_password(hash_res, password, (uint) pass_len);
 
151
  sprintf(to, "%08lx%08lx", hash_res[0], hash_res[1]);
 
152
}
 
153
 
 
154
 
 
155
/*
 
156
  Wrapper around my_make_scrambled_password_323() to maintain client lib ABI
 
157
  compatibility.
 
158
  In server code usage of my_make_scrambled_password_323() is preferred to
 
159
  avoid strlen().
 
160
  SYNOPSIS
 
161
    make_scrambled_password_323()
 
162
    to        OUT store scrambled password here
 
163
    password  IN  NULL-terminated string with user-supplied password
 
164
*/
 
165
 
 
166
void make_scrambled_password_323(char *to, const char *password)
 
167
{
 
168
  my_make_scrambled_password_323(to, password, strlen(password));
 
169
}
 
170
 
 
171
 
 
172
/*
 
173
    Scramble string with password.
 
174
    Used in pre 4.1 authentication phase.
 
175
  SYNOPSIS
 
176
    scramble_323()
 
177
    to       OUT Store scrambled message here. Buffer must be at least
 
178
                 SCRAMBLE_LENGTH_323+1 bytes long
 
179
    message  IN  Message to scramble. Message must be at least
 
180
                 SRAMBLE_LENGTH_323 bytes long.
 
181
    password IN  Password to use while scrambling
 
182
*/
 
183
 
 
184
void scramble_323(char *to, const char *message, const char *password)
 
185
{
 
186
  struct rand_struct rand_st;
 
187
  ulong hash_pass[2], hash_message[2];
 
188
 
 
189
  if (password && password[0])
 
190
  {
 
191
    char extra, *to_start=to;
 
192
    const char *message_end= message + SCRAMBLE_LENGTH_323;
 
193
    hash_password(hash_pass,password, (uint) strlen(password));
 
194
    hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
 
195
    randominit(&rand_st,hash_pass[0] ^ hash_message[0],
 
196
               hash_pass[1] ^ hash_message[1]);
 
197
    for (; message < message_end; message++)
 
198
      *to++= (char) (floor(my_rnd(&rand_st)*31)+64);
 
199
    extra=(char) (floor(my_rnd(&rand_st)*31));
 
200
    while (to_start != to)
 
201
      *(to_start++)^=extra;
 
202
  }
 
203
  *to= 0;
 
204
}
 
205
 
 
206
 
 
207
/*
 
208
    Check scrambled message
 
209
    Used in pre 4.1 password handling
 
210
  SYNOPSIS
 
211
    check_scramble_323()
 
212
    scrambled  scrambled message to check.
 
213
    message    original random message which was used for scrambling; must
 
214
               be exactly SCRAMBLED_LENGTH_323 bytes long and
 
215
               NULL-terminated.
 
216
    hash_pass  password which should be used for scrambling
 
217
    All params are IN.
 
218
 
 
219
  RETURN VALUE
 
220
    0 - password correct
 
221
   !0 - password invalid
 
222
*/
 
223
 
 
224
my_bool
 
225
check_scramble_323(const char *scrambled, const char *message,
 
226
                   ulong *hash_pass)
 
227
{
 
228
  struct rand_struct rand_st;
 
229
  ulong hash_message[2];
 
230
  char buff[16],*to,extra;                      /* Big enough for check */
 
231
  const char *pos;
 
232
 
 
233
  hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
 
234
  randominit(&rand_st,hash_pass[0] ^ hash_message[0],
 
235
             hash_pass[1] ^ hash_message[1]);
 
236
  to=buff;
 
237
  DBUG_ASSERT(sizeof(buff) > SCRAMBLE_LENGTH_323);
 
238
  for (pos=scrambled ; *pos && to < buff+sizeof(buff) ; pos++)
 
239
    *to++=(char) (floor(my_rnd(&rand_st)*31)+64);
 
240
  if (pos-scrambled != SCRAMBLE_LENGTH_323)
 
241
    return 1;
 
242
  extra=(char) (floor(my_rnd(&rand_st)*31));
 
243
  to=buff;
 
244
  while (*scrambled)
 
245
  {
 
246
    if (*scrambled++ != (char) (*to++ ^ extra))
 
247
      return 1;                                 /* Wrong password */
 
248
  }
 
249
  return 0;
 
250
}
 
251
 
 
252
static inline uint8 char_val(uint8 X)
 
253
{
 
254
  return (uint) (X >= '0' && X <= '9' ? X-'0' :
 
255
      X >= 'A' && X <= 'Z' ? X-'A'+10 : X-'a'+10);
 
256
}
 
257
 
 
258
 
 
259
/*
 
260
    Convert password from hex string (as stored in mysql.user) to binary form.
 
261
  SYNOPSIS
 
262
    get_salt_from_password_323()
 
263
    res       OUT store salt here 
 
264
    password  IN  password string as stored in mysql.user
 
265
  NOTE
 
266
    This function does not have length check for passwords. It will just crash
 
267
    Password hashes in old format must have length divisible by 8
 
268
*/
 
269
 
 
270
void get_salt_from_password_323(ulong *res, const char *password)
 
271
{
 
272
  res[0]= res[1]= 0;
 
273
  if (password)
 
274
  {
 
275
    while (*password)
 
276
    {
 
277
      ulong val=0;
 
278
      uint i;
 
279
      for (i=0 ; i < 8 ; i++)
 
280
        val=(val << 4)+char_val(*password++);
 
281
      *res++=val;
 
282
    }
 
283
  }
 
284
}
 
285
 
 
286
 
 
287
/*
 
288
    Convert scrambled password from binary form to asciiz hex string.
 
289
  SYNOPSIS
 
290
    make_password_from_salt_323()
 
291
    to    OUT store resulting string password here, at least 17 bytes 
 
292
    salt  IN  password in salt format, 2 ulongs 
 
293
*/
 
294
 
 
295
void make_password_from_salt_323(char *to, const ulong *salt)
 
296
{
 
297
  sprintf(to,"%08lx%08lx", salt[0], salt[1]);
 
298
}
 
299
 
 
300
 
 
301
/*
 
302
     **************** MySQL 4.1.1 authentication routines *************
 
303
*/
 
304
 
 
305
/*
 
306
    Generate string of printable random characters of requested length
 
307
  SYNOPSIS
 
308
    create_random_string()
 
309
    to       OUT   buffer for generation; must be at least length+1 bytes
 
310
                   long; result string is always null-terminated
 
311
    length   IN    how many random characters to put in buffer
 
312
    rand_st  INOUT structure used for number generation
 
313
*/
 
314
 
 
315
void create_random_string(char *to, uint length, struct rand_struct *rand_st)
 
316
{
 
317
  char *end= to + length;
 
318
  /* Use pointer arithmetics as it is faster way to do so. */
 
319
  for (; to < end; to++)
 
320
    *to= (char) (my_rnd(rand_st)*94+33);
 
321
  *to= '\0';
 
322
}
 
323
 
 
324
 
 
325
/* Character to use as version identifier for version 4.1 */
 
326
 
 
327
#define PVERSION41_CHAR '*'
 
328
 
 
329
 
 
330
/*
 
331
    Convert given octet sequence to asciiz string of hex characters;
 
332
    str..str+len and 'to' may not overlap.
 
333
  SYNOPSIS
 
334
    octet2hex()
 
335
    buf       OUT output buffer. Must be at least 2*len+1 bytes
 
336
    str, len  IN  the beginning and the length of the input string
 
337
 
 
338
  RETURN
 
339
    buf+len*2
 
340
*/
 
341
 
 
342
char *octet2hex(char *to, const char *str, uint len)
 
343
{
 
344
  const char *str_end= str + len; 
 
345
  for (; str != str_end; ++str)
 
346
  {
 
347
    *to++= _dig_vec_upper[((uchar) *str) >> 4];
 
348
    *to++= _dig_vec_upper[((uchar) *str) & 0x0F];
 
349
  }
 
350
  *to= '\0';
 
351
  return to;
 
352
}
 
353
 
 
354
 
 
355
/*
 
356
    Convert given asciiz string of hex (0..9 a..f) characters to octet
 
357
    sequence.
 
358
  SYNOPSIS
 
359
    hex2octet()
 
360
    to        OUT buffer to place result; must be at least len/2 bytes
 
361
    str, len  IN  begin, length for character string; str and to may not
 
362
                  overlap; len % 2 == 0
 
363
*/ 
 
364
 
 
365
static void
 
366
hex2octet(uint8 *to, const char *str, uint len)
 
367
{
 
368
  const char *str_end= str + len;
 
369
  while (str < str_end)
 
370
  {
 
371
    register char tmp= char_val(*str++);
 
372
    *to++= (tmp << 4) | char_val(*str++);
 
373
  }
 
374
}
 
375
 
 
376
 
 
377
/*
 
378
    Encrypt/Decrypt function used for password encryption in authentication.
 
379
    Simple XOR is used here but it is OK as we crypt random strings. Note,
 
380
    that XOR(s1, XOR(s1, s2)) == s2, XOR(s1, s2) == XOR(s2, s1)
 
381
  SYNOPSIS
 
382
    my_crypt()
 
383
    to      OUT buffer to hold crypted string; must be at least len bytes
 
384
                long; to and s1 (or s2) may be the same.
 
385
    s1, s2  IN  input strings (of equal length)
 
386
    len     IN  length of s1 and s2
 
387
*/
 
388
 
 
389
static void
 
390
my_crypt(char *to, const uchar *s1, const uchar *s2, uint len)
 
391
{
 
392
  const uint8 *s1_end= s1 + len;
 
393
  while (s1 < s1_end)
 
394
    *to++= *s1++ ^ *s2++;
 
395
}
 
396
 
 
397
 
 
398
/*
 
399
    MySQL 4.1.1 password hashing: SHA conversion (see RFC 2289, 3174) twice
 
400
    applied to the password string, and then produced octet sequence is
 
401
    converted to hex string.
 
402
    The result of this function is used as return value from PASSWORD() and
 
403
    is stored in the database.
 
404
  SYNOPSIS
 
405
    my_make_scrambled_password()
 
406
    buf       OUT buffer of size 2*SHA1_HASH_SIZE + 2 to store hex string
 
407
    password  IN  password string
 
408
    pass_len  IN  length of password string
 
409
*/
 
410
 
 
411
void my_make_scrambled_password(char *to, const char *password,
 
412
                                size_t pass_len)
 
413
{
 
414
  SHA1_CONTEXT sha1_context;
 
415
  uint8 hash_stage2[SHA1_HASH_SIZE];
 
416
 
 
417
  mysql_sha1_reset(&sha1_context);
 
418
  /* stage 1: hash password */
 
419
  mysql_sha1_input(&sha1_context, (uint8 *) password, (uint) pass_len);
 
420
  mysql_sha1_result(&sha1_context, (uint8 *) to);
 
421
  /* stage 2: hash stage1 output */
 
422
  mysql_sha1_reset(&sha1_context);
 
423
  mysql_sha1_input(&sha1_context, (uint8 *) to, SHA1_HASH_SIZE);
 
424
  /* separate buffer is used to pass 'to' in octet2hex */
 
425
  mysql_sha1_result(&sha1_context, hash_stage2);
 
426
  /* convert hash_stage2 to hex string */
 
427
  *to++= PVERSION41_CHAR;
 
428
  octet2hex(to, (const char*) hash_stage2, SHA1_HASH_SIZE);
 
429
}
 
430
  
 
431
 
 
432
/*
 
433
  Wrapper around my_make_scrambled_password() to maintain client lib ABI
 
434
  compatibility.
 
435
  In server code usage of my_make_scrambled_password() is preferred to
 
436
  avoid strlen().
 
437
  SYNOPSIS
 
438
    make_scrambled_password()
 
439
    buf       OUT buffer of size 2*SHA1_HASH_SIZE + 2 to store hex string
 
440
    password  IN  NULL-terminated password string
 
441
*/
 
442
 
 
443
void make_scrambled_password(char *to, const char *password)
 
444
{
 
445
  my_make_scrambled_password(to, password, strlen(password));
 
446
}
 
447
 
 
448
 
 
449
/*
 
450
    Produce an obscure octet sequence from password and random
 
451
    string, recieved from the server. This sequence corresponds to the
 
452
    password, but password can not be easily restored from it. The sequence
 
453
    is then sent to the server for validation. Trailing zero is not stored
 
454
    in the buf as it is not needed.
 
455
    This function is used by client to create authenticated reply to the
 
456
    server's greeting.
 
457
  SYNOPSIS
 
458
    scramble()
 
459
    buf       OUT store scrambled string here. The buf must be at least 
 
460
                  SHA1_HASH_SIZE bytes long. 
 
461
    message   IN  random message, must be exactly SCRAMBLE_LENGTH long and 
 
462
                  NULL-terminated.
 
463
    password  IN  users' password 
 
464
*/
 
465
 
 
466
void
 
467
scramble(char *to, const char *message, const char *password)
 
468
{
 
469
  SHA1_CONTEXT sha1_context;
 
470
  uint8 hash_stage1[SHA1_HASH_SIZE];
 
471
  uint8 hash_stage2[SHA1_HASH_SIZE];
 
472
 
 
473
  mysql_sha1_reset(&sha1_context);
 
474
  /* stage 1: hash password */
 
475
  mysql_sha1_input(&sha1_context, (uint8 *) password, (uint) strlen(password));
 
476
  mysql_sha1_result(&sha1_context, hash_stage1);
 
477
  /* stage 2: hash stage 1; note that hash_stage2 is stored in the database */
 
478
  mysql_sha1_reset(&sha1_context);
 
479
  mysql_sha1_input(&sha1_context, hash_stage1, SHA1_HASH_SIZE);
 
480
  mysql_sha1_result(&sha1_context, hash_stage2);
 
481
  /* create crypt string as sha1(message, hash_stage2) */;
 
482
  mysql_sha1_reset(&sha1_context);
 
483
  mysql_sha1_input(&sha1_context, (const uint8 *) message, SCRAMBLE_LENGTH);
 
484
  mysql_sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE);
 
485
  /* xor allows 'from' and 'to' overlap: lets take advantage of it */
 
486
  mysql_sha1_result(&sha1_context, (uint8 *) to);
 
487
  my_crypt(to, (const uchar *) to, hash_stage1, SCRAMBLE_LENGTH);
 
488
}
 
489
 
 
490
 
 
491
/*
 
492
    Check that scrambled message corresponds to the password; the function
 
493
    is used by server to check that recieved reply is authentic.
 
494
    This function does not check lengths of given strings: message must be
 
495
    null-terminated, reply and hash_stage2 must be at least SHA1_HASH_SIZE
 
496
    long (if not, something fishy is going on).
 
497
  SYNOPSIS
 
498
    check_scramble()
 
499
    scramble     clients' reply, presumably produced by scramble()
 
500
    message      original random string, previously sent to client
 
501
                 (presumably second argument of scramble()), must be 
 
502
                 exactly SCRAMBLE_LENGTH long and NULL-terminated.
 
503
    hash_stage2  hex2octet-decoded database entry
 
504
    All params are IN.
 
505
 
 
506
  RETURN VALUE
 
507
    0  password is correct
 
508
    !0  password is invalid
 
509
*/
 
510
 
 
511
my_bool
 
512
check_scramble(const char *scramble_arg, const char *message,
 
513
               const uint8 *hash_stage2)
 
514
{
 
515
  SHA1_CONTEXT sha1_context;
 
516
  uint8 buf[SHA1_HASH_SIZE];
 
517
  uint8 hash_stage2_reassured[SHA1_HASH_SIZE];
 
518
 
 
519
  mysql_sha1_reset(&sha1_context);
 
520
  /* create key to encrypt scramble */
 
521
  mysql_sha1_input(&sha1_context, (const uint8 *) message, SCRAMBLE_LENGTH);
 
522
  mysql_sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE);
 
523
  mysql_sha1_result(&sha1_context, buf);
 
524
  /* encrypt scramble */
 
525
    my_crypt((char *) buf, buf, (const uchar *) scramble_arg, SCRAMBLE_LENGTH);
 
526
  /* now buf supposedly contains hash_stage1: so we can get hash_stage2 */
 
527
  mysql_sha1_reset(&sha1_context);
 
528
  mysql_sha1_input(&sha1_context, buf, SHA1_HASH_SIZE);
 
529
  mysql_sha1_result(&sha1_context, hash_stage2_reassured);
 
530
  return memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE);
 
531
}
 
532
 
 
533
 
 
534
/*
 
535
  Convert scrambled password from asciiz hex string to binary form.
 
536
 
 
537
  SYNOPSIS
 
538
    get_salt_from_password()
 
539
    res       OUT buf to hold password. Must be at least SHA1_HASH_SIZE
 
540
                  bytes long.
 
541
    password  IN  4.1.1 version value of user.password
 
542
*/
 
543
    
 
544
void get_salt_from_password(uint8 *hash_stage2, const char *password)
 
545
{
 
546
  hex2octet(hash_stage2, password+1 /* skip '*' */, SHA1_HASH_SIZE * 2);
 
547
}
 
548
 
 
549
/*
 
550
    Convert scrambled password from binary form to asciiz hex string.
 
551
  SYNOPSIS
 
552
    make_password_from_salt()
 
553
    to    OUT store resulting string here, 2*SHA1_HASH_SIZE+2 bytes 
 
554
    salt  IN  password in salt format
 
555
*/
 
556
 
 
557
void make_password_from_salt(char *to, const uint8 *hash_stage2)
 
558
{
 
559
  *to++= PVERSION41_CHAR;
 
560
  octet2hex(to, (const char*) hash_stage2, SHA1_HASH_SIZE);
 
561
}