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