summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2003-02-14 11:47:41 +0200
committerunknown <monty@mashka.mysql.fi>2003-02-14 11:47:41 +0200
commit5a12dff30bc694f8d0af923b0bd2a5b79912d2ca (patch)
tree2bcccee0d1ca3eede87c86ba444c18bb917dd8cd /sql
parent86ec3c8f085c65b9ac2ef8776cad956465abddd7 (diff)
downloadmariadb-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.cc4
-rw-r--r--sql/item_cmpfunc.cc28
-rw-r--r--sql/item_func.cc32
-rw-r--r--sql/log_event.cc126
-rw-r--r--sql/log_event.h2
-rw-r--r--sql/mini_client.cc6
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/protocol.cc7
-rw-r--r--sql/sql_acl.cc87
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_parse.cc131
-rw-r--r--sql/time.cc6
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--;
}