diff options
author | unknown <monty@mashka.mysql.fi> | 2003-02-14 11:47:41 +0200 |
---|---|---|
committer | unknown <monty@mashka.mysql.fi> | 2003-02-14 11:47:41 +0200 |
commit | 5a12dff30bc694f8d0af923b0bd2a5b79912d2ca (patch) | |
tree | 2bcccee0d1ca3eede87c86ba444c18bb917dd8cd /sql | |
parent | 86ec3c8f085c65b9ac2ef8776cad956465abddd7 (diff) | |
download | mariadb-git-5a12dff30bc694f8d0af923b0bd2a5b79912d2ca.tar.gz |
Fixed problem when connecting to user without a password.
Fixed problem with LIKE and BINARY
BitKeeper/etc/ignore:
added scripts/fill_help_tables
client/mysqltest.c:
Better error messages
libmysql/libmysql.c:
Simple code cleanup
Simplified connect() and change_user() by using sub function
libmysqld/lib_sql.cc:
Ensure that new fields in MYSQL_FIELD structure is used
mysql-test/r/rpl_user_variables.result:
Cleaned up test
mysql-test/r/type_blob.result:
New test
mysql-test/t/rpl_user_variables.test:
Cleaned up test
mysql-test/t/type_blob.test:
New test
sql/item.cc:
Fixed that Item_ref returns the right character set
sql/item_cmpfunc.cc:
Fixed problem with LIKE and BINARY
sql/item_func.cc:
Don't store end ASCII(0) for string user variables
(Made some other code easier)
sql/log_event.cc:
Don't store end ASCII(0) for string user variables.
Fixed comment style
Some optimizations
sql/log_event.h:
Optimized type
sql/mini_client.cc:
Indentation changes
sql/mysql_priv.h:
Made is_update_query extern
sql/protocol.cc:
Simple code cleanup
sql/sql_acl.cc:
Code cleanup
Fixed problem when connecting to user without a password.
sql/sql_lex.h:
Fixed problem with uninitialized memory
sql/sql_parse.cc:
Fixed problem with user without passwords
Fixed some connect problems.
sql/time.cc:
removed reference to uninitialized memory
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 4 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 28 | ||||
-rw-r--r-- | sql/item_func.cc | 32 | ||||
-rw-r--r-- | sql/log_event.cc | 126 | ||||
-rw-r--r-- | sql/log_event.h | 2 | ||||
-rw-r--r-- | sql/mini_client.cc | 6 | ||||
-rw-r--r-- | sql/mysql_priv.h | 1 | ||||
-rw-r--r-- | sql/protocol.cc | 7 | ||||
-rw-r--r-- | sql/sql_acl.cc | 87 | ||||
-rw-r--r-- | sql/sql_lex.h | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 131 | ||||
-rw-r--r-- | sql/time.cc | 6 |
12 files changed, 207 insertions, 225 deletions
diff --git a/sql/item.cc b/sql/item.cc index ee7af1ae0fd..50f87235196 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1203,18 +1203,22 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) max_length= (*ref)->max_length; maybe_null= (*ref)->maybe_null; decimals= (*ref)->decimals; + set_charset((*ref)->charset()); fixed= 1; + if (ref && (*ref)->check_cols(1)) return 1; return 0; } + bool Item_default_value::eq(const Item *item, bool binary_cmp) const { return item->type() == DEFAULT_VALUE_ITEM && ((Item_default_value *)item)->arg->eq(arg, binary_cmp); } + bool Item_default_value::fix_fields(THD *thd, struct st_table_list *table_list, Item **items) { if (!arg) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index b189f34912c..8804bb56f6b 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1129,11 +1129,16 @@ void in_string::set(uint pos,Item *item) String *res=item->val_str(str); if (res && res != str) *str= *res; - // BAR TODO: I'm not sure this is absolutely correct if (!str->charset()) - str->set_charset(default_charset_info); + { + CHARSET_INFO *cs; + if (!(cs= item->charset())) + cs= default_charset_info; // Should never happen for STR items + str->set_charset(cs); + } } + byte *in_string::get_value(Item *item) { return (byte*) item->val_str(&tmp); @@ -1692,6 +1697,7 @@ longlong Item_func_isnull::val_int() return args[0]->is_null() ? 1: 0; } + longlong Item_func_isnotnull::val_int() { return args[0]->is_null() ? 0 : 1; @@ -1713,9 +1719,6 @@ longlong Item_func_like::val_int() return 0; } null_value=0; - if ((res->charset()->state & MY_CS_BINSORT) || - (res2->charset()->state & MY_CS_BINSORT)) - set_charset(&my_charset_bin); if (canDoTurboBM) return turboBM_matches(res->ptr(), res->length()) ? 1 : 0; return my_wildcmp(charset(), @@ -1748,10 +1751,19 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref) return 1; /* - TODO--we could do it for non-const, but we'd have to - recompute the tables for each row--probably not worth it. + Comparision is by default done according to character set of LIKE + */ + if (binary_cmp) + set_charset(&my_charset_bin); + else + set_charset(args[1]->charset()); + + /* + We could also do boyer-more for non-const items, but as we would have to + recompute the tables for each row it's not worth it. */ - if (args[1]->const_item() && !(specialflag & SPECIAL_NO_NEW_FUNC)) + if (args[1]->const_item() && !use_strnxfrm(charset()) && + !(specialflag & SPECIAL_NO_NEW_FUNC)) { String* res2 = args[1]->val_str(&tmp_value2); if (!res2) diff --git a/sql/item_func.cc b/sql/item_func.cc index 2c8b9e97fb3..45d666fb47b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2083,7 +2083,8 @@ longlong Item_func_set_user_var::val_int() { longlong value=args[0]->val_int(); - update_hash((void*) &value,sizeof(longlong),INT_RESULT, default_charset_info); + update_hash((void*) &value, sizeof(longlong), INT_RESULT, + default_charset_info); return value; } @@ -2092,9 +2093,10 @@ Item_func_set_user_var::val_str(String *str) { String *res=args[0]->val_str(str); if (!res) // Null value - update_hash((void*) 0, 0, STRING_RESULT, default_charset_info); + update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin); else - update_hash(res->c_ptr(),res->length()+1,STRING_RESULT,res->charset()); + update_hash((void*) res->ptr(), res->length(), STRING_RESULT, + res->charset()); return res; } @@ -2129,13 +2131,13 @@ Item_func_get_user_var::val_str(String *str) return NULL; switch (entry->type) { case REAL_RESULT: - str->set(*(double*) entry->value,decimals,thd_charset()); + str->set(*(double*) entry->value,decimals, &my_charset_bin); break; case INT_RESULT: - str->set(*(longlong*) entry->value,thd_charset()); + str->set(*(longlong*) entry->value, &my_charset_bin); break; case STRING_RESULT: - if (str->copy(entry->value, entry->length-1, entry->var_charset)) + if (str->copy(entry->value, entry->length, entry->var_charset)) { null_value=1; return NULL; @@ -2191,8 +2193,6 @@ longlong Item_func_get_user_var::val_int() return LL(0); // Impossible } -/* From sql_parse.cc */ -extern bool is_update_query(enum enum_sql_command command); void Item_func_get_user_var::fix_length_and_dec() { @@ -2207,13 +2207,15 @@ void Item_func_get_user_var::fix_length_and_dec() if (opt_bin_log && is_update_query(thd->lex.sql_command) && var_entry->used_query_id != thd->query_id) { + uint size; /* - First we need to store value of var_entry, when the next situation appers: + First we need to store value of var_entry, when the next situation + appers: > set @a:=1; > insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1); We have to write to binlog value @a= 1; */ - uint size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length; + size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length; if (!(user_var_event= (BINLOG_USER_VAR_EVENT *) thd->alloc(size))) goto err; @@ -2240,6 +2242,7 @@ void Item_func_get_user_var::fix_length_and_dec() } } return; + err: thd->fatal_error(); return; @@ -2247,7 +2250,9 @@ err: bool Item_func_get_user_var::const_item() const -{ return var_entry && current_thd->query_id != var_entry->update_query_id; } +{ + return var_entry && current_thd->query_id != var_entry->update_query_id; +} enum Item_result Item_func_get_user_var::result_type() const @@ -2275,14 +2280,9 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const if (this == item) return 1; // Same item is same. /* Check if other type is also a get_user_var() object */ -#ifdef FIX_THIS - if (item->eq == &Item_func_get_user_var::eq) - return 0; -#else if (item->type() != FUNC_ITEM || ((Item_func*) item)->func_name() != func_name()) return 0; -#endif Item_func_get_user_var *other=(Item_func_get_user_var*) item; return (name.length == other->name.length && !memcmp(name.str, other->name.str, name.length)); diff --git a/sql/log_event.cc b/sql/log_event.cc index 0631e21fbd1..6bd187ab8af 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1899,19 +1899,10 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli) #endif -/***************************************************************************** - ***************************************************************************** - - Rand_log_event methods - - ***************************************************************************** - ****************************************************************************/ - -/***************************************************************************** - - Rand_log_event::pack_info() +/**************************************************************************** + Rand_log_event methods +****************************************************************************/ - ****************************************************************************/ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) void Rand_log_event::pack_info(Protocol *protocol) { @@ -1924,11 +1915,7 @@ void Rand_log_event::pack_info(Protocol *protocol) } #endif -/***************************************************************************** - - Rand_log_event::Rand_log_event() - ****************************************************************************/ Rand_log_event::Rand_log_event(const char* buf, bool old_format) :Log_event(buf, old_format) { @@ -1937,11 +1924,7 @@ Rand_log_event::Rand_log_event(const char* buf, bool old_format) seed2 = uint8korr(buf+RAND_SEED2_OFFSET); } -/***************************************************************************** - Rand_log_event::write_data() - - ****************************************************************************/ int Rand_log_event::write_data(IO_CACHE* file) { char buf[16]; @@ -1950,11 +1933,7 @@ int Rand_log_event::write_data(IO_CACHE* file) return my_b_safe_write(file, (byte*) buf, sizeof(buf)); } -/***************************************************************************** - - Rand_log_event::print() - ****************************************************************************/ #ifdef MYSQL_CLIENT void Rand_log_event::print(FILE* file, bool short_form, char* last_db) { @@ -1970,11 +1949,7 @@ void Rand_log_event::print(FILE* file, bool short_form, char* last_db) } #endif // MYSQL_CLIENT -/***************************************************************************** - - Rand_log_event::exec_event() - ****************************************************************************/ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) int Rand_log_event::exec_event(struct st_relay_log_info* rli) { @@ -1986,19 +1961,10 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli) #endif // !MYSQL_CLIENT -/***************************************************************************** - ***************************************************************************** - - User_var_log_event methods - - ***************************************************************************** - ****************************************************************************/ - -/***************************************************************************** +/*************************************************************************** + User_var_log_event methods +***************************************************************************/ - User_var_log_event::pack_info() - - ****************************************************************************/ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) void User_var_log_event::pack_info(Protocol* protocol) { @@ -2019,8 +1985,8 @@ void User_var_log_event::pack_info(Protocol* protocol) double real_val; float8get(real_val, val); buf= my_malloc(val_offset + FLOATING_POINT_BUFFER, MYF(MY_WME)); - event_len += my_sprintf(buf + val_offset, - (buf + val_offset, "%.14g", real_val)); + event_len+= my_sprintf(buf + val_offset, + (buf + val_offset, "%.14g", real_val)); break; case INT_RESULT: buf= my_malloc(val_offset + 22, MYF(MY_WME)); @@ -2032,11 +1998,11 @@ void User_var_log_event::pack_info(Protocol* protocol) only. But be carefull this is may be incorrect in other cases as string may contain \ and '. */ - buf= my_malloc(val_offset + 2 + val_len, MYF(MY_WME)); + event_len= val_offset + 2 + val_len; + buf= my_malloc(event_len, MYF(MY_WME)); buf[val_offset]= '\''; memcpy(buf + val_offset + 1, val, val_len); - buf[val_offset + val_len]= '\''; - event_len= val_offset + 1 + val_len; + buf[val_offset + val_len + 1]= '\''; break; case ROW_RESULT: DBUG_ASSERT(1); @@ -2050,18 +2016,16 @@ void User_var_log_event::pack_info(Protocol* protocol) my_free(buf, MYF(MY_ALLOW_ZERO_PTR)); } #endif // !MYSQL_CLIENT -/***************************************************************************** - User_var_log_event::User_var_log_event() - ****************************************************************************/ User_var_log_event::User_var_log_event(const char* buf, bool old_format) :Log_event(buf, old_format) { buf+= (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN; name_len= uint4korr(buf); name= (char *) buf + UV_NAME_LEN_SIZE; - is_null= buf[UV_NAME_LEN_SIZE + name_len]; + buf+= UV_NAME_LEN_SIZE + name_len; + is_null= (bool) *buf; if (is_null) { type= STRING_RESULT; @@ -2070,22 +2034,16 @@ User_var_log_event::User_var_log_event(const char* buf, bool old_format) } else { - type= (Item_result) buf[UV_VAL_IS_NULL + UV_NAME_LEN_SIZE + name_len]; - charset_number= uint4korr(buf + UV_NAME_LEN_SIZE + name_len + - UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE); - val_len= uint4korr(buf + UV_NAME_LEN_SIZE + name_len + - UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + + type= (Item_result) buf[UV_VAL_IS_NULL]; + charset_number= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE); + val_len= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE); - val= (char *) buf + UV_NAME_LEN_SIZE + name_len + UV_VAL_IS_NULL + - UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE; + val= (char *) (buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE); } } -/***************************************************************************** - - User_var_log_event::write_data() - ****************************************************************************/ int User_var_log_event::write_data(IO_CACHE* file) { char buf[UV_NAME_LEN_SIZE]; @@ -2224,19 +2182,9 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) #endif // !MYSQL_CLIENT -/***************************************************************************** - ***************************************************************************** - - Slave_log_event methods - - ***************************************************************************** - ****************************************************************************/ - -/***************************************************************************** - - Slave_log_event::pack_info() - - ****************************************************************************/ +/**************************************************************************** + Slave_log_event methods +****************************************************************************/ #ifdef HAVE_REPLICATION #ifndef MYSQL_CLIENT @@ -2255,11 +2203,7 @@ void Slave_log_event::pack_info(Protocol *protocol) } #endif // !MYSQL_CLIENT -/***************************************************************************** - - Slave_log_event::Slave_log_event() - ****************************************************************************/ #ifndef MYSQL_CLIENT Slave_log_event::Slave_log_event(THD* thd_arg, struct st_relay_log_info* rli) @@ -2296,21 +2240,13 @@ Slave_log_event::Slave_log_event(THD* thd_arg, } #endif // !MYSQL_CLIENT -/***************************************************************************** - - Slave_log_event dtor - ****************************************************************************/ Slave_log_event::~Slave_log_event() { my_free(mem_pool, MYF(MY_ALLOW_ZERO_PTR)); } -/***************************************************************************** - - Slave_log_event::print() - ****************************************************************************/ #ifdef MYSQL_CLIENT void Slave_log_event::print(FILE* file, bool short_form, char* last_db) { @@ -2325,21 +2261,13 @@ master_log: '%s' master_pos: %s\n", } #endif // MYSQL_CLIENT -/***************************************************************************** - - Slave_log_event::get_data_size() - ****************************************************************************/ int Slave_log_event::get_data_size() { return master_host_len + master_log_len + 1 + SL_MASTER_HOST_OFFSET; } -/***************************************************************************** - - Slave_log_event::write_data() - ****************************************************************************/ int Slave_log_event::write_data(IO_CACHE* file) { int8store(mem_pool + SL_MASTER_POS_OFFSET, master_pos); @@ -2348,11 +2276,7 @@ int Slave_log_event::write_data(IO_CACHE* file) return my_b_safe_write(file, (byte*)mem_pool, get_data_size()); } -/***************************************************************************** - - Slave_log_event::init_from_mem_pool() - ****************************************************************************/ void Slave_log_event::init_from_mem_pool(int data_size) { master_pos = uint8korr(mem_pool + SL_MASTER_POS_OFFSET); @@ -2369,11 +2293,7 @@ void Slave_log_event::init_from_mem_pool(int data_size) master_log_len = strlen(master_log); } -/***************************************************************************** - - Slave_log_event::Slave_log_event() - ****************************************************************************/ Slave_log_event::Slave_log_event(const char* buf, int event_len) :Log_event(buf,0),mem_pool(0),master_host(0) { @@ -2387,11 +2307,7 @@ Slave_log_event::Slave_log_event(const char* buf, int event_len) init_from_mem_pool(event_len); } -/***************************************************************************** - - Slave_log_event::exec_event() - ****************************************************************************/ #ifndef MYSQL_CLIENT int Slave_log_event::exec_event(struct st_relay_log_info* rli) { diff --git a/sql/log_event.h b/sql/log_event.h index 567bf279ff1..b9b1355a304 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -635,7 +635,7 @@ public: ulong val_len; Item_result type; uint charset_number; - byte is_null; + bool is_null; #ifndef MYSQL_CLIENT User_var_log_event(THD* thd_arg, char *name_arg, uint name_len_arg, char *val_arg, ulong val_len_arg, Item_result type_arg, diff --git a/sql/mini_client.cc b/sql/mini_client.cc index 2ee4b551d71..db3a51712f2 100644 --- a/sql/mini_client.cc +++ b/sql/mini_client.cc @@ -830,13 +830,15 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, } } else + { /* - Real scramble is only sent to old servers. This can be blocked - by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1); + 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)); + } /* Add database if needed */ if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB)) { diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index dd5bee2eed5..570bddfe773 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -346,6 +346,7 @@ int quick_rm_table(enum db_type base,const char *db, bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list); bool mysql_change_db(THD *thd,const char *name); void mysql_parse(THD *thd,char *inBuf,uint length); +bool is_update_query(enum enum_sql_command command); void free_items(Item *item); bool alloc_query(THD *thd, char *packet, ulong packet_length); void mysql_init_select(LEX *lex); diff --git a/sql/protocol.cc b/sql/protocol.cc index c338feea9bc..ebee87806db 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -295,11 +295,12 @@ void send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) { NET *net= &thd->net; - if (net->no_send_ok || !net->vio) // hack for re-parsing queries - return; - char buff[MYSQL_ERRMSG_SIZE+10],*pos; DBUG_ENTER("send_ok"); + + if (net->no_send_ok || !net->vio) // hack for re-parsing queries + DBUG_VOID_RETURN; + buff[0]=0; // No fields pos=net_store_length(buff+1,(ulonglong) affected_rows); pos=net_store_length(pos, (ulonglong) id); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 40dddaad08e..41b825e3322 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -485,7 +485,7 @@ void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble) Get master privilges for user (priviliges for all tables). Required before connecting to MySQL - as we have 2 stage handshake now we cache user not to lookup + As we have 2 stage handshake now we cache user not to lookup it second time. At the second stage we do not lookup user in case we already know it; @@ -494,14 +494,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, - uint *cur_priv_version,ACL_USER** hint_user) + uint *cur_priv_version, ACL_USER **cached_user) { ulong user_access=NO_ACCESS; *priv_user= (char*) user; bool password_correct= 0; - int stage= (*hint_user != NULL); /* NULL passed as first stage */ + int stage= (*cached_user != NULL); /* NULL passed as first stage */ ACL_USER *acl_user= NULL; - DBUG_ENTER("acl_getroot"); bzero(mqh,sizeof(USER_RESOURCES)); @@ -512,7 +511,6 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, } VOID(pthread_mutex_lock(&acl_cache->lock)); - /* Get possible access from user_list. This is or'ed to others not fully specified @@ -520,9 +518,10 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, If we have cached user use it, in other case look it up. */ - if (stage && (*cur_priv_version==priv_version)) - acl_user=*hint_user; + if (stage && (*cur_priv_version == priv_version)) + acl_user= *cached_user; else + { for (uint i=0 ; i < acl_users.elements ; i++) { ACL_USER *acl_user_search=dynamic_element(&acl_users,i,ACL_USER*); @@ -531,60 +530,59 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, if (compare_hostname(&acl_user_search->host,host,ip)) { /* Found mathing user */ - acl_user=acl_user_search; + acl_user= acl_user_search; /* Store it as a cache */ - *hint_user=acl_user; - *cur_priv_version=priv_version; + *cached_user= acl_user; + *cur_priv_version= priv_version; break; } } } - + } /* Now we have acl_user found and may start our checks */ if (acl_user) { /* Password should present for both or absend for both */ - if (!acl_user->password && !*password || - (acl_user->password && *password)) + if (!acl_user->password && !*password) + password_correct=1; + else if (!acl_user->password || !*password) { - /* Quick check and accept for empty passwords*/ - if (!acl_user->password && !*password) - password_correct=1; - else /* Normal password presents */ + *cached_user= 0; // Impossible to connect + } + else + { + /* New version password is checked differently */ + if (acl_user->pversion) { - /* New version password is checked differently */ - if (acl_user->pversion) - { - if (stage) /* We check password only on the second stage */ - { - if (!validate_password(password,message,acl_user->salt)) - password_correct=1; - } - else /* First stage - just prepare scramble */ - prepare_scramble(thd,acl_user,prepared_scramble); - } - /* Old way to check password */ - else - { - /* Checking the scramble at any stage. First - old clients */ - if (!check_scramble(password,message,acl_user->salt, - (my_bool) old_ver)) - password_correct=1; - else if (!stage) /* Here if password incorrect */ - { - /* At the first stage - prepare scramble */ - prepare_scramble(thd,acl_user,prepared_scramble); - } - } + if (stage) /* We check password only on the second stage */ + { + if (!validate_password(password,message,acl_user->salt)) + password_correct=1; + } + else /* First stage - just prepare scramble */ + prepare_scramble(thd,acl_user,prepared_scramble); + } + /* Old way to check password */ + else + { + /* Checking the scramble at any stage. First - old clients */ + if (!check_scramble(password,message,acl_user->salt, + (my_bool) old_ver)) + password_correct=1; + else if (!stage) /* Here if password incorrect */ + { + /* At the first stage - prepare scramble */ + prepare_scramble(thd,acl_user,prepared_scramble); + } } } } /* If user not found password_correct will also be zero */ if (!password_correct) - goto unlock_and_exit; + goto unlock_and_exit; /* OK. User found and password checked continue validation */ @@ -1120,7 +1118,10 @@ bool change_password(THD *thd, const char *host, const char *user, if (check_change_password(thd, host, user)) DBUG_RETURN(1); - /* password should always be 0,16 or 45 chars; simple hack to avoid cracking */ + /* + password should always be 0,16 or 45 chars; + Simple hack to avoid cracking + */ length=(uint) strlen(new_password); if (length!=45) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 00852f302d8..60f48f293e4 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -225,7 +225,7 @@ public: return (void*) sql_calloc((uint) size); } static void operator delete(void *ptr,size_t size) {} - st_select_lex_node() {} + st_select_lex_node(): linkage(UNSPECIFIED_TYPE) {} virtual ~st_select_lex_node() {} inline st_select_lex_node* get_master() { return master; } virtual void init_query(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ba5862a7fde..d69f95e7248 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -181,32 +181,57 @@ end: /* Check if user is ok - Updates: - thd->user, thd->master_access, thd->priv_user, thd->db, thd->db_access + + SYNOPSIS + check_user() + thd Thread handle + command Command for connection (for log) + user Name of user trying to connect + passwd Scrambled password sent from client + db Database to connect to + check_count If set to 1, don't allow too many connection + simple_connect If 1 then client is of old type and we should connect + using the old method (no challange) + do_send_error Set to 1 if we should send error to user + prepared_scramble Buffer to store hash password of new connection + had_password Set to 1 if the user gave a password + cur_priv_version Check flag to know if someone flushed the privileges + since last code + hint_user Pointer used by acl_getroot() to remmeber user for + next call + + RETURN + 0 ok + thd->user, thd->master_access, thd->priv_user, thd->db and + thd->db_access are updated + 1 Access denied; Error sent to client + -1 If do_send_error == 1: Failed connect, error sent to client + If do_send_error == 0: Prepare for stage of connect */ static int check_user(THD *thd,enum_server_command command, const char *user, const char *passwd, const char *db, bool check_count, bool simple_connect, bool do_send_error, - char *crypted_scramble, bool had_password, + char *prepared_scramble, bool had_password, uint *cur_priv_version, ACL_USER** hint_user) { thd->db=0; thd->db_length=0; USER_RESOURCES ur; + DBUG_ENTER("check_user"); /* We shall avoid dupplicate user allocations here */ if (!thd->user && !(thd->user = my_strdup(user, MYF(0)))) { send_error(thd,ER_OUT_OF_RESOURCES); - return 1; + DBUG_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,crypted_scramble, + &ur,prepared_scramble, cur_priv_version,hint_user); DBUG_PRINT("info", @@ -222,8 +247,9 @@ static int check_user(THD *thd,enum_server_command command, const char *user, */ if (thd->master_access & NO_ACCESS) { - if (do_send_error) + if (do_send_error || !had_password || !*hint_user) { + DBUG_PRINT("info",("Access denied")); /* Old client should get nicer error message if password version is not supported @@ -244,10 +270,10 @@ static int check_user(THD *thd,enum_server_command command, const char *user, thd->host_or_ip, had_password ? ER(ER_YES) : ER(ER_NO)); } - return(1); // Error already given + DBUG_RETURN(1); // Error already given } - else - return(-1); // do not report error in special handshake + DBUG_PRINT("info",("Prepare for second part of handshake")); + DBUG_RETURN(-1); // no report error in special handshake } if (check_count) @@ -259,7 +285,7 @@ static int check_user(THD *thd,enum_server_command command, const char *user, if (tmp) { // Too many connections send_error(thd, ER_CON_COUNT_ERROR); - return(1); + DBUG_RETURN(1); } } mysql_log.write(thd,command, @@ -273,21 +299,20 @@ static int check_user(THD *thd,enum_server_command command, const char *user, /* Don't allow user to connect if he has done too many queries */ if ((ur.questions || ur.updates || ur.connections) && get_or_create_user_conn(thd,user,thd->host_or_ip,&ur)) - return -1; + DBUG_RETURN(1); if (thd->user_connect && thd->user_connect->user_resources.connections && check_for_max_user_connections(thd, thd->user_connect)) - return -1; + DBUG_RETURN(1); if (db && db[0]) { - bool error=test(mysql_change_db(thd,db)); + int error= test(mysql_change_db(thd,db)); if (error && thd->user_connect) decrease_user_connections(thd->user_connect); - return error; + DBUG_RETURN(error); } - else - send_ok(thd); // Ready to handle questions - return 0; // ok + send_ok(thd); // Ready to handle questions + DBUG_RETURN(0); // ok } @@ -492,24 +517,35 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0) /* - Check connnetion and get priviliges - Returns 0 on ok, -1 < if error is given > 0 on error. + Check connnectionn and get priviliges + + SYNOPSIS + check_connections + thd Thread handle + + RETURN + 0 ok + -1 Error, which is sent to user + > 0 Error code (not sent to user) */ #ifndef EMBEDDED_LIBRARY static int check_connections(THD *thd) { + int res; uint connect_errors=0; + uint cur_priv_version; + bool using_password; NET *net= &thd->net; char *end, *user, *passwd, *db; char prepared_scramble[SCRAMBLE41_LENGTH+4]; /* Buffer for scramble&hash */ ACL_USER* cached_user=NULL; /* Initialise to NULL for first stage */ - uint cur_priv_version; DBUG_PRINT("info",("New connection received on %s", vio_description(net->vio))); + /* Remove warning from valgrind. TODO: Fix it in password.c */ - bzero((char*) prepared_scramble, sizeof(prepared_scramble)); + bzero((char*) &prepared_scramble[0], sizeof(prepared_scramble)); if (!thd->host) // If TCP/IP connection { char ip[30]; @@ -648,11 +684,12 @@ check_connections(THD *thd) user= end; passwd= strend(user)+1; db=0; + using_password= test(passwd[0]); 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) + if (using_password && strlen(passwd) != SCRAMBLE_LENGTH) return ER_HANDSHAKE_ERROR; if (thd->client_capabilities & CLIENT_INTERACTIVE) @@ -665,24 +702,23 @@ check_connections(THD *thd) /* 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, - simple_connect, prepared_scramble, using_password, - &cur_priv_version, - &cached_user)<0) + if ((res=check_user(thd, COM_CONNECT, user, passwd, db, 1, simple_connect, + simple_connect, prepared_scramble, using_password, + &cur_priv_version, + &cached_user)) < 0) { /* Store current used and database as they are erased with next packet */ char tmp_user[USERNAME_LENGTH+1]; char tmp_db[NAME_LEN+1]; - tmp_user[0]= tmp_db[0]= 0; - /* If The client is old we just have to return error */ + /* If the client is old we just have to return error */ if (simple_connect) return -1; + DBUG_PRINT("info",("password challenge")); + + tmp_user[0]= tmp_db[0]= 0; if (user) strmake(tmp_user,user,USERNAME_LENGTH); if (db) @@ -714,10 +750,13 @@ check_connections(THD *thd) &cached_user)) return -1; } + else if (res) + return -1; // Error sent from check_user() thd->password=using_password; return 0; } + pthread_handler_decl(handle_one_connection,arg) { THD *thd=(THD*) arg; @@ -1014,14 +1053,15 @@ bool do_command(THD *thd) net->read_timeout=old_timeout; // restore it DBUG_RETURN(dispatch_command(command,thd, packet+1, (uint) packet_length)); } - #endif /* EMBEDDED_LIBRARY */ + bool dispatch_command(enum enum_server_command command, THD *thd, char* packet, uint packet_length) { + int res; NET *net= &thd->net; - bool error=0; + bool error= 0; /* Commands which will always take a long time should be marked with this so that they will not get logged to the slow query log @@ -1098,6 +1138,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, uint cur_priv_version; /* Cached grant version */ ulong pkt_len=0; /* Length of reply packet */ + bzero((char*) prepared_scramble, sizeof(prepared_scramble)); /* Small check for incomming packet */ if ((uint) ((uchar*) db - net->read_pos) > packet_length) @@ -1124,13 +1165,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd, Check user permissions. If password failure we'll get scramble back Do not retry if we already have sent error (result>0) */ - if (check_user(thd,COM_CHANGE_USER, user, passwd, db, 0, simple_connect, - simple_connect, prepared_scramble, using_password, &cur_priv_version, - &cached_user) < 0) + if ((res=check_user(thd,COM_CHANGE_USER, user, passwd, db, 0, + simple_connect, simple_connect, prepared_scramble, + using_password, &cur_priv_version, &cached_user)) < 0) { - /* If The client is old we just have to have auth failure */ + /* If the client is old we just have to have auth failure */ if (simple_connect) - goto restore_user; /* Error is already reported */ + goto restore_user; /* Error is already reported */ /* Store current used and database as they are erased with next packet */ tmp_user[0]= tmp_db[0]= 0; @@ -1149,16 +1190,18 @@ bool dispatch_command(enum enum_server_command command, THD *thd, goto restore_user_err; /* We have to get very specific packet size */ - if (pkt_len!=SCRAMBLE41_LENGTH) + if (pkt_len != SCRAMBLE41_LENGTH) goto restore_user; /* Final attempt to check the user based on reply */ if (check_user(thd,COM_CHANGE_USER, tmp_user, (char*) net->read_pos, - tmp_db, 0, 0, 1, prepared_scramble, using_password, - &cur_priv_version, - &cached_user)) + tmp_db, 0, 0, 1, prepared_scramble, using_password, + &cur_priv_version, &cached_user)) goto restore_user; } + else if (res) + goto restore_user; + /* Finally we've authenticated new user */ if (max_connections && save_uc) decrease_user_connections(save_uc); @@ -1168,10 +1211,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; /* Bad luck we shall restore old user */ - restore_user_err: +restore_user_err: send_error(thd, ER_UNKNOWN_COM_ERROR); - restore_user: +restore_user: x_free(thd->user); thd->master_access=save_master_access; thd->db_access=save_db_access; diff --git a/sql/time.cc b/sql/time.cc index 6b2f8b710da..94f9cb2e5e8 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -639,9 +639,11 @@ bool str_to_time(const char *str,uint length,TIME *l_time) for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++) value=value*10L + (long) (*str - '0'); - if (*str == ' ') + /* Move to last space */ + if (str != end && *str == ' ') { - while (++str != end && str[0] == ' ') ; + while (++str != end && str[0] == ' ') + {} str--; } |