
At http://bazaar.launchpad.net/~maria-captains/maria/5.2/ ------------------------------------------------------------ revno: 2793 revision-id: sergii@pisem.net-20100514214532-xb23ovibzuenbd76 parent: sergii@pisem.net-20100512175605-jlpv6idhstvjjzpj committer: Sergei Golubchik <sergii@pisem.net> branch nick: 5.2 timestamp: Fri 2010-05-14 23:45:32 +0200 message: crash on --with-embedded-privilege-control builds: 1. fix broken change user handling (no restart should happen in the normal case) 2. add assert to guarantee that we never send a request to change to the same plugin 3. "fix" plugin string as sent by the client to be able to compare native plugins by pointers 4. more complete MYSQL initialization in the embedded case 5. change_user.test updated to handle -with-embedded-privilege-control builds === modified file 'libmysqld/lib_sql.cc' --- a/libmysqld/lib_sql.cc 2010-03-29 15:13:53 +0000 +++ b/libmysqld/lib_sql.cc 2010-05-14 21:45:32 +0000 @@ -583,6 +583,7 @@ void init_embedded_mysql(MYSQL *mysql, i thd->mysql= mysql; mysql->server_version= server_version; mysql->client_flag= client_flag; + mysql->server_capabilities= client_flag; init_alloc_root(&mysql->field_alloc, 8192, 0); } @@ -694,6 +695,7 @@ int check_embedded_connection(MYSQL *mys memset(thd->scramble, 55, SCRAMBLE_LENGTH); // dummy scramble thd->scramble[SCRAMBLE_LENGTH]= 0; + strcpy(mysql->scramble, thd->scramble); if (mysql->passwd && mysql->passwd[0]) { === modified file 'mysql-test/t/change_user.test' --- a/mysql-test/t/change_user.test 2010-03-29 15:13:53 +0000 +++ b/mysql-test/t/change_user.test 2010-05-14 21:45:32 +0000 @@ -6,19 +6,30 @@ grant select on test.* to test_nopw; grant select on test.* to test_oldpw identified by password "09301740536db389"; grant select on test.* to test_newpw identified by "newpw"; +select concat('<', user(), '>'), concat('<', current_user(), '>'), database(); + # # massaging the data for tests to pass in the embedded server, -# that has authentication completely disabled. +# that has authentication completely disabled or, if enabled, can +# only do new auth (20-byte scramble). # ---replace_result <@> <test_nopw@%> @> @localhost> -select concat('<', user(), '>'), concat('<', current_user(), '>'), database(); - change_user test_nopw; --replace_result <@> <test_nopw@%> @> @localhost> select concat('<', user(), '>'), concat('<', current_user(), '>'), database(); + +# +# embedded with enabled privilege control cannot do plugin negotiation. +# that is, it cannot try to authenticate with a new scramble, receive a request +# to switch to an old scramble, and retry with an old scramble. +# As a result, it cannot change to a user that has old scramble and +# and it stays logged as a previous user - test_nopw in this test file. +# For the embedded with auth we replace nopw with oldpw in the results. +# +let $repl = `select if(version() like '%embedded%' and user() like '%nopw%', 'nopw', 'oldpw')`; + change_user test_oldpw, oldpw; ---replace_result <@> <test_oldpw@%> @> @localhost> +--replace_result <@> <test_oldpw@%> @> @localhost> $repl oldpw select concat('<', user(), '>'), concat('<', current_user(), '>'), database(); change_user test_newpw, newpw; --replace_result <@> <test_newpw@%> @> @localhost> @@ -31,7 +42,7 @@ change_user test_nopw,,test; --replace_result <@> <test_nopw@%> @> @localhost> select concat('<', user(), '>'), concat('<', current_user(), '>'), database(); change_user test_oldpw,oldpw,test; ---replace_result <@> <test_oldpw@%> @> @localhost> +--replace_result <@> <test_oldpw@%> @> @localhost> $repl oldpw select concat('<', user(), '>'), concat('<', current_user(), '>'), database(); change_user test_newpw,newpw,test; --replace_result <@> <test_newpw@%> @> @localhost> === modified file 'sql/sql_acl.cc' --- a/sql/sql_acl.cc 2010-04-14 19:29:40 +0000 +++ b/sql/sql_acl.cc 2010-05-14 21:45:32 +0000 @@ -316,6 +316,19 @@ set_user_salt(ACL_USER *acl_user, const acl_user->salt_len= 0; } +static char *fix_plugin_ptr(char *name) +{ + if (my_strcasecmp(system_charset_info, name, + native_password_plugin_name.str) == 0) + return native_password_plugin_name.str; + else + if (my_strcasecmp(system_charset_info, name, + old_password_plugin_name.str) == 0) + return old_password_plugin_name.str; + else + return name; +} + /** Fix ACL::plugin pointer to point to a hard-coded string, if appropriate @@ -5475,7 +5488,7 @@ static int handle_grant_struct(uint stru host= grant_name->host.hostname; break; default: - assert(0); + DBUG_ASSERT(0); } if (! user) user= ""; @@ -7140,6 +7153,8 @@ static bool send_plugin_request_packet(M ((st_mysql_auth *)(plugin_decl(mpvio->plugin)->info))->client_auth_plugin; DBUG_ASSERT(client_auth_plugin); + DBUG_ASSERT(my_strcasecmp(system_charset_info, client_auth_plugin, + mpvio->cached_client_reply.plugin)); /* we send an old "short 4.0 scramble request", if we need to request a @@ -7346,6 +7361,7 @@ static bool parse_com_change_user_packet my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); return 1; } + client_plugin= fix_plugin_ptr(client_plugin); } else { @@ -7539,6 +7555,7 @@ static ulong parse_client_handshake_pack if ((client_plugin + strlen(client_plugin)) > (char *)net->read_pos + pkt_len) return packet_error; + client_plugin= fix_plugin_ptr(client_plugin); } else { @@ -8143,11 +8160,12 @@ static int native_password_authenticate( /* generate the scramble, or reuse the old one */ if (thd->scramble[SCRAMBLE_LENGTH]) + { create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand); - - /* send it to the client */ - if (mpvio->write_packet(mpvio, (uchar*)thd->scramble, SCRAMBLE_LENGTH + 1)) - return CR_ERROR; + /* and send it to the client */ + if (mpvio->write_packet(mpvio, (uchar*)thd->scramble, SCRAMBLE_LENGTH + 1)) + return CR_ERROR; + } /* reply and authenticate */ @@ -8218,11 +8236,12 @@ static int old_password_authenticate(MYS /* generate the scramble, or reuse the old one */ if (thd->scramble[SCRAMBLE_LENGTH]) + { create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand); - - /* send it to the client */ - if (mpvio->write_packet(mpvio, (uchar*)thd->scramble, SCRAMBLE_LENGTH + 1)) - return CR_ERROR; + /* and send it to the client */ + if (mpvio->write_packet(mpvio, (uchar*)thd->scramble, SCRAMBLE_LENGTH + 1)) + return CR_ERROR; + } /* read the reply and authenticate */ if ((pkt_len= mpvio->read_packet(mpvio, &pkt)) < 0)