Commit 17053698 authored by unknown's avatar unknown

SCRUM:

WL#604 Privileges in embedded library
code added to check privileges in embedded library
NO_EMBEDDED_ACCESS_CHECKS macros inserted in code so we can exclude
access-checking parts. Actually we now can exclude these parts from
standalone server as well. Do we need it?
Access checks are disabled in embedded server by default. One should
edit libmysqld/Makefile manually to get this working.
We definitely need the separate configure for embedded server


include/mysql.h:
  options added so user of embedded library can set the client host
  it will work as if the usual client connects from this host
libmysqld/Makefile.am:
  Usually one doesn't need access checking in embedded library
  we definitely should separate configure for embedded server
libmysqld/lib_sql.cc:
  necessary code for getting passwords and access checks added
libmysqld/libmysqld.c:
  code #ifdef-ed - we use this only when we check permissions
sql-common/client.c:
  one mysql_close left now
sql/item_strfunc.cc:
  #ifndef-s added
sql/log.cc:
  #ifndef-s added
sql/mysql_priv.h:
  #ifndef-s added
  also i removed default parameters from check_access and check_table_access
  definitions to set definitions working
sql/mysqld.cc:
  #ifndef-s added
  localhost renamed to my_localhost
sql/repl_failsafe.cc:
  parameters added
sql/set_var.cc:
  #ifndef-s added
sql/sql_acl.cc:
  #ifndef-s added
sql/sql_acl.h:
  #ifndef-s added
sql/sql_base.cc:
  #ifndef-s added
sql/sql_cache.cc:
  #ifndef-s added
sql/sql_class.cc:
  #ifndef-s added
sql/sql_db.cc:
  #ifndef-s added
sql/sql_derived.cc:
  #ifndef-s added
sql/sql_insert.cc:
  #ifndef-s added
sql/sql_parse.cc:
  a horde of #ifndef-s added
sql/sql_prepare.cc:
  #ifndef-s added
sql/sql_repl.cc:
  parameters added
sql/sql_show.cc:
  #ifndef-s added
sql/sql_update.cc:
  #ifndef-s added
parent 4535f689
......@@ -142,7 +142,7 @@ enum mysql_option
MYSQL_OPT_PROTOCOL, MYSQL_SHARED_MEMORY_BASE_NAME, MYSQL_OPT_READ_TIMEOUT,
MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT,
MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
MYSQL_OPT_GUESS_CONNECTION
MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP
};
struct st_mysql_options {
......@@ -180,6 +180,7 @@ struct st_mysql_options {
my_bool separate_thread;
#endif
enum mysql_option methods_to_use;
char *client_ip;
};
enum mysql_status
......
......@@ -22,6 +22,7 @@ MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
DEFS = -DEMBEDDED_LIBRARY -DMYSQL_SERVER \
-DNO_EMBEDDED_ACCESS_CHECKS \
-DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
-DDATADIR="\"$(MYSQLDATAdir)\"" \
-DSHAREDIR="\"$(MYSQLSHAREdir)\""
......
......@@ -33,6 +33,9 @@ static const char *fake_groups[] = { "server", "embedded", 0 };
#include "../sql/mysqld.cc"
#endif
int check_user(THD *thd, enum enum_server_command command,
const char *passwd, uint passwd_len, const char *db,
bool check_count);
C_MODE_START
#include <mysql.h>
#undef ER
......@@ -42,14 +45,6 @@ C_MODE_START
static my_bool org_my_init_done;
my_bool server_inited;
static int check_connections1(THD * thd);
static int check_connections2(THD * thd);
static bool check_user(THD *thd, enum_server_command command,
const char *user, const char *passwd, const char *db,
bool check_count);
char * get_mysql_home(){ return mysql_home;};
char * get_mysql_real_data_home(){ return mysql_real_data_home;};
static my_bool STDCALL
emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
const char *header, ulong header_length,
......@@ -217,34 +212,6 @@ void THD::clear_error()
net.report_error= 0;
}
static bool check_user(THD *thd,enum_server_command command, const char *user,
const char *passwd, const char *db, bool check_count)
{
thd->db=0;
if (!(thd->user = my_strdup(user, MYF(0))))
{
send_error(thd,ER_OUT_OF_RESOURCES);
return 1;
}
thd->master_access= ~0L; // No user checking
thd->priv_user= thd->user;
mysql_log.write(thd,command,
(thd->priv_user == thd->user ?
(char*) "%s@%s on %s" :
(char*) "%s@%s as anonymous on %s"),
user,
thd->host_or_ip,
db ? db : (char*) "");
thd->db_access=0;
if (db && db[0])
return test(mysql_change_db(thd,db));
else
send_ok(thd); // Ready to handle questions
return 0; // ok
}
/*
Make a copy of array and the strings array points to
*/
......@@ -339,7 +306,7 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
error_handler_hook = my_message_sql;
opt_noacl = 1; // No permissions
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (acl_init((THD *)0, opt_noacl))
{
mysql_server_end();
......@@ -347,11 +314,16 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
}
if (!opt_noacl)
(void) grant_init((THD *)0);
#endif
init_max_user_conn();
init_update_queries();
#ifdef HAVE_DLOPEN
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (!opt_noacl)
#endif
udf_init();
#endif
......@@ -444,8 +416,10 @@ void *create_embedded_thd(int client_flag, char *db)
thd->db= db;
thd->db_length= db ? strip_sp(db) : 0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
thd->db_access= DB_ACLS;
thd->master_access= ~NO_ACCESS;
#endif
thd->net.query_cache_query= 0;
thd->data= 0;
......@@ -453,6 +427,51 @@ void *create_embedded_thd(int client_flag, char *db)
return thd;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
int check_embedded_connection(MYSQL *mysql)
{
THD *thd= (THD*)mysql->thd;
int result;
char scramble_buff[SCRAMBLE_LENGTH];
int passwd_len;
thd->host= mysql->options.client_ip ?
mysql->options.client_ip : (char*)my_localhost;
thd->ip= thd->host;
thd->host_or_ip= thd->host;
if (acl_check_host(thd->host,thd->ip))
{
result= ER_HOST_NOT_PRIVILEGED;
goto err;
}
thd->user= mysql->user;
if (mysql->passwd && mysql->passwd[0])
{
memset(thd->scramble, 55, SCRAMBLE_LENGTH); // dummy scramble
thd->scramble[SCRAMBLE_LENGTH]= 0;
scramble(scramble_buff, thd->scramble, mysql->passwd);
passwd_len= SCRAMBLE_LENGTH;
}
else
passwd_len= 0;
if((result= check_user(thd, COM_CONNECT,
scramble_buff, passwd_len, thd->db, true)))
goto err;
return 0;
err:
{
NET *net= &mysql->net;
memcpy(net->last_error, thd->net.last_error, sizeof(net->last_error));
memcpy(net->sqlstate, thd->net.sqlstate, sizeof(net->sqlstate));
}
return result;
}
#endif
C_MODE_END
bool Protocol::send_fields(List<Item> *list, uint flag)
......
......@@ -146,12 +146,17 @@ static inline int mysql_init_charset(MYSQL *mysql)
return 0;
}
int check_embedded_connection(MYSQL *mysql);
MYSQL * STDCALL
mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
const char *passwd, const char *db,
uint port, const char *unix_socket,ulong client_flag)
{
char *db_name;
char *db_name;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
char name_buff[USERNAME_LENGTH];
#endif
DBUG_ENTER("mysql_real_connect");
DBUG_PRINT("enter",("host: %s db: %s user: %s",
host ? host : "(Null)",
......@@ -190,6 +195,29 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
if (!db || !db[0])
db=mysql->options.db;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (!user || !user[0])
user=mysql->options.user;
if (!passwd)
{
passwd=mysql->options.password;
#if !defined(DONT_USE_MYSQL_PWD)
if (!passwd)
passwd=getenv("MYSQL_PWD"); /* get it from environment */
#endif
}
if (!user || !user[0])
{
read_user_name(name_buff);
if (!name_buff[0])
user= name_buff;
}
mysql->user=my_strdup(user,MYF(0));
mysql->passwd= passwd ? my_strdup(passwd,MYF(0)) : NULL;
#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
port=0;
unix_socket=0;
db_name = db ? my_strdup(db,MYF(MY_WME)) : NULL;
......@@ -198,6 +226,11 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
init_embedded_mysql(mysql, client_flag, db_name);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_embedded_connection(mysql))
goto error;
#endif
if (mysql_init_charset(mysql))
goto error;
......@@ -245,51 +278,3 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
DBUG_RETURN(0);
}
/*************************************************************************
** Send a QUIT to the server and close the connection
** If handle is alloced by mysql connect free it.
*************************************************************************/
void STDCALL mysql_close(MYSQL *mysql)
{
DBUG_ENTER("mysql_close");
if (mysql) /* Some simple safety */
{
if (mysql->methods != &embedded_methods)
{
cli_mysql_close(mysql);
DBUG_VOID_RETURN;
}
my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.db,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
if (mysql->options.init_commands)
{
DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
char **ptr= (char**)init_commands->buffer;
char **end= ptr + init_commands->elements;
for (; ptr<end; ptr++)
my_free(*ptr,MYF(MY_WME));
delete_dynamic(init_commands);
my_free((char*)init_commands,MYF(MY_WME));
}
/* Clear pointers for better safety */
bzero((char*) &mysql->options,sizeof(mysql->options));
#ifdef HAVE_OPENSSL
((VioConnectorFd*)(mysql->connector_fd))->delete();
mysql->connector_fd = 0;
#endif /* HAVE_OPENSSL */
if (mysql->free_me)
my_free((gptr) mysql,MYF(0));
}
DBUG_VOID_RETURN;
}
......@@ -48,14 +48,12 @@
#endif
#define CLI_MYSQL_REAL_CONNECT cli_mysql_real_connect
#define CLI_MYSQL_CLOSE cli_mysql_close
#undef net_flush
my_bool net_flush(NET *net);
#else /*EMBEDDED_LIBRARY*/
#define CLI_MYSQL_REAL_CONNECT mysql_real_connect
#define CLI_MYSQL_CLOSE mysql_close
#endif /*EMBEDDED_LIBRARY*/
#if !defined(MYSQL_SERVER) && (defined(__WIN__) || defined(_WIN32) || defined(_WIN64))
......@@ -2127,6 +2125,7 @@ static void mysql_close_free_options(MYSQL *mysql)
my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.client_ip,MYF(MY_ALLOW_ZERO_PTR));
if (mysql->options.init_commands)
{
DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
......@@ -2159,7 +2158,7 @@ static void mysql_close_free(MYSQL *mysql)
}
void STDCALL CLI_MYSQL_CLOSE(MYSQL *mysql)
void STDCALL mysql_close(MYSQL *mysql)
{
DBUG_ENTER("mysql_close");
if (mysql) /* Some simple safety */
......@@ -2529,6 +2528,8 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg)
case MYSQL_OPT_GUESS_CONNECTION:
mysql->options.methods_to_use= option;
break;
case MYSQL_SET_CLIENT_IP:
mysql->options.client_ip= my_strdup(arg, MYF(MY_WME));
default:
DBUG_RETURN(1);
}
......
......@@ -2277,7 +2277,9 @@ String *Item_load_file::val_str(String *str)
DBUG_ENTER("load_file");
if (!(file_name= args[0]->val_str(str)) ||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
!(current_thd->master_access & FILE_ACL) ||
#endif
!my_stat(file_name->c_ptr(), &stat_info, MYF(MY_WME)))
goto err;
if (!(stat_info.st_mode & S_IROTH))
......
......@@ -1093,8 +1093,11 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
if (thd)
{ // Normal thread
if ((thd->options & OPTION_LOG_OFF) &&
(thd->master_access & SUPER_ACL))
if ((thd->options & OPTION_LOG_OFF)
#ifndef NO_EMBEDDED_ACCESS_CHECKS
&& (thd->master_access & SUPER_ACL)
#endif
)
{
VOID(pthread_mutex_unlock(&LOCK_log));
return 0; // No logging
......@@ -1553,8 +1556,11 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
int tmp_errno=0;
char buff[80],*end;
end=buff;
if (!(thd->options & OPTION_UPDATE_LOG) &&
(thd->master_access & SUPER_ACL))
if (!(thd->options & OPTION_UPDATE_LOG)
#ifndef NO_EMBEDDED_ACCESS_CHECKS
&& (thd->master_access & SUPER_ACL)
#endif
)
{
VOID(pthread_mutex_unlock(&LOCK_log));
return 0;
......
......@@ -393,18 +393,24 @@ bool check_stack_overrun(THD *thd,char *dummy);
#define check_stack_overrun(A, B) 0
#endif
bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
bool *write_to_binlog);
void table_cache_init(void);
void table_cache_free(void);
uint cached_tables(void);
void kill_mysql(void);
void close_connection(THD *thd, uint errcode, bool lock);
bool check_access(THD *thd, ulong access, const char *db=0, ulong *save_priv=0,
bool no_grant=0, bool no_errors=0);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
bool *write_to_binlog);
bool check_access(THD *thd, ulong access, const char *db, ulong *save_priv,
bool no_grant, bool no_errors);
bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables,
bool no_errors=0);
bool no_errors);
bool check_global_access(THD *thd, ulong want_access);
#else
#define check_access(thd, access, db, save_priv, no_grant, no_errors) false
#define check_table_access(thd, want_access, tables, no_errors) false
#define check_global_access(thd, want_access) false
#endif
int mysql_backup_table(THD* thd, TABLE_LIST* table_list);
int mysql_restore_table(THD* thd, TABLE_LIST* table_list);
......@@ -717,7 +723,7 @@ extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH],
#define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list))
extern MY_TMPDIR mysql_tmpdir_list;
extern const char *command_name[];
extern const char *first_keyword, *localhost, *delayed_user, *binary_keyword;
extern const char *first_keyword, *my_localhost, *delayed_user, *binary_keyword;
extern const char **errmesg; /* Error messages */
extern const char *myisam_recover_options_str;
extern const char *in_left_expr_name, *in_additional_cond;
......
......@@ -218,7 +218,7 @@ const char *sql_mode_names[] =
TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
sql_mode_names };
const char *first_keyword= "first", *binary_keyword= "BINARY";
const char *localhost= "localhost", *delayed_user= "DELAYED";
const char *my_localhost= "localhost", *delayed_user= "DELAYED";
#if SIZEOF_OFF_T > 4 && defined(BIG_TABLES)
#define GET_HA_ROWS GET_ULL
#else
......@@ -875,8 +875,10 @@ void clean_up(bool print_message)
if (use_slave_mask)
bitmap_free(&slave_error_mask);
#endif
#ifndef NO_EMBEDDED_ACCESS_CHECKS
acl_free(1);
grant_free();
#endif
query_cache_destroy();
table_cache_free();
hostname_cache_free();
......@@ -1672,6 +1674,7 @@ static void init_signals(void)
}
#ifndef EMBEDDED_LIBRARY
static void start_signal_handler(void)
{
int error;
......@@ -1834,6 +1837,7 @@ extern "C" void *signal_hand(void *arg __attribute__((unused)))
}
return(0); /* purecov: deadcode */
}
#endif /*!EMBEDDED_LIBRARY*/
static void check_data_home(const char *path)
{}
......@@ -3111,7 +3115,7 @@ extern "C" pthread_handler_decl(handle_connections_sockets,
continue;
}
if (sock == unix_sock)
thd->host=(char*) localhost;
thd->host=(char*) my_localhost;
#ifdef __WIN__
/* Set default wait_timeout */
ulong wait_timeout= global_system_variables.net_wait_timeout * 1000;
......@@ -3201,7 +3205,7 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg)
continue;
}
/* host name is unknown */
thd->host = my_strdup(localhost,MYF(0)); /* Host is unknown */
thd->host = my_strdup(my_localhost,MYF(0)); /* Host is unknown */
create_new_thread(thd);
}
......@@ -3410,7 +3414,7 @@ Send number of connection to client
if (!event_client_read) CloseHandle(event_client_read);
continue;
}
thd->host = my_strdup(localhost,MYF(0)); /* Host is unknown */
thd->host = my_strdup(my_localhost,MYF(0)); /* Host is unknown */
create_new_thread(thd);
uint4korr(connect_number++);
}
......
......@@ -154,9 +154,8 @@ int register_slave(THD* thd, uchar* packet, uint packet_length)
SLAVE_INFO *si;
uchar *p= packet, *p_end= packet + packet_length;
if (check_access(thd, REPL_SLAVE_ACL, any_db))
if (check_access(thd, REPL_SLAVE_ACL, any_db,0,0,0))
return 1;
if (!(si = (SLAVE_INFO*)my_malloc(sizeof(SLAVE_INFO), MYF(MY_WME))))
goto err2;
......
......@@ -1723,6 +1723,7 @@ byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type,
bool sys_var_pseudo_thread_id::check(THD *thd, set_var *var)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (thd->master_access & SUPER_ACL)
return 0;
else
......@@ -1730,6 +1731,9 @@ bool sys_var_pseudo_thread_id::check(THD *thd, set_var *var)
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
return 1;
}
#else
return 0;
#endif
}
......@@ -2028,7 +2032,6 @@ int set_var::check(THD *thd)
}
if ((type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL)))
return 1;
/* value is a NULL pointer if we are using SET ... = DEFAULT */
if (!value)
{
......@@ -2091,17 +2094,25 @@ int set_var_user::update(THD *thd)
int set_var_password::check(THD *thd)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (!user->host.str)
user->host.str= (char*) thd->host_or_ip;
/* Returns 1 as the function sends error to client */
return check_change_password(thd, user->host.str, user->user.str) ? 1 : 0;
#else
return 0;
#endif
}
int set_var_password::update(THD *thd)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Returns 1 as the function sends error to client */
return (change_password(thd, user->host.str, user->user.str, password) ?
1 : 0);
#else
return 0;
#endif
}
/****************************************************************************
......
......@@ -34,6 +34,7 @@
#include <m_ctype.h>
#include <stdarg.h>
#ifndef NO_EMBEDDED_ACCESS_CHECKS
class acl_entry :public hash_filo_element
{
......@@ -985,51 +986,6 @@ ulong acl_get(const char *host, const char *ip, const char *bin_ip,
return (db_access & host_access);
}
int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr)
{
reg3 int flag;
DBUG_ENTER("wild_case_compare");
DBUG_PRINT("enter",("str: '%s' wildstr: '%s'",str,wildstr));
while (*wildstr)
{
while (*wildstr && *wildstr != wild_many && *wildstr != wild_one)
{
if (*wildstr == wild_prefix && wildstr[1])
wildstr++;
if (my_toupper(cs, *wildstr++) !=
my_toupper(cs, *str++)) DBUG_RETURN(1);
}
if (! *wildstr ) DBUG_RETURN (*str != 0);
if (*wildstr++ == wild_one)
{
if (! *str++) DBUG_RETURN (1); /* One char; skip */
}
else
{ /* Found '*' */
if (!*wildstr) DBUG_RETURN(0); /* '*' as last char: OK */
flag=(*wildstr != wild_many && *wildstr != wild_one);
do
{
if (flag)
{
char cmp;
if ((cmp= *wildstr) == wild_prefix && wildstr[1])
cmp=wildstr[1];
cmp=my_toupper(cs, cmp);
while (*str && my_toupper(cs, *str) != cmp)
str++;
if (!*str) DBUG_RETURN (1);
}
if (wild_case_compare(cs, str,wildstr) == 0) DBUG_RETURN (0);
} while (*str++);
DBUG_RETURN(1);
}
}
DBUG_RETURN (*str != '\0');
}
/*
Check if there are any possible matching entries for this host
......@@ -1136,7 +1092,7 @@ bool check_change_password(THD *thd, const char *host, const char *user)
(strcmp(thd->user,user) ||
my_strcasecmp(&my_charset_latin1, host, thd->host_or_ip)))
{
if (check_access(thd, UPDATE_ACL, "mysql",0,1))
if (check_access(thd, UPDATE_ACL, "mysql",0,1,0))
return(1);
}
if (!thd->slave_thread && !thd->user[0])
......@@ -3605,3 +3561,50 @@ template class List_iterator<LEX_USER>;
template class List<LEX_COLUMN>;
template class List<LEX_USER>;
#endif
#endif /*NO_EMBEDDED_ACCESS_CHECKS */
int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr)
{
reg3 int flag;
DBUG_ENTER("wild_case_compare");
DBUG_PRINT("enter",("str: '%s' wildstr: '%s'",str,wildstr));
while (*wildstr)
{
while (*wildstr && *wildstr != wild_many && *wildstr != wild_one)
{
if (*wildstr == wild_prefix && wildstr[1])
wildstr++;
if (my_toupper(cs, *wildstr++) !=
my_toupper(cs, *str++)) DBUG_RETURN(1);
}
if (! *wildstr ) DBUG_RETURN (*str != 0);
if (*wildstr++ == wild_one)
{
if (! *str++) DBUG_RETURN (1); /* One char; skip */
}
else
{ /* Found '*' */
if (!*wildstr) DBUG_RETURN(0); /* '*' as last char: OK */
flag=(*wildstr != wild_many && *wildstr != wild_one);
do
{
if (flag)
{
char cmp;
if ((cmp= *wildstr) == wild_prefix && wildstr[1])
cmp=wildstr[1];
cmp=my_toupper(cs, cmp);
while (*str && my_toupper(cs, *str) != cmp)
str++;
if (!*str) DBUG_RETURN (1);
}
if (wild_case_compare(cs, str,wildstr) == 0) DBUG_RETURN (0);
} while (*str++);
DBUG_RETURN(1);
}
}
DBUG_RETURN (*str != '\0');
}
......@@ -14,7 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define SELECT_ACL (1L << 0)
#define INSERT_ACL (1L << 1)
#define UPDATE_ACL (1L << 2)
......@@ -59,6 +58,8 @@
#define EXTRA_ACL (1L << 29)
#define NO_ACCESS (1L << 30)
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/*
Defines to change the above bits to how things are stored in tables
This is needed as the 'host' and 'db' table is missing a few privileges
......@@ -162,3 +163,6 @@ void get_privilege_desc(char *to, uint max_length, ulong access);
void get_mqh(const char *user, const char *host, USER_CONN *uc);
int mysql_drop_user(THD *thd, List <LEX_USER> &list);
int mysql_revoke_all(THD *thd, List <LEX_USER> &list);
#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
......@@ -158,7 +158,6 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
table_list.grant.privilege=0;
if (check_table_access(thd,SELECT_ACL | EXTRA_ACL,&table_list,1))
continue;
/* need to check if we haven't already listed it */
for (table= open_list ; table ; table=table->next)
{
......@@ -1696,8 +1695,10 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
else
thd->dupp_field=field;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_grants && check_grant_column(thd,table,name,length))
return WRONG_GRANT;
#endif
return field;
}
......@@ -2099,11 +2100,12 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
tables->alias) &&
(!db_name || !strcmp(tables->db,db_name))))
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Ensure that we have access right to all columns */
if (!(table->grant.privilege & SELECT_ACL) &&
check_grant_all_columns(thd,SELECT_ACL,table))
DBUG_RETURN(-1);
#endif
Field **ptr=table->field,*field;
thd->used_tables|=table->map;
while ((field = *ptr++))
......
......@@ -1002,6 +1002,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
Query_cache_table *table = block_table->parent;
table_list.db = table->db();
table_list.alias= table_list.real_name= table->table();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_table_access(thd,SELECT_ACL,&table_list,1))
{
DBUG_PRINT("qcache",
......@@ -1021,6 +1022,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
thd->lex.safe_to_cache_query= 0; // Don't try to cache this
goto err_unlock; // Parse query
}
#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
if (check_tables && !handler::caching_allowed(thd, table->db(),
table->key_length(),
table->type()))
......
......@@ -135,7 +135,9 @@ THD::THD():user_time(0), is_fatal_error(0),
slave_net = 0;
command=COM_CONNECT;
set_query_id=1;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
db_access=NO_ACCESS;
#endif
version=refresh_version; // For boot
*scramble= '\0';
......@@ -316,7 +318,7 @@ THD::~THD()
#endif
DBUG_PRINT("info", ("freeing host"));
if (host != localhost) // If not pointer to constant
if (host != my_localhost) // If not pointer to constant
safeFree(host);
if (user != delayed_user)
safeFree(user);
......
......@@ -592,6 +592,7 @@ bool mysql_change_db(THD *thd, const char *name)
DBUG_RETURN(1);
}
DBUG_PRINT("info",("Use database: %s", dbname));
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (test_all_bits(thd->master_access,DB_ACLS))
db_access=DB_ACLS;
else
......@@ -611,7 +612,7 @@ bool mysql_change_db(THD *thd, const char *name)
my_free(dbname,MYF(0));
DBUG_RETURN(1);
}
#endif
(void) sprintf(path,"%s/%s",mysql_data_home,dbname);
length=unpack_dirname(path,path); // Convert if not unix
if (length && path[length-1] == FN_LIBCHAR)
......@@ -626,8 +627,9 @@ bool mysql_change_db(THD *thd, const char *name)
x_free(thd->db);
thd->db=dbname; // THD::~THD will free this
thd->db_length=db_length;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
thd->db_access=db_access;
#endif
strmov(path+unpack_dirname(path,path), MY_DB_OPT_FILE);
load_db_opt(thd, path, &create);
thd->db_charset= create.table_charset ?
......@@ -656,6 +658,7 @@ int mysqld_show_create_db(THD *thd, char *dbname,
DBUG_RETURN(1);
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (test_all_bits(thd->master_access,DB_ACLS))
db_access=DB_ACLS;
else
......@@ -674,6 +677,7 @@ int mysqld_show_create_db(THD *thd, char *dbname,
dbname);
DBUG_RETURN(1);
}
#endif
(void) sprintf(path,"%s/%s",mysql_data_home, dbname);
length=unpack_dirname(path,path); // Convert if not unix
......
......@@ -91,13 +91,15 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
We have to do access checks here as this code is executed before any
sql command is started to execute.
*/
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (tables)
res= check_table_access(thd,SELECT_ACL, tables);
res= check_table_access(thd,SELECT_ACL, tables,0);
else
res= check_access(thd, SELECT_ACL, any_db);
res= check_access(thd, SELECT_ACL, any_db,0,0,0);
if (res)
DBUG_RETURN(1);
#endif
if (!(res=open_and_lock_tables(thd,tables)))
{
if (is_union || is_subsel)
......@@ -203,7 +205,9 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
org_table_list->table=table;
table->derived_select_number= select_cursor->select_number;
table->tmp_table= TMP_TABLE;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
org_table_list->grant.privilege= SELECT_ACL;
#endif
if (lex->describe)
{
// to fix a problem in EXPLAIN
......
......@@ -60,9 +60,11 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
MYF(0),counter);
return -1;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (grant_option &&
check_grant_all_columns(thd,INSERT_ACL,table))
return -1;
#endif
table->time_stamp=0; // This is saved by caller
}
else
......@@ -96,7 +98,9 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
table->time_stamp= table->timestamp_field->offset()+1;
}
// For the values we need select_priv
#ifndef NO_EMBEDDED_ACCESS_CHECKS
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
#endif
return 0;
}
......@@ -130,14 +134,15 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
thd->lex.select_lex.table_list.first;
DBUG_ENTER("mysql_insert");
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (thd->master_access & SUPER_ACL)
#endif
{
if (!(thd->options & OPTION_UPDATE_LOG))
log_on&= ~(int) DELAYED_LOG_UPDATE;
if (!(thd->options & OPTION_BIN_LOG))
log_on&= ~(int) DELAYED_LOG_BIN;
}
/*
in safe mode or with skip-new change delayed insert to be regular
if we are told to replace duplicates, the insert cannot be concurrent
......@@ -626,7 +631,7 @@ class delayed_insert :public ilink {
group_count(0)
{
thd.user=thd.priv_user=(char*) delayed_user;
thd.host=(char*) localhost;
thd.host=(char*) my_localhost;
thd.current_tablenr=0;
thd.version=refresh_version;
thd.command=COM_DELAYED_INSERT;
......
This diff is collapsed.
......@@ -524,16 +524,18 @@ static bool mysql_test_insert_fields(PREP_STMT *stmt,
List_item *values;
DBUG_ENTER("mysql_test_insert_fields");
#ifndef NO_EMBEDDED_ACCESS_CHECKS
my_bool update=(thd->lex.value_list.elements ? UPDATE_ACL : 0);
ulong privilege= (thd->lex.duplicates == DUP_REPLACE ?
INSERT_ACL | DELETE_ACL : INSERT_ACL | update);
if (check_access(thd,privilege,table_list->db,
&table_list->grant.privilege) ||
(grant_option && check_grant(thd,privilege,table_list)) ||
open_and_lock_tables(thd, table_list))
&table_list->grant.privilege,0,0) ||
(grant_option && check_grant(thd,privilege,table_list)))
DBUG_RETURN(1);
#endif
if (open_and_lock_tables(thd, table_list))
DBUG_RETURN(1);
table= table_list->table;
if ((values= its++))
......@@ -581,12 +583,14 @@ static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list,
THD *thd= stmt->thd;
DBUG_ENTER("mysql_test_upd_fields");
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_access(thd,UPDATE_ACL,table_list->db,
&table_list->grant.privilege) ||
(grant_option && check_grant(thd,UPDATE_ACL,table_list)) ||
open_and_lock_tables(thd, table_list))
&table_list->grant.privilege,0,0) ||
(grant_option && check_grant(thd,UPDATE_ACL,table_list)))
DBUG_RETURN(1);
#endif
if (open_and_lock_tables(thd, table_list))
DBUG_RETURN(1);
if (setup_tables(table_list) ||
setup_fields(thd, 0, table_list, fields, 1, 0, 0) ||
setup_conds(thd, table_list, &conds) || thd->net.report_error)
......@@ -627,15 +631,16 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
select_result *result= thd->lex.result;
DBUG_ENTER("mysql_test_select_fields");
#ifndef NO_EMBEDDED_ACCESS_CHECKS
ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL;
if (tables)
{
if (check_table_access(thd, privilege, tables))
if (check_table_access(thd, privilege, tables,0))
DBUG_RETURN(1);
}
else if (check_access(thd, privilege, "*any*"))
else if (check_access(thd, privilege, "*any*",0,0,0))
DBUG_RETURN(1);
#endif
if ((&lex->select_lex != lex->all_selects_list &&
lex->unit.create_total_list(thd, lex, &tables, 0)))
DBUG_RETURN(1);
......
......@@ -669,7 +669,7 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
int thread_mask;
DBUG_ENTER("start_slave");
if (check_access(thd, SUPER_ACL, any_db))
if (check_access(thd, SUPER_ACL, any_db,0,0,0))
DBUG_RETURN(1);
lock_slave_threads(mi); // this allows us to cleanly read slave_running
// Get a mask of _stopped_ threads
......@@ -791,7 +791,7 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
if (!thd)
thd = current_thd;
if (check_access(thd, SUPER_ACL, any_db))
if (check_access(thd, SUPER_ACL, any_db,0,0,0))
return 1;
thd->proc_info = "Killing slave";
int thread_mask;
......
......@@ -73,10 +73,12 @@ mysqld_show_dbs(THD *thd,const char *wild)
while ((file_name=it++))
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr,
thd->priv_user, file_name,0) ||
(grant_option && !check_grant_db(thd, file_name)))
#endif
{
protocol->prepare_for_resend();
protocol->store(file_name, system_charset_info);
......@@ -437,6 +439,7 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
continue;
}
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Don't show tables where we don't have any privileges */
if (db && !(col_access & TABLE_ACLS))
{
......@@ -446,6 +449,7 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
if (check_grant(thd,TABLE_ACLS,&table_list,1,1))
continue;
}
#endif
if (files->push_back(thd->strdup(file->name)))
{
my_dirend(dirp);
......@@ -674,8 +678,9 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
}
file=table->file;
file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
(void) get_table_grant(thd, table_list);
#endif
List<Item> field_list;
field_list.push_back(new Item_empty_string("Field",NAME_LEN));
field_list.push_back(new Item_empty_string("Type",40));
......@@ -755,6 +760,7 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
{
/* Add grant options & comments */
end=tmp;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
col_access= get_column_grant(thd,table_list,field) & COL_ACLS;
for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
{
......@@ -764,6 +770,9 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
end=strmov(end,grant_types.type_names[bitnr]);
}
}
#else
end=strmov(end,"");
#endif
protocol->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1),
system_charset_info);
protocol->store(field->comment.str, field->comment.length,
......
......@@ -86,8 +86,10 @@ int mysql_update(THD *thd,
/* Calculate "table->used_keys" based on the WHERE */
table->used_keys=table->keys_in_use;
table->quick_keys=0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
want_privilege=table->grant.want_privilege;
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
#endif
bzero((char*) &tables,sizeof(tables)); // For ORDER BY
tables.table= table;
......@@ -122,7 +124,9 @@ int mysql_update(THD *thd,
}
/* Check the fields we are going to modify */
#ifndef NO_EMBEDDED_ACCESS_CHECKS
table->grant.want_privilege=want_privilege;
#endif
if (setup_fields(thd, 0, update_table_list, fields, 1, 0, 0))
DBUG_RETURN(-1); /* purecov: inspected */
if (table->timestamp_field)
......@@ -134,8 +138,10 @@ int mysql_update(THD *thd,
table->timestamp_field->query_id=timestamp_query_id;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Check values */
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
#endif
if (setup_fields(thd, 0, update_table_list, values, 0, 0, 0))
{
free_underlaid_joins(thd, &thd->lex.select_lex);
......@@ -418,7 +424,9 @@ int mysql_multi_update(THD *thd,
TABLE_LIST *tl;
DBUG_ENTER("mysql_multi_update");
#ifndef NO_EMBEDDED_ACCESS_CHECKS
table_list->grant.want_privilege=(SELECT_ACL & ~table_list->grant.privilege);
#endif
if ((res=open_and_lock_tables(thd,table_list)))
DBUG_RETURN(res);
fix_tables_pointers(thd->lex.all_selects_list);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment