password.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:16k
源码类别:

MySQL数据库

开发平台:

Visual C++

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