diff options
-rw-r--r-- | client/mysqladmin.c | 6 | ||||
-rw-r--r-- | libmysql/libmysql.c | 43 | ||||
-rw-r--r-- | sql/mini_client.cc | 21 | ||||
-rw-r--r-- | sql/password.c | 2 | ||||
-rw-r--r-- | sql/sql_acl.cc | 12 | ||||
-rw-r--r-- | sql/sql_acl.h | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 49 |
7 files changed, 76 insertions, 59 deletions
diff --git a/client/mysqladmin.c b/client/mysqladmin.c index c4914c38dd7..2c8314d83ca 100644 --- a/client/mysqladmin.c +++ b/client/mysqladmin.c @@ -768,9 +768,9 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) return 1; } if (argv[1][0]) - make_scrambled_password(crypted_pw,argv[1],(find_type(argv[0], - &command_typelib,2)==ADMIN_OLD_PASSWORD), - &rand_st); + 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); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 842e8fe845d..7a5fcb8c6b7 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2228,9 +2228,12 @@ Try also with PIPE or TCP/IP { if (passwd[0]) { - /* Use something for not empty password not to match against empty one */ - end=scramble(strend(buff+5)+1, mysql->scramble_buff,"\1~MySQL#!\2", - (my_bool) (mysql->protocol_version == 9)); + /* Prepare false scramble */ + end=strend(buff+5)+1; + bfill(end, SCRAMBLE_LENGTH, 'x'); + end+=SCRAMBLE_LENGTH; + *end=0; + end++; } else /* For empty password*/ { @@ -2238,8 +2241,11 @@ Try also with PIPE or TCP/IP *end=0; /* Store zero length scramble */ } } - /* Real scramble is sent only for servers. This is to be blocked by option */ else + /* + Real scramble is only sent to old servers. This can be blocked + by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1); + */ end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd, (my_bool) (mysql->protocol_version == 9)); @@ -2265,11 +2271,12 @@ Try also with PIPE or TCP/IP 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 */ + /* This should always happen with new server unless empty password */ + if (pkt_length==24 && net->read_pos[0]) + /* OK/Error packets have zero as the first char */ { - /* Old passwords will have zero at the first byte of hash */ - if (net->read_pos[0]) + /* Old passwords will have '*' 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); @@ -2433,15 +2440,20 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, { if (passwd[0]) { - /* Use something for not empty password not to match it against empty one */ - end=scramble(end, mysql->scramble_buff,"\1~MySQL#!\2", - (my_bool) (mysql->protocol_version == 9)); + /* Prepare false scramble */ + bfill(end, SCRAMBLE_LENGTH, 'x'); + end+=SCRAMBLE_LENGTH; + *end=0; + } else /* For empty password*/ *end=0; /* Store zero length scramble */ } - /* Real scramble is sent only for servers. This is to be blocked by option */ else + /* + Real scramble is only sent to old servers. This can be blocked + by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1); + */ end=scramble(end, mysql->scramble_buff, passwd, (my_bool) (mysql->protocol_version == 9)); @@ -2458,11 +2470,12 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, 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 */ + /* This should always happen with new server unless empty password */ + if (pkt_length==24 && net->read_pos[0]) + /* Err/OK messages has first character=0 */ { /* Old passwords will have zero at the first byte of hash */ - if (net->read_pos[0]) + if (net->read_pos[0] != '*') { /* Build full password hash as it is required to decode scramble */ password_hash_stage1(buff, passwd); diff --git a/sql/mini_client.cc b/sql/mini_client.cc index 7f841255454..31668e38a6f 100644 --- a/sql/mini_client.cc +++ b/sql/mini_client.cc @@ -810,9 +810,12 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, { 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)); + /* Prepare false scramble */ + end=strend(buff+5)+1; + bfill(end, SCRAMBLE_LENGTH, 'x'); + end+=SCRAMBLE_LENGTH; + *end=0; + end++; } else /* For empty password*/ { @@ -820,8 +823,11 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, *end=0; /* Store zero length scramble */ } } - /* Real scramble is sent only for old servers. This is to be blocked by option */ else + /* + Real scramble is only sent to old servers. This can be blocked + by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1); + */ end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd, (my_bool) (mysql->protocol_version == 9)); @@ -847,11 +853,12 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, 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 */ + /* This should always happen with new server unless empty password */ + if (pkt_length==24 && net->read_pos[0]) + /* OK/Error message has zero as the first character */ { /* Old passwords will have zero at the first byte of hash */ - if (net->read_pos[0]) + if (net->read_pos[0] != '*') { /* Build full password hash as it is required to decode scramble */ password_hash_stage1(buff, passwd); diff --git a/sql/password.c b/sql/password.c index 6f1557bbd34..b5254ad06b7 100644 --- a/sql/password.c +++ b/sql/password.c @@ -556,7 +556,7 @@ void get_hash_and_password(ulong* salt, uint8 pversion, char* hash, unsigned cha val=*(++salt); for (t=3; t>=0; t--) { - bin_password[t]=val%256; + bin_password[t]=val & 255; val>>=8; /* Scroll 8 bits to get next part*/ } bin_password+=4; /* Get to next 4 chars*/ diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 47b641bc519..e2c1051eac9 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -461,6 +461,9 @@ void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble) thd->scramble[SCRAMBLE41_LENGTH]=0; /* Get binary form, First 4 bytes of prepared scramble is salt */ get_hash_and_password(acl_user->salt,acl_user->pversion,prepared_scramble,(unsigned char*)bin_password); + /* Store "*" as identifier for old passwords */ + if (!acl_user->pversion) + prepared_scramble[0]='*'; /* Finally encrypt password to get prepared scramble */ password_crypt(thd->scramble,prepared_scramble+4,bin_password,SCRAMBLE41_LENGTH); } @@ -482,12 +485,13 @@ void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble) ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, const char *password,const char *message,char **priv_user, bool old_ver, USER_RESOURCES *mqh,char* prepared_scramble, - int stage,uint *cur_priv_version,ACL_USER** hint_user) + uint *cur_priv_version,ACL_USER** hint_user) { ulong user_access=NO_ACCESS; - *priv_user=(char*) user; - bool password_correct=0; - ACL_USER *acl_user=NULL; + *priv_user= (char*) user; + bool password_correct= 0; + int stage= (*hint_user != NULL); /* NULL passed as first stage */ + ACL_USER *acl_user= NULL; DBUG_ENTER("acl_getroot"); diff --git a/sql/sql_acl.h b/sql/sql_acl.h index cfab9bf22cf..ceb866d809f 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -138,7 +138,7 @@ ulong acl_get(const char *host, const char *ip, const char *bin_ip, 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,char* prepared_scramble, - int stage, uint *cur_priv_version, ACL_USER **cached_user); + uint *cur_priv_version, ACL_USER **cached_user); 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, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ed4f1387fa9..086f58e0fd6 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -187,7 +187,7 @@ end: static int check_user(THD *thd,enum_server_command command, const char *user, const char *passwd, const char *db, bool check_count, - bool do_send_error, char* crypted_scramble,int stage, + bool do_send_error, char* crypted_scramble, bool had_password,uint *cur_priv_version, ACL_USER** hint_user) { @@ -207,7 +207,7 @@ static int check_user(THD *thd,enum_server_command command, const char *user, protocol_version == 9 || !(thd->client_capabilities & CLIENT_LONG_PASSWORD),&ur,crypted_scramble, - stage,cur_priv_version,hint_user); + cur_priv_version,hint_user); DBUG_PRINT("info", ("Capabilities: %d packet_length: %d Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'", @@ -628,7 +628,7 @@ check_connections(THD *thd) char prepared_scramble[SCRAMBLE41_LENGTH+4]; /* Buffer for scramble and hash */ - ACL_USER* cached_user; + ACL_USER* cached_user=NULL; /* Initialise to NULL as first stage indication */ uint cur_priv_version; /* Simple connect only for old clients. New clients always use secure auth */ @@ -636,10 +636,9 @@ check_connections(THD *thd) /* 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,&cur_priv_version,&cached_user)<0) + prepared_scramble,using_password,&cur_priv_version,&cached_user)<0) { /* If The client is old we just have to return error */ if (simple_connect) @@ -659,8 +658,8 @@ check_connections(THD *thd) strmake(tmp_db,db,NAME_LEN); /* Write hash and encrypted scramble to client */ - if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) - || net_flush(net)) + if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) || + net_flush(net)) { inc_host_errors(&thd->remote.sin_addr); return ER_HANDSHAKE_ERROR; @@ -679,7 +678,7 @@ check_connections(THD *thd) } /* 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,&cur_priv_version, + tmp_db, 1, 1,prepared_scramble,using_password,&cur_priv_version, &cached_user)) return -1; } @@ -1059,7 +1058,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, goto restore_user_err; char prepared_scramble[SCRAMBLE41_LENGTH+4];/* Buffer for scramble,hash */ - ACL_USER* cached_user; /* Cached user */ + ACL_USER* cached_user ; /* Cached user */ + cached_user= NULL; uint cur_priv_version; /* Cached grant version */ /* Simple connect only for old clients. New clients always use sec. auth*/ @@ -1076,7 +1076,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, Do not retry if we already have sent error (result>0) */ if (check_user(thd,COM_CHANGE_USER, user, passwd, db, 0, simple_connect, - prepared_scramble,0,using_password,&cur_priv_version,&cached_user)<0) + prepared_scramble,using_password,&cur_priv_version,&cached_user)<0) { /* If The client is old we just have to have auth failure */ if (simple_connect) @@ -1086,26 +1086,19 @@ bool dispatch_command(enum enum_server_command command, THD *thd, char tmp_user[USERNAME_LENGTH+1]; char tmp_db[NAME_LEN+1]; - + + tmp_user[0]=0; 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; + strmake(tmp_user,user,USERNAME_LENGTH); + + tmp_db[0]=0; if (db) - { - strncpy(tmp_db,db,NAME_LEN+1); - tmp_db[NAME_LEN]=0; - } - else - tmp_db[0]=0; + strmake(tmp_db,db,NAME_LEN); + /* Write hash and encrypted scramble to client */ - if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) - || net_flush(net)) + if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) || + net_flush(net)) goto restore_user_err; /* Reading packet back */ @@ -1117,8 +1110,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, goto restore_user; /* Final attempt to check the user based on reply */ - if (check_user(thd,COM_CONNECT, tmp_user, (char*)net->read_pos, - tmp_db, 0, 1,prepared_scramble,1,using_password,&cur_priv_version, + if (check_user(thd,COM_CHANGE_USER, tmp_user, (char*)net->read_pos, + tmp_db, 0, 1,prepared_scramble,using_password,&cur_priv_version, &cached_user)) goto restore_user; } |