~ubuntu-branches/ubuntu/trusty/mariadb-5.5/trusty-proposed

« back to all changes in this revision

Viewing changes to sql/password.c

  • Committer: Package Import Robot
  • Author(s): Otto Kekäläinen
  • Date: 2013-12-22 10:27:05 UTC
  • Revision ID: package-import@ubuntu.com-20131222102705-mndw7s12mz0szrcn
Tags: upstream-5.5.32
Import upstream version 5.5.32

Show diffs side-by-side

added added

removed removed

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