Style fixes, comments for 4.1.1 authorization
Now special 1-byte packet is used for request of old password Fixed bug with --skip-grant-tables and acl_getroot
This commit is contained in:
parent
d90129d1e9
commit
09e53b0169
@ -228,8 +228,8 @@ typedef struct st_mysql
|
|||||||
my_bool free_me; /* If free in mysql_close */
|
my_bool free_me; /* If free in mysql_close */
|
||||||
my_bool reconnect; /* set to 1 if automatic reconnect */
|
my_bool reconnect; /* set to 1 if automatic reconnect */
|
||||||
|
|
||||||
char scramble[SCRAMBLE_LENGTH+1]; /* for new servers */
|
/* session-wide random string */
|
||||||
char scramble_323[SCRAMBLE_LENGTH_323+1]; /* for old servers */
|
char scramble[max(SCRAMBLE_LENGTH,SCRAMBLE_LENGTH_323)+1];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Set if this is the original connection, not a master or a slave we have
|
Set if this is the original connection, not a master or a slave we have
|
||||||
|
@ -318,9 +318,9 @@ void randominit(struct rand_struct *, unsigned long seed1,
|
|||||||
double my_rnd(struct rand_struct *);
|
double my_rnd(struct rand_struct *);
|
||||||
void create_random_string(char *to, uint length, struct rand_struct *rand_st);
|
void create_random_string(char *to, uint length, struct rand_struct *rand_st);
|
||||||
|
|
||||||
void hash_password(ulong *to, const char *password);
|
void hash_password(ulong *to, const char *password, uint password_len);
|
||||||
void make_scrambled_password_323(char *to, const char *password);
|
void make_scrambled_password_323(char *to, const char *password);
|
||||||
char *scramble_323(char *to, const char *message, const char *password);
|
void scramble_323(char *to, const char *message, const char *password);
|
||||||
my_bool check_scramble_323(const char *, const char *message,
|
my_bool check_scramble_323(const char *, const char *message,
|
||||||
unsigned long *salt);
|
unsigned long *salt);
|
||||||
void get_salt_from_password_323(unsigned long *res, const char *password);
|
void get_salt_from_password_323(unsigned long *res, const char *password);
|
||||||
|
@ -626,7 +626,10 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
|
|||||||
end+= SCRAMBLE_LENGTH;
|
end+= SCRAMBLE_LENGTH;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
end= scramble_323(end, mysql->scramble_323, passwd);
|
{
|
||||||
|
scramble_323(end, mysql->scramble, passwd);
|
||||||
|
end+= SCRAMBLE_LENGTH_323 + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*end++= '\0'; // empty password
|
*end++= '\0'; // empty password
|
||||||
@ -642,15 +645,14 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
|
|||||||
if (pkt_length == packet_error)
|
if (pkt_length == packet_error)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (net->read_pos[0] == mysql->scramble_323[0] &&
|
if (pkt_length == 1 && net->read_pos[0] == 254 &&
|
||||||
pkt_length == SCRAMBLE_LENGTH_323 + 1 &&
|
|
||||||
mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
|
mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
By sending this very specific reply server asks us to send scrambled
|
By sending this very specific reply server asks us to send scrambled
|
||||||
password in old format. The reply contains scramble_323.
|
password in old format. The reply contains scramble_323.
|
||||||
*/
|
*/
|
||||||
scramble_323(buff, mysql->scramble_323, passwd);
|
scramble_323(buff, mysql->scramble, passwd);
|
||||||
if (my_net_write(net, buff, SCRAMBLE_LENGTH_323 + 1) || net_flush(net))
|
if (my_net_write(net, buff, SCRAMBLE_LENGTH_323 + 1) || net_flush(net))
|
||||||
{
|
{
|
||||||
net->last_errno= CR_SERVER_LOST;
|
net->last_errno= CR_SERVER_LOST;
|
||||||
|
@ -1641,9 +1641,8 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
|
|||||||
Scramble is split into two parts because old clients does not understand
|
Scramble is split into two parts because old clients does not understand
|
||||||
long scrambles; here goes the first part.
|
long scrambles; here goes the first part.
|
||||||
*/
|
*/
|
||||||
strmake(mysql->scramble_323, end, SCRAMBLE_LENGTH_323);
|
strmake(mysql->scramble, end, SCRAMBLE_LENGTH_323);
|
||||||
end+= SCRAMBLE_LENGTH_323+1;
|
end+= SCRAMBLE_LENGTH_323+1;
|
||||||
memcpy(mysql->scramble, mysql->scramble_323, SCRAMBLE_LENGTH_323);
|
|
||||||
|
|
||||||
if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
|
if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
|
||||||
mysql->server_capabilities=uint2korr(end);
|
mysql->server_capabilities=uint2korr(end);
|
||||||
@ -1842,7 +1841,10 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
|
|||||||
end+= SCRAMBLE_LENGTH;
|
end+= SCRAMBLE_LENGTH;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
end= scramble_323(end, mysql->scramble_323, passwd) + 1;
|
{
|
||||||
|
scramble_323(end, mysql->scramble, passwd);
|
||||||
|
end+= SCRAMBLE_LENGTH_323 + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*end++= '\0'; /* empty password */
|
*end++= '\0'; /* empty password */
|
||||||
@ -1871,15 +1873,14 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
|
|||||||
if ((pkt_length=net_safe_read(mysql)) == packet_error)
|
if ((pkt_length=net_safe_read(mysql)) == packet_error)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (net->read_pos[0] == mysql->scramble_323[0] &&
|
if (pkt_length == 1 && net->read_pos[0] == 254 &&
|
||||||
pkt_length == SCRAMBLE_LENGTH_323 + 1 &&
|
|
||||||
mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
|
mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
By sending this very specific reply server asks us to send scrambled
|
By sending this very specific reply server asks us to send scrambled
|
||||||
password in old format. The reply contains scramble_323.
|
password in old format. The reply contains scramble_323.
|
||||||
*/
|
*/
|
||||||
scramble_323(buff, mysql->scramble_323, passwd);
|
scramble_323(buff, mysql->scramble, passwd);
|
||||||
if (my_net_write(net, buff, SCRAMBLE_LENGTH_323 + 1) || net_flush(net))
|
if (my_net_write(net, buff, SCRAMBLE_LENGTH_323 + 1) || net_flush(net))
|
||||||
{
|
{
|
||||||
net->last_errno= CR_SERVER_LOST;
|
net->last_errno= CR_SERVER_LOST;
|
||||||
|
@ -110,15 +110,17 @@ double my_rnd(struct rand_struct *rand_st)
|
|||||||
Used for Pre-4.1 password handling
|
Used for Pre-4.1 password handling
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
hash_password()
|
hash_password()
|
||||||
result OUT store hash in this location
|
result OUT store hash in this location
|
||||||
password IN plain text password to build hash
|
password IN plain text password to build hash
|
||||||
|
password_len IN password length (password may be not null-terminated)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void hash_password(ulong *result, const char *password)
|
void hash_password(ulong *result, const char *password, uint password_len)
|
||||||
{
|
{
|
||||||
register ulong nr=1345345333L, add=7, nr2=0x12345671L;
|
register ulong nr=1345345333L, add=7, nr2=0x12345671L;
|
||||||
ulong tmp;
|
ulong tmp;
|
||||||
for (; *password ; password++)
|
const char *password_end= password + password_len;
|
||||||
|
for (; password < password_end; password++)
|
||||||
{
|
{
|
||||||
if (*password == ' ' || *password == '\t')
|
if (*password == ' ' || *password == '\t')
|
||||||
continue; /* skip space in password */
|
continue; /* skip space in password */
|
||||||
@ -129,7 +131,6 @@ void hash_password(ulong *result, const char *password)
|
|||||||
}
|
}
|
||||||
result[0]=nr & (((ulong) 1L << 31) -1L); /* Don't use sign bit (str2int) */;
|
result[0]=nr & (((ulong) 1L << 31) -1L); /* Don't use sign bit (str2int) */;
|
||||||
result[1]=nr2 & (((ulong) 1L << 31) -1L);
|
result[1]=nr2 & (((ulong) 1L << 31) -1L);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -145,7 +146,7 @@ void hash_password(ulong *result, const char *password)
|
|||||||
void make_scrambled_password_323(char *to, const char *password)
|
void make_scrambled_password_323(char *to, const char *password)
|
||||||
{
|
{
|
||||||
ulong hash_res[2];
|
ulong hash_res[2];
|
||||||
hash_password(hash_res, password);
|
hash_password(hash_res, password, strlen(password));
|
||||||
sprintf(to, "%08lx%08lx", hash_res[0], hash_res[1]);
|
sprintf(to, "%08lx%08lx", hash_res[0], hash_res[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,14 +158,12 @@ void make_scrambled_password_323(char *to, const char *password)
|
|||||||
scramble_323()
|
scramble_323()
|
||||||
to OUT Store scrambled message here. Buffer must be at least
|
to OUT Store scrambled message here. Buffer must be at least
|
||||||
SCRAMBLE_LENGTH_323+1 bytes long
|
SCRAMBLE_LENGTH_323+1 bytes long
|
||||||
message IN Message to scramble. Message must be exactly
|
message IN Message to scramble. Message must be at least
|
||||||
SRAMBLE_LENGTH_323 long and NULL terminated.
|
SRAMBLE_LENGTH_323 bytes long.
|
||||||
password IN Password to use while scrambling
|
password IN Password to use while scrambling
|
||||||
RETURN
|
|
||||||
End of scrambled string
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *scramble_323(char *to, const char *message, const char *password)
|
void scramble_323(char *to, const char *message, const char *password)
|
||||||
{
|
{
|
||||||
struct rand_struct rand_st;
|
struct rand_struct rand_st;
|
||||||
ulong hash_pass[2], hash_message[2];
|
ulong hash_pass[2], hash_message[2];
|
||||||
@ -172,18 +171,18 @@ char *scramble_323(char *to, const char *message, const char *password)
|
|||||||
if (password && password[0])
|
if (password && password[0])
|
||||||
{
|
{
|
||||||
char *to_start=to;
|
char *to_start=to;
|
||||||
hash_password(hash_pass,password);
|
hash_password(hash_pass,password, strlen(password));
|
||||||
hash_password(hash_message, message);
|
hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
|
||||||
randominit(&rand_st,hash_pass[0] ^ hash_message[0],
|
randominit(&rand_st,hash_pass[0] ^ hash_message[0],
|
||||||
hash_pass[1] ^ hash_message[1]);
|
hash_pass[1] ^ hash_message[1]);
|
||||||
while (*message++)
|
const char *message_end= message + SCRAMBLE_LENGTH_323;
|
||||||
|
for (; message < message_end; message++)
|
||||||
*to++= (char) (floor(my_rnd(&rand_st)*31)+64);
|
*to++= (char) (floor(my_rnd(&rand_st)*31)+64);
|
||||||
char extra=(char) (floor(my_rnd(&rand_st)*31));
|
char extra=(char) (floor(my_rnd(&rand_st)*31));
|
||||||
while (to_start != to)
|
while (to_start != to)
|
||||||
*(to_start++)^=extra;
|
*(to_start++)^=extra;
|
||||||
}
|
}
|
||||||
*to= 0;
|
*to= 0;
|
||||||
return to;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -192,11 +191,13 @@ char *scramble_323(char *to, const char *message, const char *password)
|
|||||||
Used in pre 4.1 password handling
|
Used in pre 4.1 password handling
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
check_scramble_323()
|
check_scramble_323()
|
||||||
scrambled IN scrambled message to check.
|
scrambled scrambled message to check.
|
||||||
message IN original random message which was used for scrambling; must
|
message original random message which was used for scrambling; must
|
||||||
be exactly SCRAMBLED_LENGTH_323 bytes long and
|
be exactly SCRAMBLED_LENGTH_323 bytes long and
|
||||||
NULL-terminated.
|
NULL-terminated.
|
||||||
hash_pass IN password which should be used for scrambling
|
hash_pass password which should be used for scrambling
|
||||||
|
All params are IN.
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
0 - password correct
|
0 - password correct
|
||||||
!0 - password invalid
|
!0 - password invalid
|
||||||
@ -211,11 +212,7 @@ check_scramble_323(const char *scrambled, const char *message,
|
|||||||
char buff[16],*to,extra; /* Big enough for check */
|
char buff[16],*to,extra; /* Big enough for check */
|
||||||
const char *pos;
|
const char *pos;
|
||||||
|
|
||||||
/* Check if this exactly N bytes. Overwise this is something fishy */
|
hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
|
||||||
if (strlen(message) != SCRAMBLE_LENGTH_323)
|
|
||||||
return 1; /* Wrong password */
|
|
||||||
|
|
||||||
hash_password(hash_message,message);
|
|
||||||
randominit(&rand_st,hash_pass[0] ^ hash_message[0],
|
randominit(&rand_st,hash_pass[0] ^ hash_message[0],
|
||||||
hash_pass[1] ^ hash_message[1]);
|
hash_pass[1] ^ hash_message[1]);
|
||||||
to=buff;
|
to=buff;
|
||||||
@ -231,7 +228,7 @@ check_scramble_323(const char *scrambled, const char *message,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8 char_val(uint8 X)
|
static inline uint8 char_val(uint8 X)
|
||||||
{
|
{
|
||||||
return (uint) (X >= '0' && X <= '9' ? X-'0' :
|
return (uint) (X >= '0' && X <= '9' ? X-'0' :
|
||||||
X >= 'A' && X <= 'Z' ? X-'A'+10 : X-'a'+10);
|
X >= 'A' && X <= 'Z' ? X-'A'+10 : X-'a'+10);
|
||||||
@ -280,7 +277,10 @@ void make_password_from_salt_323(char *to, const ulong *salt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************* MySQL 4.1.1 authentification routines ******************/
|
/*
|
||||||
|
**************** MySQL 4.1.1 authentification routines *************
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Generate string of printable random characters of requested length
|
Generate string of printable random characters of requested length
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
@ -315,19 +315,16 @@ void create_random_string(char *to, uint length, struct rand_struct *rand_st)
|
|||||||
str, len IN the beginning and the length of the input string
|
str, len IN the beginning and the length of the input string
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static
|
static void
|
||||||
void
|
|
||||||
octet2hex(char *to, const uint8 *str, uint len)
|
octet2hex(char *to, const uint8 *str, uint len)
|
||||||
{
|
{
|
||||||
static const char alphabet[] = { '0', '1', '2', '3', '4', '5', '6', '7',
|
|
||||||
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
|
||||||
const uint8 *str_end= str + len;
|
const uint8 *str_end= str + len;
|
||||||
for (; str != str_end; ++str)
|
for (; str != str_end; ++str)
|
||||||
{
|
{
|
||||||
*to++= alphabet[(*str & 0xF0) >> 4];
|
*to++= _dig_vec[(*str & 0xF0) >> 4];
|
||||||
*to++= alphabet[*str & 0x0F];
|
*to++= _dig_vec[*str & 0x0F];
|
||||||
}
|
}
|
||||||
*to++= '\0';
|
*to= '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -341,15 +338,14 @@ octet2hex(char *to, const uint8 *str, uint len)
|
|||||||
overlap; len % 2 == 0
|
overlap; len % 2 == 0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static
|
static void
|
||||||
void
|
|
||||||
hex2octet(uint8 *to, const char *str, uint len)
|
hex2octet(uint8 *to, const char *str, uint len)
|
||||||
{
|
{
|
||||||
const char *str_end= str + len;
|
const char *str_end= str + len;
|
||||||
while (str < str_end)
|
while (str < str_end)
|
||||||
{
|
{
|
||||||
*to= char_val(*str++) << 4;
|
register char tmp= char_val(*str++);
|
||||||
*to++|= char_val(*str++);
|
*to++= (tmp << 4) | char_val(*str++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,9 +362,8 @@ hex2octet(uint8 *to, const char *str, uint len)
|
|||||||
len IN length of s1 and s2
|
len IN length of s1 and s2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static
|
static void
|
||||||
void
|
my_crypt(char *to, const uchar *s1, const uchar *s2, uint len)
|
||||||
my_crypt(char *to, const uint8 *s1, const uint8 *s2, uint len)
|
|
||||||
{
|
{
|
||||||
const uint8 *s1_end= s1 + len;
|
const uint8 *s1_end= s1 + len;
|
||||||
while (s1 < s1_end)
|
while (s1 < s1_end)
|
||||||
@ -447,7 +442,7 @@ scramble(char *to, const char *message, const char *password)
|
|||||||
sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE);
|
sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE);
|
||||||
/* xor allows 'from' and 'to' overlap: lets take advantage of it */
|
/* xor allows 'from' and 'to' overlap: lets take advantage of it */
|
||||||
sha1_result(&sha1_context, (uint8 *) to);
|
sha1_result(&sha1_context, (uint8 *) to);
|
||||||
my_crypt(to, (const uint8 *) to, hash_stage1, SCRAMBLE_LENGTH);
|
my_crypt(to, (const uchar *) to, hash_stage1, SCRAMBLE_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -459,11 +454,13 @@ scramble(char *to, const char *message, const char *password)
|
|||||||
long (if not, something fishy is going on).
|
long (if not, something fishy is going on).
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
check_scramble()
|
check_scramble()
|
||||||
scramble IN clients' reply, presumably produced by scramble()
|
scramble clients' reply, presumably produced by scramble()
|
||||||
message IN original random string, previously sent to client
|
message original random string, previously sent to client
|
||||||
(presumably second argument of scramble()), must be
|
(presumably second argument of scramble()), must be
|
||||||
exactly SCRAMBLE_LENGTH long and NULL-terminated.
|
exactly SCRAMBLE_LENGTH long and NULL-terminated.
|
||||||
hash_stage2 IN hex2octet-decoded database entry
|
hash_stage2 hex2octet-decoded database entry
|
||||||
|
All params are IN.
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
0 password is correct
|
0 password is correct
|
||||||
!0 password is invalid
|
!0 password is invalid
|
||||||
@ -483,7 +480,7 @@ check_scramble(const char *scramble, const char *message,
|
|||||||
sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE);
|
sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE);
|
||||||
sha1_result(&sha1_context, buf);
|
sha1_result(&sha1_context, buf);
|
||||||
/* encrypt scramble */
|
/* encrypt scramble */
|
||||||
my_crypt((char *) buf, buf, (const uint8 *) scramble, SCRAMBLE_LENGTH);
|
my_crypt((char *) buf, buf, (const uchar *) scramble, SCRAMBLE_LENGTH);
|
||||||
/* now buf supposedly contains hash_stage1: so we can get hash_stage2 */
|
/* now buf supposedly contains hash_stage1: so we can get hash_stage2 */
|
||||||
sha1_reset(&sha1_context);
|
sha1_reset(&sha1_context);
|
||||||
sha1_input(&sha1_context, buf, SHA1_HASH_SIZE);
|
sha1_input(&sha1_context, buf, SHA1_HASH_SIZE);
|
||||||
|
@ -348,6 +348,25 @@ send_eof(THD *thd, bool no_flush)
|
|||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Please client to send scrambled_password in old format.
|
||||||
|
SYNOPSYS
|
||||||
|
send_old_password_request()
|
||||||
|
thd thread handle
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
0 ok
|
||||||
|
!0 error
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool send_old_password_request(THD *thd)
|
||||||
|
{
|
||||||
|
static char buff[1]= { (char) 254 };
|
||||||
|
NET *net= &thd->net;
|
||||||
|
return my_net_write(net, buff, 1) || net_flush(net);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* EMBEDDED_LIBRARY */
|
#endif /* EMBEDDED_LIBRARY */
|
||||||
|
|
||||||
|
|
||||||
|
@ -164,6 +164,7 @@ void net_printf(THD *thd,uint sql_errno, ...);
|
|||||||
void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L,
|
void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L,
|
||||||
const char *info=0);
|
const char *info=0);
|
||||||
void send_eof(THD *thd, bool no_flush=0);
|
void send_eof(THD *thd, bool no_flush=0);
|
||||||
|
bool send_old_password_request(THD *thd);
|
||||||
char *net_store_length(char *packet,ulonglong length);
|
char *net_store_length(char *packet,ulonglong length);
|
||||||
char *net_store_length(char *packet,uint length);
|
char *net_store_length(char *packet,uint length);
|
||||||
char *net_store_data(char *to,const char *from, uint length);
|
char *net_store_data(char *to,const char *from, uint length);
|
||||||
|
@ -264,10 +264,11 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
|
|||||||
{
|
{
|
||||||
switch (password_len) {
|
switch (password_len) {
|
||||||
case 45: /* 4.1: to be removed */
|
case 45: /* 4.1: to be removed */
|
||||||
sql_print_error("Found 4.1 style password for user '%s'. "
|
sql_print_error("Found 4.1 style password for user '%s@%s'. "
|
||||||
"Ignoring user. "
|
"Ignoring user. "
|
||||||
"You should change password for this user.",
|
"You should change password for this user.",
|
||||||
user.user ? user.user : "");
|
user.user ? user.user : "",
|
||||||
|
user.host.hostname ? user.host.hostname : "");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sql_print_error("Found invalid password for user: '%s@%s'; "
|
sql_print_error("Found invalid password for user: '%s@%s'; "
|
||||||
@ -526,23 +527,30 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
|
|||||||
/*
|
/*
|
||||||
Seek ACL entry for a user, check password, SSL cypher, and if
|
Seek ACL entry for a user, check password, SSL cypher, and if
|
||||||
everything is OK, update THD user data and USER_RESOURCES struct.
|
everything is OK, update THD user data and USER_RESOURCES struct.
|
||||||
|
|
||||||
|
IMPLEMENTATION
|
||||||
This function does not check if the user has any sensible privileges:
|
This function does not check if the user has any sensible privileges:
|
||||||
only user's existence and validity is checked.
|
only user's existence and validity is checked.
|
||||||
Note, that entire operation is protected by acl_cache_lock.
|
Note, that entire operation is protected by acl_cache_lock.
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
thd INOUT thread handle. If all checks are OK,
|
acl_getroot()
|
||||||
thd->priv_user, thd->master_access are updated.
|
thd thread handle. If all checks are OK,
|
||||||
thd->host, thd->ip, thd->user are used for checks.
|
thd->priv_user, thd->master_access are updated.
|
||||||
mqh OUT user resources; on success mqh is reset, else
|
thd->host, thd->ip, thd->user are used for checks.
|
||||||
unchanged
|
mqh user resources; on success mqh is reset, else
|
||||||
passwd IN scrambled & crypted password, recieved from client
|
unchanged
|
||||||
(to check): thd->scramble or thd->scramble_323 is
|
passwd scrambled & crypted password, recieved from client
|
||||||
used to decrypt passwd, so they must contain
|
(to check): thd->scramble or thd->scramble_323 is
|
||||||
original random string,
|
used to decrypt passwd, so they must contain
|
||||||
passwd_len IN length of passwd, must be one of 0, 8,
|
original random string,
|
||||||
SCRAMBLE_LENGTH_323, SCRAMBLE_LENGTH
|
passwd_len length of passwd, must be one of 0, 8,
|
||||||
|
SCRAMBLE_LENGTH_323, SCRAMBLE_LENGTH
|
||||||
|
'thd' and 'mqh' are updated on success; other params are IN.
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
0 success: thread data and mqh are updated
|
0 success: thd->priv_user, thd->priv_host, thd->master_access, mqh are
|
||||||
|
updated
|
||||||
1 user not found or authentification failure
|
1 user not found or authentification failure
|
||||||
2 user found, has long (4.1.1) salt, but passwd is in old (3.23) format.
|
2 user found, has long (4.1.1) salt, but passwd is in old (3.23) format.
|
||||||
-1 user found, has short (3.23) salt, but passwd is in new (4.1.1) format.
|
-1 user found, has short (3.23) salt, but passwd is in new (4.1.1) format.
|
||||||
@ -553,9 +561,16 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh,
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("acl_getroot");
|
DBUG_ENTER("acl_getroot");
|
||||||
|
|
||||||
if (!initialized) /* if no data allow anything */
|
if (!initialized)
|
||||||
{
|
{
|
||||||
DBUG_RETURN(1);
|
/*
|
||||||
|
here if mysqld's been started with --skip-grant-tables option.
|
||||||
|
*/
|
||||||
|
thd->priv_user= (char *) ""; // privileges for
|
||||||
|
*thd->priv_host= '\0'; // the user are unknown
|
||||||
|
thd->master_access= ~NO_ACCESS; // everything is allowed
|
||||||
|
bzero(mqh, sizeof(*mqh));
|
||||||
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int res= 1;
|
int res= 1;
|
||||||
@ -582,7 +597,7 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh,
|
|||||||
if (user_i->salt_len == 0 ||
|
if (user_i->salt_len == 0 ||
|
||||||
user_i->salt_len == SCRAMBLE_LENGTH &&
|
user_i->salt_len == SCRAMBLE_LENGTH &&
|
||||||
check_scramble(passwd, thd->scramble, user_i->salt) == 0 ||
|
check_scramble(passwd, thd->scramble, user_i->salt) == 0 ||
|
||||||
check_scramble_323(passwd, thd->scramble_323,
|
check_scramble_323(passwd, thd->scramble,
|
||||||
(ulong *) user_i->salt) == 0)
|
(ulong *) user_i->salt) == 0)
|
||||||
{
|
{
|
||||||
acl_user= user_i;
|
acl_user= user_i;
|
||||||
@ -1346,8 +1361,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
|
|||||||
{
|
{
|
||||||
int error = -1;
|
int error = -1;
|
||||||
bool old_row_exists=0;
|
bool old_row_exists=0;
|
||||||
char empty_string[]= { '\0' };
|
const char *password= "";
|
||||||
char *password= empty_string;
|
|
||||||
uint password_len= 0;
|
uint password_len= 0;
|
||||||
char what= (revoke_grant) ? 'N' : 'Y';
|
char what= (revoke_grant) ? 'N' : 'Y';
|
||||||
DBUG_ENTER("replace_user_table");
|
DBUG_ENTER("replace_user_table");
|
||||||
|
@ -547,13 +547,7 @@ public:
|
|||||||
DYNAMIC_ARRAY user_var_events;
|
DYNAMIC_ARRAY user_var_events;
|
||||||
|
|
||||||
/* scramble - random string sent to client on handshake */
|
/* scramble - random string sent to client on handshake */
|
||||||
char scramble[SCRAMBLE_LENGTH+1];
|
char scramble[max(SCRAMBLE_LENGTH, SCRAMBLE_LENGTH_323)+1];
|
||||||
/*
|
|
||||||
The same as scramble but for old password checking routines. It always
|
|
||||||
contains first N bytes of scramble.
|
|
||||||
See check_connection() at sql_parse.cc for authentification details.
|
|
||||||
*/
|
|
||||||
char scramble_323[SCRAMBLE_LENGTH_323+1];
|
|
||||||
|
|
||||||
uint8 query_cache_type; // type of query cache processing
|
uint8 query_cache_type; // type of query cache processing
|
||||||
bool slave_thread;
|
bool slave_thread;
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
SQL_CRYPT::SQL_CRYPT(const char *password)
|
SQL_CRYPT::SQL_CRYPT(const char *password)
|
||||||
{
|
{
|
||||||
ulong rand_nr[2];
|
ulong rand_nr[2];
|
||||||
hash_password(rand_nr,password);
|
hash_password(rand_nr,password, strlen(password));
|
||||||
crypt_init(rand_nr);
|
crypt_init(rand_nr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,17 +181,20 @@ end:
|
|||||||
Check if user exist and password supplied is correct.
|
Check if user exist and password supplied is correct.
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
check_user()
|
check_user()
|
||||||
thd INOUT thread handle, thd->{host,user,ip} are used
|
thd thread handle, thd->{host,user,ip} are used
|
||||||
command IN originator of the check: now check_user is called
|
command originator of the check: now check_user is called
|
||||||
during connect and change user procedures; used for
|
during connect and change user procedures; used for
|
||||||
logging.
|
logging.
|
||||||
passwd IN scrambled password recieved from client
|
passwd scrambled password recieved from client
|
||||||
passwd_len IN length of scrambled password
|
passwd_len length of scrambled password
|
||||||
db IN database name to connect to, may be NULL
|
db database name to connect to, may be NULL
|
||||||
check_count IN dont know exactly
|
check_count dont know exactly
|
||||||
|
|
||||||
Note, that host, user and passwd may point to communication buffer.
|
Note, that host, user and passwd may point to communication buffer.
|
||||||
Current implementation does not depened on that, but future changes
|
Current implementation does not depened on that, but future changes
|
||||||
should be done with this in mind.
|
should be done with this in mind; 'thd' is INOUT, all other params
|
||||||
|
are 'IN'.
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
0 OK; thd->user, thd->master_access, thd->priv_user, thd->db and
|
0 OK; thd->user, thd->master_access, thd->priv_user, thd->db and
|
||||||
thd->db_access are updated; OK is sent to client;
|
thd->db_access are updated; OK is sent to client;
|
||||||
@ -226,8 +229,10 @@ static int check_user(THD *thd, enum enum_server_command command,
|
|||||||
DBUG_RETURN(ER_HANDSHAKE_ERROR);
|
DBUG_RETURN(ER_HANDSHAKE_ERROR);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Why this is set here? - probably to reset current DB to 'no database
|
Clear thd->db as it points to something, that will be freed when
|
||||||
selected' in case of 'change user' failure.
|
connection is closed. We don't want to accidently free a wrong pointer
|
||||||
|
if connect failed. Also in case of 'CHANGE USER' failure, current
|
||||||
|
database will be switched to 'no database selected'.
|
||||||
*/
|
*/
|
||||||
thd->db= 0;
|
thd->db= 0;
|
||||||
thd->db_length= 0;
|
thd->db_length= 0;
|
||||||
@ -244,6 +249,7 @@ static int check_user(THD *thd, enum enum_server_command command,
|
|||||||
scramble_323()). Here we please client to send scrambled_password
|
scramble_323()). Here we please client to send scrambled_password
|
||||||
in old format.
|
in old format.
|
||||||
*/
|
*/
|
||||||
|
NET *net= &thd->net;
|
||||||
if (opt_secure_auth_local)
|
if (opt_secure_auth_local)
|
||||||
{
|
{
|
||||||
net_printf(thd, ER_SERVER_IS_IN_SECURE_AUTH_MODE,
|
net_printf(thd, ER_SERVER_IS_IN_SECURE_AUTH_MODE,
|
||||||
@ -258,9 +264,7 @@ static int check_user(THD *thd, enum enum_server_command command,
|
|||||||
strmake(buff, db, NAME_LEN);
|
strmake(buff, db, NAME_LEN);
|
||||||
db= buff;
|
db= buff;
|
||||||
}
|
}
|
||||||
NET *net= &thd->net;
|
if (send_old_password_request(thd) ||
|
||||||
if (my_net_write(net, thd->scramble_323, SCRAMBLE_LENGTH_323 + 1) ||
|
|
||||||
net_flush(net) ||
|
|
||||||
my_net_read(net) != SCRAMBLE_LENGTH_323 + 1) // We have to read very
|
my_net_read(net) != SCRAMBLE_LENGTH_323 + 1) // We have to read very
|
||||||
{ // specific packet size
|
{ // specific packet size
|
||||||
inc_host_errors(&thd->remote.sin_addr);
|
inc_host_errors(&thd->remote.sin_addr);
|
||||||
@ -288,7 +292,7 @@ static int check_user(THD *thd, enum enum_server_command command,
|
|||||||
{
|
{
|
||||||
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
||||||
bool count_ok= thread_count < max_connections + delayed_insert_threads
|
bool count_ok= thread_count < max_connections + delayed_insert_threads
|
||||||
|| thd->master_access & SUPER_ACL;
|
|| (thd->master_access & SUPER_ACL);
|
||||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
||||||
if (!count_ok)
|
if (!count_ok)
|
||||||
{ // too many connections
|
{ // too many connections
|
||||||
@ -305,7 +309,11 @@ static int check_user(THD *thd, enum enum_server_command command,
|
|||||||
thd->user, thd->host_or_ip,
|
thd->user, thd->host_or_ip,
|
||||||
db ? db : (char*) "");
|
db ? db : (char*) "");
|
||||||
|
|
||||||
/* Why is it set here? */
|
/*
|
||||||
|
This is the default access rights for the current database. It's
|
||||||
|
set to 0 here because we don't have an active database yet (and we
|
||||||
|
may not have an active database to set.
|
||||||
|
*/
|
||||||
thd->db_access=0;
|
thd->db_access=0;
|
||||||
|
|
||||||
/* Don't allow user to connect if he has done too many queries */
|
/* Don't allow user to connect if he has done too many queries */
|
||||||
@ -554,9 +562,10 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0)
|
|||||||
Perform handshake, authorize client and update thd ACL variables.
|
Perform handshake, authorize client and update thd ACL variables.
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
check_connection()
|
check_connection()
|
||||||
thd INOUT thread handle
|
thd thread handle
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
0 success, OK is sent to user
|
0 success, OK is sent to user, thd is updated.
|
||||||
-1 error, which is sent to user
|
-1 error, which is sent to user
|
||||||
> 0 error code (not sent to user)
|
> 0 error code (not sent to user)
|
||||||
*/
|
*/
|
||||||
@ -644,14 +653,12 @@ check_connection(THD *thd)
|
|||||||
each handshake.
|
each handshake.
|
||||||
*/
|
*/
|
||||||
create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
|
create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
|
||||||
strmake(thd->scramble_323, thd->scramble, SCRAMBLE_LENGTH_323);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Old clients does not understand long scrambles, but can ignore packet
|
Old clients does not understand long scrambles, but can ignore packet
|
||||||
tail: that's why first part of the scramble is placed here, and second
|
tail: that's why first part of the scramble is placed here, and second
|
||||||
part at the end of packet.
|
part at the end of packet.
|
||||||
*/
|
*/
|
||||||
end= strmake(end, thd->scramble_323, SCRAMBLE_LENGTH_323) + 1;
|
end= strmake(end, thd->scramble, SCRAMBLE_LENGTH_323) + 1;
|
||||||
|
|
||||||
int2store(end, client_flags);
|
int2store(end, client_flags);
|
||||||
/* write server characteristics: up to 16 bytes allowed */
|
/* write server characteristics: up to 16 bytes allowed */
|
||||||
@ -754,8 +761,6 @@ check_connection(THD *thd)
|
|||||||
return(ER_HANDSHAKE_ERROR);
|
return(ER_HANDSHAKE_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* why has it been put here? */
|
|
||||||
|
|
||||||
if (thd->client_capabilities & CLIENT_INTERACTIVE)
|
if (thd->client_capabilities & CLIENT_INTERACTIVE)
|
||||||
thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
|
thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
|
||||||
if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
|
if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
|
||||||
@ -778,9 +783,8 @@ check_connection(THD *thd)
|
|||||||
|
|
||||||
if (thd->user)
|
if (thd->user)
|
||||||
x_free(thd->user);
|
x_free(thd->user);
|
||||||
thd->user= my_strdup(user, MYF(0));
|
if (!(thd->user= my_strdup(user, MYF(0))))
|
||||||
if (!thd->user)
|
return (ER_OUT_OF_RESOURCES);
|
||||||
return(ER_OUT_OF_RESOURCES);
|
|
||||||
return check_user(thd, COM_CONNECT, passwd, passwd_len, db, true);
|
return check_user(thd, COM_CONNECT, passwd, passwd_len, db, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user