Commit 35ccfd0b authored by peter@mysql.com's avatar peter@mysql.com

SCRUM: Main change for Secure connection handling. Still needs some more coding. Commit

done for merge with newer version of code.
parent 96131759
......@@ -87,7 +87,7 @@ enum commands {
ADMIN_FLUSH_HOSTS, ADMIN_FLUSH_TABLES, ADMIN_PASSWORD,
ADMIN_PING, ADMIN_EXTENDED_STATUS, ADMIN_FLUSH_STATUS,
ADMIN_FLUSH_PRIVILEGES, ADMIN_START_SLAVE, ADMIN_STOP_SLAVE,
ADMIN_FLUSH_THREADS
ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD
};
static const char *command_names[]= {
"create", "drop", "shutdown",
......@@ -97,7 +97,7 @@ static const char *command_names[]= {
"flush-hosts", "flush-tables", "password",
"ping", "extended-status", "flush-status",
"flush-privileges", "start-slave", "stop-slave",
"flush-threads",
"flush-threads","old-password",
NullS
};
......@@ -419,7 +419,8 @@ static my_bool sql_connect(MYSQL *mysql, uint wait)
static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
const char *status;
struct rand_struct rand_st;
for (; argc > 0 ; argv++,argc--)
{
switch (find_type(argv[0],&command_typelib,2)) {
......@@ -721,17 +722,23 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
break;
}
case ADMIN_OLD_PASSWORD:
case ADMIN_PASSWORD:
{
char buff[128],crypted_pw[33];
char buff[128],crypted_pw[64];
time_t start_time;
/* Do initialization the same way as we do in mysqld */
start_time=time((time_t*) 0);
randominit(&rand_st,(ulong) start_time,(ulong) start_time/2);
if (argc < 2)
{
my_printf_error(0,"Too few arguments to change password",MYF(ME_BELL));
return 1;
}
if (argv[1][0])
make_scrambled_password(crypted_pw,argv[1],0); /* New passwords only */
make_scrambled_password(crypted_pw,argv[1],(find_type(argv[0],&command_typelib,2)
==ADMIN_OLD_PASSWORD),&rand_st);
else
crypted_pw[0]=0; /* No password */
sprintf(buff,"set password='%s',sql_log_off=0",crypted_pw);
......@@ -836,7 +843,8 @@ static void usage(void)
kill id,id,... Kill mysql threads");
#if MYSQL_VERSION_ID >= 32200
puts("\
password new-password Change old password to new-password");
password new-password Change old password to new-password, MySQL 4.1 hashing.\n\
old-password new-password Change old password to new-password in old format.\n");
#endif
puts("\
ping Check if mysqld is alive\n\
......
......@@ -181,7 +181,7 @@ typedef struct st_mysql
enum mysql_status status;
my_bool free_me; /* If free in mysql_close */
my_bool reconnect; /* set to 1 if automatic reconnect */
char scramble_buff[9];
char scramble_buff[21]; /* New protocol requires longer scramble*/
/*
Set if this is the original connection, not a master or a slave we have
......
......@@ -280,10 +280,17 @@ extern unsigned long net_buffer_length;
void randominit(struct rand_struct *,unsigned long seed1,
unsigned long seed2);
double rnd(struct rand_struct *);
void make_scrambled_password(char *to,const char *password,my_bool force_old_scramble);
void make_scrambled_password(char *to,const char *password,my_bool force_old_scramble,struct rand_struct *rand_st);
uint get_password_length(my_bool force_old_scramble);
uint8 get_password_version(const char* password);
void create_random_string(int length,struct rand_struct *rand_st,char* target);
my_bool validate_password(const char* password, const char* message, ulong* salt);
void password_hash_stage1(char *to, const char *password);
void password_hash_stage2(char *to,const char *salt);
void password_crypt(const char* from,char* to, const char* password,int length);
void get_hash_and_password(ulong* salt, uint8 pversion,char* hash, unsigned char* bin_password);
void get_salt_from_password(unsigned long *res,const char *password);
void create_key_from_old_password(const char* password,char* key);
void make_password_from_salt(char *to, unsigned long *hash_res, uint8 password_version);
char *scramble(char *to,const char *message,const char *password,
my_bool old_ver);
......
......@@ -67,7 +67,7 @@ ulong net_write_timeout= NET_WRITE_TIMEOUT;
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG \
| CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS \
| CLIENT_PROTOCOL_41)
| CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION)
#ifdef __WIN__
......@@ -1585,6 +1585,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
{
char buff[NAME_LEN+USERNAME_LENGTH+100],charset_name_buff[16];
char *end,*host_info,*charset_name;
char password_hash[20]; /* Used for tmp storage of stage1 hash */
my_socket sock;
uint32 ip_addr;
struct sockaddr_in sock_addr;
......@@ -1789,7 +1790,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
if ((pkt_length=net_safe_read(mysql)) == packet_error)
goto error;
/* Check if version of protocoll matches current one */
/* Check if version of protocol matches current one */
mysql->protocol_version= net->read_pos[0];
DBUG_DUMP("packet",(char*) net->read_pos,10);
......@@ -1855,7 +1856,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
}
goto error;
}
/* Save connection information */
if (!user) user="";
if (!passwd) passwd="";
......@@ -1962,32 +1963,105 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
DBUG_PRINT("info",("Server version = '%s' capabilites: %ld status: %d client_flag: %d",
mysql->server_version,mysql->server_capabilities,
mysql->server_status, client_flag));
int3store(buff+2,max_allowed_packet);
if (user && user[0])
strmake(buff+5,user,32); /* Max user name */
else
read_user_name((char*) buff+5);
/* We have to handle different version of handshake here */
#ifdef _CUSTOMCONFIG_
#include "_cust_libmysql.h";
#endif
DBUG_PRINT("info",("user: %s",buff+5));
end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd,
(my_bool) (mysql->protocol_version == 9));
/*
We always start with old type handshake the only difference is message sent
If server handles secure connection type we'll not send the real scramble
*/
if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{
if (passwd[0])
{
/* Use something for not empty password not to match it against empty one */
end=scramble(strend(buff+5)+1, mysql->scramble_buff,"~MySQL#!",
(my_bool) (mysql->protocol_version == 9));
}
else /* For empty password*/
{
end=strend(buff+5)+1;
*end=0; /* Store zero length scramble */
}
}
/* Real scramble is sent only for servers. This is to be blocked by option */
else
end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd,
(my_bool) (mysql->protocol_version == 9));
/* Add database if needed */
if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
{
end=strmake(end+1,db,NAME_LEN);
end=strmake(end+1,db,NAME_LEN);
mysql->db=my_strdup(db,MYF(MY_WME));
db=0;
}
/* Write authentication package */
if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net))
{
net->last_errno= CR_SERVER_LOST;
net->last_errno= CR_SERVER_LOST;
strmov(net->last_error,ER(net->last_errno));
goto error;
}
if (net_safe_read(mysql) == packet_error)
/* We shall only query sever if it expect us to do so */
if ( (pkt_length=net_safe_read(mysql)) == packet_error)
goto error;
if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{
/* This should basically always happen with new server unless empty password */
if (pkt_length==24) /* We have new hash back */
{
/* Old passwords will have zero at the first byte of hash */
if (net->read_pos[0])
{
/* Build full password hash as it is required to decode scramble */
password_hash_stage1(buff, passwd);
/* Store copy as we'll need it later */
memcpy(password_hash,buff,20);
/* Finally hash complete password using hash we got from server */
password_hash_stage2(password_hash,net->read_pos);
/* Decypt and store scramble 4 = hash for stage2 */
password_crypt(net->read_pos+4,mysql->scramble_buff,password_hash,20);
mysql->scramble_buff[20]=0;
/* Encode scramble with password. Recycle buffer */
password_crypt(mysql->scramble_buff,buff,buff,20);
}
else
{
/* Create password to decode scramble */
create_key_from_old_password(passwd,password_hash);
/* Decypt and store scramble 4 = hash for stage2 */
password_crypt(net->read_pos+4,mysql->scramble_buff,password_hash,20);
mysql->scramble_buff[20]=0;
/* Finally scramble decoded scramble with password */
scramble(buff, mysql->scramble_buff, passwd,
(my_bool) (mysql->protocol_version == 9));
}
/* Write second package of authentication */
if (my_net_write(net,buff,20) || net_flush(net))
{
net->last_errno= CR_SERVER_LOST;
strmov(net->last_error,ER(net->last_errno));
goto error;
}
/* Read What server thinks about out new auth message report */
if (net_safe_read(mysql) == packet_error)
goto error;
}
}
/* End of authentication part of handshake */
if (client_flag & CLIENT_COMPRESS) /* We will use compression */
net->compress=1;
if (db && mysql_select_db(mysql,db))
......
......@@ -123,7 +123,7 @@ then
c_u="$c_u CREATE TABLE user ("
c_u="$c_u Host char(60) binary DEFAULT '' NOT NULL,"
c_u="$c_u User char(16) binary DEFAULT '' NOT NULL,"
c_u="$c_u Password char(16) binary DEFAULT '' NOT NULL,"
c_u="$c_u Password char(45) binary DEFAULT '' NOT NULL,"
c_u="$c_u Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
......
......@@ -5,7 +5,7 @@ master-bin.000001
4
127.0.0.1
replicate
aaaaaaaaaaaaaaabthispartofthepasswordisnotused
aaaaaaaaaaaaaaab
$MASTER_MYPORT
1
0
......
......@@ -170,6 +170,7 @@ fi
@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
alter table user
change password password char(45) not null,
add max_questions int(11) NOT NULL AFTER x509_subject,
add max_updates int(11) unsigned NOT NULL AFTER max_questions,
add max_connections int(11) unsigned NOT NULL AFTER max_updates;
......
......@@ -213,7 +213,7 @@ then
c_u="$c_u CREATE TABLE user ("
c_u="$c_u Host char(60) binary DEFAULT '' NOT NULL,"
c_u="$c_u User char(16) binary DEFAULT '' NOT NULL,"
c_u="$c_u Password char(16) binary DEFAULT '' NOT NULL,"
c_u="$c_u Password char(45) binary DEFAULT '' NOT NULL,"
c_u="$c_u Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
......
......@@ -1279,7 +1279,7 @@ String *Item_func_password::val_str(String *str)
return 0;
if (res->length() == 0)
return &empty_string;
make_scrambled_password(tmp_value,res->c_ptr(),opt_old_passwords);
make_scrambled_password(tmp_value,res->c_ptr(),opt_old_passwords,&current_thd->rand);
str->set(tmp_value,get_password_length(opt_old_passwords),res->charset());
return str;
}
......@@ -1291,7 +1291,7 @@ String *Item_func_old_password::val_str(String *str)
return 0;
if (res->length() == 0)
return &empty_string;
make_scrambled_password(tmp_value,res->c_ptr(),1);
make_scrambled_password(tmp_value,res->c_ptr(),1,&current_thd->rand);
str->set(tmp_value,16,res->charset());
return str;
}
......
......@@ -87,7 +87,9 @@ static MYSQL_DATA *mc_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES)
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \
CLIENT_LOCAL_FILES | CLIENT_SECURE_CONNECTION)
#if defined(MSDOS) || defined(__WIN__)
#define perror(A)
......@@ -488,6 +490,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
uint net_read_timeout)
{
char buff[NAME_LEN+USERNAME_LENGTH+100],*end,*host_info;
char password_hash[20];
my_socket sock;
ulong ip_addr;
struct sockaddr_in sock_addr;
......@@ -510,7 +513,6 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
user ? user : "(Null)",
net_read_timeout,
(uint) slave_net_timeout));
net->vio = 0; /* If something goes wrong */
mysql->charset=default_charset_info; /* Set character set */
if (!port)
......@@ -799,22 +801,96 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
}
DBUG_PRINT("info",("user: %s",buff+5));
end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd,
(my_bool) (mysql->protocol_version == 9));
if (db)
/*
We always start with old type handshake the only difference is message sent
If server handles secure connection type we'll not send the real scramble
*/
if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{
if (passwd[0])
{
/* Use something for not empty password not to match it against empty one */
end=scramble(strend(buff+5)+1, mysql->scramble_buff,"~MySQL#!",
(my_bool) (mysql->protocol_version == 9));
}
else /* For empty password*/
{
end=strend(buff+5)+1;
*end=0; /* Store zero length scramble */
}
}
/* Real scramble is sent only for old servers. This is to be blocked by option */
else
end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd,
(my_bool) (mysql->protocol_version == 9));
/* Add database if needed */
if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
{
end=strmake(end+1,db,NAME_LEN);
mysql->db=my_strdup(db,MYF(MY_WME));
db=0;
}
/* Write authentication package */
if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net))
{
net->last_errno= CR_SERVER_LOST;
strmov(net->last_error,ER(net->last_errno));
strmov(net->last_error,ER(net->last_errno));
goto error;
}
if (mc_net_safe_read(mysql) == packet_error)
/* We shall only query sever if it expect us to do so */
if ( (pkt_length=mc_net_safe_read(mysql)) == packet_error)
goto error;
if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{
/* This should basically always happen with new server unless empty password */
if (pkt_length==24) /* We have new hash back */
{
/* Old passwords will have zero at the first byte of hash */
if (net->read_pos[0])
{
/* Build full password hash as it is required to decode scramble */
password_hash_stage1(buff, passwd);
/* Store copy as we'll need it later */
memcpy(password_hash,buff,20);
/* Finally hash complete password using hash we got from server */
password_hash_stage2(password_hash,(char*)net->read_pos);
/* Decypt and store scramble 4 = hash for stage2 */
password_crypt((char*)net->read_pos+4,mysql->scramble_buff,password_hash,20);
mysql->scramble_buff[20]=0;
/* Encode scramble with password. Recycle buffer */
password_crypt(mysql->scramble_buff,buff,buff,20);
}
else
{
/* Create password to decode scramble */
create_key_from_old_password(passwd,password_hash);
/* Decypt and store scramble 4 = hash for stage2 */
password_crypt((char*)net->read_pos+4,mysql->scramble_buff,password_hash,20);
mysql->scramble_buff[20]=0;
/* Finally scramble decoded scramble with password */
scramble(buff, mysql->scramble_buff, passwd,
(my_bool) (mysql->protocol_version == 9));
}
/* Write second package of authentication */
if (my_net_write(net,buff,20) || net_flush(net))
{
net->last_errno= CR_SERVER_LOST;
strmov(net->last_error,ER(net->last_errno));
goto error;
}
/* Read What server thinks about out new auth message report */
if (mc_net_safe_read(mysql) == packet_error)
goto error;
}
}
/* End of authentication part of handshake */
if (client_flag & CLIENT_COMPRESS) /* We will use compression */
net->compress=1;
DBUG_PRINT("exit",("Mysql handler: %lx",mysql));
......
......@@ -317,7 +317,6 @@ uint volatile thread_count=0, thread_running=0, kill_cached_threads=0,
ulong thd_startup_options=(OPTION_UPDATE_LOG | OPTION_AUTO_IS_NULL |
OPTION_BIN_LOG | OPTION_QUOTE_SHOW_CREATE );
uint protocol_version=PROTOCOL_VERSION;
uint connection_auth_flag=0; /* Supported authentication mode */
struct system_variables global_system_variables;
struct system_variables max_system_variables;
ulong keybuff_size,table_cache_size,
......
This diff is collapsed.
This diff is collapsed.
......@@ -88,7 +88,7 @@ ulong acl_get(const char *host, const char *ip, const char *bin_ip,
const char *user, const char *db);
ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
const char *password,const char *scramble,char **priv_user,
bool old_ver, USER_RESOURCES *max);
bool old_ver, USER_RESOURCES *max,char* prepared_scramble, int stage);
bool acl_check_host(const char *host, const char *ip);
bool check_change_password(THD *thd, const char *host, const char *user);
bool change_password(THD *thd, const char *host, const char *user,
......
......@@ -496,7 +496,7 @@ class THD :public ilink {
uint select_number; //number of select (used for EXPLAIN)
/* variables.transaction_isolation is reset to this after each commit */
enum_tx_isolation session_tx_isolation;
char scramble[9];
char scramble[21]; // extend scramble to handle new auth
uint8 query_cache_type; // type of query cache processing
bool slave_thread;
bool set_query_id,locked,count_cuted_fields,some_tables_deleted;
......
......@@ -45,13 +45,13 @@
#define MIN_HANDSHAKE_SIZE 6
#endif /* HAVE_OPENSSL */
#define SCRAMBLE_LENGTH 8
#define SCRAMBLE41_LENGTH 20
#define MEM_ROOT_BLOCK_SIZE 8192
#define MEM_ROOT_PREALLOC 8192
#define TRANS_MEM_ROOT_BLOCK_SIZE 4096
#define TRANS_MEM_ROOT_PREALLOC 4096
extern uint connection_auth_flag;
extern int yyparse(void);
extern "C" pthread_mutex_t THR_LOCK_keycache;
......@@ -180,40 +180,51 @@ static int get_or_create_user_conn(THD *thd, const char *user,
*/
static bool check_user(THD *thd,enum_server_command command, const char *user,
const char *passwd, const char *db, bool check_count)
const char *passwd, const char *db, bool check_count,
bool do_send_error, char* crypted_scramble,int stage,
bool had_password)
{
thd->db=0;
thd->db_length=0;
USER_RESOURCES ur;
if (!(thd->user = my_strdup(user, MYF(0))))
{
send_error(thd,ER_OUT_OF_RESOURCES);
return 1;
}
/* We shall avoid dupplicate user allocations here */
if (!(thd->user))
if (!(thd->user = my_strdup(user, MYF(0))))
{
send_error(thd,ER_OUT_OF_RESOURCES);
return 1;
}
thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user,
passwd, thd->scramble, &thd->priv_user,
protocol_version == 9 ||
!(thd->client_capabilities &
CLIENT_LONG_PASSWORD),&ur);
CLIENT_LONG_PASSWORD),&ur,crypted_scramble,stage);
DBUG_PRINT("info",
("Capabilities: %d packet_length: %d Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'",
thd->client_capabilities, thd->max_client_packet_length,
thd->host_or_ip, thd->priv_user,
passwd[0] ? "yes": "no",
had_password ? "yes": "no",
thd->master_access, thd->db ? thd->db : "*none*"));
/* in case we're going to retry we should not send error message at this point */
if (thd->master_access & NO_ACCESS)
{
net_printf(thd, ER_ACCESS_DENIED_ERROR,
thd->user,
if (do_send_error)
{
net_printf(thd, ER_ACCESS_DENIED_ERROR,
thd->user,
thd->host_or_ip,
passwd[0] ? ER(ER_YES) : ER(ER_NO));
mysql_log.write(thd,COM_CONNECT,ER(ER_ACCESS_DENIED_ERROR),
had_password ? ER(ER_YES) : ER(ER_NO));
mysql_log.write(thd,COM_CONNECT,ER(ER_ACCESS_DENIED_ERROR),
thd->user,
thd->host_or_ip,
passwd[0] ? ER(ER_YES) : ER(ER_NO));
return(1); // Error already given
had_password ? ER(ER_YES) : ER(ER_NO));
return(1); // Error already given
}
else
return(-1); // do not report error in special handshake
}
if (check_count)
{
VOID(pthread_mutex_lock(&LOCK_thread_count));
......@@ -505,9 +516,10 @@ check_connections(THD *thd)
ulong pkt_len=0;
{
/* buff[] needs to big enough to hold the server_version variable */
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+32],*end;
char buff[SERVER_VERSION_LENGTH +
SCRAMBLE_LENGTH+64],*end;
int client_flags = CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
CLIENT_PROTOCOL_41 | connection_auth_flag;
CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION;
if (opt_using_transactions)
client_flags|=CLIENT_TRANSACTIONS;
......@@ -529,6 +541,8 @@ check_connections(THD *thd)
int2store(end+3,thd->server_status);
bzero(end+5,13);
end+=18;
// At this point we write connection message and read reply
if (net_write_command(net,(uchar) protocol_version, "", 0, buff,
(uint) (end-buff)) ||
(pkt_len= my_net_read(net)) == packet_error ||
......@@ -581,19 +595,82 @@ check_connections(THD *thd)
char *user= (char*) net->read_pos+5;
char *passwd= strend(user)+1;
char *db=0;
if (passwd[0] && strlen(passwd) != SCRAMBLE_LENGTH)
return ER_HANDSHAKE_ERROR;
if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
db=strend(passwd)+1;
if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
db=strend(passwd)+1;
/* We can get only old hash at this point */
if (passwd[0] && strlen(passwd)!=SCRAMBLE_LENGTH)
return ER_HANDSHAKE_ERROR;
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) &&
opt_using_transactions)
thd->net.return_status= &thd->server_status;
opt_using_transactions)
thd->net.return_status= &thd->server_status;
net->read_timeout=(uint) thd->variables.net_read_timeout;
if (check_user(thd,COM_CONNECT, user, passwd, db, 1))
return (-1);
thd->password=test(passwd[0]);
char prepared_scramble[SCRAMBLE41_LENGTH+4]; /* Buffer for scramble and hash */
/* Simple connect only for old clients. New clients always use secure auth */
bool simple_connect=(!(thd->client_capabilities & CLIENT_SECURE_CONNECTION));
/* Store information if we used password. passwd will be dammaged */
bool using_password=test(passwd[0]);
/* Check user permissions. If password failure we'll get scramble back */
if (check_user(thd,COM_CONNECT, user, passwd, db, 1, simple_connect,
prepared_scramble,0,using_password))
{
/* If The client is old we just have to return error */
if (simple_connect)
return -1;
/* Store current used and database as they are erased with next packet */
char tmp_user[USERNAME_LENGTH+1];
char tmp_db[NAME_LEN+1];
if (user)
{
strncpy(tmp_user,user,USERNAME_LENGTH+1);
/* Extra safety if we have too long data */
tmp_user[USERNAME_LENGTH]=0;
}
else
tmp_user[0]=0;
if (db)
{
strncpy(tmp_db,db,NAME_LEN+1);
tmp_db[NAME_LEN]=0;
}
else
tmp_db[0]=0;
/* Write hash and encrypted scramble to client */
if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4)
|| net_flush(net))
{
inc_host_errors(&thd->remote.sin_addr);
return ER_HANDSHAKE_ERROR;
}
/* Reading packet back */
if ((pkt_len=my_net_read(net)) == packet_error)
{
inc_host_errors(&thd->remote.sin_addr);
return ER_HANDSHAKE_ERROR;
}
/* We have to get very specific packet size */
if (pkt_len!=SCRAMBLE41_LENGTH)
{
inc_host_errors(&thd->remote.sin_addr);
return ER_HANDSHAKE_ERROR;
}
/* Final attempt to check the user based on reply */
if (check_user(thd,COM_CONNECT, tmp_user, (char*)net->read_pos,
tmp_db, 1, 1,prepared_scramble,1,using_password))
return -1;
}
thd->password=using_password;
return 0;
}
......@@ -954,7 +1031,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
send_error(thd, ER_UNKNOWN_COM_ERROR);
break;
}
if (check_user(thd, COM_CHANGE_USER, user, passwd, db, 0))
/* WARNING THIS HAS TO BE REWRITTEN */
char tmp_buffer[64];
printf("Change user called: %s %s %s\n",user,passwd,db);
if (check_user(thd, COM_CHANGE_USER, user, passwd, db, 0,1,tmp_buffer,0,1))
{ // Restore old user
x_free(thd->user);
x_free(thd->db);
......
......@@ -3745,7 +3745,7 @@ text_or_password:
else
{
char *buff=(char*) sql_alloc(HASH_PASSWORD_LENGTH+1);
make_scrambled_password(buff,$3.str,opt_old_passwords);
make_scrambled_password(buff,$3.str,opt_old_passwords,&current_thd->rand);
$$=buff;
}
}
......@@ -4041,7 +4041,7 @@ grant_user:
char *buff=(char*) sql_alloc(HASH_PASSWORD_LENGTH+1);
if (buff)
{
make_scrambled_password(buff,$4.str,opt_old_passwords);
make_scrambled_password(buff,$4.str,opt_old_passwords,&current_thd->rand);
$1->password.str=buff;
$1->password.length=HASH_PASSWORD_LENGTH;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment