diff options
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r-- | sql/sql_parse.cc | 177 |
1 files changed, 62 insertions, 115 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2ef8e9761b1..8a59189e3eb 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -501,9 +501,8 @@ static void handle_bootstrap_impl(THD *thd) #endif /* EMBEDDED_LIBRARY */ thd_proc_info(thd, 0); - thd->security_ctx->priv_user= - thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME)); - thd->security_ctx->priv_host[0]=0; + thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME)); + thd->security_ctx->priv_user[0]= thd->security_ctx->priv_host[0]=0; /* Make the "client" handle multiple results. This is necessary to enable stored procedures with SELECTs and Dynamic SQL @@ -976,96 +975,34 @@ bool dispatch_command(enum enum_server_command command, THD *thd, case COM_CHANGE_USER: { status_var_increment(thd->status_var.com_other); - char *user= (char*) packet, *packet_end= packet + packet_length; - /* Safe because there is always a trailing \0 at the end of the packet */ - char *passwd= strend(user)+1; thd->change_user(); thd->clear_error(); // if errors from rollback - /* - Old clients send null-terminated string ('\0' for empty string) for - password. New clients send the size (1 byte) + string (not null - terminated, so also '\0' for empty string). + /* acl_authenticate() takes the data from net->read_pos */ + net->read_pos= (uchar*)packet; - Cast *passwd to an unsigned char, so that it doesn't extend the sign - for *passwd > 127 and become 2**32-127 after casting to uint. - */ - char db_buff[NAME_LEN+1]; // buffer to store db in utf8 - char *db= passwd; - char *save_db; - /* - If there is no password supplied, the packet must contain '\0', - in any type of handshake (4.1 or pre-4.1). - */ - if (passwd >= packet_end) - { - my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); - break; - } - uint passwd_len= (thd->client_capabilities & CLIENT_SECURE_CONNECTION ? - (uchar)(*passwd++) : strlen(passwd)); - uint dummy_errors, save_db_length, db_length; - int res; + uint save_db_length= thd->db_length; + char *save_db= thd->db; + USER_CONN *save_user_connect= thd->user_connect; Security_context save_security_ctx= *thd->security_ctx; - USER_CONN *save_user_connect; - - db+= passwd_len + 1; - /* - Database name is always NUL-terminated, so in case of empty database - the packet must contain at least the trailing '\0'. - */ - if (db >= packet_end) - { - my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); - break; - } - db_length= strlen(db); - - char *ptr= db + db_length + 1; - uint cs_number= 0; - - if (ptr < packet_end) - { - if (ptr + 2 > packet_end) - { - my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); - break; - } - - cs_number= uint2korr(ptr); - } - - /* Convert database name to utf8 */ - db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1, - system_charset_info, db, db_length, - thd->charset(), &dummy_errors)]= 0; - db= db_buff; + CHARSET_INFO *save_character_set_client= + thd->variables.character_set_client; + CHARSET_INFO *save_collation_connection= + thd->variables.collation_connection; + CHARSET_INFO *save_character_set_results= + thd->variables.character_set_results; - /* Save user and privileges */ - save_db_length= thd->db_length; - save_db= thd->db; - save_user_connect= thd->user_connect; - - if (!(thd->security_ctx->user= my_strdup(user, MYF(0)))) - { - thd->security_ctx->user= save_security_ctx.user; - my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); - break; - } - - /* Clear variables that are allocated */ - thd->user_connect= 0; - thd->security_ctx->priv_user= thd->security_ctx->user; - res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE); - - if (res) + if (acl_authenticate(thd, 0, packet_length)) { my_free(thd->security_ctx->user); *thd->security_ctx= save_security_ctx; thd->user_connect= save_user_connect; - thd->db= save_db; - thd->db_length= save_db_length; + thd->reset_db (save_db, save_db_length); + thd->variables.character_set_client= save_character_set_client; + thd->variables.collation_connection= save_collation_connection; + thd->variables.character_set_results= save_character_set_results; + thd->update_charset(); } else { @@ -1076,12 +1013,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, #endif /* NO_EMBEDDED_ACCESS_CHECKS */ my_free(save_db); my_free(save_security_ctx.user); - - if (cs_number) - { - thd_init_client_charset(thd, cs_number); - thd->update_charset(); - } } break; } @@ -3844,7 +3775,8 @@ end_with_restore_list: case SQLCOM_REVOKE: case SQLCOM_GRANT: { - if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL, + if (lex->type != TYPE_ENUM_PROXY && + check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL, first_table ? first_table->db : select_lex->db, first_table ? &first_table->grant.privilege : NULL, first_table ? &first_table->grant.m_internal : NULL, @@ -3854,6 +3786,7 @@ end_with_restore_list: if (thd->security_ctx->user) // If not replication { LEX_USER *user, *tmp_user; + bool first_user= TRUE; List_iterator <LEX_USER> user_list(lex->users_list); while ((tmp_user= user_list++)) @@ -3868,20 +3801,23 @@ end_with_restore_list: user->host.str); // Are we trying to change a password of another user DBUG_ASSERT(user->host.str != 0); - if (strcmp(thd->security_ctx->user, user->user.str) || - my_strcasecmp(system_charset_info, - user->host.str, thd->security_ctx->host_or_ip)) + + /* + GRANT/REVOKE PROXY has the target user as a first entry in the list. + */ + if (lex->type == TYPE_ENUM_PROXY && first_user) { - // TODO: use check_change_password() - if (is_acl_user(user->host.str, user->user.str) && - user->password.str && - check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 1)) - { - my_message(ER_PASSWORD_NOT_ALLOWED, - ER(ER_PASSWORD_NOT_ALLOWED), MYF(0)); + first_user= FALSE; + if (acl_check_proxy_grant_access (thd, user->host.str, user->user.str, + lex->grant & GRANT_ACL)) goto error; - } - } + } + else if (is_acl_user(user->host.str, user->user.str) && + user->password.str && + check_change_password (thd, user->host.str, user->user.str, + user->password.str, + user->password.length)) + goto error; } } if (first_table) @@ -3916,16 +3852,19 @@ end_with_restore_list: } else { - if (lex->columns.elements || lex->type) + if (lex->columns.elements || (lex->type && lex->type != TYPE_ENUM_PROXY)) { my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER(ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0)); goto error; } else - /* Conditionally writes to binlog */ - res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant, - lex->sql_command == SQLCOM_REVOKE); + { + /* Conditionally writes to binlog */ + res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant, + lex->sql_command == SQLCOM_REVOKE, + lex->type == TYPE_ENUM_PROXY); + } if (!res) { if (lex->sql_command == SQLCOM_GRANT) @@ -4221,8 +4160,8 @@ end_with_restore_list: if (sp_grant_privileges(thd, lex->sphead->m_db.str, name, lex->sql_command == SQLCOM_CREATE_PROCEDURE)) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_PROC_AUTO_GRANT_FAIL, - ER(ER_PROC_AUTO_GRANT_FAIL)); + ER_PROC_AUTO_GRANT_FAIL, ER(ER_PROC_AUTO_GRANT_FAIL)); + thd->clear_error(); } /* @@ -5108,12 +5047,19 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, { // We can never grant this DBUG_PRINT("error",("No possible access")); if (!no_errors) - my_error(ER_ACCESS_DENIED_ERROR, MYF(0), - sctx->priv_user, - sctx->priv_host, - (thd->password ? - ER(ER_YES) : - ER(ER_NO))); /* purecov: tested */ + { + if (thd->password == 2) + my_error(ER_ACCESS_DENIED_NO_PASSWORD_ERROR, MYF(0), + sctx->priv_user, + sctx->priv_host); + else + my_error(ER_ACCESS_DENIED_ERROR, MYF(0), + sctx->priv_user, + sctx->priv_host, + (thd->password ? + ER(ER_YES) : + ER(ER_NO))); /* purecov: tested */ + } DBUG_RETURN(TRUE); /* purecov: tested */ } @@ -7604,8 +7550,9 @@ void get_default_definer(THD *thd, LEX_USER *definer) definer->host.str= (char *) sctx->priv_host; definer->host.length= strlen(definer->host.str); - definer->password.str= NULL; - definer->password.length= 0; + definer->password= null_lex_str; + definer->plugin= empty_lex_str; + definer->auth= empty_lex_str; } |