1
/* Copyright (C) 2000-2003 MySQL AB
1
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
3
3
This program is free software; you can redistribute it and/or modify
4
4
it under the terms of the GNU General Public License as published by
195
195
static my_bool acl_load(THD *thd, TABLE_LIST *tables);
196
196
static my_bool grant_load(THD *thd, TABLE_LIST *tables);
197
static inline void get_grantor(THD *thd, char* grantor);
199
200
Convert scrambled password to binary form, according to scramble type,
1627
1629
if (!(table= open_ltable(thd, &tables, TL_WRITE, 0)))
1628
1630
DBUG_RETURN(1);
1633
This statement will be replicated as a statement, even when using
1634
row-based replication. The flag will be reset at the end of the
1637
if ((save_binlog_row_based= thd->current_stmt_binlog_row_based))
1638
thd->clear_current_stmt_binlog_row_based();
1630
1640
VOID(pthread_mutex_lock(&acl_cache->lock));
1631
1641
ACL_USER *acl_user;
1632
1642
if (!(acl_user= find_acl_user(host, user, TRUE)))
1653
1663
if (mysql_bin_log.is_open())
1657
(buff,"SET PASSWORD FOR '%-.120s'@'%-.120s'='%-.120s'",
1658
acl_user->user ? acl_user->user : "",
1659
acl_user->host.hostname ? acl_user->host.hostname : "",
1665
query_length= sprintf(buff, "SET PASSWORD FOR '%-.120s'@'%-.120s'='%-.120s'",
1666
acl_user->user ? acl_user->user : "",
1667
acl_user->host.hostname ? acl_user->host.hostname : "",
1661
1669
thd->clear_error();
1662
1670
result= thd->binlog_query(THD::MYSQL_QUERY_TYPE, buff, query_length,
1663
1671
FALSE, FALSE, 0);
1666
1674
close_thread_tables(thd);
1676
/* Restore the state of binlog format */
1677
DBUG_ASSERT(!thd->current_stmt_binlog_row_based);
1678
if (save_binlog_row_based)
1679
thd->set_current_stmt_binlog_row_based();
1667
1681
DBUG_RETURN(result);
1957
1971
else if (!password_len && no_auto_create)
1959
my_error(ER_PASSWORD_NO_MATCH, MYF(0), combo.user.str, combo.host.str);
1973
my_error(ER_PASSWORD_NO_MATCH, MYF(0));
1962
1976
else if (!can_create_user)
1964
my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0),
1965
thd->security_ctx->user, thd->security_ctx->host_or_ip);
1978
my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0));
1968
1981
old_row_exists = 0;
2704
2717
DBUG_RETURN(result);
2720
static inline void get_grantor(THD *thd, char *grantor)
2722
const char *user= thd->security_ctx->user;
2723
const char *host= thd->security_ctx->host_or_ip;
2725
#if defined(HAVE_REPLICATION)
2726
if (thd->slave_thread && thd->has_invoker())
2728
user= thd->get_invoker_user().str;
2729
host= thd->get_invoker_host().str;
2732
strxmov(grantor, user, "@", host, NullS);
2708
2735
static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
2709
2736
TABLE *table, const LEX_USER &combo,
2718
2745
uchar user_key[MAX_KEY_LENGTH];
2719
2746
DBUG_ENTER("replace_table_table");
2721
strxmov(grantor, thd->security_ctx->user, "@",
2722
thd->security_ctx->host_or_ip, NullS);
2748
get_grantor(thd, grantor);
2725
2750
The following should always succeed as new users are created before
2726
2751
this function is called!
2850
2875
DBUG_RETURN(-1);
2853
strxmov(grantor, thd->security_ctx->user, "@",
2854
thd->security_ctx->host_or_ip, NullS);
2878
get_grantor(thd, grantor);
2857
2880
New users are created before this function is called.
5357
5380
Handle an in-memory privilege structure.
5360
handle_grant_struct()
5361
struct_no The number of the structure to handle (0..3).
5362
drop If user_from is to be dropped.
5363
user_from The the user to be searched/dropped/renamed.
5364
user_to The new name for the user if to be renamed,
5382
@param struct_no The number of the structure to handle (0..4).
5383
@param drop If user_from is to be dropped.
5384
@param user_from The the user to be searched/dropped/renamed.
5385
@param user_to The new name for the user if to be renamed, NULL otherwise.
5368
5388
Scan through all elements in an in-memory grant structure and apply
5369
5389
the requested operation.
5370
5390
Delete from grant structure if drop is true.
5376
5396
2 column_priv_hash
5380
> 0 At least one element matched.
5381
0 OK, but no element matched.
5382
-1 Wrong arguments to function
5400
@retval > 0 At least one element matched.
5401
@retval 0 OK, but no element matched.
5402
@retval -1 Wrong arguments to function.
5385
5405
static int handle_grant_struct(uint struct_no, bool drop,
5393
5413
ACL_USER *acl_user= NULL;
5394
5414
ACL_DB *acl_db= NULL;
5395
5415
GRANT_NAME *grant_name= NULL;
5416
HASH *grant_name_hash= NULL;
5396
5417
DBUG_ENTER("handle_grant_struct");
5397
5418
DBUG_PRINT("info",("scan struct: %u search: '%s'@'%s'",
5398
5419
struct_no, user_from->user.str, user_from->host.str));
5414
5435
elements= column_priv_hash.records;
5436
grant_name_hash= &column_priv_hash;
5417
5439
elements= proc_priv_hash.records;
5440
grant_name_hash= &proc_priv_hash;
5443
elements= func_priv_hash.records;
5444
grant_name_hash= &func_priv_hash;
5447
grant_name= (GRANT_NAME*) hash_element(&column_priv_hash, idx);
5448
user= grant_name->user;
5449
host= grant_name->host.hostname;
5453
grant_name= (GRANT_NAME*) hash_element(&proc_priv_hash, idx);
5476
grant_name= (GRANT_NAME*) hash_element(grant_name_hash, idx);
5454
5477
user= grant_name->user;
5455
5478
host= grant_name->host.hostname;
5482
MY_ASSERT_UNREACHABLE();
5486
hash_delete(&column_priv_hash, (uchar*) grant_name);
5490
hash_delete(&proc_priv_hash, (uchar*) grant_name);
5512
hash_delete(grant_name_hash, (uchar*) grant_name);
5517
- If we are iterating through an array then we just have moved all
5518
elements after the current element one position closer to its head.
5519
This means that we have to take another look at the element at
5520
current position as it is a new element from the array's tail.
5521
- If we are iterating through a hash the current element was replaced
5522
with one of elements from the tail. So we also have to take a look
5523
at the new element in current position.
5524
Note that in our HASH implementation hash_delete() won't move any
5525
elements with position after current one to position before the
5526
current (i.e. from the tail to the head), so it is safe to continue
5527
iteration without re-starting.
5496
5531
else if ( user_to )
5512
Update the grant structure with the new user name and
5515
grant_name->set_user_details(user_to->host.str, grant_name->db,
5516
user_to->user.str, grant_name->tname,
5520
Since username is part of the hash key, when the user name
5521
is renamed, the hash key is changed. Update the hash to
5522
ensure that the position matches the new hash key value
5524
hash_update(&column_priv_hash, (uchar*) grant_name,
5525
(uchar*) grant_name->hash_key, grant_name->key_length);
5549
Save old hash key and its length to be able properly update
5550
element position in hash.
5552
char *old_key= grant_name->hash_key;
5553
size_t old_key_length= grant_name->key_length;
5556
Update the grant structure with the new user name and host name.
5558
grant_name->set_user_details(user_to->host.str, grant_name->db,
5559
user_to->user.str, grant_name->tname,
5563
Since username is part of the hash key, when the user name
5564
is renamed, the hash key is changed. Update the hash to
5565
ensure that the position matches the new hash key value
5567
hash_update(grant_name_hash, (uchar*) grant_name, (uchar*) old_key,
5570
hash_update() operation could have moved element from the tail
5571
of the hash to the current position. So we need to take a look
5572
at the element in current position once again.
5573
Thanks to the fact that hash_update() for our HASH implementation
5574
won't move any elements from the tail of the hash to the positions
5575
before the current one (a.k.a. head) it is safe to continue
5576
iteration without restarting.
5612
/* Handle procedures table. */
5666
/* Handle stored routines table. */
5613
5667
if ((found= handle_grant_table(tables, 4, drop, user_from, user_to)) < 0)
5615
5669
/* Handle of table failed, don't touch in-memory array. */
5626
5680
if (! drop && ! user_to)
5683
/* Handle funcs array. */
5684
if (((handle_grant_struct(4, drop, user_from, user_to) && ! result) ||
5687
result= 1; /* At least one record/element found. */
5688
/* If search is requested, we do not need to search further. */
5689
if (! drop && ! user_to)
5631
5694
/* Handle tables table. */
5741
5803
some_users_created= TRUE;
5742
sql_mode= thd->variables.sql_mode;
5743
5804
if (replace_user_table(thd, tables[0].table, *user_name, 0, 0, 1, 0))
5745
5806
append_user(&wrong_users, user_name);