1 /*
2    Copyright (c) 2000, 2021, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    Without limiting anything contained in the foregoing, this file,
16    which is part of C Driver for MySQL (Connector/C), is also subject to the
17    Universal FOSS Exception, version 1.0, a copy of which can be found at
18    http://oss.oracle.com/licenses/universal-foss-exception.
19 
20    This program is distributed in the hope that it will be useful,
21    but WITHOUT ANY WARRANTY; without even the implied warranty of
22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23    GNU General Public License, version 2.0, for more details.
24 
25    You should have received a copy of the GNU General Public License
26    along with this program; if not, write to the Free Software
27    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
28 
29 /* password checking routines */
30 /*****************************************************************************
31   The main idea is that no password are sent between client & server on
32   connection and that no password are saved in mysql in a decodable form.
33 
34   On connection a random string is generated and sent to the client.
35   The client generates a new string with a random generator inited with
36   the hash values from the password and the sent string.
37   This 'check' string is sent to the server where it is compared with
38   a string generated from the stored hash_value of the password and the
39   random string.
40 
41   The password is saved (in user.password) by using the PASSWORD() function in
42   mysql.
43 
44   This is .c file because it's used in libperconaserverclient, which is entirely in C.
45   (we need it to be portable to a variety of systems).
46   Example:
47     update user set password=PASSWORD("hello") where user="test"
48   This saves a hashed number as a string in the password field.
49 
50   The new authentication is performed in following manner:
51 
52   SERVER:  public_seed=generate_user_salt()
53            send(public_seed)
54 
55   CLIENT:  recv(public_seed)
56            hash_stage1=sha1("password")
57            hash_stage2=sha1(hash_stage1)
58            reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
59 
60            // this three steps are done in scramble()
61 
62            send(reply)
63 
64 
65   SERVER:  recv(reply)
66            hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
67            candidate_hash2=sha1(hash_stage1)
68            check(candidate_hash2==hash_stage2)
69 
70            // this three steps are done in check_scramble()
71 
72 *****************************************************************************/
73 
74 #include <password.h>
75 #include <my_global.h>
76 #include <my_sys.h>
77 #include <m_string.h>
78 #include <sha1.h>
79 #include <my_rnd.h>
80 #include "mysql.h"
81 #include "crypt_genhash_impl.h"
82 
randominit(struct rand_struct * rand_st,ulong seed1,ulong seed2)83 void randominit(struct rand_struct *rand_st, ulong seed1, ulong seed2)
84 {                                               /* For mysql 3.21.# */
85   rand_st->max_value= 0x3FFFFFFFL;
86   rand_st->max_value_dbl=(double) rand_st->max_value;
87   rand_st->seed1=seed1%rand_st->max_value ;
88   rand_st->seed2=seed2%rand_st->max_value;
89 }
90 
91 /*
92     Generate binary hash from raw text string
93     Used for Pre-4.1 password handling
94   SYNOPSIS
95     hash_password()
96     result       OUT store hash in this location
97     password     IN  plain text password to build hash
98     password_len IN  password length (password may be not null-terminated)
99 */
100 
hash_password(ulong * result,const char * password,uint password_len)101 void hash_password(ulong *result, const char *password, uint password_len)
102 {
103   ulong nr=1345345333L, add=7, nr2=0x12345671L;
104   ulong tmp;
105   const char *password_end= password + password_len;
106   for (; password < password_end; password++)
107   {
108     if (*password == ' ' || *password == '\t')
109       continue;                                 /* skip space in password */
110     tmp= (ulong) (uchar) *password;
111     nr^= (((nr & 63)+add)*tmp)+ (nr << 8);
112     nr2+=(nr2 << 8) ^ nr;
113     add+=tmp;
114   }
115   result[0]=nr & (((ulong) 1L << 31) -1L); /* Don't use sign bit (str2int) */;
116   result[1]=nr2 & (((ulong) 1L << 31) -1L);
117 }
118 
char_val(uint8 X)119 static inline uint8 char_val(uint8 X)
120 {
121   return (uint) (X >= '0' && X <= '9' ? X - '0' :
122                  X >= 'A' && X <= 'Z' ? X - 'A' + 10 : X - 'a' + 10);
123 }
124 
125 /* Character to use as version identifier for version 4.1 */
126 
127 #define PVERSION41_CHAR '*'
128 
129 
130 /*
131     Convert given octet sequence to asciiz string of hex characters;
132     str..str+len and 'to' may not overlap.
133   SYNOPSIS
134     octet2hex()
135     buf       OUT output buffer. Must be at least 2*len+1 bytes
136     str, len  IN  the beginning and the length of the input string
137 
138   RETURN
139     buf+len*2
140 */
141 
octet2hex(char * to,const char * str,uint len)142 char *octet2hex(char *to, const char *str, uint len)
143 {
144   const char *str_end= str + len;
145   for (; str != str_end; ++str)
146   {
147     *to++= _dig_vec_upper[((uchar) *str) >> 4];
148     *to++= _dig_vec_upper[((uchar) *str) & 0x0F];
149   }
150   *to= '\0';
151   return to;
152 }
153 
154 
155 /*
156     Convert given asciiz string of hex (0..9 a..f) characters to octet
157     sequence.
158   SYNOPSIS
159     hex2octet()
160     to        OUT buffer to place result; must be at least len/2 bytes
161     str, len  IN  begin, length for character string; str and to may not
162                   overlap; len % 2 == 0
163 */
164 
165 static void
hex2octet(uint8 * to,const char * str,uint len)166 hex2octet(uint8 *to, const char *str, uint len)
167 {
168   const char *str_end= str + len;
169   while (str < str_end)
170   {
171     char tmp= char_val(*str++);
172     *to++= (tmp << 4) | char_val(*str++);
173   }
174 }
175 
176 
177 /*
178     Encrypt/Decrypt function used for password encryption in authentication.
179     Simple XOR is used here but it is OK as we crypt random strings. Note,
180     that XOR(s1, XOR(s1, s2)) == s2, XOR(s1, s2) == XOR(s2, s1)
181   SYNOPSIS
182     my_crypt()
183     to      OUT buffer to hold crypted string; must be at least len bytes
184                 long; to and s1 (or s2) may be the same.
185     s1, s2  IN  input strings (of equal length)
186     len     IN  length of s1 and s2
187 */
188 
189 static void
my_crypt(char * to,const uchar * s1,const uchar * s2,uint len)190 my_crypt(char *to, const uchar *s1, const uchar *s2, uint len)
191 {
192   const uint8 *s1_end= s1 + len;
193   while (s1 < s1_end)
194     *to++= *s1++ ^ *s2++;
195 }
196 
197 #if defined(HAVE_OPENSSL)
my_make_scrambled_password(char * to,const char * password,size_t pass_len)198 void my_make_scrambled_password(char *to, const char *password,
199                                 size_t pass_len)
200 {
201 
202   char salt[CRYPT_SALT_LENGTH + 1];
203 
204   generate_user_salt(salt, CRYPT_SALT_LENGTH + 1);
205   my_crypt_genhash(to,
206                      CRYPT_MAX_PASSWORD_SIZE,
207                      password,
208                      pass_len,
209                      salt,
210                      0);
211 
212 }
213 #endif
214 /**
215   Compute two stage SHA1 hash of the password :
216 
217     hash_stage1=sha1("password")
218     hash_stage2=sha1(hash_stage1)
219 
220   @param password    [IN]   Password string.
221   @param pass_len    [IN]   Length of the password.
222   @param hash_stage1 [OUT]  sha1(password)
223   @param hash_stage2 [OUT]  sha1(hash_stage1)
224 */
225 
226 inline static
compute_two_stage_sha1_hash(const char * password,size_t pass_len,uint8 * hash_stage1,uint8 * hash_stage2)227 void compute_two_stage_sha1_hash(const char *password, size_t pass_len,
228                                  uint8 *hash_stage1, uint8 *hash_stage2)
229 {
230   /* Stage 1: hash password */
231   compute_sha1_hash(hash_stage1, password, pass_len);
232 
233   /* Stage 2 : hash first stage's output. */
234   compute_sha1_hash(hash_stage2, (const char *) hash_stage1, SHA1_HASH_SIZE);
235 }
236 
237 
238 /*
239     MySQL 4.1.1 password hashing: SHA conversion (see RFC 2289, 3174) twice
240     applied to the password string, and then produced octet sequence is
241     converted to hex string.
242     The result of this function is used as return value from PASSWORD() and
243     is stored in the database.
244   SYNOPSIS
245     my_make_scrambled_password_sha1()
246     buf       OUT buffer of size 2*SHA1_HASH_SIZE + 2 to store hex string
247     password  IN  password string
248     pass_len  IN  length of password string
249 */
250 
my_make_scrambled_password_sha1(char * to,const char * password,size_t pass_len)251 void my_make_scrambled_password_sha1(char *to, const char *password,
252                                      size_t pass_len)
253 {
254   uint8 hash_stage2[SHA1_HASH_SIZE];
255 
256   /* Two stage SHA1 hash of the password. */
257   compute_two_stage_sha1_hash(password, pass_len, (uint8 *) to, hash_stage2);
258 
259   /* convert hash_stage2 to hex string */
260   *to++= PVERSION41_CHAR;
261   octet2hex(to, (const char*) hash_stage2, SHA1_HASH_SIZE);
262 }
263 
264 
265 /*
266   Wrapper around my_make_scrambled_password() to maintain client lib ABI
267   compatibility.
268   In server code usage of my_make_scrambled_password() is preferred to
269   avoid strlen().
270   SYNOPSIS
271     make_scrambled_password()
272     buf       OUT buffer of size 2*SHA1_HASH_SIZE + 2 to store hex string
273     password  IN  NULL-terminated password string
274 */
275 
make_scrambled_password(char * to,const char * password)276 void make_scrambled_password(char *to, const char *password)
277 {
278   my_make_scrambled_password_sha1(to, password, strlen(password));
279 }
280 
281 
282 /*
283     Produce an obscure octet sequence from password and random
284     string, received from the server. This sequence corresponds to the
285     password, but password can not be easily restored from it. The sequence
286     is then sent to the server for validation. Trailing zero is not stored
287     in the buf as it is not needed.
288     This function is used by client to create authenticated reply to the
289     server's greeting.
290   SYNOPSIS
291     scramble()
292     buf       OUT store scrambled string here. The buf must be at least
293                   SHA1_HASH_SIZE bytes long.
294     message   IN  random message, must be exactly SCRAMBLE_LENGTH long and
295                   NULL-terminated.
296     password  IN  users' password
297 */
298 
299 void
scramble(char * to,const char * message,const char * password)300 scramble(char *to, const char *message, const char *password)
301 {
302   uint8 hash_stage1[SHA1_HASH_SIZE];
303   uint8 hash_stage2[SHA1_HASH_SIZE];
304 
305   /* Two stage SHA1 hash of the password. */
306   compute_two_stage_sha1_hash(password, strlen(password), hash_stage1,
307                               hash_stage2);
308 
309   /* create crypt string as sha1(message, hash_stage2) */;
310   compute_sha1_hash_multi((uint8 *) to, message, SCRAMBLE_LENGTH,
311                           (const char *) hash_stage2, SHA1_HASH_SIZE);
312   my_crypt(to, (const uchar *) to, hash_stage1, SCRAMBLE_LENGTH);
313 }
314 
315 
316 /*
317     Check that scrambled message corresponds to the password; the function
318     is used by server to check that received reply is authentic.
319     This function does not check lengths of given strings: message must be
320     null-terminated, reply and hash_stage2 must be at least SHA1_HASH_SIZE
321     long (if not, something fishy is going on).
322   SYNOPSIS
323     check_scramble_sha1()
324     scramble     clients' reply, presumably produced by scramble()
325     message      original random string, previously sent to client
326                  (presumably second argument of scramble()), must be
327                  exactly SCRAMBLE_LENGTH long and NULL-terminated.
328     hash_stage2  hex2octet-decoded database entry
329     All params are IN.
330 
331   RETURN VALUE
332     0  password is correct
333     !0  password is invalid
334 */
335 
336 my_bool
check_scramble_sha1(const uchar * scramble_arg,const char * message,const uint8 * hash_stage2)337 check_scramble_sha1(const uchar *scramble_arg, const char *message,
338                     const uint8 *hash_stage2)
339 {
340   uint8 buf[SHA1_HASH_SIZE];
341   uint8 hash_stage2_reassured[SHA1_HASH_SIZE];
342 
343   /* create key to encrypt scramble */
344   compute_sha1_hash_multi(buf, message, SCRAMBLE_LENGTH,
345                           (const char *) hash_stage2, SHA1_HASH_SIZE);
346   /* encrypt scramble */
347   my_crypt((char *) buf, buf, scramble_arg, SCRAMBLE_LENGTH);
348 
349   /* now buf supposedly contains hash_stage1: so we can get hash_stage2 */
350   compute_sha1_hash(hash_stage2_reassured, (const char *) buf, SHA1_HASH_SIZE);
351 
352   return MY_TEST(memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE));
353 }
354 
355 my_bool
check_scramble(const uchar * scramble_arg,const char * message,const uint8 * hash_stage2)356 check_scramble(const uchar *scramble_arg, const char *message,
357                const uint8 *hash_stage2)
358 {
359   return check_scramble_sha1(scramble_arg, message, hash_stage2);
360 }
361 
362 /*
363   Convert scrambled password from asciiz hex string to binary form.
364 
365   SYNOPSIS
366     get_salt_from_password()
367     res       OUT buf to hold password. Must be at least SHA1_HASH_SIZE
368                   bytes long.
369     password  IN  4.1.1 version value of user.password
370 */
371 
get_salt_from_password(uint8 * hash_stage2,const char * password)372 void get_salt_from_password(uint8 *hash_stage2, const char *password)
373 {
374   hex2octet(hash_stage2, password+1 /* skip '*' */, SHA1_HASH_SIZE * 2);
375 }
376 
377 /*
378     Convert scrambled password from binary form to asciiz hex string.
379   SYNOPSIS
380     make_password_from_salt()
381     to    OUT store resulting string here, 2*SHA1_HASH_SIZE+2 bytes
382     salt  IN  password in salt format
383 */
384 
make_password_from_salt(char * to,const uint8 * hash_stage2)385 void make_password_from_salt(char *to, const uint8 *hash_stage2)
386 {
387   *to++= PVERSION41_CHAR;
388   octet2hex(to, (const char*) hash_stage2, SHA1_HASH_SIZE);
389 }
390 
391