#include "mysql_priv.h"#include "hash_filo.h"#include <m_ctype.h>#include <stdarg.h>#include "sp_head.h"#include "sp.h"Include dependency graph for sql_acl.cc:

Go to the source code of this file.
Classes | |
| class | acl_entry |
| class | GRANT_COLUMN |
| class | GRANT_NAME |
| class | GRANT_TABLE |
Defines | |
| #define | FIRST_NON_YN_FIELD 26 |
| #define | IP_ADDR_STRLEN (3+1+3+1+3+1+3) |
| #define | ACL_KEY_LENGTH (IP_ADDR_STRLEN+1+NAME_LEN+1+USERNAME_LENGTH+1) |
| #define | GRANT_TABLES 5 |
Functions | |
| static byte * | acl_entry_get_key (acl_entry *entry, uint *length, my_bool not_used __attribute__((unused))) |
| static ulong | get_access (TABLE *form, uint fieldnr, uint *next_field=0) |
| static int | acl_compare (ACL_ACCESS *a, ACL_ACCESS *b) |
| static ulong | get_sort (uint count,...) |
| static void | init_check_host (void) |
| static void | rebuild_check_host (void) |
| static ACL_USER * | find_acl_user (const char *host, const char *user, my_bool exact) |
| static bool | update_user_table (THD *thd, TABLE *table, const char *host, const char *user, const char *new_password, uint new_password_len) |
| static void | update_hostname (acl_host_and_ip *host, const char *hostname) |
| static bool | compare_hostname (const acl_host_and_ip *host, const char *hostname, const char *ip) |
| static my_bool | acl_load (THD *thd, TABLE_LIST *tables) |
| static my_bool | grant_load (TABLE_LIST *tables) |
| static void | set_user_salt (ACL_USER *acl_user, const char *password, uint password_len) |
| static void | restrict_update_of_old_passwords_var (THD *thd, enum_var_type var_type) |
| my_bool | acl_init (bool dont_read_acl_tables) |
| void | acl_free (bool end) |
| my_bool | acl_reload (THD *thd) |
| int | acl_getroot (THD *thd, USER_RESOURCES *mqh, const char *passwd, uint passwd_len) |
| bool | acl_getroot_no_password (Security_context *sctx, char *user, char *host, char *ip, char *db) |
| static byte * | check_get_key (ACL_USER *buff, uint *length, my_bool not_used __attribute__((unused))) |
| static void | acl_update_user (const char *user, const char *host, const char *password, uint password_len, enum SSL_type ssl_type, const char *ssl_cipher, const char *x509_issuer, const char *x509_subject, USER_RESOURCES *mqh, ulong privileges) |
| static void | acl_insert_user (const char *user, const char *host, const char *password, uint password_len, enum SSL_type ssl_type, const char *ssl_cipher, const char *x509_issuer, const char *x509_subject, USER_RESOURCES *mqh, ulong privileges) |
| static void | acl_update_db (const char *user, const char *host, const char *db, ulong privileges) |
| static void | acl_insert_db (const char *user, const char *host, const char *db, ulong privileges) |
| ulong | acl_get (const char *host, const char *ip, const char *user, const char *db, my_bool db_is_pattern) |
| bool | acl_check_host (const char *host, const char *ip) |
| bool | check_change_password (THD *thd, const char *host, const char *user, char *new_password, uint new_password_len) |
| bool | change_password (THD *thd, const char *host, const char *user, char *new_password) |
| bool | is_acl_user (const char *host, const char *user) |
| static const char * | calc_ip (const char *ip, long *val, char end) |
| bool | hostname_requires_resolving (const char *hostname) |
| static bool | test_if_create_new_users (THD *thd) |
| static int | replace_user_table (THD *thd, TABLE *table, const LEX_USER &combo, ulong rights, bool revoke_grant, bool can_create_user, bool no_auto_create) |
| static int | replace_db_table (TABLE *table, const char *db, const LEX_USER &combo, ulong rights, bool revoke_grant) |
| static byte * | get_key_column (GRANT_COLUMN *buff, uint *length, my_bool not_used __attribute__((unused))) |
| static byte * | get_grant_table (GRANT_NAME *buff, uint *length, my_bool not_used __attribute__((unused))) |
| void | free_grant_table (GRANT_TABLE *grant_table) |
| static GRANT_NAME * | name_hash_search (HASH *name_hash, const char *host, const char *ip, const char *db, const char *user, const char *tname, bool exact) |
| GRANT_NAME * | routine_hash_search (const char *host, const char *ip, const char *db, const char *user, const char *tname, bool proc, bool exact) |
| GRANT_TABLE * | table_hash_search (const char *host, const char *ip, const char *db, const char *user, const char *tname, bool exact) |
| GRANT_COLUMN * | column_hash_search (GRANT_TABLE *t, const char *cname, uint length) |
| static int | replace_column_table (GRANT_TABLE *g_t, TABLE *table, const LEX_USER &combo, List< LEX_COLUMN > &columns, const char *db, const char *table_name, ulong rights, bool revoke_grant) |
| static int | replace_table_table (THD *thd, GRANT_TABLE *grant_table, TABLE *table, const LEX_USER &combo, const char *db, const char *table_name, ulong rights, ulong col_rights, bool revoke_grant) |
| static int | replace_routine_table (THD *thd, GRANT_NAME *grant_name, TABLE *table, const LEX_USER &combo, const char *db, const char *routine_name, bool is_proc, ulong rights, bool revoke_grant) |
| bool | mysql_table_grant (THD *thd, TABLE_LIST *table_list, List< LEX_USER > &user_list, List< LEX_COLUMN > &columns, ulong rights, bool revoke_grant) |
| bool | mysql_routine_grant (THD *thd, TABLE_LIST *table_list, bool is_proc, List< LEX_USER > &user_list, ulong rights, bool revoke_grant, bool no_error) |
| bool | mysql_grant (THD *thd, const char *db, List< LEX_USER > &list, ulong rights, bool revoke_grant) |
| void | grant_free (void) |
| my_bool | grant_init () |
| my_bool | grant_reload (THD *thd) |
| bool | check_grant (THD *thd, ulong want_access, TABLE_LIST *tables, uint show_table, uint number, bool no_errors) |
| bool | check_grant_column (THD *thd, GRANT_INFO *grant, const char *db_name, const char *table_name, const char *name, uint length, Security_context *sctx) |
| bool | check_column_grant_in_table_ref (THD *thd, TABLE_LIST *table_ref, const char *name, uint length) |
| bool | check_grant_all_columns (THD *thd, ulong want_access, GRANT_INFO *grant, const char *db_name, const char *table_name, Field_iterator *fields) |
| bool | check_grant_db (THD *thd, const char *db) |
| bool | check_grant_routine (THD *thd, ulong want_access, TABLE_LIST *procs, bool is_proc, bool no_errors) |
| bool | check_routine_level_acl (THD *thd, const char *db, const char *name, bool is_proc) |
| ulong | get_table_grant (THD *thd, TABLE_LIST *table) |
| ulong | get_column_grant (THD *thd, GRANT_INFO *grant, const char *db_name, const char *table_name, const char *field_name) |
| static void | add_user_option (String *grant, ulong value, const char *name) |
| static int | show_routine_grants (THD *thd, LEX_USER *lex_user, HASH *hash, const char *type, int typelen, char *buff, int buffsize) |
| bool | mysql_show_grants (THD *thd, LEX_USER *lex_user) |
| void | get_privilege_desc (char *to, uint max_length, ulong access) |
| void | get_mqh (const char *user, const char *host, USER_CONN *uc) |
| int | open_grant_tables (THD *thd, TABLE_LIST *tables) |
| ACL_USER * | check_acl_user (LEX_USER *user_name, uint *acl_acl_userdx) |
| static int | modify_grant_table (TABLE *table, Field *host_field, Field *user_field, LEX_USER *user_to) |
| static int | handle_grant_table (TABLE_LIST *tables, uint table_no, bool drop, LEX_USER *user_from, LEX_USER *user_to) |
| static int | handle_grant_struct (uint struct_no, bool drop, LEX_USER *user_from, LEX_USER *user_to) |
| static int | handle_grant_data (TABLE_LIST *tables, bool drop, LEX_USER *user_from, LEX_USER *user_to) |
| static void | append_user (String *str, LEX_USER *user) |
| bool | mysql_create_user (THD *thd, List< LEX_USER > &list) |
| bool | mysql_drop_user (THD *thd, List< LEX_USER > &list) |
| bool | mysql_rename_user (THD *thd, List< LEX_USER > &list) |
| bool | mysql_revoke_all (THD *thd, List< LEX_USER > &list) |
| bool | sp_revoke_privileges (THD *thd, const char *sp_db, const char *sp_name, bool is_proc) |
| bool | sp_grant_privileges (THD *thd, const char *sp_db, const char *sp_name, bool is_proc) |
| int | wild_case_compare (CHARSET_INFO *cs, const char *str, const char *wildstr) |
| void | update_schema_privilege (TABLE *table, char *buff, const char *db, const char *t_name, const char *column, uint col_length, const char *priv, uint priv_length, const char *is_grantable) |
| int | fill_schema_user_privileges (THD *thd, TABLE_LIST *tables, COND *cond) |
| int | fill_schema_schema_privileges (THD *thd, TABLE_LIST *tables, COND *cond) |
| int | fill_schema_table_privileges (THD *thd, TABLE_LIST *tables, COND *cond) |
| int | fill_schema_column_privileges (THD *thd, TABLE_LIST *tables, COND *cond) |
| void | fill_effective_table_privileges (THD *thd, GRANT_INFO *grant, const char *db, const char *table) |
Variables | |
| time_t | mysql_db_table_last_check = 0L |
| TABLE_FIELD_W_TYPE | mysql_db_table_fields [MYSQL_DB_FIELD_COUNT] |
| static DYNAMIC_ARRAY | acl_hosts |
| static DYNAMIC_ARRAY | acl_users |
| static DYNAMIC_ARRAY | acl_dbs |
| static MEM_ROOT | mem |
| static MEM_ROOT | memex |
| static bool | initialized = 0 |
| static bool | allow_all_hosts = 1 |
| static HASH | acl_check_hosts |
| static HASH | column_priv_hash |
| static HASH | proc_priv_hash |
| static HASH | func_priv_hash |
| static DYNAMIC_ARRAY | acl_wild_hosts |
| static hash_filo * | acl_cache |
| static uint | grant_version = 0 |
| static const char * | command_array [] |
| static uint | command_lengths [] |
| #define ACL_KEY_LENGTH (IP_ADDR_STRLEN+1+NAME_LEN+1+USERNAME_LENGTH+1) |
| #define FIRST_NON_YN_FIELD 26 |
Definition at line 153 of file sql_acl.cc.
| #define GRANT_TABLES 5 |
Definition at line 4785 of file sql_acl.cc.
Referenced by mysql_create_user(), mysql_drop_user(), mysql_rename_user(), mysql_revoke_all(), open_grant_tables(), and sp_revoke_privileges().
| #define IP_ADDR_STRLEN (3+1+3+1+3+1+3) |
Definition at line 171 of file sql_acl.cc.
| bool acl_check_host | ( | const char * | host, | |
| const char * | ip | |||
| ) |
Definition at line 1469 of file sql_acl.cc.
References acl_cache, acl_check_hosts, acl_wild_hosts, allow_all_hosts, compare_hostname(), dynamic_element, st_dynamic_array::elements, hash_search(), hash_filo::lock, pthread_mutex_lock, pthread_mutex_unlock, strlen(), and VOID.
Referenced by check_connection().
01470 { 01471 if (allow_all_hosts) 01472 return 0; 01473 VOID(pthread_mutex_lock(&acl_cache->lock)); 01474 01475 if (host && hash_search(&acl_check_hosts,(byte*) host,(uint) strlen(host)) || 01476 ip && hash_search(&acl_check_hosts,(byte*) ip,(uint) strlen(ip))) 01477 { 01478 VOID(pthread_mutex_unlock(&acl_cache->lock)); 01479 return 0; // Found host 01480 } 01481 for (uint i=0 ; i < acl_wild_hosts.elements ; i++) 01482 { 01483 acl_host_and_ip *acl=dynamic_element(&acl_wild_hosts,i,acl_host_and_ip*); 01484 if (compare_hostname(acl, host, ip)) 01485 { 01486 VOID(pthread_mutex_unlock(&acl_cache->lock)); 01487 return 0; // Host ok 01488 } 01489 } 01490 VOID(pthread_mutex_unlock(&acl_cache->lock)); 01491 return 1; // Host is not allowed 01492 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int acl_compare | ( | ACL_ACCESS * | a, | |
| ACL_ACCESS * | b | |||
| ) | [static] |
Definition at line 820 of file sql_acl.cc.
References ACL_ACCESS::sort.
Referenced by acl_insert_db(), acl_insert_user(), and acl_load().
00821 { 00822 if (a->sort > b->sort) 00823 return -1; 00824 if (a->sort < b->sort) 00825 return 1; 00826 return 0; 00827 }
Here is the caller graph for this function:

| static byte* acl_entry_get_key | ( | acl_entry * | entry, | |
| uint * | length, | |||
| my_bool not_used | __attribute__((unused)) | |||
| ) | [static] |
Definition at line 164 of file sql_acl.cc.
Referenced by acl_init().
Here is the caller graph for this function:

| void acl_free | ( | bool | end | ) |
Definition at line 630 of file sql_acl.cc.
References acl_cache, acl_check_hosts, acl_dbs, acl_hosts, acl_users, acl_wild_hosts, hash_filo::clear(), delete_dynamic(), free_root(), hash_free(), mem, and MYF.
Referenced by acl_reload(), and clean_up().
00631 { 00632 free_root(&mem,MYF(0)); 00633 delete_dynamic(&acl_hosts); 00634 delete_dynamic(&acl_users); 00635 delete_dynamic(&acl_dbs); 00636 delete_dynamic(&acl_wild_hosts); 00637 hash_free(&acl_check_hosts); 00638 if (!end) 00639 acl_cache->clear(1); /* purecov: inspected */ 00640 else 00641 { 00642 delete acl_cache; 00643 acl_cache=0; 00644 } 00645 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulong acl_get | ( | const char * | host, | |
| const char * | ip, | |||
| const char * | user, | |||
| const char * | db, | |||
| my_bool | db_is_pattern | |||
| ) |
Definition at line 1319 of file sql_acl.cc.
References acl_cache, acl_dbs, ACL_KEY_LENGTH, compare_hostname(), DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, dynamic_element, st_dynamic_array::elements, exit, files_charset_info, key, key_length, hash_filo::lock, lower_case_table_names, my_casedn_str, pthread_mutex_lock, pthread_mutex_unlock, hash_filo::search(), strcmp(), strmov(), VOID, and wild_compare().
Referenced by check_access(), fill_effective_table_privileges(), fill_schema_shemata(), get_all_tables(), mysql_change_db(), mysqld_show_create_db(), and test_if_create_new_users().
01321 { 01322 ulong host_access= ~(ulong)0, db_access= 0; 01323 uint i,key_length; 01324 char key[ACL_KEY_LENGTH],*tmp_db,*end; 01325 acl_entry *entry; 01326 DBUG_ENTER("acl_get"); 01327 01328 VOID(pthread_mutex_lock(&acl_cache->lock)); 01329 end=strmov((tmp_db=strmov(strmov(key, ip ? ip : "")+1,user)+1),db); 01330 if (lower_case_table_names) 01331 { 01332 my_casedn_str(files_charset_info, tmp_db); 01333 db=tmp_db; 01334 } 01335 key_length=(uint) (end-key); 01336 if (!db_is_pattern && (entry=(acl_entry*) acl_cache->search(key,key_length))) 01337 { 01338 db_access=entry->access; 01339 VOID(pthread_mutex_unlock(&acl_cache->lock)); 01340 DBUG_PRINT("exit", ("access: 0x%lx", db_access)); 01341 DBUG_RETURN(db_access); 01342 } 01343 01344 /* 01345 Check if there are some access rights for database and user 01346 */ 01347 for (i=0 ; i < acl_dbs.elements ; i++) 01348 { 01349 ACL_DB *acl_db=dynamic_element(&acl_dbs,i,ACL_DB*); 01350 if (!acl_db->user || !strcmp(user,acl_db->user)) 01351 { 01352 if (compare_hostname(&acl_db->host,host,ip)) 01353 { 01354 if (!acl_db->db || !wild_compare(db,acl_db->db,db_is_pattern)) 01355 { 01356 db_access=acl_db->access; 01357 if (acl_db->host.hostname) 01358 goto exit; // Fully specified. Take it 01359 break; /* purecov: tested */ 01360 } 01361 } 01362 } 01363 } 01364 if (!db_access) 01365 goto exit; // Can't be better 01366 01367 /* 01368 No host specified for user. Get hostdata from host table 01369 */ 01370 host_access=0; // Host must be found 01371 for (i=0 ; i < acl_hosts.elements ; i++) 01372 { 01373 ACL_HOST *acl_host=dynamic_element(&acl_hosts,i,ACL_HOST*); 01374 if (compare_hostname(&acl_host->host,host,ip)) 01375 { 01376 if (!acl_host->db || !wild_compare(db,acl_host->db,db_is_pattern)) 01377 { 01378 host_access=acl_host->access; // Fully specified. Take it 01379 break; 01380 } 01381 } 01382 } 01383 exit: 01384 /* Save entry in cache for quick retrieval */ 01385 if (!db_is_pattern && 01386 (entry= (acl_entry*) malloc(sizeof(acl_entry)+key_length))) 01387 { 01388 entry->access=(db_access & host_access); 01389 entry->length=key_length; 01390 memcpy((gptr) entry->key,key,key_length); 01391 acl_cache->add(entry); 01392 } 01393 VOID(pthread_mutex_unlock(&acl_cache->lock)); 01394 DBUG_PRINT("exit", ("access: 0x%lx", db_access & host_access)); 01395 DBUG_RETURN(db_access & host_access); 01396 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int acl_getroot | ( | THD * | thd, | |
| USER_RESOURCES * | mqh, | |||
| const char * | passwd, | |||
| uint | passwd_len | |||
| ) |
Definition at line 862 of file sql_acl.cc.
References acl_cache, acl_users, bzero, check_scramble(), check_scramble_323(), compare_hostname(), DBUG_ENTER, DBUG_RETURN, dynamic_element, st_dynamic_array::elements, hash_filo::lock, NO_ACCESS, pthread_mutex_lock, SCRAMBLE_LENGTH, strcmp(), and VOID.
Referenced by check_user().
00864 { 00865 ulong user_access= NO_ACCESS; 00866 int res= 1; 00867 ACL_USER *acl_user= 0; 00868 Security_context *sctx= thd->security_ctx; 00869 DBUG_ENTER("acl_getroot"); 00870 00871 if (!initialized) 00872 { 00873 /* 00874 here if mysqld's been started with --skip-grant-tables option. 00875 */ 00876 sctx->skip_grants(); 00877 bzero((char*) mqh, sizeof(*mqh)); 00878 DBUG_RETURN(0); 00879 } 00880 00881 VOID(pthread_mutex_lock(&acl_cache->lock)); 00882 00883 /* 00884 Find acl entry in user database. Note, that find_acl_user is not the same, 00885 because it doesn't take into account the case when user is not empty, 00886 but acl_user->user is empty 00887 */ 00888 00889 for (uint i=0 ; i < acl_users.elements ; i++) 00890 { 00891 ACL_USER *acl_user_tmp= dynamic_element(&acl_users,i,ACL_USER*); 00892 if (!acl_user_tmp->user || !strcmp(sctx->user, acl_user_tmp->user)) 00893 { 00894 if (compare_hostname(&acl_user_tmp->host, sctx->host, sctx->ip)) 00895 { 00896 /* check password: it should be empty or valid */ 00897 if (passwd_len == acl_user_tmp->salt_len) 00898 { 00899 if (acl_user_tmp->salt_len == 0 || 00900 (acl_user_tmp->salt_len == SCRAMBLE_LENGTH ? 00901 check_scramble(passwd, thd->scramble, acl_user_tmp->salt) : 00902 check_scramble_323(passwd, thd->scramble, 00903 (ulong *) acl_user_tmp->salt)) == 0) 00904 { 00905 acl_user= acl_user_tmp; 00906 res= 0; 00907 } 00908 } 00909 else if (passwd_len == SCRAMBLE_LENGTH && 00910 acl_user_tmp->salt_len == SCRAMBLE_LENGTH_323) 00911 res= -1; 00912 else if (passwd_len == SCRAMBLE_LENGTH_323 && 00913 acl_user_tmp->salt_len == SCRAMBLE_LENGTH) 00914 res= 2; 00915 /* linear search complete: */ 00916 break; 00917 } 00918 } 00919 } 00920 /* 00921 This was moved to separate tree because of heavy HAVE_OPENSSL case. 00922 If acl_user is not null, res is 0. 00923 */ 00924 00925 if (acl_user) 00926 { 00927 /* OK. User found and password checked continue validation */ 00928 #ifdef HAVE_OPENSSL 00929 Vio *vio=thd->net.vio; 00930 SSL *ssl= (SSL*) vio->ssl_arg; 00931 #endif 00932 00933 /* 00934 At this point we know that user is allowed to connect 00935 from given host by given username/password pair. Now 00936 we check if SSL is required, if user is using SSL and 00937 if X509 certificate attributes are OK 00938 */ 00939 switch (acl_user->ssl_type) { 00940 case SSL_TYPE_NOT_SPECIFIED: // Impossible 00941 case SSL_TYPE_NONE: // SSL is not required 00942 user_access= acl_user->access; 00943 break; 00944 #ifdef HAVE_OPENSSL 00945 case SSL_TYPE_ANY: // Any kind of SSL is ok 00946 if (vio_type(vio) == VIO_TYPE_SSL) 00947 user_access= acl_user->access; 00948 break; 00949 case SSL_TYPE_X509: /* Client should have any valid certificate. */ 00950 /* 00951 Connections with non-valid certificates are dropped already 00952 in sslaccept() anyway, so we do not check validity here. 00953 00954 We need to check for absence of SSL because without SSL 00955 we should reject connection. 00956 */ 00957 if (vio_type(vio) == VIO_TYPE_SSL && 00958 SSL_get_verify_result(ssl) == X509_V_OK && 00959 SSL_get_peer_certificate(ssl)) 00960 user_access= acl_user->access; 00961 break; 00962 case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */ 00963 /* 00964 We do not check for absence of SSL because without SSL it does 00965 not pass all checks here anyway. 00966 If cipher name is specified, we compare it to actual cipher in 00967 use. 00968 */ 00969 X509 *cert; 00970 if (vio_type(vio) != VIO_TYPE_SSL || 00971 SSL_get_verify_result(ssl) != X509_V_OK) 00972 break; 00973 if (acl_user->ssl_cipher) 00974 { 00975 DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'", 00976 acl_user->ssl_cipher,SSL_get_cipher(ssl))); 00977 if (!strcmp(acl_user->ssl_cipher,SSL_get_cipher(ssl))) 00978 user_access= acl_user->access; 00979 else 00980 { 00981 if (global_system_variables.log_warnings) 00982 sql_print_information("X509 ciphers mismatch: should be '%s' but is '%s'", 00983 acl_user->ssl_cipher, 00984 SSL_get_cipher(ssl)); 00985 break; 00986 } 00987 } 00988 /* Prepare certificate (if exists) */ 00989 DBUG_PRINT("info",("checkpoint 1")); 00990 if (!(cert= SSL_get_peer_certificate(ssl))) 00991 { 00992 user_access=NO_ACCESS; 00993 break; 00994 } 00995 DBUG_PRINT("info",("checkpoint 2")); 00996 /* If X509 issuer is specified, we check it... */ 00997 if (acl_user->x509_issuer) 00998 { 00999 DBUG_PRINT("info",("checkpoint 3")); 01000 char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); 01001 DBUG_PRINT("info",("comparing issuers: '%s' and '%s'", 01002 acl_user->x509_issuer, ptr)); 01003 if (strcmp(acl_user->x509_issuer, ptr)) 01004 { 01005 if (global_system_variables.log_warnings) 01006 sql_print_information("X509 issuer mismatch: should be '%s' " 01007 "but is '%s'", acl_user->x509_issuer, ptr); 01008 free(ptr); 01009 break; 01010 } 01011 user_access= acl_user->access; 01012 free(ptr); 01013 } 01014 DBUG_PRINT("info",("checkpoint 4")); 01015 /* X509 subject is specified, we check it .. */ 01016 if (acl_user->x509_subject) 01017 { 01018 char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); 01019 DBUG_PRINT("info",("comparing subjects: '%s' and '%s'", 01020 acl_user->x509_subject, ptr)); 01021 if (strcmp(acl_user->x509_subject,ptr)) 01022 { 01023 if (global_system_variables.log_warnings) 01024 sql_print_information("X509 subject mismatch: '%s' vs '%s'", 01025 acl_user->x509_subject, ptr); 01026 } 01027 else 01028 user_access= acl_user->access; 01029 free(ptr); 01030 } 01031 break; 01032 #else /* HAVE_OPENSSL */ 01033 default: 01034 /* 01035 If we don't have SSL but SSL is required for this user the 01036 authentication should fail. 01037 */ 01038 break; 01039 #endif /* HAVE_OPENSSL */ 01040 } 01041 sctx->master_access= user_access; 01042 sctx->priv_user= acl_user->user ? sctx->user : (char *) ""; 01043 *mqh= acl_user->user_resource; 01044 01045 if (acl_user->host.hostname) 01046 strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME); 01047 else 01048 *sctx->priv_host= 0; 01049 } 01050 VOID(pthread_mutex_unlock(&acl_cache->lock)); 01051 DBUG_RETURN(res); 01052 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool acl_getroot_no_password | ( | Security_context * | sctx, | |
| char * | user, | |||
| char * | host, | |||
| char * | ip, | |||
| char * | db | |||
| ) |
Definition at line 1072 of file sql_acl.cc.
References acl_cache, acl_users, compare_hostname(), DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, dynamic_element, st_dynamic_array::elements, FALSE, ACL_USER::host, initialized, hash_filo::lock, pthread_mutex_lock, strcmp(), ACL_USER::user, and VOID.
Referenced by change_security_context(), st_table_list::prepare_view_securety_context(), and sp_change_security_context().
01074 { 01075 int res= 1; 01076 uint i; 01077 ACL_USER *acl_user= 0; 01078 DBUG_ENTER("acl_getroot_no_password"); 01079 01080 DBUG_PRINT("enter", ("Host: '%s', Ip: '%s', User: '%s', db: '%s'", 01081 (host ? host : "(NULL)"), (ip ? ip : "(NULL)"), 01082 user, (db ? db : "(NULL)"))); 01083 sctx->user= user; 01084 sctx->host= host; 01085 sctx->ip= ip; 01086 sctx->host_or_ip= host ? host : (ip ? ip : ""); 01087 01088 if (!initialized) 01089 { 01090 /* 01091 here if mysqld's been started with --skip-grant-tables option. 01092 */ 01093 sctx->skip_grants(); 01094 DBUG_RETURN(FALSE); 01095 } 01096 01097 VOID(pthread_mutex_lock(&acl_cache->lock)); 01098 01099 sctx->master_access= 0; 01100 sctx->db_access= 0; 01101 sctx->priv_user= (char *) ""; 01102 *sctx->priv_host= 0; 01103 01104 /* 01105 Find acl entry in user database. 01106 This is specially tailored to suit the check we do for CALL of 01107 a stored procedure; user is set to what is actually a 01108 priv_user, which can be ''. 01109 */ 01110 for (i=0 ; i < acl_users.elements ; i++) 01111 { 01112 acl_user= dynamic_element(&acl_users,i,ACL_USER*); 01113 if ((!acl_user->user && !user[0]) || 01114 (acl_user->user && strcmp(user, acl_user->user) == 0)) 01115 { 01116 if (compare_hostname(&acl_user->host, host, ip)) 01117 { 01118 res= 0; 01119 break; 01120 } 01121 } 01122 } 01123 01124 if (acl_user) 01125 { 01126 for (i=0 ; i < acl_dbs.elements ; i++) 01127 { 01128 ACL_DB *acl_db= dynamic_element(&acl_dbs, i, ACL_DB*); 01129 if (!acl_db->user || 01130 (user && user[0] && !strcmp(user, acl_db->user))) 01131 { 01132 if (compare_hostname(&acl_db->host, host, ip)) 01133 { 01134 if (!acl_db->db || (db && !wild_compare(db, acl_db->db, 0))) 01135 { 01136 sctx->db_access= acl_db->access; 01137 break; 01138 } 01139 } 01140 } 01141 } 01142 sctx->master_access= acl_user->access; 01143 sctx->priv_user= acl_user->user ? user : (char *) ""; 01144 01145 if (acl_user->host.hostname) 01146 strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME); 01147 else 01148 *sctx->priv_host= 0; 01149 } 01150 VOID(pthread_mutex_unlock(&acl_cache->lock)); 01151 DBUG_RETURN(res); 01152 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 258 of file sql_acl.cc.
References acl_cache, ACL_CACHE_SIZE, acl_entry_get_key(), acl_reload(), DBUG_ENTER, DBUG_RETURN, free, lower_case_file_system, my_charset_bin, my_pthread_setspecific_ptr, and system_charset_info.
Referenced by main().
00259 { 00260 THD *thd; 00261 my_bool return_val; 00262 DBUG_ENTER("acl_init"); 00263 00264 acl_cache= new hash_filo(ACL_CACHE_SIZE, 0, 0, 00265 (hash_get_key) acl_entry_get_key, 00266 (hash_free_key) free, 00267 lower_case_file_system ? 00268 system_charset_info : &my_charset_bin); 00269 if (dont_read_acl_tables) 00270 { 00271 DBUG_RETURN(0); /* purecov: tested */ 00272 } 00273 00274 /* 00275 To be able to run this from boot, we allocate a temporary THD 00276 */ 00277 if (!(thd=new THD)) 00278 DBUG_RETURN(1); /* purecov: inspected */ 00279 thd->thread_stack= (char*) &thd; 00280 thd->store_globals(); 00281 /* 00282 It is safe to call acl_reload() since acl_* arrays and hashes which 00283 will be freed there are global static objects and thus are initialized 00284 by zeros at startup. 00285 */ 00286 return_val= acl_reload(thd); 00287 delete thd; 00288 /* Remember that we don't have a THD */ 00289 my_pthread_setspecific_ptr(THR_THD, 0); 00290 DBUG_RETURN(return_val); 00291 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void acl_insert_db | ( | const char * | user, | |
| const char * | host, | |||
| const char * | db, | |||
| ulong | privileges | |||
| ) | [static] |
Definition at line 1295 of file sql_acl.cc.
References ACL_ACCESS::access, acl_cache, acl_compare(), acl_dbs, ACL_DB::db, dynamic_element, get_sort(), ACL_DB::host, acl_host_and_ip::hostname, hash_filo::lock, mem, push_dynamic, qsort(), qsort_cmp, safe_mutex_assert_owner, ACL_ACCESS::sort, strdup_root(), update_hostname(), ACL_DB::user, and VOID.
Referenced by replace_db_table().
01297 { 01298 ACL_DB acl_db; 01299 safe_mutex_assert_owner(&acl_cache->lock); 01300 acl_db.user=strdup_root(&mem,user); 01301 update_hostname(&acl_db.host, *host ? strdup_root(&mem,host) : 0); 01302 acl_db.db=strdup_root(&mem,db); 01303 acl_db.access=privileges; 01304 acl_db.sort=get_sort(3,acl_db.host.hostname,acl_db.db,acl_db.user); 01305 VOID(push_dynamic(&acl_dbs,(gptr) &acl_db)); 01306 qsort((gptr) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements, 01307 sizeof(ACL_DB),(qsort_cmp) acl_compare); 01308 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void acl_insert_user | ( | const char * | user, | |
| const char * | host, | |||
| const char * | password, | |||
| uint | password_len, | |||
| enum SSL_type | ssl_type, | |||
| const char * | ssl_cipher, | |||
| const char * | x509_issuer, | |||
| const char * | x509_subject, | |||
| USER_RESOURCES * | mqh, | |||
| ulong | privileges | |||
| ) | [static] |
Definition at line 1212 of file sql_acl.cc.
References ACL_ACCESS::access, acl_cache, acl_compare(), acl_users, allow_all_hosts, dynamic_element, get_sort(), ACL_USER::host, acl_host_and_ip::hostname, ACL_USER::hostname_length, hash_filo::lock, mem, push_dynamic, qsort(), qsort_cmp, rebuild_check_host(), safe_mutex_assert_owner, set_user_salt(), ACL_ACCESS::sort, ACL_USER::ssl_cipher, ACL_USER::ssl_type, SSL_TYPE_NONE, SSL_TYPE_NOT_SPECIFIED, strdup_root(), strlen(), update_hostname(), ACL_USER::user, ACL_USER::user_resource, VOID, wild_many, ACL_USER::x509_issuer, and ACL_USER::x509_subject.
Referenced by replace_user_table().
01220 { 01221 ACL_USER acl_user; 01222 01223 safe_mutex_assert_owner(&acl_cache->lock); 01224 01225 acl_user.user=*user ? strdup_root(&mem,user) : 0; 01226 update_hostname(&acl_user.host, *host ? strdup_root(&mem, host): 0); 01227 acl_user.access=privileges; 01228 acl_user.user_resource = *mqh; 01229 acl_user.sort=get_sort(2,acl_user.host.hostname,acl_user.user); 01230 acl_user.hostname_length=(uint) strlen(host); 01231 acl_user.ssl_type= (ssl_type != SSL_TYPE_NOT_SPECIFIED ? 01232 ssl_type : SSL_TYPE_NONE); 01233 acl_user.ssl_cipher= ssl_cipher ? strdup_root(&mem,ssl_cipher) : 0; 01234 acl_user.x509_issuer= x509_issuer ? strdup_root(&mem,x509_issuer) : 0; 01235 acl_user.x509_subject=x509_subject ? strdup_root(&mem,x509_subject) : 0; 01236 01237 set_user_salt(&acl_user, password, password_len); 01238 01239 VOID(push_dynamic(&acl_users,(gptr) &acl_user)); 01240 if (!acl_user.host.hostname || 01241 (acl_user.host.hostname[0] == wild_many && !acl_user.host.hostname[1])) 01242 allow_all_hosts=1; // Anyone can connect /* purecov: tested */ 01243 qsort((gptr) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, 01244 sizeof(ACL_USER),(qsort_cmp) acl_compare); 01245 01246 /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ 01247 rebuild_check_host(); 01248 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static my_bool acl_load | ( | THD * | thd, | |
| TABLE_LIST * | tables | |||
| ) | [static] |
Definition at line 309 of file sql_acl.cc.
References ACL_ALLOC_BLOCK_SIZE, acl_cache, acl_compare(), acl_dbs, acl_hosts, acl_users, sys_var::after_update, ALTER_ACL, ALTER_PROC_ACL, atoi(), bzero, hash_filo::clear(), CREATE_ACL, CREATE_PROC_ACL, CREATE_TMP_ACL, CREATE_USER_ACL, CREATE_VIEW_ACL, db, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, dynamic_element, end_read_record(), EVENT_ACL, EXECUTE_ACL, FILE_ACL, files_charset_info, fix_rights_for_db, freeze_size(), get_access(), get_field(), get_sort(), GLOBAL_ACLS, global_system_variables, GRANT_ACL, host, hostname_requires_resolving(), INDEX_ACL, init_check_host(), init_read_record(), init_sql_alloc(), LOCK_global_system_variables, LOCK_TABLES_ACL, lower_case_table_names, mem, mqh_used, my_casedn_str, my_init_dynamic_array, MYSQL_DB_FIELD_DB, MYSQL_DB_FIELD_HOST, MYSQL_DB_FIELD_USER, mysql_proc_table_exists, NAME_LEN, NULL, system_variables::old_passwords, opt_secure_auth, PROCESS_ACL, pthread_mutex_lock, pthread_mutex_unlock, push_dynamic, qsort(), qsort_cmp, st_read_record::read_record, REFERENCES_ACL, REPL_CLIENT_ACL, REPL_SLAVE_ACL, restrict_update_of_old_passwords_var(), SCRAMBLED_PASSWORD_CHAR_LENGTH, SCRAMBLED_PASSWORD_CHAR_LENGTH_323, set_user_salt(), SHOW_DB_ACL, SHOW_VIEW_ACL, SPECIAL_NO_RESOLVE, specialflag, sql_print_error(), sql_print_warning(), SSL_TYPE_ANY, SSL_TYPE_NONE, SSL_TYPE_SPECIFIED, SSL_TYPE_X509, strcmp(), strlen(), strmov(), SUPER_ACL, sys_old_passwords, TRIGGER_ACL, update_hostname(), user, VOID, and wild_many.
Referenced by acl_reload().
00310 { 00311 TABLE *table; 00312 READ_RECORD read_record_info; 00313 my_bool return_val= 1; 00314 bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE; 00315 char tmp_name[NAME_LEN+1]; 00316 int password_length; 00317 DBUG_ENTER("acl_load"); 00318 00319 grant_version++; /* Privileges updated */ 00320 mysql_proc_table_exists= 1; // Assume mysql.proc exists 00321 00322 acl_cache->clear(1); // Clear locked hostname cache 00323 00324 init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0); 00325 init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0); 00326 table->use_all_columns(); 00327 VOID(my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST),20,50)); 00328 while (!(read_record_info.read_record(&read_record_info))) 00329 { 00330 ACL_HOST host; 00331 update_hostname(&host.host,get_field(&mem, table->field[0])); 00332 host.db= get_field(&mem, table->field[1]); 00333 if (lower_case_table_names && host.db) 00334 { 00335 /* 00336 convert db to lower case and give a warning if the db wasn't 00337 already in lower case 00338 */ 00339 (void) strmov(tmp_name, host.db); 00340 my_casedn_str(files_charset_info, host.db); 00341 if (strcmp(host.db, tmp_name) != 0) 00342 sql_print_warning("'host' entry '%s|%s' had database in mixed " 00343 "case that has been forced to lowercase because " 00344 "lower_case_table_names is set. It will not be " 00345 "possible to remove this privilege using REVOKE.", 00346 host.host.hostname ? host.host.hostname : "", 00347 host.db ? host.db : ""); 00348 } 00349 host.access= get_access(table,2); 00350 host.access= fix_rights_for_db(host.access); 00351 host.sort= get_sort(2,host.host.hostname,host.db); 00352 if (check_no_resolve && hostname_requires_resolving(host.host.hostname)) 00353 { 00354 sql_print_warning("'host' entry '%s|%s' " 00355 "ignored in --skip-name-resolve mode.", 00356 host.host.hostname ? host.host.hostname : "", 00357 host.db ? host.db : ""); 00358 continue; 00359 } 00360 #ifndef TO_BE_REMOVED 00361 if (table->s->fields == 8) 00362 { // Without grant 00363 if (host.access & CREATE_ACL) 00364 host.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL | CREATE_TMP_ACL; 00365 } 00366 #endif 00367 VOID(push_dynamic(&acl_hosts,(gptr) &host)); 00368 } 00369 qsort((gptr) dynamic_element(&acl_hosts,0,ACL_HOST*),acl_hosts.elements, 00370 sizeof(ACL_HOST),(qsort_cmp) acl_compare); 00371 end_read_record(&read_record_info); 00372 freeze_size(&acl_hosts); 00373 00374 init_read_record(&read_record_info,thd,table=tables[1].table,NULL,1,0); 00375 table->use_all_columns(); 00376 VOID(my_init_dynamic_array(&acl_users,sizeof(ACL_USER),50,100)); 00377 password_length= table->field[2]->field_length / 00378 table->field[2]->charset()->mbmaxlen; 00379 if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH_323) 00380 { 00381 sql_print_error("Fatal error: mysql.user table is damaged or in " 00382 "unsupported 3.20 format."); 00383 goto end; 00384 } 00385 00386 DBUG_PRINT("info",("user table fields: %d, password length: %d", 00387 table->s->fields, password_length)); 00388 00389 pthread_mutex_lock(&LOCK_global_system_variables); 00390 if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH) 00391 { 00392 if (opt_secure_auth) 00393 { 00394 pthread_mutex_unlock(&LOCK_global_system_variables); 00395 sql_print_error("Fatal error: mysql.user table is in old format, " 00396 "but server started with --secure-auth option."); 00397 goto end; 00398 } 00399 sys_old_passwords.after_update= restrict_update_of_old_passwords_var; 00400 if (global_system_variables.old_passwords) 00401 pthread_mutex_unlock(&LOCK_global_system_variables); 00402 else 00403 { 00404 global_system_variables.old_passwords= 1; 00405 pthread_mutex_unlock(&LOCK_global_system_variables); 00406 sql_print_warning("mysql.user table is not updated to new password format; " 00407 "Disabling new password usage until " 00408 "mysql_fix_privilege_tables is run"); 00409 } 00410 thd->variables.old_passwords= 1; 00411 } 00412 else 00413 { 00414 sys_old_passwords.after_update= 0; 00415 pthread_mutex_unlock(&LOCK_global_system_variables); 00416 } 00417 00418 allow_all_hosts=0; 00419 while (!(read_record_info.read_record(&read_record_info))) 00420 { 00421 ACL_USER user; 00422 update_hostname(&user.host, get_field(&mem, table->field[0])); 00423 user.user= get_field(&mem, table->field[1]); 00424 if (check_no_resolve && hostname_requires_resolving(user.host.hostname)) 00425 { 00426 sql_print_warning("'user' entry '%s@%s' " 00427 "ignored in --skip-name-resolve mode.", 00428 user.user ? user.user : "", 00429 user.host.hostname ? user.host.hostname : ""); 00430 continue; 00431 } 00432 00433 const char *password= get_field(&mem, table->field[2]); 00434 uint password_len= password ? strlen(password) : 0; 00435 set_user_salt(&user, password, password_len); 00436 if (user.salt_len == 0 && password_len != 0) 00437 { 00438 switch (password_len) { 00439 case 45: /* 4.1: to be removed */ 00440 sql_print_warning("Found 4.1 style password for user '%s@%s'. " 00441 "Ignoring user. " 00442 "You should change password for this user.", 00443 user.user ? user.user : "", 00444 user.host.hostname ? user.host.hostname : ""); 00445 break; 00446 default: 00447 sql_print_warning("Found invalid password for user: '%s@%s'; " 00448 "Ignoring user", user.user ? user.user : "", 00449 user.host.hostname ? user.host.hostname : ""); 00450 break; 00451 } 00452 } 00453 else // password is correct 00454 { 00455 uint next_field; 00456 user.access= get_access(table,3,&next_field) & GLOBAL_ACLS; 00457 /* 00458 if it is pre 5.0.1 privilege table then map CREATE privilege on 00459 CREATE VIEW & SHOW VIEW privileges 00460 */ 00461 if (table->s->fields <= 31 && (user.access & CREATE_ACL)) 00462 user.access|= (CREATE_VIEW_ACL | SHOW_VIEW_ACL); 00463 00464 /* 00465 if it is pre 5.0.2 privilege table then map CREATE/ALTER privilege on 00466 CREATE PROCEDURE & ALTER PROCEDURE privileges 00467 */ 00468 if (table->s->fields <= 33 && (user.access & CREATE_ACL)) 00469 user.access|= CREATE_PROC_ACL; 00470 if (table->s->fields <= 33 && (user.access & ALTER_ACL)) 00471 user.access|= ALTER_PROC_ACL; 00472 00473 /* 00474 pre 5.0.3 did not have CREATE_USER_ACL 00475 */ 00476 if (table->s->fields <= 36 && (user.access & GRANT_ACL)) 00477 user.access|= CREATE_USER_ACL; 00478 00479 00480 /* 00481 if it is pre 5.1.6 privilege table then map CREATE privilege on 00482 CREATE|ALTER|DROP|EXECUTE EVENT 00483 */ 00484 if (table->s->fields <= 37 && (user.access & SUPER_ACL)) 00485 user.access|= EVENT_ACL; 00486 00487 /* 00488 if it is pre 5.1.6 privilege then map TRIGGER privilege on CREATE. 00489 */ 00490 if (table->s->fields <= 38 && (user.access & SUPER_ACL)) 00491 user.access|= TRIGGER_ACL; 00492 00493 user.sort= get_sort(2,user.host.hostname,user.user); 00494 user.hostname_length= (user.host.hostname ? 00495 (uint) strlen(user.host.hostname) : 0); 00496 00497 /* Starting from 4.0.2 we have more fields */ 00498 if (table->s->fields >= 31) 00499 { 00500 char *ssl_type=get_field(&mem, table->field[next_field++]); 00501 if (!ssl_type) 00502 user.ssl_type=SSL_TYPE_NONE; 00503 else if (!strcmp(ssl_type, "ANY")) 00504 user.ssl_type=SSL_TYPE_ANY; 00505 else if (!strcmp(ssl_type, "X509")) 00506 user.ssl_type=SSL_TYPE_X509; 00507 else /* !strcmp(ssl_type, "SPECIFIED") */ 00508 user.ssl_type=SSL_TYPE_SPECIFIED; 00509 00510 user.ssl_cipher= get_field(&mem, table->field[next_field++]); 00511 user.x509_issuer= get_field(&mem, table->field[next_field++]); 00512 user.x509_subject= get_field(&mem, table->field[next_field++]); 00513 00514 char *ptr = get_field(&mem, table->field[next_field++]); 00515 user.user_resource.questions=ptr ? atoi(ptr) : 0; 00516 ptr = get_field(&mem, table->field[next_field++]); 00517 user.user_resource.updates=ptr ? atoi(ptr) : 0; 00518 ptr = get_field(&mem, table->field[next_field++]); 00519 user.user_resource.conn_per_hour= ptr ? atoi(ptr) : 0; 00520 if (user.user_resource.questions || user.user_resource.updates || 00521 user.user_resource.conn_per_hour) 00522 mqh_used=1; 00523 00524 if (table->s->fields >= 36) 00525 { 00526 /* Starting from 5.0.3 we have max_user_connections field */ 00527 ptr= get_field(&mem, table->field[next_field++]); 00528 user.user_resource.user_conn= ptr ? atoi(ptr) : 0; 00529 } 00530 else 00531 user.user_resource.user_conn= 0; 00532 } 00533 else 00534 { 00535 user.ssl_type=SSL_TYPE_NONE; 00536 bzero((char *)&(user.user_resource),sizeof(user.user_resource)); 00537 #ifndef TO_BE_REMOVED 00538 if (table->s->fields <= 13) 00539 { // Without grant 00540 if (user.access & CREATE_ACL) 00541 user.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL; 00542 } 00543 /* Convert old privileges */ 00544 user.access|= LOCK_TABLES_ACL | CREATE_TMP_ACL | SHOW_DB_ACL; 00545 if (user.access & FILE_ACL) 00546 user.access|= REPL_CLIENT_ACL | REPL_SLAVE_ACL; 00547 if (user.access & PROCESS_ACL) 00548 user.access|= SUPER_ACL | EXECUTE_ACL; 00549 #endif 00550 } 00551 VOID(push_dynamic(&acl_users,(gptr) &user)); 00552 if (!user.host.hostname || 00553 (user.host.hostname[0] == wild_many && !user.host.hostname[1])) 00554 allow_all_hosts=1; // Anyone can connect 00555 } 00556 } 00557 qsort((gptr) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, 00558 sizeof(ACL_USER),(qsort_cmp) acl_compare); 00559 end_read_record(&read_record_info); 00560 freeze_size(&acl_users); 00561 00562 init_read_record(&read_record_info,thd,table=tables[2].table,NULL,1,0); 00563 table->use_all_columns(); 00564 VOID(my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB),50,100)); 00565 while (!(read_record_info.read_record(&read_record_info))) 00566 { 00567 ACL_DB db; 00568 update_hostname(&db.host,get_field(&mem, table->field[MYSQL_DB_FIELD_HOST])); 00569 db.db=get_field(&mem, table->field[MYSQL_DB_FIELD_DB]); 00570 if (!db.db) 00571 { 00572 sql_print_warning("Found an entry in the 'db' table with empty database name; Skipped"); 00573 continue; 00574 } 00575 db.user=get_field(&mem, table->field[MYSQL_DB_FIELD_USER]); 00576 if (check_no_resolve && hostname_requires_resolving(db.host.hostname)) 00577 { 00578 sql_print_warning("'db' entry '%s %s@%s' " 00579 "ignored in --skip-name-resolve mode.", 00580 db.db, 00581 db.user ? db.user : "", 00582 db.host.hostname ? db.host.hostname : ""); 00583 continue; 00584 } 00585 db.access=get_access(table,3); 00586 db.access=fix_rights_for_db(db.access); 00587 if (lower_case_table_names) 00588 { 00589 /* 00590 convert db to lower case and give a warning if the db wasn't 00591 already in lower case 00592 */ 00593 (void)strmov(tmp_name, db.db); 00594 my_casedn_str(files_charset_info, db.db); 00595 if (strcmp(db.db, tmp_name) != 0) 00596 { 00597 sql_print_warning("'db' entry '%s %s@%s' had database in mixed " 00598 "case that has been forced to lowercase because " 00599 "lower_case_table_names is set. It will not be " 00600 "possible to remove this privilege using REVOKE.", 00601 db.db, 00602 db.user ? db.user : "", 00603 db.host.hostname ? db.host.hostname : ""); 00604 } 00605 } 00606 db.sort=get_sort(3,db.host.hostname,db.db,db.user); 00607 #ifndef TO_BE_REMOVED 00608 if (table->s->fields <= 9) 00609 { // Without grant 00610 if (db.access & CREATE_ACL) 00611 db.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL; 00612 } 00613 #endif 00614 VOID(push_dynamic(&acl_dbs,(gptr) &db)); 00615 } 00616 qsort((gptr) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements, 00617 sizeof(ACL_DB),(qsort_cmp) acl_compare); 00618 end_read_record(&read_record_info); 00619 freeze_size(&acl_dbs); 00620 init_check_host(); 00621 00622 initialized=1; 00623 return_val=0; 00624 00625 end: 00626 DBUG_RETURN(return_val); 00627 }
Here is the call graph for this function:

Here is the caller graph for this function:

| my_bool acl_reload | ( | THD * | thd | ) |
Definition at line 667 of file sql_acl.cc.
References acl_cache, acl_check_hosts, acl_dbs, acl_free(), acl_hosts, acl_load(), acl_users, acl_wild_hosts, bzero, close_thread_tables(), DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, delete_dynamic(), free_root(), hash_free(), init_check_host(), hash_filo::lock, mem, MYF, pthread_mutex_lock, pthread_mutex_unlock, simple_open_n_lock_tables(), sql_print_error(), TL_READ, and VOID.
Referenced by acl_init(), and reload_acl_and_cache().
00668 { 00669 TABLE_LIST tables[3]; 00670 DYNAMIC_ARRAY old_acl_hosts,old_acl_users,old_acl_dbs; 00671 MEM_ROOT old_mem; 00672 bool old_initialized; 00673 my_bool return_val= 1; 00674 DBUG_ENTER("acl_reload"); 00675 00676 if (thd->locked_tables) 00677 { // Can't have locked tables here 00678 thd->lock=thd->locked_tables; 00679 thd->locked_tables=0; 00680 close_thread_tables(thd); 00681 } 00682 00683 /* 00684 To avoid deadlocks we should obtain table locks before 00685 obtaining acl_cache->lock mutex. 00686 */ 00687 bzero((char*) tables, sizeof(tables)); 00688 tables[0].alias= tables[0].table_name= (char*) "host"; 00689 tables[1].alias= tables[1].table_name= (char*) "user"; 00690 tables[2].alias= tables[2].table_name= (char*) "db"; 00691 tables[0].db=tables[1].db=tables[2].db=(char*) "mysql"; 00692 tables[0].next_local= tables[0].next_global= tables+1; 00693 tables[1].next_local= tables[1].next_global= tables+2; 00694 tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_READ; 00695 00696 if (simple_open_n_lock_tables(thd, tables)) 00697 { 00698 sql_print_error("Fatal error: Can't open and lock privilege tables: %s", 00699 thd->net.last_error); 00700 goto end; 00701 } 00702 00703 if ((old_initialized=initialized)) 00704 VOID(pthread_mutex_lock(&acl_cache->lock)); 00705 00706 old_acl_hosts=acl_hosts; 00707 old_acl_users=acl_users; 00708 old_acl_dbs=acl_dbs; 00709 old_mem=mem; 00710 delete_dynamic(&acl_wild_hosts); 00711 hash_free(&acl_check_hosts); 00712 00713 if ((return_val= acl_load(thd, tables))) 00714 { // Error. Revert to old list 00715 DBUG_PRINT("error",("Reverting to old privileges")); 00716 acl_free(); /* purecov: inspected */ 00717 acl_hosts=old_acl_hosts; 00718 acl_users=old_acl_users; 00719 acl_dbs=old_acl_dbs; 00720 mem=old_mem; 00721 init_check_host(); 00722 } 00723 else 00724 { 00725 free_root(&old_mem,MYF(0)); 00726 delete_dynamic(&old_acl_hosts); 00727 delete_dynamic(&old_acl_users); 00728 delete_dynamic(&old_acl_dbs); 00729 } 00730 if (old_initialized) 00731 VOID(pthread_mutex_unlock(&acl_cache->lock)); 00732 end: 00733 close_thread_tables(thd); 00734 DBUG_RETURN(return_val); 00735 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void acl_update_db | ( | const char * | user, | |
| const char * | host, | |||
| const char * | db, | |||
| ulong | privileges | |||
| ) | [static] |
Definition at line 1251 of file sql_acl.cc.
References acl_cache, acl_dbs, delete_dynamic_element(), dynamic_element, st_dynamic_array::elements, hash_filo::lock, my_strcasecmp, safe_mutex_assert_owner, strcmp(), and system_charset_info.
Referenced by replace_db_table().
01253 { 01254 safe_mutex_assert_owner(&acl_cache->lock); 01255 01256 for (uint i=0 ; i < acl_dbs.elements ; i++) 01257 { 01258 ACL_DB *acl_db=dynamic_element(&acl_dbs,i,ACL_DB*); 01259 if (!acl_db->user && !user[0] || 01260 acl_db->user && 01261 !strcmp(user,acl_db->user)) 01262 { 01263 if (!acl_db->host.hostname && !host[0] || 01264 acl_db->host.hostname && 01265 !my_strcasecmp(system_charset_info, host, acl_db->host.hostname)) 01266 { 01267 if (!acl_db->db && !db[0] || 01268 acl_db->db && !strcmp(db,acl_db->db)) 01269 { 01270 if (privileges) 01271 acl_db->access=privileges; 01272 else 01273 delete_dynamic_element(&acl_dbs,i); 01274 } 01275 } 01276 } 01277 } 01278 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void acl_update_user | ( | const char * | user, | |
| const char * | host, | |||
| const char * | password, | |||
| uint | password_len, | |||
| enum SSL_type | ssl_type, | |||
| const char * | ssl_cipher, | |||
| const char * | x509_issuer, | |||
| const char * | x509_subject, | |||
| USER_RESOURCES * | mqh, | |||
| ulong | privileges | |||
| ) | [static] |
Definition at line 1162 of file sql_acl.cc.
References acl_cache, acl_users, user_resources::conn_per_hour, user_resources::CONNECTIONS_PER_HOUR, dynamic_element, st_dynamic_array::elements, hash_filo::lock, mem, my_strcasecmp, user_resources::QUERIES_PER_HOUR, user_resources::questions, safe_mutex_assert_owner, set_user_salt(), user_resources::specified_limits, SSL_TYPE_NOT_SPECIFIED, strcmp(), strdup_root(), system_charset_info, user_resources::updates, user_resources::UPDATES_PER_HOUR, user_resources::user_conn, and user_resources::USER_CONNECTIONS.
Referenced by replace_user_table().
01170 { 01171 safe_mutex_assert_owner(&acl_cache->lock); 01172 01173 for (uint i=0 ; i < acl_users.elements ; i++) 01174 { 01175 ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*); 01176 if (!acl_user->user && !user[0] || 01177 acl_user->user && !strcmp(user,acl_user->user)) 01178 { 01179 if (!acl_user->host.hostname && !host[0] || 01180 acl_user->host.hostname && 01181 !my_strcasecmp(system_charset_info, host, acl_user->host.hostname)) 01182 { 01183 acl_user->access=privileges; 01184 if (mqh->specified_limits & USER_RESOURCES::QUERIES_PER_HOUR) 01185 acl_user->user_resource.questions=mqh->questions; 01186 if (mqh->specified_limits & USER_RESOURCES::UPDATES_PER_HOUR) 01187 acl_user->user_resource.updates=mqh->updates; 01188 if (mqh->specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR) 01189 acl_user->user_resource.conn_per_hour= mqh->conn_per_hour; 01190 if (mqh->specified_limits & USER_RESOURCES::USER_CONNECTIONS) 01191 acl_user->user_resource.user_conn= mqh->user_conn; 01192 if (ssl_type != SSL_TYPE_NOT_SPECIFIED) 01193 { 01194 acl_user->ssl_type= ssl_type; 01195 acl_user->ssl_cipher= (ssl_cipher ? strdup_root(&mem,ssl_cipher) : 01196 0); 01197 acl_user->x509_issuer= (x509_issuer ? strdup_root(&mem,x509_issuer) : 01198 0); 01199 acl_user->x509_subject= (x509_subject ? 01200 strdup_root(&mem,x509_subject) : 0); 01201 } 01202 if (password) 01203 set_user_salt(acl_user, password, password_len); 01204 /* search complete: */ 01205 break; 01206 } 01207 } 01208 } 01209 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 4247 of file sql_acl.cc.
References String::append(), int10_to_str(), p, and strlen().
Referenced by mysql_show_grants().
04248 { 04249 if (value) 04250 { 04251 char buff[22], *p; // just as in int2str 04252 grant->append(' '); 04253 grant->append(name, strlen(name)); 04254 grant->append(' '); 04255 p=int10_to_str(value, buff, 10); 04256 grant->append(buff,p-buff); 04257 } 04258 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 5362 of file sql_acl.cc.
References String::append(), String::length(), STRING_WITH_LEN, and user.
Referenced by mysql_create_user(), mysql_drop_user(), and mysql_rename_user().
05363 { 05364 if (str->length()) 05365 str->append(','); 05366 str->append('\''); 05367 str->append(user->user.str); 05368 str->append(STRING_WITH_LEN("'@'")); 05369 str->append(user->host.str); 05370 str->append('\''); 05371 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static const char* calc_ip | ( | const char * | ip, | |
| long * | val, | |||
| char | end | |||
| ) | [static] |
Definition at line 1720 of file sql_acl.cc.
References str2int().
Referenced by compare_hostname(), and update_hostname().
01721 { 01722 long ip_val,tmp; 01723 if (!(ip=str2int(ip,10,0,255,&ip_val)) || *ip != '.') 01724 return 0; 01725 ip_val<<=24; 01726 if (!(ip=str2int(ip+1,10,0,255,&tmp)) || *ip != '.') 01727 return 0; 01728 ip_val+=tmp<<16; 01729 if (!(ip=str2int(ip+1,10,0,255,&tmp)) || *ip != '.') 01730 return 0; 01731 ip_val+=tmp<<8; 01732 if (!(ip=str2int(ip+1,10,0,255,&tmp)) || *ip != end) 01733 return 0; 01734 *val=ip_val+tmp; 01735 return ip; 01736 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool change_password | ( | THD * | thd, | |
| const char * | host, | |||
| const char * | user, | |||
| char * | new_password | |||
| ) |
Definition at line 1561 of file sql_acl.cc.
References acl_cache, bzero, check_change_password(), hash_filo::clear(), close_thread_tables(), DBUG_ASSERT, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, ER, ER_PASSWORD_NO_MATCH, FALSE, find_acl_user(), ACL_USER::host, acl_host_and_ip::hostname, Rpl_filter::is_on(), MYSQL_LOG::is_open(), hash_filo::lock, my_message(), my_sprintf, MYF, mysql_bin_log, open_ltable(), pthread_mutex_lock, pthread_mutex_unlock, rpl_filter, set_user_salt(), strlen(), Rpl_filter::tables_ok(), TL_WRITE, TRUE, update_user_table(), ACL_USER::user, and VOID.
Referenced by set_var_password::update().
01563 { 01564 TABLE_LIST tables; 01565 TABLE *table; 01566 /* Buffer should be extended when password length is extended. */ 01567 char buff[512]; 01568 ulong query_length; 01569 uint new_password_len= strlen(new_password); 01570 bool result= 1; 01571 DBUG_ENTER("change_password"); 01572 DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'", 01573 host,user,new_password)); 01574 DBUG_ASSERT(host != 0); // Ensured by parent 01575 01576 if (check_change_password(thd, host, user, new_password, new_password_len)) 01577 DBUG_RETURN(1); 01578 01579 bzero((char*) &tables, sizeof(tables)); 01580 tables.alias= tables.table_name= (char*) "user"; 01581 tables.db= (char*) "mysql"; 01582 01583 #ifdef HAVE_REPLICATION 01584 /* 01585 GRANT and REVOKE are applied the slave in/exclusion rules as they are 01586 some kind of updates to the mysql.% tables. 01587 */ 01588 if (thd->slave_thread && rpl_filter->is_on()) 01589 { 01590 /* 01591 The tables must be marked "updating" so that tables_ok() takes them into 01592 account in tests. It's ok to leave 'updating' set after tables_ok. 01593 */ 01594 tables.updating= 1; 01595 /* Thanks to bzero, tables.next==0 */ 01596 if (!(thd->spcont || rpl_filter->tables_ok(0, &tables))) 01597 DBUG_RETURN(0); 01598 } 01599 #endif 01600 01601 if (!(table= open_ltable(thd, &tables, TL_WRITE))) 01602 DBUG_RETURN(1); 01603 01604 VOID(pthread_mutex_lock(&acl_cache->lock)); 01605 ACL_USER *acl_user; 01606 if (!(acl_user= find_acl_user(host, user, TRUE))) 01607 { 01608 VOID(pthread_mutex_unlock(&acl_cache->lock)); 01609 my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH), MYF(0)); 01610 goto end; 01611 } 01612 /* update loaded acl entry: */ 01613 set_user_salt(acl_user, new_password, new_password_len); 01614 01615 if (update_user_table(thd, table, 01616 acl_user->host.hostname ? acl_user->host.hostname : "", 01617 acl_user->user ? acl_user->user : "", 01618 new_password, new_password_len)) 01619 { 01620 VOID(pthread_mutex_unlock(&acl_cache->lock)); /* purecov: deadcode */ 01621 goto end; 01622 } 01623 01624 acl_cache->clear(1); // Clear locked hostname cache 01625 VOID(pthread_mutex_unlock(&acl_cache->lock)); 01626 result= 0; 01627 if (mysql_bin_log.is_open()) 01628 { 01629 query_length= 01630 my_sprintf(buff, 01631 (buff,"SET PASSWORD FOR \"%-.120s\"@\"%-.120s\"=\"%-.120s\"", 01632 acl_user->user ? acl_user->user : "", 01633 acl_user->host.hostname ? acl_user->host.hostname : "", 01634 new_password)); 01635 thd->clear_error(); 01636 thd->binlog_query(THD::MYSQL_QUERY_TYPE, buff, query_length, FALSE, FALSE); 01637 } 01638 end: 01639 close_thread_tables(thd); 01640 DBUG_RETURN(result); 01641 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 4841 of file sql_acl.cc.
References acl_cache, acl_users, counter, dynamic_element, st_dynamic_array::elements, st_lex_user::host, ACL_USER::host, host, acl_host_and_ip::hostname, hash_filo::lock, my_strcasecmp, safe_mutex_assert_owner, LEX_STRING::str, strcmp(), system_charset_info, st_lex_user::user, ACL_USER::user, and user.
04843 { 04844 ACL_USER *acl_user= 0; 04845 uint counter; 04846 04847 safe_mutex_assert_owner(&acl_cache->lock); 04848 04849 for (counter= 0 ; counter < acl_users.elements ; counter++) 04850 { 04851 const char *user,*host; 04852 acl_user= dynamic_element(&acl_users, counter, ACL_USER*); 04853 if (!(user=acl_user->user)) 04854 user= ""; 04855 if (!(host=acl_user->host.hostname)) 04856 host= ""; 04857 if (!strcmp(user_name->user.str,user) && 04858 !my_strcasecmp(system_charset_info, user_name->host.str, host)) 04859 break; 04860 } 04861 if (counter == acl_users.elements) 04862 return 0; 04863 04864 *acl_acl_userdx= counter; 04865 return acl_user; 04866 }
Here is the call graph for this function:

| bool check_change_password | ( | THD * | thd, | |
| const char * | host, | |||
| const char * | user, | |||
| char * | new_password, | |||
| uint | new_password_len | |||
| ) |
Definition at line 1513 of file sql_acl.cc.
References check_access(), ER, ER_OPTION_PREVENTS_STATEMENT, ER_PASSWD_LENGTH, ER_PASSWORD_ANONYMOUS_USER, initialized, my_error(), my_message(), my_strcasecmp, MYF, SCRAMBLED_PASSWORD_CHAR_LENGTH, SCRAMBLED_PASSWORD_CHAR_LENGTH_323, strcmp(), strlen(), system_charset_info, and UPDATE_ACL.
Referenced by change_password(), and set_var_password::check().
01515 { 01516 if (!initialized) 01517 { 01518 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables"); 01519 return(1); 01520 } 01521 if (!thd->slave_thread && 01522 (strcmp(thd->security_ctx->user, user) || 01523 my_strcasecmp(system_charset_info, host, 01524 thd->security_ctx->priv_host))) 01525 { 01526 if (check_access(thd, UPDATE_ACL, "mysql",0,1,0,0)) 01527 return(1); 01528 } 01529 if (!thd->slave_thread && !thd->security_ctx->user[0]) 01530 { 01531 my_message(ER_PASSWORD_ANONYMOUS_USER, ER(ER_PASSWORD_ANONYMOUS_USER), 01532 MYF(0)); 01533 return(1); 01534 } 01535 uint len=strlen(new_password); 01536 if (len && len != SCRAMBLED_PASSWORD_CHAR_LENGTH && 01537 len != SCRAMBLED_PASSWORD_CHAR_LENGTH_323) 01538 { 01539 my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH); 01540 return -1; 01541 } 01542 return(0); 01543 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool check_column_grant_in_table_ref | ( | THD * | thd, | |
| TABLE_LIST * | table_ref, | |||
| const char * | name, | |||
| uint | length | |||
| ) |
Definition at line 3923 of file sql_acl.cc.
References st_table_list::allowed_show, st_table_list::belong_to_view, check_grant_column(), st_table_share::db, ER, ER_VIEW_NO_EXPLAIN, FALSE, st_table_list::field_translation, get_column_grant(), st_table_list::grant, st_table::grant, my_message(), MYF, st_table::s, st_table_list::security_ctx, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_FIELDS, LEX_STRING::str, st_table_list::table, st_table_share::table_name, test, TRUE, st_table_list::view, VIEW_ANY_ACL, st_table_list::view_db, st_table_list::view_name, and st_grant_info::want_privilege.
Referenced by find_field_in_table_ref().
03925 { 03926 GRANT_INFO *grant; 03927 const char *db_name; 03928 const char *table_name; 03929 Security_context *sctx= test(table_ref->security_ctx) ? 03930 table_ref->security_ctx : thd->security_ctx; 03931 03932 if (table_ref->view || table_ref->field_translation) 03933 { 03934 /* View or derived information schema table. */ 03935 ulong view_privs; 03936 grant= &(table_ref->grant); 03937 db_name= table_ref->view_db.str; 03938 table_name= table_ref->view_name.str; 03939 if (table_ref->belong_to_view && 03940 (thd->lex->sql_command == SQLCOM_SHOW_FIELDS || 03941 thd->lex->sql_command == SQLCOM_SHOW_CREATE)) 03942 { 03943 view_privs= get_column_grant(thd, grant, db_name, table_name, name); 03944 if (view_privs & VIEW_ANY_ACL) 03945 { 03946 table_ref->belong_to_view->allowed_show= TRUE; 03947 return FALSE; 03948 } 03949 table_ref->belong_to_view->allowed_show= FALSE; 03950 my_message(ER_VIEW_NO_EXPLAIN, ER(ER_VIEW_NO_EXPLAIN), MYF(0)); 03951 return TRUE; 03952 } 03953 } 03954 else 03955 { 03956 /* Normal or temporary table. */ 03957 TABLE *table= table_ref->table; 03958 grant= &(table->grant); 03959 db_name= table->s->db.str; 03960 table_name= table->s->table_name.str; 03961 } 03962 03963 if (grant->want_privilege) 03964 return check_grant_column(thd, grant, db_name, table_name, name, 03965 length, sctx); 03966 else 03967 return FALSE; 03968 03969 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static byte* check_get_key | ( | ACL_USER * | buff, | |
| uint * | length, | |||
| my_bool not_used | __attribute__((unused)) | |||
| ) | [static] |
Definition at line 1154 of file sql_acl.cc.
References ACL_USER::host, acl_host_and_ip::hostname, and ACL_USER::hostname_length.
Referenced by init_check_host().
01156 { 01157 *length=buff->hostname_length; 01158 return (byte*) buff->host.hostname; 01159 }
Here is the caller graph for this function:

| bool check_grant | ( | THD * | thd, | |
| ulong | want_access, | |||
| TABLE_LIST * | tables, | |||
| uint | show_table, | |||
| uint | number, | |||
| bool | no_errors | |||
| ) |
Definition at line 3730 of file sql_acl.cc.
References COL_ACLS, st_table_list::db, DBUG_ASSERT, DBUG_ENTER, DBUG_RETURN, st_table_list::derived, ER_TABLEACCESS_DENIED_ERROR, err, get_privilege_desc(), st_table_list::grant, st_grant_info::grant_table, grant_version, LOCK_grant, my_error(), MYF, st_table_list::next_global, st_grant_info::orig_want_privilege, st_grant_info::privilege, st_table_list::referencing_view, rw_rdlock, rw_unlock, st_table_list::schema_table, st_table_list::security_ctx, SHOW_VIEW_ACL, table_hash_search(), st_table_list::table_name, test, st_grant_info::version, and st_grant_info::want_privilege.
Referenced by check_single_table_access(), check_some_access(), create_table_precheck(), dispatch_command(), find_files(), multi_update_precheck(), mysql_create_view(), mysql_execute_command(), prepare_schema_table(), and test_if_create_new_users().
03732 { 03733 TABLE_LIST *table, *first_not_own_table= thd->lex->first_not_own_table(); 03734 Security_context *sctx= thd->security_ctx; 03735 uint i; 03736 ulong orig_want_access= want_access; 03737 DBUG_ENTER("check_grant"); 03738 DBUG_ASSERT(number > 0); 03739 03740 /* 03741 Walk through the list of tables that belong to the query and save the 03742 requested access (orig_want_privilege) to be able to use it when 03743 checking access rights to the underlying tables of a view. Our grant 03744 system gradually eliminates checked bits from want_privilege and thus 03745 after all checks are done we can no longer use it. 03746 The check that first_not_own_table is not reached is for the case when 03747 the given table list refers to the list for prelocking (contains tables 03748 of other queries). For simple queries first_not_own_table is 0. 03749 */ 03750 for (i= 0, table= tables; 03751 table != first_not_own_table && i < number; 03752 table= table->next_global, i++) 03753 { 03754 /* Remove SHOW_VIEW_ACL, because it will be checked during making view */ 03755 table->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL); 03756 } 03757 03758 rw_rdlock(&LOCK_grant); 03759 for (table= tables; 03760 table && number-- && table != first_not_own_table; 03761 table= table->next_global) 03762 { 03763 GRANT_TABLE *grant_table; 03764 sctx = test(table->security_ctx) ? 03765 table->security_ctx : thd->security_ctx; 03766 03767 want_access= orig_want_access; 03768 want_access&= ~sctx->master_access; 03769 if (!want_access) 03770 continue; // ok 03771 03772 if (!(~table->grant.privilege & want_access) || 03773 table->derived || table->schema_table) 03774 { 03775 /* 03776 It is subquery in the FROM clause. VIEW set table->derived after 03777 table opening, but this function always called before table opening. 03778 */ 03779 if (!table->referencing_view) 03780 { 03781 /* 03782 If it's a temporary table created for a subquery in the FROM 03783 clause, or an INFORMATION_SCHEMA table, drop the request for 03784 a privilege. 03785 */ 03786 table->grant.want_privilege= 0; 03787 } 03788 continue; 03789 } 03790 if (!(grant_table= table_hash_search(sctx->host, sctx->ip, 03791 table->db, sctx->priv_user, 03792 table->table_name,0))) 03793 { 03794 want_access &= ~table->grant.privilege; 03795 goto err; // No grants 03796 } 03797 if (show_table) 03798 continue; // We have some priv on this 03799 03800 table->grant.grant_table=grant_table; // Remember for column test 03801 table->grant.version=grant_version; 03802 table->grant.privilege|= grant_table->privs; 03803 table->grant.want_privilege= ((want_access & COL_ACLS) 03804 & ~table->grant.privilege); 03805 03806 if (!(~table->grant.privilege & want_access)) 03807 continue; 03808 03809 if (want_access & ~(grant_table->cols | table->grant.privilege)) 03810 { 03811 want_access &= ~(grant_table->cols | table->grant.privilege); 03812 goto err; // impossible 03813 } 03814 } 03815 rw_unlock(&LOCK_grant); 03816 DBUG_RETURN(0); 03817 03818 err: 03819 rw_unlock(&LOCK_grant); 03820 if (!no_errors) // Not a silent skip of table 03821 { 03822 char command[128]; 03823 get_privilege_desc(command, sizeof(command), want_access); 03824 my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), 03825 command, 03826 sctx->priv_user, 03827 sctx->host_or_ip, 03828 table ? table->table_name : "unknown"); 03829 } 03830 DBUG_RETURN(1); 03831 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool check_grant_all_columns | ( | THD * | thd, | |
| ulong | want_access, | |||
| GRANT_INFO * | grant, | |||
| const char * | db_name, | |||
| const char * | table_name, | |||
| Field_iterator * | fields | |||
| ) |
Definition at line 3972 of file sql_acl.cc.
References column_hash_search(), Field_iterator::end_of_fields(), ER_COLUMNACCESS_DENIED_ERROR, err, get_privilege_desc(), grant_option, st_grant_info::grant_table, grant_version, LOCK_grant, my_error(), MYF, Field_iterator::name(), Field_iterator::next(), st_grant_info::privilege, GRANT_COLUMN::rights, rw_rdlock, rw_unlock, strlen(), table_hash_search(), and st_grant_info::version.
Referenced by check_insert_fields(), and insert_fields().
03975 { 03976 Security_context *sctx= thd->security_ctx; 03977 GRANT_TABLE *grant_table; 03978 GRANT_COLUMN *grant_column; 03979 03980 want_access &= ~grant->privilege; 03981 if (!want_access) 03982 return 0; // Already checked 03983 if (!grant_option) 03984 goto err2; 03985 03986 rw_rdlock(&LOCK_grant); 03987 03988 /* reload table if someone has modified any grants */ 03989 03990 if (grant->version != grant_version) 03991 { 03992 grant->grant_table= 03993 table_hash_search(sctx->host, sctx->ip, db_name, 03994 sctx->priv_user, 03995 table_name, 0); /* purecov: inspected */ 03996 grant->version= grant_version; /* purecov: inspected */ 03997 } 03998 /* The following should always be true */ 03999 if (!(grant_table= grant->grant_table)) 04000 goto err; /* purecov: inspected */ 04001 04002 for (; !fields->end_of_fields(); fields->next()) 04003 { 04004 const char *field_name= fields->name(); 04005 grant_column= column_hash_search(grant_table, field_name, 04006 (uint) strlen(field_name)); 04007 if (!grant_column || (~grant_column->rights & want_access)) 04008 goto err; 04009 } 04010 rw_unlock(&LOCK_grant); 04011 return 0; 04012 04013 err: 04014 rw_unlock(&LOCK_grant); 04015 err2: 04016 char command[128]; 04017 get_privilege_desc(command, sizeof(command), want_access); 04018 my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), 04019 command, 04020 sctx->priv_user, 04021 sctx->host_or_ip, 04022 fields->name(), 04023 table_name); 04024 return 1; 04025 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool check_grant_column | ( | THD * | thd, | |
| GRANT_INFO * | grant, | |||
| const char * | db_name, | |||
| const char * | table_name, | |||
| const char * | name, | |||
| uint | length, | |||
| Security_context * | sctx | |||
| ) |
Definition at line 3852 of file sql_acl.cc.
References column_hash_search(), DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, ER_COLUMNACCESS_DENIED_ERROR, err, get_privilege_desc(), st_grant_info::grant_table, grant_version, LOCK_grant, my_error(), MYF, st_grant_info::privilege, GRANT_COLUMN::rights, rw_rdlock, rw_unlock, table_hash_search(), st_grant_info::version, and st_grant_info::want_privilege.
Referenced by check_column_grant_in_table_ref(), and Item_trigger_field::fix_fields().
03855 { 03856 GRANT_TABLE *grant_table; 03857 GRANT_COLUMN *grant_column; 03858 ulong want_access= grant->want_privilege & ~grant->privilege; 03859 DBUG_ENTER("check_grant_column"); 03860 DBUG_PRINT("enter", ("table: %s want_access: %u", table_name, want_access)); 03861 03862 if (!want_access) 03863 DBUG_RETURN(0); // Already checked 03864 03865 rw_rdlock(&LOCK_grant); 03866 03867 /* reload table if someone has modified any grants */ 03868 03869 if (grant->version != grant_version) 03870 { 03871 grant->grant_table= 03872 table_hash_search(sctx->host, sctx->ip, db_name, 03873 sctx->priv_user, 03874 table_name, 0); /* purecov: inspected */ 03875 grant->version= grant_version; /* purecov: inspected */ 03876 } 03877 if (!(grant_table= grant->grant_table)) 03878 goto err; /* purecov: deadcode */ 03879 03880 grant_column=column_hash_search(grant_table, name, length); 03881 if (grant_column && !(~grant_column->rights & want_access)) 03882 { 03883 rw_unlock(&LOCK_grant); 03884 DBUG_RETURN(0); 03885 } 03886 03887 err: 03888 rw_unlock(&LOCK_grant); 03889 char command[128]; 03890 get_privilege_desc(command, sizeof(command), want_access); 03891 my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), 03892 command, 03893 sctx->priv_user, 03894 sctx->host_or_ip, 03895 name, 03896 table_name); 03897 DBUG_RETURN(1); 03898 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool check_grant_db | ( | THD * | thd, | |
| const char * | db | |||
| ) |
Definition at line 4034 of file sql_acl.cc.
References column_priv_hash, compare_hostname(), error, hash_element(), key_length, LOCK_grant, memcmp(), NAME_LEN, st_hash::records, rw_rdlock, strmov(), and USERNAME_LENGTH.
Referenced by fill_schema_shemata(), get_all_tables(), mysql_change_db(), mysqld_show_create_db(), and prepare_schema_table().
04035 { 04036 Security_context *sctx= thd->security_ctx; 04037 char helping [NAME_LEN+USERNAME_LENGTH+2]; 04038 uint len; 04039 bool error= 1; 04040 04041 len= (uint) (strmov(strmov(helping, sctx->priv_user) + 1, db) - helping) + 1; 04042 rw_rdlock(&LOCK_grant); 04043 04044 for (uint idx=0 ; idx < column_priv_hash.records ; idx++) 04045 { 04046 GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, 04047 idx); 04048 if (len < grant_table->key_length && 04049 !memcmp(grant_table->hash_key,helping,len) && 04050 compare_hostname(&grant_table->host, sctx->host, sctx->ip)) 04051 { 04052 error=0; // Found match 04053 break; 04054 } 04055 } 04056 rw_unlock(&LOCK_grant); 04057 return error; 04058 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool check_grant_routine | ( | THD * | thd, | |
| ulong | want_access, | |||
| TABLE_LIST * | procs, | |||
| bool | is_proc, | |||
| bool | no_errors | |||
| ) |
Definition at line 4078 of file sql_acl.cc.
References st_table_list::db, DBUG_ENTER, DBUG_RETURN, err, st_table_list::grant, host, LOCK_grant, st_table_list::next_global, st_grant_info::privilege, routine_hash_search(), rw_rdlock, st_table_list::table_name, and user.
Referenced by check_routine_access(), and mysql_execute_command().
04080 { 04081 TABLE_LIST *table; 04082 Security_context *sctx= thd->security_ctx; 04083 char *user= sctx->priv_user; 04084 char *host= sctx->priv_host; 04085 DBUG_ENTER("check_grant_routine"); 04086 04087 want_access&= ~sctx->master_access; 04088 if (!want_access) 04089 DBUG_RETURN(0); // ok 04090 04091 rw_rdlock(&LOCK_grant); 04092 for (table= procs; table; table= table->next_global) 04093 { 04094 GRANT_NAME *grant_proc; 04095 if ((grant_proc= routine_hash_search(host, sctx->ip, table->db, user, 04096 table->table_name, is_proc, 0))) 04097 table->grant.privilege|= grant_proc->privs; 04098 04099 if (want_access & ~table->grant.privilege) 04100 { 04101 want_access &= ~table->grant.privilege; 04102 goto err; 04103 } 04104 } 04105 rw_unlock(&LOCK_grant); 04106 DBUG_RETURN(0); 04107 err: 04108 rw_unlock(&LOCK_grant); 04109 if (!no_errors) 04110 { 04111 char buff[1024]; 04112 const char *command=""; 04113 if (table) 04114 strxmov(buff, table->db, ".", table->table_name, NullS); 04115 if (want_access & EXECUTE_ACL) 04116 command= "execute"; 04117 else if (want_access & ALTER_PROC_ACL) 04118 command= "alter routine"; 04119 else if (want_access & GRANT_ACL) 04120 command= "grant"; 04121 my_error(ER_PROCACCESS_DENIED_ERROR, MYF(0), 04122 command, user, host, table ? buff : "unknown"); 04123 } 04124 DBUG_RETURN(1); 04125 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 4143 of file sql_acl.cc.
References grant_option, LOCK_grant, GRANT_NAME::privs, routine_hash_search(), rw_rdlock, rw_unlock, and SHOW_PROC_ACLS.
Referenced by check_some_routine_access().
04145 { 04146 bool no_routine_acl= 1; 04147 if (grant_option) 04148 { 04149 GRANT_NAME *grant_proc; 04150 Security_context *sctx= thd->security_ctx; 04151 rw_rdlock(&LOCK_grant); 04152 if ((grant_proc= routine_hash_search(sctx->priv_host, 04153 sctx->ip, db, 04154 sctx->priv_user, 04155 name, is_proc, 0))) 04156 no_routine_acl= !(grant_proc->privs & SHOW_PROC_ACLS); 04157 rw_unlock(&LOCK_grant); 04158 } 04159 return no_routine_acl; 04160 }
Here is the call graph for this function:

Here is the caller graph for this function:

| GRANT_COLUMN* column_hash_search | ( | GRANT_TABLE * | t, | |
| const char * | cname, | |||
| uint | length | |||
| ) | [inline] |
Definition at line 2453 of file sql_acl.cc.
References GRANT_TABLE::hash_columns, and hash_search().
Referenced by check_grant_all_columns(), check_grant_column(), get_column_grant(), mysql_table_grant(), and replace_column_table().
02454 { 02455 return (GRANT_COLUMN*) hash_search(&t->hash_columns, (byte*) cname,length); 02456 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static bool compare_hostname | ( | const acl_host_and_ip * | host, | |
| const char * | hostname, | |||
| const char * | ip | |||
| ) | [static] |
Definition at line 1751 of file sql_acl.cc.
References calc_ip(), host, system_charset_info, wild_case_compare(), and wild_compare().
Referenced by acl_check_host(), acl_get(), acl_getroot(), acl_getroot_no_password(), check_grant_db(), find_acl_user(), and name_hash_search().
01753 { 01754 long tmp; 01755 if (host->ip_mask && ip && calc_ip(ip,&tmp,'\0')) 01756 { 01757 return (tmp & host->ip_mask) == host->ip; 01758 } 01759 return (!host->hostname || 01760 (hostname && !wild_case_compare(system_charset_info, 01761 hostname, host->hostname)) || 01762 (ip && !wild_compare(ip, host->hostname, 0))); 01763 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void fill_effective_table_privileges | ( | THD * | thd, | |
| GRANT_INFO * | grant, | |||
| const char * | db, | |||
| const char * | table | |||
| ) |
Definition at line 6271 of file sql_acl.cc.
References acl_get(), DBUG_ENTER, DBUG_PRINT, DBUG_VOID_RETURN, grant_option, st_grant_info::grant_table, grant_version, initialized, LOCK_grant, NO_ACCESS, st_grant_info::privilege, GRANT_NAME::privs, rw_rdlock, rw_unlock, table_hash_search(), and st_grant_info::version.
Referenced by mysql_create_view(), st_table_list::prepare_security(), and Table_triggers_list::process_triggers().
06273 { 06274 Security_context *sctx= thd->security_ctx; 06275 DBUG_ENTER("fill_effective_table_privileges"); 06276 DBUG_PRINT("enter", ("Host: '%s', Ip: '%s', User: '%s', table: `%s`.`%s`", 06277 sctx->priv_host, (sctx->ip ? sctx->ip : "(NULL)"), 06278 (sctx->priv_user ? sctx->priv_user : "(NULL)"), 06279 db, table)); 06280 /* --skip-grants */ 06281 if (!initialized) 06282 { 06283 DBUG_PRINT("info", ("skip grants")); 06284 grant->privilege= ~NO_ACCESS; // everything is allowed 06285 DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege)); 06286 DBUG_VOID_RETURN; 06287 } 06288 06289 /* global privileges */ 06290 grant->privilege= sctx->master_access; 06291 06292 if (!sctx->priv_user) 06293 { 06294 DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege)); 06295 DBUG_VOID_RETURN; // it is slave 06296 } 06297 06298 /* db privileges */ 06299 grant->privilege|= acl_get(sctx->host, sctx->ip, sctx->priv_user, db, 0); 06300 06301 if (!grant_option) 06302 { 06303 DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege)); 06304 DBUG_VOID_RETURN; 06305 } 06306 06307 /* table privileges */ 06308 rw_rdlock(&LOCK_grant); 06309 if (grant->version != grant_version) 06310 { 06311 grant->grant_table= 06312 table_hash_search(sctx->host, sctx->ip, db, 06313 sctx->priv_user, 06314 table, 0); /* purecov: inspected */ 06315 grant->version= grant_version; /* purecov: inspected */ 06316 } 06317 if (grant->grant_table != 0) 06318 { 06319 grant->privilege|= grant->grant_table->privs; 06320 } 06321 rw_unlock(&LOCK_grant); 06322 06323 DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege)); 06324 DBUG_VOID_RETURN; 06325 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int fill_schema_column_privileges | ( | THD * | thd, | |
| TABLE_LIST * | tables, | |||
| COND * | cond | |||
| ) |
Definition at line 6185 of file sql_acl.cc.
References check_access(), GRANT_TABLE::cols, column_priv_hash, command_array, command_lengths, GRANT_NAME::db, DBUG_ENTER, DBUG_RETURN, GRANT_ACL, GRANT_TABLE::hash_columns, hash_element(), GRANT_NAME::host, host, acl_host_and_ip::hostname, index(), LOCK_grant, my_strcasecmp, NullS, GRANT_NAME::privs, st_hash::records, rw_rdlock, rw_unlock, SELECT_ACL, strcmp(), strxmov(), system_charset_info, st_table_list::table, TABLE_ACLS, GRANT_NAME::tname, update_schema_privilege(), and GRANT_NAME::user.
06186 { 06187 #ifndef NO_EMBEDDED_ACCESS_CHECKS 06188 uint index; 06189 char buff[100]; 06190 TABLE *table= tables->table; 06191 bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0); 06192 char *curr_host= thd->security_ctx->priv_host_name(); 06193 DBUG_ENTER("fill_schema_table_privileges"); 06194 06195 rw_rdlock(&LOCK_grant); 06196 06197 for (index=0 ; index < column_priv_hash.records ; index++) 06198 { 06199 const char *user, *host, *is_grantable= "YES"; 06200 GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, 06201 index); 06202 if (!(user=grant_table->user)) 06203 user= ""; 06204 if (!(host= grant_table->host.hostname)) 06205 host= ""; 06206 06207 if (no_global_access && 06208 (strcmp(thd->security_ctx->priv_user, user) || 06209 my_strcasecmp(system_charset_info, curr_host, host))) 06210 continue; 06211 06212 ulong table_access= grant_table->cols; 06213 if (table_access != 0) 06214 { 06215 if (!(grant_table->privs & GRANT_ACL)) 06216 is_grantable= "NO"; 06217 06218 ulong test_access= table_access & ~GRANT_ACL; 06219 strxmov(buff, "'", user, "'@'", host, "'", NullS); 06220 if (!test_access) 06221 continue; 06222 else 06223 { 06224 ulong j; 06225 int cnt; 06226 for (cnt= 0, j= SELECT_ACL; j <= TABLE_ACLS; cnt++, j<<= 1) 06227 { 06228 if (test_access & j) 06229 { 06230 for (uint col_index=0 ; 06231 col_index < grant_table->hash_columns.records ; 06232 col_index++) 06233 { 06234 GRANT_COLUMN *grant_column = (GRANT_COLUMN*) 06235 hash_element(&grant_table->hash_columns,col_index); 06236 if ((grant_column->rights & j) && (table_access & j)) 06237 update_schema_privilege(table, buff, grant_table->db, 06238 grant_table->tname, 06239 grant_column->column, 06240 grant_column->key_length, 06241 command_array[cnt], 06242 command_lengths[cnt], is_grantable); 06243 } 06244 } 06245 } 06246 } 06247 } 06248 } 06249 06250 rw_unlock(&LOCK_grant); 06251 06252 DBUG_RETURN(0); 06253 #else 06254 return (0); 06255 #endif 06256 }
Here is the call graph for this function:

| int fill_schema_schema_privileges | ( | THD * | thd, | |
| TABLE_LIST * | tables, | |||
| COND * | cond | |||
| ) |
Definition at line 6055 of file sql_acl.cc.
References ACL_ACCESS::access, acl_cache, acl_dbs, check_access(), command_array, command_lengths, counter, ACL_DB::db, DB_ACLS, DBUG_ENTER, DBUG_RETURN, dynamic_element, st_dynamic_array::elements, GRANT_ACL, ACL_DB::host, host, acl_host_and_ip::hostname, hash_filo::lock, my_strcasecmp, NullS, pthread_mutex_lock, pthread_mutex_unlock, SELECT_ACL, strcmp(), STRING_WITH_LEN, strxmov(), system_charset_info, st_table_list::table, update_schema_privilege(), and ACL_DB::user.
06056 { 06057 #ifndef NO_EMBEDDED_ACCESS_CHECKS 06058 uint counter; 06059 ACL_DB *acl_db; 06060 ulong want_access; 06061 char buff[100]; 06062 TABLE *table= tables->table; 06063 bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0); 06064 char *curr_host= thd->security_ctx->priv_host_name(); 06065 DBUG_ENTER("fill_schema_schema_privileges"); 06066 06067 pthread_mutex_lock(&acl_cache->lock); 06068 06069 for (counter=0 ; counter < acl_dbs.elements ; counter++) 06070 { 06071 const char *user, *host, *is_grantable="YES"; 06072 06073 acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); 06074 if (!(user=acl_db->user)) 06075 user= ""; 06076 if (!(host=acl_db->host.hostname)) 06077 host= ""; 06078 06079 if (no_global_access && 06080 (strcmp(thd->security_ctx->priv_user, user) || 06081 my_strcasecmp(system_charset_info, curr_host, host))) 06082 continue; 06083 06084 want_access=acl_db->access; 06085 if (want_access) 06086 { 06087 if (!(want_access & GRANT_ACL)) 06088 { 06089 is_grantable= "NO"; 06090 } 06091 strxmov(buff,"'",user,"'@'",host,"'",NullS); 06092 if (!(want_access & ~GRANT_ACL)) 06093 update_schema_privilege(table, buff, acl_db->db, 0, 0, 06094 0, STRING_WITH_LEN("USAGE"), is_grantable); 06095 else 06096 { 06097 int cnt; 06098 ulong j,test_access= want_access & ~GRANT_ACL; 06099 for (cnt=0, j = SELECT_ACL; j <= DB_ACLS; cnt++,j <<= 1) 06100 if (test_access & j) 06101 update_schema_privilege(table, buff, acl_db->db, 0, 0, 0, 06102 command_array[cnt], command_lengths[cnt], 06103 is_grantable); 06104 } 06105 } 06106 } 06107 06108 pthread_mutex_unlock(&acl_cache->lock); 06109 06110 DBUG_RETURN(0); 06111 #else 06112 return (0); 06113 #endif 06114 }
Here is the call graph for this function:

| int fill_schema_table_privileges | ( | THD * | thd, | |
| TABLE_LIST * | tables, | |||
| COND * | cond | |||
| ) |
Definition at line 6117 of file sql_acl.cc.
References check_access(), GRANT_TABLE::cols, column_priv_hash, command_array, command_lengths, GRANT_NAME::db, DBUG_ENTER, DBUG_RETURN, GRANT_ACL, hash_element(), GRANT_NAME::host, host, acl_host_and_ip::hostname, index(), LOCK_grant, my_strcasecmp, NullS, GRANT_NAME::privs, st_hash::records, rw_rdlock, rw_unlock, SELECT_ACL, strcmp(), STRING_WITH_LEN, strxmov(), system_charset_info, st_table_list::table, TABLE_ACLS, GRANT_NAME::tname, update_schema_privilege(), and GRANT_NAME::user.
06118 { 06119 #ifndef NO_EMBEDDED_ACCESS_CHECKS 06120 uint index; 06121 char buff[100]; 06122 TABLE *table= tables->table; 06123 bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0); 06124 char *curr_host= thd->security_ctx->priv_host_name(); 06125 DBUG_ENTER("fill_schema_table_privileges"); 06126 06127 rw_rdlock(&LOCK_grant); 06128 06129 for (index=0 ; index < column_priv_hash.records ; index++) 06130 { 06131 const char *user, *host, *is_grantable= "YES"; 06132 GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, 06133 index); 06134 if (!(user=grant_table->user)) 06135 user= ""; 06136 if (!(host= grant_table->host.hostname)) 06137 host= ""; 06138 06139 if (no_global_access && 06140 (strcmp(thd->security_ctx->priv_user, user) || 06141 my_strcasecmp(system_charset_info, curr_host, host))) 06142 continue; 06143 06144 ulong table_access= grant_table->privs; 06145 if (table_access) 06146 { 06147 ulong test_access= table_access & ~GRANT_ACL; 06148 /* 06149 We should skip 'usage' privilege on table if 06150 we have any privileges on column(s) of this table 06151 */ 06152 if (!test_access && grant_table->cols) 06153 continue; 06154 if (!(table_access & GRANT_ACL)) 06155 is_grantable= "NO"; 06156 06157 strxmov(buff, "'", user, "'@'", host, "'", NullS); 06158 if (!test_access) 06159 update_schema_privilege(table, buff, grant_table->db, grant_table->tname, 06160 0, 0, STRING_WITH_LEN("USAGE"), is_grantable); 06161 else 06162 { 06163 ulong j; 06164 int cnt; 06165 for (cnt= 0, j= SELECT_ACL; j <= TABLE_ACLS; cnt++, j<<= 1) 06166 { 06167 if (test_access & j) 06168 update_schema_privilege(table, buff, grant_table->db, 06169 grant_table->tname, 0, 0, command_array[cnt], 06170 command_lengths[cnt], is_grantable); 06171 } 06172 } 06173 } 06174 } 06175 06176 rw_unlock(&LOCK_grant); 06177 06178 DBUG_RETURN(0); 06179 #else 06180 return (0); 06181 #endif 06182 }
Here is the call graph for this function:

| int fill_schema_user_privileges | ( | THD * | thd, | |
| TABLE_LIST * | tables, | |||
| COND * | cond | |||
| ) |
Definition at line 5996 of file sql_acl.cc.
References ACL_ACCESS::access, acl_cache, acl_users, check_access(), command_array, command_lengths, counter, DBUG_ENTER, DBUG_RETURN, dynamic_element, st_dynamic_array::elements, GLOBAL_ACLS, GRANT_ACL, ACL_USER::host, host, acl_host_and_ip::hostname, hash_filo::lock, my_strcasecmp, NullS, pthread_mutex_lock, pthread_mutex_unlock, SELECT_ACL, strcmp(), STRING_WITH_LEN, strxmov(), system_charset_info, st_table_list::table, update_schema_privilege(), and ACL_USER::user.
05997 { 05998 #ifndef NO_EMBEDDED_ACCESS_CHECKS 05999 uint counter; 06000 ACL_USER *acl_user; 06001 ulong want_access; 06002 char buff[100]; 06003 TABLE *table= tables->table; 06004 bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0); 06005 char *curr_host= thd->security_ctx->priv_host_name(); 06006 DBUG_ENTER("fill_schema_user_privileges"); 06007 06008 pthread_mutex_lock(&acl_cache->lock); 06009 06010 for (counter=0 ; counter < acl_users.elements ; counter++) 06011 { 06012 const char *user,*host, *is_grantable="YES"; 06013 acl_user=dynamic_element(&acl_users,counter,ACL_USER*); 06014 if (!(user=acl_user->user)) 06015 user= ""; 06016 if (!(host=acl_user->host.hostname)) 06017 host= ""; 06018 06019 if (no_global_access && 06020 (strcmp(thd->security_ctx->priv_user, user) || 06021 my_strcasecmp(system_charset_info, curr_host, host))) 06022 continue; 06023 06024 want_access= acl_user->access; 06025 if (!(want_access & GRANT_ACL)) 06026 is_grantable= "NO"; 06027 06028 strxmov(buff,"'",user,"'@'",host,"'",NullS); 06029 if (!(want_access & ~GRANT_ACL)) 06030 update_schema_privilege(table, buff, 0, 0, 0, 0, 06031 STRING_WITH_LEN("USAGE"), is_grantable); 06032 else 06033 { 06034 uint priv_id; 06035 ulong j,test_access= want_access & ~GRANT_ACL; 06036 for (priv_id=0, j = SELECT_ACL;j <= GLOBAL_ACLS; priv_id++,j <<= 1) 06037 { 06038 if (test_access & j) 06039 update_schema_privilege(table, buff, 0, 0, 0, 0, 06040 command_array[priv_id], 06041 command_lengths[priv_id], is_grantable); 06042 } 06043 } 06044 } 06045 06046 pthread_mutex_unlock(&acl_cache->lock); 06047 06048 DBUG_RETURN(0); 06049 #else 06050 return(0); 06051 #endif 06052 }
Here is the call graph for this function:

Definition at line 1677 of file sql_acl.cc.
References acl_cache, acl_users, compare_hostname(), DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, dynamic_element, st_dynamic_array::elements, hash_filo::lock, my_strcasecmp, safe_mutex_assert_owner, strcmp(), and system_charset_info.
Referenced by change_password(), get_mqh(), is_acl_user(), mysql_revoke_all(), mysql_show_grants(), replace_db_table(), replace_routine_table(), replace_table_table(), and sp_grant_privileges().
01678 { 01679 DBUG_ENTER("find_acl_user"); 01680 DBUG_PRINT("enter",("host: '%s' user: '%s'",host,user)); 01681 01682 safe_mutex_assert_owner(&acl_cache->lock); 01683 01684 for (uint i=0 ; i < acl_users.elements ; i++) 01685 { 01686 ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*); 01687 DBUG_PRINT("info",("strcmp('%s','%s'), compare_hostname('%s','%s'),", 01688 user, acl_user->user ? acl_user->user : "", 01689 host, 01690 acl_user->host.hostname ? acl_user->host.hostname : 01691 "")); 01692 if (!acl_user->user && !user[0] || 01693 acl_user->user && !strcmp(user,acl_user->user)) 01694 { 01695 if (exact ? !my_strcasecmp(system_charset_info, host, 01696 acl_user->host.hostname ? 01697 acl_user->host.hostname : "") : 01698 compare_hostname(&acl_user->host,host,host)) 01699 { 01700 DBUG_RETURN(acl_user); 01701 } 01702 } 01703 } 01704 DBUG_RETURN(0); 01705 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void free_grant_table | ( | GRANT_TABLE * | grant_table | ) |
Definition at line 2387 of file sql_acl.cc.
References GRANT_TABLE::hash_columns, and hash_free().
Referenced by grant_load().
02388 { 02389 hash_free(&grant_table->hash_columns); 02390 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 757 of file sql_acl.cc.
References st_typelib::count, st_table::field, FIELD_TYPE_ENUM, my_charset_latin1, my_toupper, pos(), and typelib().
Referenced by acl_load(), replace_db_table(), and replace_user_table().
00758 { 00759 ulong access_bits=0,bit; 00760 char buff[2]; 00761 String res(buff,sizeof(buff),&my_charset_latin1); 00762 Field **pos; 00763 00764 for (pos=form->field+fieldnr, bit=1; 00765 *pos && (*pos)->real_type() == FIELD_TYPE_ENUM && 00766 ((Field_enum*) (*pos))->typelib->count == 2 ; 00767 pos++, fieldnr++, bit<<=1) 00768 { 00769 (*pos)->val_str(&res); 00770 if (my_toupper(&my_charset_latin1, res[0]) == 'Y') 00771 access_bits|= bit; 00772 } 00773 if (next_field) 00774 *next_field=fieldnr; 00775 return access_bits; 00776 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulong get_column_grant | ( | THD * | thd, | |
| GRANT_INFO * | grant, | |||
| const char * | db_name, | |||
| const char * | table_name, | |||
| const char * | field_name | |||
| ) |
Definition at line 4209 of file sql_acl.cc.
References column_hash_search(), st_grant_info::grant_table, grant_version, LOCK_grant, st_grant_info::privilege, GRANT_NAME::privs, GRANT_COLUMN::rights, rw_rdlock, rw_unlock, strlen(), table_hash_search(), and st_grant_info::version.
Referenced by check_column_grant_in_table_ref(), Item_field::fix_fields(), get_schema_column_record(), and insert_fields().
04212 { 04213 GRANT_TABLE *grant_table; 04214 GRANT_COLUMN *grant_column; 04215 ulong priv; 04216 04217 rw_rdlock(&LOCK_grant); 04218 /* reload table if someone has modified any grants */ 04219 if (grant->version != grant_version) 04220 { 04221 Security_context *sctx= thd->security_ctx; 04222 grant->grant_table= 04223 table_hash_search(sctx->host, sctx->ip, 04224 db_name, sctx->priv_user, 04225 table_name, 0); /* purecov: inspected */ 04226 grant->version= grant_version; /* purecov: inspected */ 04227 } 04228 04229 if (!(grant_table= grant->grant_table)) 04230 priv= grant->privilege; 04231 else 04232 { 04233 grant_column= column_hash_search(grant_table, field_name, 04234 (uint) strlen(field_name)); 04235 if (!grant_column) 04236 priv= (grant->privilege | grant_table->privs); 04237 else 04238 priv= (grant->privilege | grant_table->privs | grant_column->rights); 04239 } 04240 rw_unlock(&LOCK_grant); 04241 return priv; 04242 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static byte* get_grant_table | ( | GRANT_NAME * | buff, | |
| uint * | length, | |||
| my_bool not_used | __attribute__((unused)) | |||
| ) | [static] |
Definition at line 2379 of file sql_acl.cc.
References GRANT_NAME::hash_key, and GRANT_NAME::key_length.
Referenced by grant_load().
02381 { 02382 *length=buff->key_length; 02383 return (byte*) buff->hash_key; 02384 }
Here is the caller graph for this function:

| static byte* get_key_column | ( | GRANT_COLUMN * | buff, | |
| uint * | length, | |||
| my_bool not_used | __attribute__((unused)) | |||
| ) | [static] |
Definition at line 2208 of file sql_acl.cc.
References GRANT_COLUMN::column, and GRANT_COLUMN::key_length.
Referenced by GRANT_TABLE::GRANT_TABLE().
02210 { 02211 *length=buff->key_length; 02212 return (byte*) buff->column; 02213 }
Here is the caller graph for this function:

| void get_mqh | ( | const char * | user, | |
| const char * | host, | |||
| USER_CONN * | uc | |||
| ) |
Definition at line 4750 of file sql_acl.cc.
References acl_cache, bzero, FALSE, find_acl_user(), initialized, hash_filo::lock, pthread_mutex_lock, pthread_mutex_unlock, ACL_USER::user_resource, and user_conn::user_resources.
Referenced by reset_mqh().
04751 { 04752 ACL_USER *acl_user; 04753 04754 pthread_mutex_lock(&acl_cache->lock); 04755 04756 if (initialized && (acl_user= find_acl_user(host,user, FALSE))) 04757 uc->user_resources= acl_user->user_resource; 04758 else 04759 bzero((char*) &uc->user_resources, sizeof(uc->user_resources)); 04760 04761 pthread_mutex_unlock(&acl_cache->lock); 04762 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 4726 of file sql_acl.cc.
References command_array, command_lengths, DBUG_ASSERT, pos(), start(), and strmov().
Referenced by check_global_access(), check_grant(), check_grant_all_columns(), check_grant_column(), mysql_table_grant(), and Table_triggers_list::process_triggers().
04727 { 04728 uint pos; 04729 char *start=to; 04730 DBUG_ASSERT(max_length >= 30); // For end ',' removal 04731 04732 if (access) 04733 { 04734 max_length--; // Reserve place for end-zero 04735 for (pos=0 ; access ; pos++, access>>=1) 04736 { 04737 if ((access & 1) && 04738 command_lengths[pos] + (uint) (to-start) < max_length) 04739 { 04740 to= strmov(to, command_array[pos]); 04741 *to++=','; 04742 } 04743 } 04744 to--; // Remove end ',' 04745 } 04746 *to=0; 04747 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 786 of file sql_acl.cc.
References args, DBUG_ASSERT, min, start(), wild_many, wild_one, and wild_prefix.
Referenced by acl_insert_db(), acl_insert_user(), acl_load(), and GRANT_NAME::GRANT_NAME().
00787 { 00788 va_list args; 00789 va_start(args,count); 00790 ulong sort=0; 00791 00792 /* Should not use this function with more than 4 arguments for compare. */ 00793 DBUG_ASSERT(count <= 4); 00794 00795 while (count--) 00796 { 00797 char *start, *str= va_arg(args,char*); 00798 uint chars= 0; 00799 uint wild_pos= 0; /* first wildcard position */ 00800 00801 if ((start= str)) 00802 { 00803 for (; *str ; str++) 00804 { 00805 if (*str == wild_many || *str == wild_one || *str == wild_prefix) 00806 { 00807 wild_pos= (uint) (str - start) + 1; 00808 break; 00809 } 00810 chars= 128; // Marker that chars existed 00811 } 00812 } 00813 sort= (sort << 8) + (wild_pos ? min(wild_pos, 127) : chars); 00814 } 00815 va_end(args); 00816 return sort; 00817 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulong get_table_grant | ( | THD * | thd, | |
| TABLE_LIST * | table | |||
| ) |
Definition at line 4167 of file sql_acl.cc.
References db, st_table_list::db, st_table_list::grant, st_grant_info::grant_table, grant_version, LOCK_grant, NULL, st_grant_info::privilege, GRANT_NAME::privs, rw_rdlock, rw_unlock, table_hash_search(), st_table_list::table_name, and st_grant_info::version.
04168 { 04169 ulong privilege; 04170 Security_context *sctx= thd->security_ctx; 04171 const char *db = table->db ? table->db : thd->db; 04172 GRANT_TABLE *grant_table; 04173 04174 rw_rdlock(&LOCK_grant); 04175 #ifdef EMBEDDED_LIBRARY 04176 grant_table= NULL; 04177 #else 04178 grant_table= table_hash_search(sctx->host, sctx->ip, db, sctx->priv_user, 04179 table->table_name, 0); 04180 #endif 04181 table->grant.grant_table=grant_table; // Remember for column test 04182 table->grant.version=grant_version; 04183 if (grant_table) 04184 table->grant.privilege|= grant_table->privs; 04185 privilege= table->grant.privilege; 04186 rw_unlock(&LOCK_grant); 04187 return privilege; 04188 }
Here is the call graph for this function:

| void grant_free | ( | void | ) |
Definition at line 3431 of file sql_acl.cc.
References column_priv_hash, DBUG_ENTER, DBUG_VOID_RETURN, FALSE, free_root(), func_priv_hash, grant_option, hash_free(), memex, MYF, and proc_priv_hash.
Referenced by clean_up(), and grant_reload().
03432 { 03433 DBUG_ENTER("grant_free"); 03434 grant_option = FALSE; 03435 hash_free(&column_priv_hash); 03436 hash_free(&proc_priv_hash); 03437 hash_free(&func_priv_hash); 03438 free_root(&memex,MYF(0)); 03439 DBUG_VOID_RETURN; 03440 }
Here is the call graph for this function:

Here is the caller graph for this function:

| my_bool grant_init | ( | ) |
Definition at line 3455 of file sql_acl.cc.
References DBUG_ENTER, DBUG_RETURN, grant_reload(), and my_pthread_setspecific_ptr.
Referenced by main().
03456 { 03457 THD *thd; 03458 my_bool return_val; 03459 DBUG_ENTER("grant_init"); 03460 03461 if (!(thd= new THD)) 03462 DBUG_RETURN(1); /* purecov: deadcode */ 03463 thd->thread_stack= (char*) &thd; 03464 thd->store_globals(); 03465 return_val= grant_reload(thd); 03466 delete thd; 03467 /* Remember that we don't have a THD */ 03468 my_pthread_setspecific_ptr(THR_THD, 0); 03469 DBUG_RETURN(return_val); 03470 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static my_bool grant_load | ( | TABLE_LIST * | tables | ) | [static] |
Definition at line 3488 of file sql_acl.cc.
References ACL_ALLOC_BLOCK_SIZE, column_priv_hash, DBUG_ENTER, DBUG_RETURN, FALSE, st_table::file, fix_rights_for_procedure, free_grant_table(), func_priv_hash, get_grant_table(), grant_option, handler::ha_index_end(), handler::ha_index_init(), hash(), hash_init, GRANT_NAME::host, acl_host_and_ip::hostname, hostname_requires_resolving(), handler::index_first(), handler::index_next(), init_sql_alloc(), memex, my_hash_insert(), my_pthread_getspecific_ptr, my_pthread_setspecific_ptr, GRANT_NAME::ok(), GRANT_TABLE::ok(), GRANT_NAME::privs, proc_priv_hash, st_table::record, SPECIAL_NO_RESOLVE, specialflag, sql_print_warning(), system_charset_info, st_table_list::table, GRANT_NAME::tname, TRUE, TYPE_ENUM_FUNCTION, TYPE_ENUM_PROCEDURE, st_table::use_all_columns(), and GRANT_NAME::user.
Referenced by grant_reload().
03489 { 03490 MEM_ROOT *memex_ptr; 03491 my_bool return_val= 1; 03492 TABLE *t_table, *c_table, *p_table; 03493 bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE; 03494 MEM_ROOT **save_mem_root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, 03495 THR_MALLOC); 03496 DBUG_ENTER("grant_load"); 03497 03498 grant_option = FALSE; 03499 (void) hash_init(&column_priv_hash,system_charset_info, 03500 0,0,0, (hash_get_key) get_grant_table, 03501 (hash_free_key) free_grant_table,0); 03502 (void) hash_init(&proc_priv_hash,system_charset_info, 03503 0,0,0, (hash_get_key) get_grant_table, 03504 0,0); 03505 (void) hash_init(&func_priv_hash,system_charset_info, 03506 0,0,0, (hash_get_key) get_grant_table, 03507 0,0); 03508 init_sql_alloc(&memex, ACL_ALLOC_BLOCK_SIZE, 0); 03509 03510 t_table = tables[0].table; 03511 c_table = tables[1].table; 03512 p_table= tables[2].table; 03513 t_table->file->ha_index_init(0, 1); 03514 p_table->file->ha_index_init(0, 1); 03515 t_table->use_all_columns(); 03516 c_table->use_all_columns(); 03517 p_table->use_all_columns(); 03518 if (!t_table->file->index_first(t_table->record[0])) 03519 { 03520 memex_ptr= &memex; 03521 my_pthread_setspecific_ptr(THR_MALLOC, &memex_ptr); 03522 do 03523 { 03524 GRANT_TABLE *mem_check; 03525 if (!(mem_check=new (memex_ptr) GRANT_TABLE(t_table,c_table))) 03526 { 03527 /* This could only happen if we are out memory */ 03528 grant_option= FALSE; 03529 goto end_unlock; 03530 } 03531 03532 if (check_no_resolve) 03533 { 03534 if (hostname_requires_resolving(mem_check->host.hostname)) 03535 { 03536 sql_print_warning("'tables_priv' entry '%s %s@%s' " 03537 "ignored in --skip-name-resolve mode.", 03538 mem_check->tname, 03539 mem_check->user ? mem_check->user : "", 03540 mem_check->host.hostname ? 03541 mem_check->host.hostname : ""); 03542 continue; 03543 } 03544 } 03545 03546 if (! mem_check->ok()) 03547 delete mem_check; 03548 else if (my_hash_insert(&column_priv_hash,(byte*) mem_check)) 03549 { 03550 delete mem_check; 03551 grant_option= FALSE; 03552 goto end_unlock; 03553 } 03554 } 03555 while (!t_table->file->index_next(t_table->record[0])); 03556 } 03557 if (!p_table->file->index_first(p_table->record[0])) 03558 { 03559 memex_ptr= &memex; 03560 my_pthread_setspecific_ptr(THR_MALLOC, &memex_ptr); 03561 do 03562 { 03563 GRANT_NAME *mem_check; 03564 HASH *hash; 03565 if (!(mem_check=new (&memex) GRANT_NAME(p_table))) 03566 { 03567 /* This could only happen if we are out memory */ 03568 grant_option= FALSE; 03569 goto end_unlock; 03570 } 03571 03572 if (check_no_resolve) 03573 { 03574 if (hostname_requires_resolving(mem_check->host.hostname)) 03575 { 03576 sql_print_warning("'procs_priv' entry '%s %s@%s' " 03577 "ignored in --skip-name-resolve mode.", 03578 mem_check->tname, mem_check->user, 03579 mem_check->host.hostname ? 03580 mem_check->host.hostname : ""); 03581 continue; 03582 } 03583 } 03584 if (p_table->field[4]->val_int() == TYPE_ENUM_PROCEDURE) 03585 { 03586 hash= &proc_priv_hash; 03587 } 03588 else 03589 if (p_table->field[4]->val_int() == TYPE_ENUM_FUNCTION) 03590 { 03591 hash= &func_priv_hash; 03592 } 03593 else 03594 { 03595 sql_print_warning("'procs_priv' entry '%s' " 03596 "ignored, bad routine type", 03597 mem_check->tname); 03598 continue; 03599 } 03600 03601 mem_check->privs= fix_rights_for_procedure(mem_check->privs); 03602 if (! mem_check->ok()) 03603 delete mem_check; 03604 else if (my_hash_insert(hash, (byte*) mem_check)) 03605 { 03606 delete mem_check; 03607 grant_option= FALSE; 03608 goto end_unlock; 03609 } 03610 } 03611 while (!p_table->file->index_next(p_table->record[0])); 03612 } 03613 grant_option= TRUE; 03614 return_val=0; // Return ok 03615 03616 end_unlock: 03617 t_table->file->ha_index_end(); 03618 p_table->file->ha_index_end(); 03619 my_pthread_setspecific_ptr(THR_MALLOC, save_mem_root_ptr); 03620 DBUG_RETURN(return_val); 03621 }
Here is the call graph for this function:

Here is the caller graph for this function:

| my_bool grant_reload | ( | THD * | thd | ) |
Definition at line 3642 of file sql_acl.cc.
References bzero, close_thread_tables(), column_priv_hash, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, free_root(), func_priv_hash, grant_free(), grant_load(), grant_option, grant_version, hash_free(), initialized, LOCK_grant, memex, MYF, proc_priv_hash, rw_unlock, rw_wrlock, simple_open_n_lock_tables(), and TL_READ.
Referenced by grant_init(), and reload_acl_and_cache().
03643 { 03644 TABLE_LIST tables[3]; 03645 HASH old_column_priv_hash, old_proc_priv_hash, old_func_priv_hash; 03646 bool old_grant_option; 03647 MEM_ROOT old_mem; 03648 my_bool return_val= 1; 03649 DBUG_ENTER("grant_reload"); 03650 03651 /* Don't do anything if running with --skip-grant-tables */ 03652 if (!initialized) 03653 DBUG_RETURN(0); 03654 03655 bzero((char*) tables, sizeof(tables)); 03656 tables[0].alias= tables[0].table_name= (char*) "tables_priv"; 03657 tables[1].alias= tables[1].table_name= (char*) "columns_priv"; 03658 tables[2].alias= tables[2].table_name= (char*) "procs_priv"; 03659 tables[0].db= tables[1].db= tables[2].db= (char *) "mysql"; 03660 tables[0].next_local= tables[0].next_global= tables+1; 03661 tables[1].next_local= tables[1].next_global= tables+2; 03662 tables[0].lock_type= tables[1].lock_type= tables[2].lock_type= TL_READ; 03663 03664 /* 03665 To avoid deadlocks we should obtain table locks before 03666 obtaining LOCK_grant rwlock. 03667 */ 03668 if (simple_open_n_lock_tables(thd, tables)) 03669 goto end; 03670 03671 rw_wrlock(&LOCK_grant); 03672 grant_version++; 03673 old_column_priv_hash= column_priv_hash; 03674 old_proc_priv_hash= proc_priv_hash; 03675 old_func_priv_hash= func_priv_hash; 03676 old_grant_option= grant_option; 03677 old_mem= memex; 03678 03679 if ((return_val= grant_load(tables))) 03680 { // Error. Revert to old hash 03681 DBUG_PRINT("error",("Reverting to old privileges")); 03682 grant_free(); /* purecov: deadcode */ 03683 column_priv_hash= old_column_priv_hash; /* purecov: deadcode */ 03684 proc_priv_hash= old_proc_priv_hash; 03685 func_priv_hash= old_func_priv_hash; 03686 grant_option= old_grant_option; /* purecov: deadcode */ 03687 memex= old_mem; /* purecov: deadcode */ 03688 } 03689 else 03690 { 03691 hash_free(&old_column_priv_hash); 03692 hash_free(&old_proc_priv_hash); 03693 hash_free(&old_func_priv_hash); 03694 free_root(&old_mem,MYF(0)); 03695 } 03696 rw_unlock(&LOCK_grant); 03697 end: 03698 close_thread_tables(thd); 03699 DBUG_RETURN(return_val); 03700 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int handle_grant_data | ( | TABLE_LIST * | tables, | |
| bool | drop, | |||
| LEX_USER * | user_from, | |||
| LEX_USER * | user_to | |||
| ) | [static] |
Definition at line 5263 of file sql_acl.cc.
References DBUG_ENTER, DBUG_RETURN, handle_grant_struct(), and handle_grant_table().
Referenced by mysql_create_user(), mysql_drop_user(), and mysql_rename_user().
05265 { 05266 int result= 0; 05267 int found; 05268 DBUG_ENTER("handle_grant_data"); 05269 05270 /* Handle user table. */ 05271 if ((found= handle_grant_table(tables, 0, drop, user_from, user_to)) < 0) 05272 { 05273 /* Handle of table failed, don't touch the in-memory array. */ 05274 result= -1; 05275 } 05276 else 05277 { 05278 /* Handle user array. */ 05279 if ((handle_grant_struct(0, drop, user_from, user_to) && ! result) || 05280 found) 05281 { 05282 result= 1; /* At least one record/element found. */ 05283 /* If search is requested, we do not need to search further. */ 05284 if (! drop && ! user_to) 05285 goto end; 05286 } 05287 } 05288 05289 /* Handle db table. */ 05290 if ((found= handle_grant_table(tables, 1, drop, user_from, user_to)) < 0) 05291 { 05292 /* Handle of table failed, don't touch the in-memory array. */ 05293 result= -1; 05294 } 05295 else 05296 { 05297 /* Handle db array. */ 05298 if (((handle_grant_struct(1, drop, user_from, user_to) && ! result) || 05299 found) && ! result) 05300 { 05301 result= 1; /* At least one record/element found. */ 05302 /* If search is requested, we do not need to search further. */ 05303 if (! drop && ! user_to) 05304 goto end; 05305 } 05306 } 05307 05308 /* Handle procedures table. */ 05309 if ((found= handle_grant_table(tables, 4, drop, user_from, user_to)) < 0) 05310 { 05311 /* Handle of table failed, don't touch in-memory array. */ 05312 result= -1; 05313 } 05314 else 05315 { 05316 /* Handle procs array. */ 05317 if (((handle_grant_struct(3, drop, user_from, user_to) && ! result) || 05318 found) && ! result) 05319 { 05320 result= 1; /* At least one record/element found. */ 05321 /* If search is requested, we do not need to search further. */ 05322 if (! drop && ! user_to) 05323 goto end; 05324 } 05325 } 05326 05327 /* Handle tables table. */ 05328 if ((found= handle_grant_table(tables, 2, drop, user_from, user_to)) < 0) 05329 { 05330 /* Handle of table failed, don't touch columns and in-memory array. */ 05331 result= -1; 05332 } 05333 else 05334 { 05335 if (found && ! result) 05336 { 05337 result= 1; /* At least one record found. */ 05338 /* If search is requested, we do not need to search further. */ 05339 if (! drop && ! user_to) 05340 goto end; 05341 } 05342 05343 /* Handle columns table. */ 05344 if ((found= handle_grant_table(tables, 3, drop, user_from, user_to)) < 0) 05345 { 05346 /* Handle of table failed, don't touch the in-memory array. */ 05347 result= -1; 05348 } 05349 else 05350 { 05351 /* Handle columns hash. */ 05352 if (((handle_grant_struct(2, drop, user_from, user_to) && ! result) || 05353 found) && ! result) 05354 result= 1; /* At least one record/element found. */ 05355 } 05356 } 05357 end: 05358 DBUG_RETURN(result); 05359 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int handle_grant_struct | ( | uint | struct_no, | |
| bool | drop, | |||
| LEX_USER * | user_from, | |||
| LEX_USER * | user_to | |||
| ) | [static] |
Definition at line 5092 of file sql_acl.cc.
References acl_cache, acl_dbs, acl_users, column_priv_hash, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, delete_dynamic_element(), dynamic_element, st_dynamic_array::elements, hash_delete(), hash_element(), GRANT_NAME::host, ACL_DB::host, ACL_USER::host, st_lex_user::host, host, acl_host_and_ip::hostname, LINT_INIT, hash_filo::lock, mem, my_strcasecmp, proc_priv_hash, st_hash::records, safe_mutex_assert_owner, LEX_STRING::str, strcmp(), strdup_root(), system_charset_info, update_hostname(), GRANT_NAME::user, ACL_DB::user, ACL_USER::user, st_lex_user::user, and user.
Referenced by handle_grant_data().
05094 { 05095 int result= 0; 05096 uint idx; 05097 uint elements; 05098 const char *user; 05099 const char *host; 05100 ACL_USER *acl_user; 05101 ACL_DB *acl_db; 05102 GRANT_NAME *grant_name; 05103 DBUG_ENTER("handle_grant_struct"); 05104 DBUG_PRINT("info",("scan struct: %u search: '%s'@'%s'", 05105 struct_no, user_from->user.str, user_from->host.str)); 05106 05107 LINT_INIT(acl_user); 05108 LINT_INIT(acl_db); 05109 LINT_INIT(grant_name); 05110 LINT_INIT(user); 05111 LINT_INIT(host); 05112 05113 safe_mutex_assert_owner(&acl_cache->lock); 05114 05115 /* Get the number of elements in the in-memory structure. */ 05116 switch (struct_no) { 05117 case 0: 05118 elements= acl_users.elements; 05119 break; 05120 case 1: 05121 elements= acl_dbs.elements; 05122 break; 05123 case 2: 05124 elements= column_priv_hash.records; 05125 break; 05126 case 3: 05127 elements= proc_priv_hash.records; 05128 break; 05129 default: 05130 return -1; 05131 } 05132 05133 #ifdef EXTRA_DEBUG 05134 DBUG_PRINT("loop",("scan struct: %u search user: '%s' host: '%s'", 05135 struct_no, user_from->user.str, user_from->host.str)); 05136 #endif 05137 /* Loop over all elements. */ 05138 for (idx= 0; idx < elements; idx++) 05139 { 05140 /* 05141 Get a pointer to the element. 05142 */ 05143 switch (struct_no) { 05144 case 0: 05145 acl_user= dynamic_element(&acl_users, idx, ACL_USER*); 05146 user= acl_user->user; 05147 host= acl_user->host.hostname; 05148 break; 05149 05150 case 1: 05151 acl_db= dynamic_element(&acl_dbs, idx, ACL_DB*); 05152 user= acl_db->user; 05153 host= acl_db->host.hostname; 05154 break; 05155 05156 case 2: 05157 grant_name= (GRANT_NAME*) hash_element(&column_priv_hash, idx); 05158 user= grant_name->user; 05159 host= grant_name->host.hostname; 05160 break; 05161 05162 case 3: 05163 grant_name= (GRANT_NAME*) hash_element(&proc_priv_hash, idx); 05164 user= grant_name->user; 05165 host= grant_name->host.hostname; 05166 break; 05167 } 05168 if (! user) 05169 user= ""; 05170 if (! host) 05171 host= ""; 05172 05173 #ifdef EXTRA_DEBUG 05174 DBUG_PRINT("loop",("scan struct: %u index: %u user: '%s' host: '%s'", 05175 struct_no, idx, user, host)); 05176 #endif 05177 if (strcmp(user_from->user.str, user) || 05178 my_strcasecmp(system_charset_info, user_from->host.str, host)) 05179 continue; 05180 05181 result= 1; /* At least one element found. */ 05182 if ( drop ) 05183 { 05184 switch ( struct_no ) { 05185 case 0: 05186 delete_dynamic_element(&acl_users, idx); 05187 break; 05188 05189 case 1: 05190 delete_dynamic_element(&acl_dbs, idx); 05191 break; 05192 05193 case 2: 05194 hash_delete(&column_priv_hash, (byte*) grant_name); 05195 break; 05196 05197 case 3: 05198 hash_delete(&proc_priv_hash, (byte*) grant_name); 05199 break; 05200 } 05201 elements--; 05202 idx--; 05203 } 05204 else if ( user_to ) 05205 { 05206 switch ( struct_no ) { 05207 case 0: 05208 acl_user->user= strdup_root(&mem, user_to->user.str); 05209 acl_user->host.hostname= strdup_root(&mem, user_to->host.str); 05210 break; 05211 05212 case 1: 05213 acl_db->user= strdup_root(&mem, user_to->user.str); 05214 acl_db->host.hostname= strdup_root(&mem, user_to->host.str); 05215 break; 05216 05217 case 2: 05218 case 3: 05219 grant_name->user= strdup_root(&mem, user_to->user.str); 05220 update_hostname(&grant_name->host, 05221 strdup_root(&mem, user_to->host.str)); 05222 break; 05223 } 05224 } 05225 else 05226 { 05227 /* If search is requested, we do not need to search further. */ 05228 break; 05229 } 05230 } 05231 #ifdef EXTRA_DEBUG 05232 DBUG_PRINT("loop",("scan struct: %u result %d", struct_no, result)); 05233 #endif 05234 05235 DBUG_RETURN(result); 05236 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int handle_grant_table | ( | TABLE_LIST * | tables, | |
| uint | table_no, | |||
| bool | drop, | |||
| LEX_USER * | user_from, | |||
| LEX_USER * | user_to | |||
| ) | [static] |
Definition at line 4947 of file sql_acl.cc.
References DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, error, st_table::field, st_table::file, get_field(), HA_ERR_END_OF_FILE, HA_ERR_KEY_NOT_FOUND, HA_READ_KEY_EXACT, handler::ha_rnd_end(), handler::ha_rnd_init(), host, st_lex_user::host, handler::index_read_idx(), key_copy(), st_table::key_info, st_key::key_part, LEX_STRING::length, MAX_KEY_LENGTH, mem, modify_grant_table(), my_strcasecmp, MYF, handler::print_error(), st_table::record, handler::rnd_next(), st_table::s, Field::store(), st_key_part_info::store_length, LEX_STRING::str, strcmp(), system_charset_info, st_table_list::table, st_table_share::table_name, st_table::use_all_columns(), user, and st_lex_user::user.
Referenced by handle_grant_data().
04949 { 04950 int result= 0; 04951 int error; 04952 TABLE *table= tables[table_no].table; 04953 Field *host_field= table->field[0]; 04954 Field *user_field= table->field[table_no ? 2 : 1]; 04955 char *host_str= user_from->host.str; 04956 char *user_str= user_from->user.str; 04957 const char *host; 04958 const char *user; 04959 byte user_key[MAX_KEY_LENGTH]; 04960 uint key_prefix_length; 04961 DBUG_ENTER("handle_grant_table"); 04962 04963 table->use_all_columns(); 04964 if (! table_no) // mysql.user table 04965 { 04966 /* 04967 The 'user' table has an unique index on (host, user). 04968 Thus, we can handle everything with a single index access. 04969 The host- and user fields are consecutive in the user table records. 04970 So we set host- and user fields of table->record[0] and use the 04971 pointer to the host field as key. 04972 index_read_idx() will replace table->record[0] (its first argument) 04973 by the searched record, if it exists. 04974 */ 04975 DBUG_PRINT("info",("read table: '%s' search: '%s'@'%s'", 04976 table->s->table_name.str, user_str, host_str)); 04977 host_field->store(host_str, user_from->host.length, system_charset_info); 04978 user_field->store(user_str, user_from->user.length, system_charset_info); 04979 04980 key_prefix_length= (table->key_info->key_part[0].store_length + 04981 table->key_info->key_part[1].store_length); 04982 key_copy(user_key, table->record[0], table->key_info, key_prefix_length); 04983 04984 if ((error= table->file->index_read_idx(table->record[0], 0, 04985 user_key, key_prefix_length, 04986 HA_READ_KEY_EXACT))) 04987 { 04988 if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) 04989 { 04990 table->file->print_error(error, MYF(0)); 04991 result= -1; 04992 } 04993 } 04994 else 04995 { 04996 /* If requested, delete or update the record. */ 04997 result= ((drop || user_to) && 04998 modify_grant_table(table, host_field, user_field, user_to)) ? 04999 -1 : 1; /* Error or found. */ 05000 } 05001 DBUG_PRINT("info",("read result: %d", result)); 05002 } 05003 else 05004 { 05005 /* 05006 The non-'user' table do not have indexes on (host, user). 05007 And their host- and user fields are not consecutive. 05008 Thus, we need to do a table scan to find all matching records. 05009 */ 05010 if ((error= table->file->ha_rnd_init(1))) 05011 { 05012 table->file->print_error(error, MYF(0)); 05013 result= -1; 05014 } 05015 else 05016 { 05017 #ifdef EXTRA_DEBUG 05018 DBUG_PRINT("info",("scan table: '%s' search: '%s'@'%s'", 05019 table->s->table_name.str, user_str, host_str)); 05020 #endif 05021 while ((error= table->file->rnd_next(table->record[0])) != 05022 HA_ERR_END_OF_FILE) 05023 { 05024 if (error) 05025 { 05026 /* Most probable 'deleted record'. */ 05027 DBUG_PRINT("info",("scan error: %d", error)); 05028 continue; 05029 } 05030 if (! (host= get_field(&mem, host_field))) 05031 host= ""; 05032 if (! (user= get_field(&mem, user_field))) 05033 user= ""; 05034 05035 #ifdef EXTRA_DEBUG 05036 DBUG_PRINT("loop",("scan fields: '%s'@'%s' '%s' '%s' '%s'", 05037 user, host, 05038 get_field(&mem, table->field[1]) /*db*/, 05039 get_field(&mem, table->field[3]) /*table*/, 05040 get_field(&mem, table->field[4]) /*column*/)); 05041 #endif 05042 if (strcmp(user_str, user) || 05043 my_strcasecmp(system_charset_info, host_str, host)) 05044 continue; 05045 05046 /* If requested, delete or update the record. */ 05047 result= ((drop || user_to) && 05048 modify_grant_table(table, host_field, user_field, user_to)) ? 05049 -1 : result ? result : 1; /* Error or keep result or found. */ 05050 /* If search is requested, we do not need to search further. */ 05051 if (! drop && ! user_to) 05052 break ; 05053 } 05054 (void) table->file->ha_rnd_end(); 05055 DBUG_PRINT("info",("scan result: %d", result)); 05056 } 05057 } 05058 05059 DBUG_RETURN(result); 05060 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool hostname_requires_resolving | ( | const char * | hostname | ) |
Definition at line 1765 of file sql_acl.cc.
References FALSE, my_localhost, my_strnncoll, strlen(), system_charset_info, and TRUE.
Referenced by acl_load(), grant_load(), and mysql_execute_command().
01766 { 01767 char cur; 01768 if (!hostname) 01769 return FALSE; 01770 int namelen= strlen(hostname); 01771 int lhlen= strlen(my_localhost); 01772 if ((namelen == lhlen) && 01773 !my_strnncoll(system_charset_info, (const uchar *)hostname, namelen, 01774 (const uchar *)my_localhost, strlen(my_localhost))) 01775 return FALSE; 01776 for (; (cur=*hostname); hostname++) 01777 { 01778 if ((cur != '%') && (cur != '_') && (cur != '.') && (cur != '/') && 01779 ((cur < '0') || (cur > '9'))) 01780 return TRUE; 01781 } 01782 return FALSE; 01783 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void init_check_host | ( | void | ) | [static] |
Definition at line 1406 of file sql_acl.cc.
References acl_check_hosts, acl_users, acl_wild_hosts, allow_all_hosts, check_get_key(), DBUG_ENTER, DBUG_VOID_RETURN, dynamic_element, st_dynamic_array::elements, hash_init, hash_search(), my_hash_insert(), my_init_dynamic_array, my_strcasecmp, push_dynamic, strchr(), strlen(), system_charset_info, VOID, wild_many, and wild_one.
Referenced by acl_load(), acl_reload(), and rebuild_check_host().
01407 { 01408 DBUG_ENTER("init_check_host"); 01409 VOID(my_init_dynamic_array(&acl_wild_hosts,sizeof(struct acl_host_and_ip), 01410 acl_users.elements,1)); 01411 VOID(hash_init(&acl_check_hosts,system_charset_info,acl_users.elements,0,0, 01412 (hash_get_key) check_get_key,0,0)); 01413 if (!allow_all_hosts) 01414 { 01415 for (uint i=0 ; i < acl_users.elements ; i++) 01416 { 01417 ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*); 01418 if (strchr(acl_user->host.hostname,wild_many) || 01419 strchr(acl_user->host.hostname,wild_one) || 01420 acl_user->host.ip_mask) 01421 { // Has wildcard 01422 uint j; 01423 for (j=0 ; j < acl_wild_hosts.elements ; j++) 01424 { // Check if host already exists 01425 acl_host_and_ip *acl=dynamic_element(&acl_wild_hosts,j, 01426 acl_host_and_ip *); 01427 if (!my_strcasecmp(system_charset_info, 01428 acl_user->host.hostname, acl->hostname)) 01429 break; // already stored 01430 } 01431 if (j == acl_wild_hosts.elements) // If new 01432 (void) push_dynamic(&acl_wild_hosts,(char*) &acl_user->host); 01433 } 01434 else if (!hash_search(&acl_check_hosts,(byte*) acl_user->host.hostname, 01435 (uint) strlen(acl_user->host.hostname))) 01436 { 01437 if (my_hash_insert(&acl_check_hosts,(byte*) acl_user)) 01438 { // End of memory 01439 allow_all_hosts=1; // Should never happen 01440 DBUG_VOID_RETURN; 01441 } 01442 } 01443 } 01444 } 01445 freeze_size(&acl_wild_hosts); 01446 freeze_size(&acl_check_hosts.array); 01447 DBUG_VOID_RETURN; 01448 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool is_acl_user | ( | const char * | host, | |
| const char * | user | |||
| ) |
Definition at line 1657 of file sql_acl.cc.
References acl_cache, find_acl_user(), initialized, hash_filo::lock, NULL, pthread_mutex_lock, pthread_mutex_unlock, TRUE, and VOID.
Referenced by Table_triggers_list::create_trigger(), mysql_create_view(), and mysql_execute_command().
01658 { 01659 bool res; 01660 01661 /* --skip-grants */ 01662 if (!initialized) 01663 return TRUE; 01664 01665 VOID(pthread_mutex_lock(&acl_cache->lock)); 01666 res= find_acl_user(host, user, TRUE) != NULL; 01667 VOID(pthread_mutex_unlock(&acl_cache->lock)); 01668 return res; 01669 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int modify_grant_table | ( | TABLE * | table, | |
| Field * | host_field, | |||
| Field * | user_field, | |||
| LEX_USER * | user_to | |||
| ) | [static] |
Definition at line 4888 of file sql_acl.cc.
References DBUG_ENTER, DBUG_RETURN, error, st_table::file, handler::ha_delete_row(), st_lex_user::host, LEX_STRING::length, MYF, handler::print_error(), st_table::record, Field::store(), store_record, LEX_STRING::str, system_charset_info, and st_lex_user::user.
Referenced by handle_grant_table().
04890 { 04891 int error; 04892 DBUG_ENTER("modify_grant_table"); 04893 04894 if (user_to) 04895 { 04896 /* rename */ 04897 store_record(table, record[1]); 04898 host_field->store(user_to->host.str, user_to->host.length, 04899 system_charset_info); 04900 user_field->store(user_to->user.str, user_to->user.length, 04901 system_charset_info); 04902 if ((error= table->file->ha_update_row(table->record[1], table->record[0]))) 04903 table->file->print_error(error, MYF(0)); 04904 } 04905 else 04906 { 04907 /* delete */ 04908 if ((error=table->file->ha_delete_row(table->record[0]))) 04909 table->file->print_error(error, MYF(0)); 04910 } 04911 04912 DBUG_RETURN(error); 04913 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 5387 of file sql_acl.cc.
References acl_cache, append_user(), String::c_ptr_safe(), close_thread_tables(), DBUG_ENTER, DBUG_RETURN, ER_CANNOT_USER, get_current_user(), GRANT_TABLES, handle_grant_data(), st_lex_user::host, HOSTNAME_LENGTH, LEX_STRING::length, list(), hash_filo::lock, LOCK_grant, my_error(), MYF, NULL, open_grant_tables(), pthread_mutex_lock, pthread_mutex_unlock, replace_user_table(), rw_unlock, rw_wrlock, TRUE, st_lex_user::user, USERNAME_LENGTH, and VOID.
Referenced by mysql_execute_command().
05388 { 05389 int result; 05390 String wrong_users; 05391 ulong sql_mode; 05392 LEX_USER *user_name, *tmp_user_name; 05393 List_iterator <LEX_USER> user_list(list); 05394 TABLE_LIST tables[GRANT_TABLES]; 05395 DBUG_ENTER("mysql_create_user"); 05396 05397 /* CREATE USER may be skipped on replication client. */ 05398 if ((result= open_grant_tables(thd, tables))) 05399 DBUG_RETURN(result != 1); 05400 05401 rw_wrlock(&LOCK_grant); 05402 VOID(pthread_mutex_lock(&acl_cache->lock)); 05403 05404 while ((tmp_user_name= user_list++)) 05405 { 05406 if (!(user_name= get_current_user(thd, tmp_user_name))) 05407 { 05408 result= TRUE; 05409 continue; 05410 } 05411 05412 if (user_name->host.length > HOSTNAME_LENGTH || 05413 user_name->user.length > USERNAME_LENGTH) 05414 { 05415 append_user(&wrong_users, user_name); 05416 result= TRUE; 05417 continue; 05418 } 05419 05420 /* 05421 Search all in-memory structures and grant tables 05422 for a mention of the new user name. 05423 */ 05424 if (handle_grant_data(tables, 0, user_name, NULL)) 05425 { 05426 append_user(&wrong_users, user_name); 05427 result= TRUE; 05428 continue; 05429 } 05430 05431 sql_mode= thd->variables.sql_mode; 05432 if (replace_user_table(thd, tables[0].table, *user_name, 0, 0, 1, 0)) 05433 { 05434 append_user(&wrong_users, user_name); 05435 result= TRUE; 05436 } 05437 } 05438 05439 VOID(pthread_mutex_unlock(&acl_cache->lock)); 05440 rw_unlock(&LOCK_grant); 05441 close_thread_tables(thd); 05442 if (result) 05443 my_error(ER_CANNOT_USER, MYF(0), "CREATE USER", wrong_users.c_ptr_safe()); 05444 DBUG_RETURN(result); 05445 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 5461 of file sql_acl.cc.
References acl_cache, append_user(), String::c_ptr_safe(), close_thread_tables(), DBUG_ENTER, DBUG_RETURN, ER_CANNOT_USER, get_current_user(), GRANT_TABLES, handle_grant_data(), list(), hash_filo::lock, LOCK_grant, my_error(), MYF, NULL, open_grant_tables(), pthread_mutex_lock, pthread_mutex_unlock, rebuild_check_host(), rw_unlock, rw_wrlock, TRUE, and VOID.
Referenced by mysql_execute_command().
05462 { 05463 int result; 05464 String wrong_users; 05465 LEX_USER *user_name, *tmp_user_name; 05466 List_iterator <LEX_USER> user_list(list); 05467 TABLE_LIST tables[GRANT_TABLES]; 05468 DBUG_ENTER("mysql_drop_user"); 05469 05470 /* DROP USER may be skipped on replication client. */ 05471 if ((result= open_grant_tables(thd, tables))) 05472 DBUG_RETURN(result != 1); 05473 05474 rw_wrlock(&LOCK_grant); 05475 VOID(pthread_mutex_lock(&acl_cache->lock)); 05476 05477 while ((tmp_user_name= user_list++)) 05478 { 05479 user_name= get_current_user(thd, tmp_user_name); 05480 if (!(user_name= get_current_user(thd, tmp_user_name))) 05481 { 05482 result= TRUE; 05483 continue; 05484 } 05485 if (handle_grant_data(tables, 1, user_name, NULL) <= 0) 05486 { 05487 append_user(&wrong_users, user_name); 05488 result= TRUE; 05489 } 05490 } 05491 05492 /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ 05493 rebuild_check_host(); 05494 05495 VOID(pthread_mutex_unlock(&acl_cache->lock)); 05496 rw_unlock(&LOCK_grant); 05497 close_thread_tables(thd); 05498 if (result) 05499 my_error(ER_CANNOT_USER, MYF(0), "DROP USER", wrong_users.c_ptr_safe()); 05500 DBUG_RETURN(result); 05501 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_grant | ( | THD * | thd, | |
| const char * | db, | |||
| List< LEX_USER > & | list, | |||
| ulong | rights, | |||
| bool | revoke_grant | |||
| ) |
Definition at line 3320 of file sql_acl.cc.
References acl_cache, bzero, close_thread_tables(), DB_ACLS, DBUG_ENTER, DBUG_RETURN, ER, ER_GRANT_WRONG_HOST_OR_USER, ER_OPTION_PREVENTS_STATEMENT, ER_WRONG_USAGE, FALSE, files_charset_info, get_current_user(), grant_version, HOSTNAME_LENGTH, initialized, Rpl_filter::is_on(), list(), hash_filo::lock, LOCK_grant, lower_case_table_names, MODE_NO_AUTO_CREATE_USER, my_casedn_str, my_error(), my_message(), MYF, NAME_LEN, pthread_mutex_lock, pthread_mutex_unlock, replace_db_table(), replace_user_table(), rpl_filter, rw_unlock, rw_wrlock, send_ok(), simple_open_n_lock_tables(), Str, strmov(), Rpl_filter::tables_ok(), test, test_if_create_new_users(), TL_WRITE, TRUE, USERNAME_LENGTH, and VOID.
Referenced by mysql_execute_command().
03322 { 03323 List_iterator <LEX_USER> str_list (list); 03324 LEX_USER *Str, *tmp_Str; 03325 char tmp_db[NAME_LEN+1]; 03326 bool create_new_users=0; 03327 TABLE_LIST tables[2]; 03328 DBUG_ENTER("mysql_grant"); 03329 if (!initialized) 03330 { 03331 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), 03332 "--skip-grant-tables"); /* purecov: tested */ 03333 DBUG_RETURN(TRUE); /* purecov: tested */ 03334 } 03335 03336 if (lower_case_table_names && db) 03337 { 03338 strmov(tmp_db,db); 03339 my_casedn_str(files_charset_info, tmp_db); 03340 db=tmp_db; 03341 } 03342 03343 /* open the mysql.user and mysql.db tables */ 03344 bzero((char*) &tables,sizeof(tables)); 03345 tables[0].alias=tables[0].table_name=(char*) "user"; 03346 tables[1].alias=tables[1].table_name=(char*) "db"; 03347 tables[0].next_local= tables[0].next_global= tables+1; 03348 tables[0].lock_type=tables[1].lock_type=TL_WRITE; 03349 tables[0].db=tables[1].db=(char*) "mysql"; 03350 03351 #ifdef HAVE_REPLICATION 03352 /* 03353 GRANT and REVOKE are applied the slave in/exclusion rules as they are 03354 some kind of updates to the mysql.% tables. 03355 */ 03356 if (thd->slave_thread && rpl_filter->is_on()) 03357 { 03358 /* 03359 The tables must be marked "updating" so that tables_ok() takes them into 03360 account in tests. 03361 */ 03362 tables[0].updating= tables[1].updating= 1; 03363 if (!(thd->spcont || rpl_filter->tables_ok(0, tables))) 03364 DBUG_RETURN(FALSE); 03365 } 03366 #endif 03367 03368 if (simple_open_n_lock_tables(thd,tables)) 03369 { // This should never happen 03370 close_thread_tables(thd); /* purecov: deadcode */ 03371 DBUG_RETURN(TRUE); /* purecov: deadcode */ 03372 } 03373 03374 if (!revoke_grant) 03375 create_new_users= test_if_create_new_users(thd); 03376 03377 /* go through users in user_list */ 03378 rw_wrlock(&LOCK_grant); 03379 VOID(pthread_mutex_lock(&acl_cache->lock)); 03380 grant_version++; 03381 03382 int result=0; 03383 while ((tmp_Str = str_list++)) 03384 { 03385 if (!(Str= get_current_user(thd, tmp_Str))) 03386 { 03387 result= TRUE; 03388 continue; 03389 } 03390 if (Str->host.length > HOSTNAME_LENGTH || 03391 Str->user.length > USERNAME_LENGTH) 03392 { 03393 my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER), 03394 MYF(0)); 03395 result= -1; 03396 continue; 03397 } 03398 if (replace_user_table(thd, tables[0].table, *Str, 03399 (!db ? rights : 0), revoke_grant, create_new_users, 03400 test(thd->variables.sql_mode & 03401 MODE_NO_AUTO_CREATE_USER))) 03402 result= -1; 03403 else if (db) 03404 { 03405 ulong db_rights= rights & DB_ACLS; 03406 if (db_rights == rights) 03407 { 03408 if (replace_db_table(tables[1].table, db, *Str, db_rights, 03409 revoke_grant)) 03410 result= -1; 03411 } 03412 else 03413 { 03414 my_error(ER_WRONG_USAGE, MYF(0), "DB GRANT", "GLOBAL PRIVILEGES"); 03415 result= -1; 03416 } 03417 } 03418 } 03419 VOID(pthread_mutex_unlock(&acl_cache->lock)); 03420 rw_unlock(&LOCK_grant); 03421 close_thread_tables(thd); 03422 03423 if (!result) 03424 send_ok(thd); 03425 DBUG_RETURN(result); 03426 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 5517 of file sql_acl.cc.
References acl_cache, append_user(), String::c_ptr_safe(), close_thread_tables(), DBUG_ASSERT, DBUG_ENTER, DBUG_RETURN, ER_CANNOT_USER, get_current_user(), GRANT_TABLES, handle_grant_data(), list(), hash_filo::lock, LOCK_grant, my_error(), MYF, NULL, open_grant_tables(), pthread_mutex_lock, pthread_mutex_unlock, rebuild_check_host(), rw_unlock, rw_wrlock, TRUE, and VOID.
Referenced by mysql_execute_command().
05518 { 05519 int result; 05520 String wrong_users; 05521 LEX_USER *user_from, *tmp_user_from; 05522 LEX_USER *user_to, *tmp_user_to; 05523 List_iterator <LEX_USER> user_list(list); 05524 TABLE_LIST tables[GRANT_TABLES]; 05525 DBUG_ENTER("mysql_rename_user"); 05526 05527 /* RENAME USER may be skipped on replication client. */ 05528 if ((result= open_grant_tables(thd, tables))) 05529 DBUG_RETURN(result != 1); 05530 05531 rw_wrlock(&LOCK_grant); 05532 VOID(pthread_mutex_lock(&acl_cache->lock)); 05533 05534 while ((tmp_user_from= user_list++)) 05535 { 05536 if (!(user_from= get_current_user(thd, tmp_user_from))) 05537 { 05538 result= TRUE; 05539 continue; 05540 } 05541 tmp_user_to= user_list++; 05542 if (!(user_to= get_current_user(thd, tmp_user_to))) 05543 { 05544 result= TRUE; 05545 continue; 05546 } 05547 DBUG_ASSERT(user_to != 0); /* Syntax enforces pairs of users. */ 05548 05549 /* 05550 Search all in-memory structures and grant tables 05551 for a mention of the new user name. 05552 */ 05553 if (handle_grant_data(tables, 0, user_to, NULL) || 05554 handle_grant_data(tables, 0, user_from, user_to) <= 0) 05555 { 05556 append_user(&wrong_users, user_from); 05557 result= TRUE; 05558 } 05559 } 05560 05561 /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ 05562 rebuild_check_host(); 05563 05564 VOID(pthread_mutex_unlock(&acl_cache->lock)); 05565 rw_unlock(&LOCK_grant); 05566 close_thread_tables(thd); 05567 if (result) 05568 my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr_safe()); 05569 DBUG_RETURN(result); 05570 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 5587 of file sql_acl.cc.
References acl_cache, acl_dbs, column_priv_hash, counter, ACL_DB::db, GRANT_NAME::db, DBUG_ENTER, DBUG_RETURN, dynamic_element, st_dynamic_array::elements, find_acl_user(), get_current_user(), GRANT_TABLES, hash_element(), st_lex_user::host, host, ACL_DB::host, GRANT_NAME::host, acl_host_and_ip::hostname, list(), hash_filo::lock, LOCK_grant, my_strcasecmp, open_grant_tables(), pthread_mutex_lock, st_hash::records, replace_column_table(), replace_db_table(), replace_table_table(), replace_user_table(), rw_wrlock, sql_print_error(), LEX_STRING::str, strcmp(), system_charset_info, GRANT_NAME::tname, TRUE, st_lex_user::user, user, ACL_DB::user, GRANT_NAME::user, and VOID.
Referenced by mysql_execute_command().
05588 { 05589 uint counter, revoked, is_proc; 05590 int result; 05591 ACL_DB *acl_db; 05592 TABLE_LIST tables[GRANT_TABLES]; 05593 DBUG_ENTER("mysql_revoke_all"); 05594 05595 if ((result= open_grant_tables(thd, tables))) 05596 DBUG_RETURN(result != 1); 05597 05598 rw_wrlock(&LOCK_grant); 05599 VOID(pthread_mutex_lock(&acl_cache->lock)); 05600 05601 LEX_USER *lex_user, *tmp_lex_user; 05602 List_iterator <LEX_USER> user_list(list); 05603 while ((tmp_lex_user= user_list++)) 05604 { 05605 if (!(lex_user= get_current_user(thd, tmp_lex_user))) 05606 { 05607 result= -1; 05608 continue; 05609 } 05610 if (!find_acl_user(lex_user->host.str, lex_user->user.str, TRUE)) 05611 { 05612 sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' does not " 05613 "exists", lex_user->user.str, lex_user->host.str); 05614 result= -1; 05615 continue; 05616 } 05617 05618 if (replace_user_table(thd, tables[0].table, 05619 *lex_user, ~(ulong)0, 1, 0, 0)) 05620 { 05621 result= -1; 05622 continue; 05623 } 05624 05625 /* Remove db access privileges */ 05626 /* 05627 Because acl_dbs and column_priv_hash shrink and may re-order 05628 as privileges are removed, removal occurs in a repeated loop 05629 until no more privileges are revoked. 05630 */ 05631 do 05632 { 05633 for (counter= 0, revoked= 0 ; counter < acl_dbs.elements ; ) 05634 { 05635 const char *user,*host; 05636 05637 acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); 05638 if (!(user=acl_db->user)) 05639 user= ""; 05640 if (!(host=acl_db->host.hostname)) 05641 host= ""; 05642 05643 if (!strcmp(lex_user->user.str,user) && 05644 !my_strcasecmp(system_charset_info, lex_user->host.str, host)) 05645 { 05646 if (!replace_db_table(tables[1].table, acl_db->db, *lex_user, 05647 ~(ulong)0, 1)) 05648 { 05649 /* 05650 Don't increment counter as replace_db_table deleted the 05651 current element in acl_dbs. 05652 */ 05653 revoked= 1; 05654 continue; 05655 } 05656 result= -1; // Something went wrong 05657 } 05658 counter++; 05659 } 05660 } while (revoked); 05661 05662 /* Remove column access */ 05663 do 05664 { 05665 for (counter= 0, revoked= 0 ; counter < column_priv_hash.records ; ) 05666 { 05667 const char *user,*host; 05668 GRANT_TABLE *grant_table= (GRANT_TABLE*)hash_element(&column_priv_hash, 05669 counter); 05670 if (!(user=grant_table->user)) 05671 user= ""; 05672 if (!(host=grant_table->host.hostname)) 05673 host= ""; 05674 05675 if (!strcmp(lex_user->user.str,user) && 05676 !my_strcasecmp(system_charset_info, lex_user->host.str, host)) 05677 { 05678 if (replace_table_table(thd,grant_table,tables[2].table,*lex_user, 05679 grant_table->db, 05680 grant_table->tname, 05681 ~(ulong)0, 0, 1)) 05682 { 05683 result= -1; 05684 } 05685 else 05686 { 05687 if (!grant_table->cols) 05688 { 05689 revoked= 1; 05690 continue; 05691 } 05692 List<LEX_COLUMN> columns; 05693 if (!replace_column_table(grant_table,tables[3].table, *lex_user, 05694 columns, 05695 grant_table->db, 05696 grant_table->tname, 05697 ~(ulong)0, 1)) 05698 { 05699 revoked= 1; 05700 continue; 05701 } 05702 result= -1; 05703 } 05704 } 05705 counter++; 05706 } 05707 } while (revoked); 05708 05709 /* Remove procedure access */ 05710 for (is_proc=0; is_proc<2; is_proc++) do { 05711 HASH *hash= is_proc ? &proc_priv_hash : &func_priv_hash; 05712 for (counter= 0, revoked= 0 ; counter < hash->records ; ) 05713 { 05714 const char *user,*host; 05715 GRANT_NAME *grant_proc= (GRANT_NAME*) hash_element(hash, counter); 05716 if (!(user=grant_proc->user)) 05717 user= ""; 05718 if (!(host=grant_proc->host.hostname)) 05719 host= ""; 05720 05721 if (!strcmp(lex_user->user.str,user) && 05722 !my_strcasecmp(system_charset_info, lex_user->host.str, host)) 05723 { 05724 if (!replace_routine_table(thd,grant_proc,tables[4].table,*lex_user, 05725 grant_proc->db, 05726 grant_proc->tname, 05727 is_proc, 05728 ~(ulong)0, 1)) 05729 { 05730 revoked= 1; 05731 continue; 05732 } 05733 result= -1; // Something went wrong 05734 } 05735 counter++; 05736 } 05737 } while (revoked); 05738 } 05739 05740 VOID(pthread_mutex_unlock(&acl_cache->lock)); 05741 rw_unlock(&LOCK_grant); 05742 close_thread_tables(thd); 05743 05744 if (result) 05745 my_message(ER_REVOKE_GRANTS, ER(ER_REVOKE_GRANTS), MYF(0)); 05746 05747 DBUG_RETURN(result); 05748 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_routine_grant | ( | THD * | thd, | |
| TABLE_LIST * | table_list, | |||
| bool | is_proc, | |||
| List< LEX_USER > & | user_list, | |||
| ulong | rights, | |||
| bool | revoke_grant, | |||
| bool | no_error | |||
| ) |
Definition at line 3174 of file sql_acl.cc.
References acl_cache, bzero, close_thread_tables(), st_table_list::db, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, ER, ER_GRANT_WRONG_HOST_OR_USER, ER_ILLEGAL_GRANT_FOR_TABLE, ER_NONEXISTING_PROC_GRANT, ER_OPTION_PREVENTS_STATEMENT, error, FALSE, func_priv_hash, get_current_user(), grant_option, HOSTNAME_LENGTH, initialized, Rpl_filter::is_on(), hash_filo::lock, LOCK_grant, memex, MODE_NO_AUTO_CREATE_USER, my_error(), my_hash_insert(), my_message(), MYF, NullS, PROC_ACLS, proc_priv_hash, pthread_mutex_lock, pthread_mutex_unlock, replace_routine_table(), replace_user_table(), routine_hash_search(), rpl_filter, rw_unlock, rw_wrlock, send_ok(), simple_open_n_lock_tables(), sp_exist_routines(), Str, st_table_list::table_name, Rpl_filter::tables_ok(), test, test_if_create_new_users(), TL_WRITE, TRUE, and USERNAME_LENGTH.
Referenced by mysql_execute_command(), and sp_grant_privileges().
03177 { 03178 List_iterator <LEX_USER> str_list (user_list); 03179 LEX_USER *Str, *tmp_Str; 03180 TABLE_LIST tables[2]; 03181 bool create_new_users=0, result=0; 03182 char *db_name, *table_name; 03183 DBUG_ENTER("mysql_routine_grant"); 03184 03185 if (!initialized) 03186 { 03187 if (!no_error) 03188 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), 03189 "--skip-grant-tables"); 03190 DBUG_RETURN(TRUE); 03191 } 03192 if (rights & ~PROC_ACLS) 03193 { 03194 if (!no_error) 03195 my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER(ER_ILLEGAL_GRANT_FOR_TABLE), 03196 MYF(0)); 03197 DBUG_RETURN(TRUE); 03198 } 03199 03200 if (!revoke_grant) 03201 { 03202 if (sp_exist_routines(thd, table_list, is_proc, no_error)<0) 03203 DBUG_RETURN(TRUE); 03204 } 03205 03206 /* open the mysql.user and mysql.procs_priv tables */ 03207 03208 bzero((char*) &tables,sizeof(tables)); 03209 tables[0].alias=tables[0].table_name= (char*) "user"; 03210 tables[1].alias=tables[1].table_name= (char*) "procs_priv"; 03211 tables[0].next_local= tables[0].next_global= tables+1; 03212 tables[0].lock_type=tables[1].lock_type=TL_WRITE; 03213 tables[0].db=tables[1].db=(char*) "mysql"; 03214 03215 #ifdef HAVE_REPLICATION 03216 /* 03217 GRANT and REVOKE are applied the slave in/exclusion rules as they are 03218 some kind of updates to the mysql.% tables. 03219 */ 03220 if (thd->slave_thread && rpl_filter->is_on()) 03221 { 03222 /* 03223 The tables must be marked "updating" so that tables_ok() takes them into 03224 account in tests. 03225 */ 03226 tables[0].updating= tables[1].updating= 1; 03227 if (!(thd->spcont || rpl_filter->tables_ok(0, tables))) 03228 DBUG_RETURN(FALSE); 03229 } 03230 #endif 03231 03232 if (simple_open_n_lock_tables(thd,tables)) 03233 { // Should never happen 03234 close_thread_tables(thd); 03235 DBUG_RETURN(TRUE); 03236 } 03237 03238 if (!revoke_grant) 03239 create_new_users= test_if_create_new_users(thd); 03240 rw_wrlock(&LOCK_grant); 03241 pthread_mutex_lock(&acl_cache->lock); 03242 MEM_ROOT *old_root= thd->mem_root; 03243 thd->mem_root= &memex; 03244 03245 DBUG_PRINT("info",("now time to iterate and add users")); 03246 03247 while ((tmp_Str= str_list++)) 03248 { 03249 int error; 03250 GRANT_NAME *grant_name; 03251 if (!(Str= get_current_user(thd, tmp_Str))) 03252 { 03253 result= TRUE; 03254 continue; 03255 } 03256 if (Str->host.length > HOSTNAME_LENGTH || 03257 Str->user.length > USERNAME_LENGTH) 03258 { 03259 if (!no_error) 03260 my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER), 03261 MYF(0)); 03262 result= TRUE; 03263 continue; 03264 } 03265 /* Create user if needed */ 03266 error=replace_user_table(thd, tables[0].table, *Str, 03267 0, revoke_grant, create_new_users, 03268 test(thd->variables.sql_mode & 03269 MODE_NO_AUTO_CREATE_USER)); 03270 if (error) 03271 { 03272 result= TRUE; // Remember error 03273 continue; // Add next user 03274 } 03275 03276 db_name= table_list->db; 03277 table_name= table_list->table_name; 03278 03279 grant_name= routine_hash_search(Str->host.str, NullS, db_name, 03280 Str->user.str, table_name, is_proc, 1); 03281 if (!grant_name) 03282 { 03283 if (revoke_grant) 03284 { 03285 if (!no_error) 03286 my_error(ER_NONEXISTING_PROC_GRANT, MYF(0), 03287 Str->user.str, Str->host.str, table_name); 03288 result= TRUE; 03289 continue; 03290 } 03291 grant_name= new GRANT_NAME(Str->host.str, db_name, 03292 Str->user.str, table_name, 03293 rights); 03294 if (!grant_name) 03295 { 03296 result= TRUE; 03297 continue; 03298 } 03299 my_hash_insert(is_proc ? &proc_priv_hash : &func_priv_hash,(byte*) grant_name); 03300 } 03301 03302 if (replace_routine_table(thd, grant_name, tables[1].table, *Str, 03303 db_name, table_name, is_proc, rights, revoke_grant)) 03304 { 03305 result= TRUE; 03306 continue; 03307 } 03308 } 03309 grant_option=TRUE; 03310 thd->mem_root= old_root; 03311 pthread_mutex_unlock(&acl_cache->lock); 03312 rw_unlock(&LOCK_grant); 03313 if (!result && !no_error) 03314 send_ok(thd); 03315 /* Tables are automatically closed */ 03316 DBUG_RETURN(result); 03317 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 4289 of file sql_acl.cc.
References ACL_ACCESS::access, acl_cache, acl_dbs, add_user_option(), String::append(), append_identifier(), String::charset(), GRANT_TABLE::cols, column_priv_hash, user_resources::conn_per_hour, counter, db, ACL_DB::db, DB_ACLS, DBUG_ENTER, DBUG_RETURN, dynamic_element, st_dynamic_array::elements, ER, ER_GRANT_WRONG_HOST_OR_USER, ER_NONEXISTING_GRANT, ER_OPTION_PREVENTS_STATEMENT, error, find_acl_user(), GLOBAL_ACLS, GRANT_ACL, GRANT_TABLE::hash_columns, hash_element(), st_lex_user::host, host, ACL_DB::host, GRANT_NAME::host, acl_host_and_ip::hostname, HOSTNAME_LENGTH, index(), initialized, LEX_STRING::length, String::length(), LINT_INIT, hash_filo::lock, LOCK_grant, make_password_from_salt(), make_password_from_salt_323(), Item::max_length, my_charset_latin1, my_error(), my_message(), my_strcasecmp, MYF, Item::name, NullS, Protocol::prepare_for_resend(), GRANT_NAME::privs, pthread_mutex_lock, pthread_mutex_unlock, String::ptr(), List< T >::push_back(), user_resources::questions, st_hash::records, rw_rdlock, rw_unlock, ACL_USER::salt, ACL_USER::salt_len, SCRAMBLE_LENGTH, SCRAMBLED_PASSWORD_CHAR_LENGTH, SELECT_ACL, Protocol::SEND_EOF, Protocol::send_fields(), Protocol::SEND_NUM_ROWS, ACL_USER::ssl_cipher, ACL_USER::ssl_type, SSL_TYPE_ANY, SSL_TYPE_SPECIFIED, SSL_TYPE_X509, Protocol::store(), LEX_STRING::str, strcmp(), STRING_WITH_LEN, strlen(), strxmov(), system_charset_info, TABLE_ACLS, test_all_bits, TRUE, user_resources::updates, st_lex_user::user, user, ACL_DB::user, GRANT_NAME::user, user_resources::user_conn, ACL_USER::user_resource, USERNAME_LENGTH, VOID, Protocol::write(), ACL_USER::x509_issuer, and ACL_USER::x509_subject.
Referenced by mysql_execute_command().
04290 { 04291 ulong want_access; 04292 uint counter,index; 04293 int error = 0; 04294 ACL_USER *acl_user; 04295 ACL_DB *acl_db; 04296 char buff[1024]; 04297 Protocol *protocol= thd->protocol; 04298 DBUG_ENTER("mysql_show_grants"); 04299 04300 LINT_INIT(acl_user); 04301 if (!initialized) 04302 { 04303 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables"); 04304 DBUG_RETURN(TRUE); 04305 } 04306 04307 if (lex_user->host.length > HOSTNAME_LENGTH || 04308 lex_user->user.length > USERNAME_LENGTH) 04309 { 04310 my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER), 04311 MYF(0)); 04312 DBUG_RETURN(TRUE); 04313 } 04314 04315 rw_rdlock(&LOCK_grant); 04316 VOID(pthread_mutex_lock(&acl_cache->lock)); 04317 04318 acl_user= find_acl_user(lex_user->host.str, lex_user->user.str, TRUE); 04319 if (!acl_user) 04320 { 04321 VOID(pthread_mutex_unlock(&acl_cache->lock)); 04322 rw_unlock(&LOCK_grant); 04323 04324 my_error(ER_NONEXISTING_GRANT, MYF(0), 04325 lex_user->user.str, lex_user->host.str); 04326 DBUG_RETURN(TRUE); 04327 } 04328 04329 Item_string *field=new Item_string("",0,&my_charset_latin1); 04330 List<Item> field_list; 04331 field->name=buff; 04332 field->max_length=1024; 04333 strxmov(buff,"Grants for ",lex_user->user.str,"@", 04334 lex_user->host.str,NullS); 04335 field_list.push_back(field); 04336 if (protocol->send_fields(&field_list, 04337 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) 04338 { 04339 VOID(pthread_mutex_unlock(&acl_cache->lock)); 04340 rw_unlock(&LOCK_grant); 04341 04342 DBUG_RETURN(TRUE); 04343 } 04344 04345 /* Add first global access grants */ 04346 { 04347 String global(buff,sizeof(buff),system_charset_info); 04348 global.length(0); 04349 global.append(STRING_WITH_LEN("GRANT ")); 04350 04351 want_access= acl_user->access; 04352 if (test_all_bits(want_access, (GLOBAL_ACLS & ~ GRANT_ACL))) 04353 global.append(STRING_WITH_LEN("ALL PRIVILEGES")); 04354 else if (!(want_access & ~GRANT_ACL)) 04355 global.append(STRING_WITH_LEN("USAGE")); 04356 else 04357 { 04358 bool found=0; 04359 ulong j,test_access= want_access & ~GRANT_ACL; 04360 for (counter=0, j = SELECT_ACL;j <= GLOBAL_ACLS;counter++,j <<= 1) 04361 { 04362 if (test_access & j) 04363 { 04364 if (found) 04365 global.append(STRING_WITH_LEN(", ")); 04366 found=1; 04367 global.append(command_array[counter],command_lengths[counter]); 04368 } 04369 } 04370 } 04371 global.append (STRING_WITH_LEN(" ON *.* TO '")); 04372 global.append(lex_user->user.str, lex_user->user.length, 04373 system_charset_info); 04374 global.append (STRING_WITH_LEN("'@'")); 04375 global.append(lex_user->host.str,lex_user->host.length, 04376 system_charset_info); 04377 global.append ('\''); 04378 if (acl_user->salt_len) 04379 { 04380 char passwd_buff[SCRAMBLED_PASSWORD_CHAR_LENGTH+1]; 04381 if (acl_user->salt_len == SCRAMBLE_LENGTH) 04382 make_password_from_salt(passwd_buff, acl_user->salt); 04383 else 04384 make_password_from_salt_323(passwd_buff, (ulong *) acl_user->salt); 04385 global.append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '")); 04386 global.append(passwd_buff); 04387 global.append('\''); 04388 } 04389 /* "show grants" SSL related stuff */ 04390 if (acl_user->ssl_type == SSL_TYPE_ANY) 04391 global.append(STRING_WITH_LEN(" REQUIRE SSL")); 04392 else if (acl_user->ssl_type == SSL_TYPE_X509) 04393 global.append(STRING_WITH_LEN(" REQUIRE X509")); 04394 else if (acl_user->ssl_type == SSL_TYPE_SPECIFIED) 04395 { 04396 int ssl_options = 0; 04397 global.append(STRING_WITH_LEN(" REQUIRE ")); 04398 if (acl_user->x509_issuer) 04399 { 04400 ssl_options++; 04401 global.append(STRING_WITH_LEN("ISSUER \'")); 04402 global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer)); 04403 global.append('\''); 04404 } 04405 if (acl_user->x509_subject) 04406 { 04407 if (ssl_options++) 04408 global.append(' '); 04409 global.append(STRING_WITH_LEN("SUBJECT \'")); 04410 global.append(acl_user->x509_subject,strlen(acl_user->x509_subject), 04411 system_charset_info); 04412 global.append('\''); 04413 } 04414 if (acl_user->ssl_cipher) 04415 { 04416 if (ssl_options++) 04417 global.append(' '); 04418 global.append(STRING_WITH_LEN("CIPHER '")); 04419 global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher), 04420 system_charset_info); 04421 global.append('\''); 04422 } 04423 } 04424 if ((want_access & GRANT_ACL) || 04425 (acl_user->user_resource.questions || 04426 acl_user->user_resource.updates || 04427 acl_user->user_resource.conn_per_hour || 04428 acl_user->user_resource.user_conn)) 04429 { 04430 global.append(STRING_WITH_LEN(" WITH")); 04431 if (want_access & GRANT_ACL) 04432 global.append(STRING_WITH_LEN(" GRANT OPTION")); 04433 add_user_option(&global, acl_user->user_resource.questions, 04434 "MAX_QUERIES_PER_HOUR"); 04435 add_user_option(&global, acl_user->user_resource.updates, 04436 "MAX_UPDATES_PER_HOUR"); 04437 add_user_option(&global, acl_user->user_resource.conn_per_hour, 04438 "MAX_CONNECTIONS_PER_HOUR"); 04439 add_user_option(&global, acl_user->user_resource.user_conn, 04440 "MAX_USER_CONNECTIONS"); 04441 } 04442 protocol->prepare_for_resend(); 04443 protocol->store(global.ptr(),global.length(),global.charset()); 04444 if (protocol->write()) 04445 { 04446 error= -1; 04447 goto end; 04448 } 04449 } 04450 04451 /* Add database access */ 04452 for (counter=0 ; counter < acl_dbs.elements ; counter++) 04453 { 04454 const char *user, *host; 04455 04456 acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); 04457 if (!(user=acl_db->user)) 04458 user= ""; 04459 if (!(host=acl_db->host.hostname)) 04460 host= ""; 04461 04462 if (!strcmp(lex_user->user.str,user) && 04463 !my_strcasecmp(system_charset_info, lex_user->host.str, host)) 04464 { 04465 want_access=acl_db->access; 04466 if (want_access) 04467 { 04468 String db(buff,sizeof(buff),system_charset_info); 04469 db.length(0); 04470 db.append(STRING_WITH_LEN("GRANT ")); 04471 04472 if (test_all_bits(want_access,(DB_ACLS & ~GRANT_ACL))) 04473 db.append(STRING_WITH_LEN("ALL PRIVILEGES")); 04474 else if (!(want_access & ~GRANT_ACL)) 04475 db.append(STRING_WITH_LEN("USAGE")); 04476 else 04477 { 04478 int found=0, cnt; 04479 ulong j,test_access= want_access & ~GRANT_ACL; 04480 for (cnt=0, j = SELECT_ACL; j <= DB_ACLS; cnt++,j <<= 1) 04481 { 04482 if (test_access & j) 04483 { 04484 if (found) 04485 db.append(STRING_WITH_LEN(", ")); 04486 found = 1; 04487 db.append(command_array[cnt],command_lengths[cnt]); 04488 } 04489 } 04490 } 04491 db.append (STRING_WITH_LEN(" ON ")); 04492 append_identifier(thd, &db, acl_db->db, strlen(acl_db->db)); 04493 db.append (STRING_WITH_LEN(".* TO '")); 04494 db.append(lex_user->user.str, lex_user->user.length, 04495 system_charset_info); 04496 db.append (STRING_WITH_LEN("'@'")); 04497 db.append(lex_user->host.str, lex_user->host.length, 04498 system_charset_info); 04499 db.append ('\''); 04500 if (want_access & GRANT_ACL) 04501 db.append(STRING_WITH_LEN(" WITH GRANT OPTION")); 04502 protocol->prepare_for_resend(); 04503 protocol->store(db.ptr(),db.length(),db.charset()); 04504 if (protocol->write()) 04505 { 04506 error= -1; 04507 goto end; 04508 } 04509 } 04510 } 04511 } 04512 04513 /* Add table & column access */ 04514 for (index=0 ; index < column_priv_hash.records ; index++) 04515 { 04516 const char *user, *host; 04517 GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, 04518 index); 04519 04520 if (!(user=grant_table->user)) 04521 user= ""; 04522 if (!(host= grant_table->host.hostname)) 04523 host= ""; 04524 04525 if (!strcmp(lex_user->user.str,user) && 04526 !my_strcasecmp(system_charset_info, lex_user->host.str, host)) 04527 { 04528 ulong table_access= grant_table->privs; 04529 if ((table_access | grant_table->cols) != 0) 04530 { 04531 String global(buff, sizeof(buff), system_charset_info); 04532 ulong test_access= (table_access | grant_table->cols) & ~GRANT_ACL; 04533 04534 global.length(0); 04535 global.append(STRING_WITH_LEN("GRANT ")); 04536 04537 if (test_all_bits(table_access, (TABLE_ACLS & ~GRANT_ACL))) 04538 global.append(STRING_WITH_LEN("ALL PRIVILEGES")); 04539 else if (!test_access) 04540 global.append(STRING_WITH_LEN("USAGE")); 04541 else 04542 { 04543 /* Add specific column access */ 04544 int found= 0; 04545 ulong j; 04546 04547 for (counter= 0, j= SELECT_ACL; j <= TABLE_ACLS; counter++, j<<= 1) 04548 { 04549 if (test_access & j) 04550 { 04551 if (found) 04552 global.append(STRING_WITH_LEN(", ")); 04553 found= 1; 04554 global.append(command_array[counter],command_lengths[counter]); 04555 04556 if (grant_table->cols) 04557 { 04558 uint found_col= 0; 04559 for (uint col_index=0 ; 04560 col_index < grant_table->hash_columns.records ; 04561 col_index++) 04562 { 04563 GRANT_COLUMN *grant_column = (GRANT_COLUMN*) 04564 hash_element(&grant_table->hash_columns,col_index); 04565 if (grant_column->rights & j) 04566 { 04567 if (!found_col) 04568 { 04569 found_col= 1; 04570 /* 04571 If we have a duplicated table level privilege, we 04572 must write the access privilege name again. 04573 */ 04574 if (table_access & j) 04575 { 04576 global.append(STRING_WITH_LEN(", ")); 04577 global.append(command_array[counter], 04578 command_lengths[counter]); 04579 } 04580 global.append(STRING_WITH_LEN(" (")); 04581 } 04582 else 04583 global.append(STRING_WITH_LEN(", ")); 04584 global.append(grant_column->column, 04585 grant_column->key_length, 04586 system_charset_info); 04587 } 04588 } 04589 if (found_col) 04590 global.append(')'); 04591 } 04592 } 04593 } 04594 } 04595 global.append(STRING_WITH_LEN(" ON ")); 04596 append_identifier(thd, &global, grant_table->db, 04597 strlen(grant_table->db)); 04598 global.append('.'); 04599 append_identifier(thd, &global, grant_table->tname, 04600 strlen(grant_table->tname)); 04601 global.append(STRING_WITH_LEN(" TO '")); 04602 global.append(lex_user->user.str, lex_user->user.length, 04603 system_charset_info); 04604 global.append(STRING_WITH_LEN("'@'")); 04605 global.append(lex_user->host.str,lex_user->host.length, 04606 system_charset_info); 04607 global.append('\''); 04608 if (table_access & GRANT_ACL) 04609 global.append(STRING_WITH_LEN(" WITH GRANT OPTION")); 04610 protocol->prepare_for_resend(); 04611 protocol->store(global.ptr(),global.length(),global.charset()); 04612 if (protocol->write()) 04613 { 04614 error= -1; 04615 break; 04616 } 04617 } 04618 } 04619 } 04620 04621 if (show_routine_grants(thd, lex_user, &proc_priv_hash, 04622 STRING_WITH_LEN("PROCEDURE"), buff, sizeof(buff))) 04623 { 04624 error= -1; 04625 goto end; 04626 } 04627 04628 if (show_routine_grants(thd, lex_user, &func_priv_hash, 04629 STRING_WITH_LEN("FUNCTION"), buff, sizeof(buff))) 04630 { 04631 error= -1; 04632 goto end; 04633 } 04634 04635 end: 04636 VOID(pthread_mutex_unlock(&acl_cache->lock)); 04637 rw_unlock(&LOCK_grant); 04638 04639 send_eof(thd); 04640 DBUG_RETURN(error); 04641 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_table_grant | ( | THD * | thd, | |
| TABLE_LIST * | table_list, | |||
| List< LEX_USER > & | user_list, | |||
| List< LEX_COLUMN > & | columns, | |||
| ulong | rights, | |||
| bool | revoke_grant | |||
| ) |
Definition at line 2902 of file sql_acl.cc.
References access, acl_cache, st_table_list::alias, buf, build_table_filename(), bzero, String::c_ptr(), close_thread_tables(), COL_ACLS, GRANT_TABLE::cols, LEX_COLUMN::column, column_hash_search(), column_priv_hash, CREATE_ACL, st_table_list::db, DBUG_ENTER, DBUG_RETURN, base_list::elements, ER, ER_BAD_FIELD_ERROR, ER_GRANT_WRONG_HOST_OR_USER, ER_ILLEGAL_GRANT_FOR_TABLE, ER_NO_SUCH_TABLE, ER_NONEXISTING_TABLE_GRANT, ER_OPTION_PREVENTS_STATEMENT, ER_TABLEACCESS_DENIED_ERROR, error, f, F_OK, FALSE, find_field_in_table_ref(), fn_format(), FN_REFLEN, get_current_user(), get_privilege_desc(), st_table_list::grant, grant_option, grant_version, GRANT_TABLE::hash_columns, hash_element(), HOSTNAME_LENGTH, initialized, Rpl_filter::is_on(), String::length(), LEX_STRING::length, hash_filo::lock, LOCK_grant, memex, MODE_NO_AUTO_CREATE_USER, MY_APPEND_EXT, my_error(), my_hash_insert(), my_message(), MY_RESOLVE_SYMLINKS, MY_RETURN_REAL_PATH, MY_UNPACK_FILENAME, MYF, NO_CACHED_FIELD_INDEX, NULL, NullS, open_and_lock_tables(), pthread_mutex_lock, pthread_mutex_unlock, String::ptr(), st_hash::records, reg_ext, replace_column_table(), replace_table_table(), replace_user_table(), GRANT_COLUMN::rights, rpl_filter, rw_unlock, rw_wrlock, send_ok(), simple_open_n_lock_tables(), Str, LEX_STRING::str, TABLE_ACLS, table_hash_search(), st_table_list::table_name, Rpl_filter::tables_ok(), test, test_if_create_new_users(), TL_WRITE, TRUE, USERNAME_LENGTH, st_table_list::view_db, st_table_list::view_name, and st_grant_info::want_privilege.
Referenced by mysql_execute_command().
02906 { 02907 ulong column_priv= 0; 02908 List_iterator <LEX_USER> str_list (user_list); 02909 LEX_USER *Str, *tmp_Str; 02910 TABLE_LIST tables[3]; 02911 bool create_new_users=0; 02912 char *db_name, *table_name; 02913 DBUG_ENTER("mysql_table_grant"); 02914 02915 if (!initialized) 02916 { 02917 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), 02918 "--skip-grant-tables"); /* purecov: inspected */ 02919 DBUG_RETURN(TRUE); /* purecov: inspected */ 02920 } 02921 if (rights & ~TABLE_ACLS) 02922 { 02923 my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER(ER_ILLEGAL_GRANT_FOR_TABLE), 02924 MYF(0)); 02925 DBUG_RETURN(TRUE); 02926 } 02927 02928 if (!revoke_grant) 02929 { 02930 if (columns.elements) 02931 { 02932 class LEX_COLUMN *column; 02933 List_iterator <LEX_COLUMN> column_iter(columns); 02934 02935 if (open_and_lock_tables(thd, table_list)) 02936 DBUG_RETURN(TRUE); 02937 02938 while ((column = column_iter++)) 02939 { 02940 uint unused_field_idx= NO_CACHED_FIELD_INDEX; 02941 TABLE_LIST *dummy; 02942 Field *f=find_field_in_table_ref(thd, table_list, column->column.ptr(), 02943 column->column.length(), 02944 column->column.ptr(), NULL, NULL, 02945 NULL, TRUE, FALSE, 02946 &unused_field_idx, FALSE, &dummy); 02947 if (f == (Field*)0) 02948 { 02949 my_error(ER_BAD_FIELD_ERROR, MYF(0), 02950 column->column.c_ptr(), table_list->alias); 02951 DBUG_RETURN(TRUE); 02952 } 02953 if (f == (Field *)-1) 02954 DBUG_RETURN(TRUE); 02955 column_priv|= column->rights; 02956 } 02957 close_thread_tables(thd); 02958 } 02959 else 02960 { 02961 if (!(rights & CREATE_ACL)) 02962 { 02963 char buf[FN_REFLEN]; 02964 build_table_filename(buf, sizeof(buf), table_list->db, 02965 table_list->table_name, reg_ext, 0); 02966 fn_format(buf, buf, "", "", MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS | 02967 MY_RETURN_REAL_PATH | MY_APPEND_EXT); 02968 if (access(buf,F_OK)) 02969 { 02970 my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db, table_list->alias); 02971 DBUG_RETURN(TRUE); 02972 } 02973 } 02974 if (table_list->grant.want_privilege) 02975 { 02976 char command[128]; 02977 get_privilege_desc(command, sizeof(command), 02978 table_list->grant.want_privilege); 02979 my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), 02980 command, thd->security_ctx->priv_user, 02981 thd->security_ctx->host_or_ip, table_list->alias); 02982 DBUG_RETURN(-1); 02983 } 02984 } 02985 } 02986 02987 /* open the mysql.tables_priv and mysql.columns_priv tables */ 02988 02989 bzero((char*) &tables,sizeof(tables)); 02990 tables[0].alias=tables[0].table_name= (char*) "user"; 02991 tables[1].alias=tables[1].table_name= (char*) "tables_priv"; 02992 tables[2].alias=tables[2].table_name= (char*) "columns_priv"; 02993 tables[0].next_local= tables[0].next_global= tables+1; 02994 /* Don't open column table if we don't need it ! */ 02995 tables[1].next_local= 02996 tables[1].next_global= ((column_priv || 02997 (revoke_grant && 02998 ((rights & COL_ACLS) || columns.elements))) 02999 ? tables+2 : 0); 03000 tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_WRITE; 03001 tables[0].db=tables[1].db=tables[2].db=(char*) "mysql"; 03002 03003 #ifdef HAVE_REPLICATION 03004 /* 03005 GRANT and REVOKE are applied the slave in/exclusion rules as they are 03006 some kind of updates to the mysql.% tables. 03007 */ 03008 if (thd->slave_thread && rpl_filter->is_on()) 03009 { 03010 /* 03011 The tables must be marked "updating" so that tables_ok() takes them into 03012 account in tests. 03013 */ 03014 tables[0].updating= tables[1].updating= tables[2].updating= 1; 03015 if (!(thd->spcont || rpl_filter->tables_ok(0, tables))) 03016 DBUG_RETURN(FALSE); 03017 } 03018 #endif 03019 03020 if (simple_open_n_lock_tables(thd,tables)) 03021 { // Should never happen 03022 close_thread_tables(thd); /* purecov: deadcode */ 03023 DBUG_RETURN(TRUE); /* purecov: deadcode */ 03024 } 03025 03026 if (!revoke_grant) 03027 create_new_users= test_if_create_new_users(thd); 03028 bool result= FALSE; 03029 rw_wrlock(&LOCK_grant); 03030 pthread_mutex_lock(&acl_cache->lock); 03031 MEM_ROOT *old_root= thd->mem_root; 03032 thd->mem_root= &memex; 03033 grant_version++; 03034 03035 while ((tmp_Str = str_list++)) 03036 { 03037 int error; 03038 GRANT_TABLE *grant_table; 03039 if (!(Str= get_current_user(thd, tmp_Str))) 03040 { 03041 result= TRUE; 03042 continue; 03043 } 03044 if (Str->host.length > HOSTNAME_LENGTH || 03045 Str->user.length > USERNAME_LENGTH) 03046 { 03047 my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER), 03048 MYF(0)); 03049 result= TRUE; 03050 continue; 03051 } 03052 /* Create user if needed */ 03053 error=replace_user_table(thd, tables[0].table, *Str, 03054 0, revoke_grant, create_new_users, 03055 test(thd->variables.sql_mode & 03056 MODE_NO_AUTO_CREATE_USER)); 03057 if (error) 03058 { 03059 result= TRUE; // Remember error 03060 continue; // Add next user 03061 } 03062 03063 db_name= (table_list->view_db.length ? 03064 table_list->view_db.str : 03065 table_list->db); 03066 table_name= (table_list->view_name.length ? 03067 table_list->view_name.str : 03068 table_list->table_name); 03069 03070 /* Find/create cached table grant */ 03071 grant_table= table_hash_search(Str->host.str, NullS, db_name, 03072 Str->user.str, table_name, 1); 03073 if (!grant_table) 03074 { 03075 if (revoke_grant) 03076 { 03077 my_error(ER_NONEXISTING_TABLE_GRANT, MYF(0), 03078 Str->user.str, Str->host.str, table_list->table_name); 03079 result= TRUE; 03080 continue; 03081 } 03082 grant_table = new GRANT_TABLE (Str->host.str, db_name, 03083 Str->user.str, table_name, 03084 rights, 03085 column_priv); 03086 if (!grant_table) // end of memory 03087 { 03088 result= TRUE; /* purecov: deadcode */ 03089 continue; /* purecov: deadcode */ 03090 } 03091 my_hash_insert(&column_priv_hash,(byte*) grant_table); 03092 } 03093 03094 /* If revoke_grant, calculate the new column privilege for tables_priv */ 03095 if (revoke_grant) 03096 { 03097 class LEX_COLUMN *column; 03098 List_iterator <LEX_COLUMN> column_iter(columns); 03099 GRANT_COLUMN *grant_column; 03100 03101 /* Fix old grants */ 03102 while ((column = column_iter++)) 03103 { 03104 grant_column = column_hash_search(grant_table, 03105 column->column.ptr(), 03106 column->column.length()); 03107 if (grant_column) 03108 grant_column->rights&= ~(column->rights | rights); 03109 } 03110 /* scan trough all columns to get new column grant */ 03111 column_priv= 0; 03112 for (uint idx=0 ; idx < grant_table->hash_columns.records ; idx++) 03113 { 03114 grant_column= (GRANT_COLUMN*) hash_element(&grant_table->hash_columns, 03115 idx); 03116 grant_column->rights&= ~rights; // Fix other columns 03117 column_priv|= grant_column->rights; 03118 } 03119 } 03120 else 03121 { 03122 column_priv|= grant_table->cols; 03123 } 03124 03125 03126 /* update table and columns */ 03127 03128 if (replace_table_table(thd, grant_table, tables[1].table, *Str, 03129 db_name, table_name, 03130 rights, column_priv, revoke_grant)) 03131 { 03132 /* Should only happen if table is crashed */ 03133 result= TRUE; /* purecov: deadcode */ 03134 } 03135 else if (tables[2].table) 03136 { 03137 if ((replace_column_table(grant_table, tables[2].table, *Str, 03138 columns, 03139 db_name, table_name, 03140 rights, revoke_grant))) 03141 { 03142 result= TRUE; 03143 } 03144 } 03145 } 03146 grant_option=TRUE; 03147 thd->mem_root= old_root; 03148 pthread_mutex_unlock(&acl_cache->lock); 03149 rw_unlock(&LOCK_grant); 03150 if (!result) 03151 send_ok(thd); 03152 /* Tables are automatically closed */ 03153 DBUG_RETURN(result); 03154 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static GRANT_NAME* name_hash_search | ( | HASH * | name_hash, | |
| const char * | host, | |||
| const char * | ip, | |||
| const char * | db, | |||
| const char * | user, | |||
| const char * | tname, | |||
| bool | exact | |||
| ) | [static] |
Definition at line 2395 of file sql_acl.cc.
References compare_hostname(), hash_first(), hash_next(), GRANT_NAME::host, acl_host_and_ip::hostname, my_strcasecmp, NAME_LEN, GRANT_NAME::sort, strcmp(), strmov(), system_charset_info, and USERNAME_LENGTH.
Referenced by routine_hash_search(), and table_hash_search().
02400 { 02401 char helping [NAME_LEN*2+USERNAME_LENGTH+3]; 02402 uint len; 02403 GRANT_NAME *grant_name,*found=0; 02404 HASH_SEARCH_STATE state; 02405 02406 len = (uint) (strmov(strmov(strmov(helping,user)+1,db)+1,tname)-helping)+ 1; 02407 for (grant_name= (GRANT_NAME*) hash_first(name_hash, (byte*) helping, 02408 len, &state); 02409 grant_name ; 02410 grant_name= (GRANT_NAME*) hash_next(name_hash,(byte*) helping, 02411 len, &state)) 02412 { 02413 if (exact) 02414 { 02415 if (!grant_name->host.hostname || 02416 (host && 02417 !my_strcasecmp(system_charset_info, host, 02418 grant_name->host.hostname)) || 02419 (ip && !strcmp(ip, grant_name->host.hostname))) 02420 return grant_name; 02421 } 02422 else 02423 { 02424 if (compare_hostname(&grant_name->host, host, ip) && 02425 (!found || found->sort < grant_name->sort)) 02426 found=grant_name; // Host ok 02427 } 02428 } 02429 return found; 02430 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int open_grant_tables | ( | THD * | thd, | |
| TABLE_LIST * | tables | |||
| ) |
Definition at line 4786 of file sql_acl.cc.
References bzero, close_thread_tables(), db, DBUG_ENTER, DBUG_RETURN, ER_OPTION_PREVENTS_STATEMENT, GRANT_TABLES, initialized, Rpl_filter::is_on(), my_error(), MYF, rpl_filter, simple_open_n_lock_tables(), Rpl_filter::tables_ok(), and TL_WRITE.
Referenced by mysql_create_user(), mysql_drop_user(), mysql_rename_user(), mysql_revoke_all(), and sp_revoke_privileges().
04787 { 04788 DBUG_ENTER("open_grant_tables"); 04789 04790 if (!initialized) 04791 { 04792 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables"); 04793 DBUG_RETURN(-1); 04794 } 04795 04796 bzero((char*) tables, GRANT_TABLES*sizeof(*tables)); 04797 tables->alias= tables->table_name= (char*) "user"; 04798 (tables+1)->alias= (tables+1)->table_name= (char*) "db"; 04799 (tables+2)->alias= (tables+2)->table_name= (char*) "tables_priv"; 04800 (tables+3)->alias= (tables+3)->table_name= (char*) "columns_priv"; 04801 (tables+4)->alias= (tables+4)->table_name= (char*) "procs_priv"; 04802 tables->next_local= tables->next_global= tables+1; 04803 (tables+1)->next_local= (tables+1)->next_global= tables+2; 04804 (tables+2)->next_local= (tables+2)->next_global= tables+3; 04805 (tables+3)->next_local= (tables+3)->next_global= tables+4; 04806 tables->lock_type= (tables+1)->lock_type= 04807 (tables+2)->lock_type= (tables+3)->lock_type= 04808 (tables+4)->lock_type= TL_WRITE; 04809 tables->db= (tables+1)->db= (tables+2)->db= 04810 (tables+3)->db= (tables+4)->db= (char*) "mysql"; 04811 04812 #ifdef HAVE_REPLICATION 04813 /* 04814 GRANT and REVOKE are applied the slave in/exclusion rules as they are 04815 some kind of updates to the mysql.% tables. 04816 */ 04817 if (thd->slave_thread && rpl_filter->is_on()) 04818 { 04819 /* 04820 The tables must be marked "updating" so that tables_ok() takes them into 04821 account in tests. 04822 */ 04823 tables[0].updating=tables[1].updating=tables[2].updating= 04824 tables[3].updating=tables[4].updating=1; 04825 if (!(thd->spcont || rpl_filter->tables_ok(0, tables))) 04826 DBUG_RETURN(1); 04827 tables[0].updating=tables[1].updating=tables[2].updating= 04828 tables[3].updating=tables[4].updating=0;; 04829 } 04830 #endif 04831 04832 if (simple_open_n_lock_tables(thd, tables)) 04833 { // This should never happen 04834 close_thread_tables(thd); 04835 DBUG_RETURN(-1); 04836 } 04837 04838 DBUG_RETURN(0); 04839 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void rebuild_check_host | ( | void | ) | [static] |
Definition at line 1459 of file sql_acl.cc.
References acl_check_hosts, acl_wild_hosts, delete_dynamic(), hash_free(), and init_check_host().
Referenced by acl_insert_user(), mysql_drop_user(), and mysql_rename_user().
01460 { 01461 delete_dynamic(&acl_wild_hosts); 01462 hash_free(&acl_check_hosts); 01463 init_check_host(); 01464 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int replace_column_table | ( | GRANT_TABLE * | g_t, | |
| TABLE * | table, | |||
| const LEX_USER & | combo, | |||
| List< LEX_COLUMN > & | columns, | |||
| const char * | db, | |||
| const char * | table_name, | |||
| ulong | rights, | |||
| bool | revoke_grant | |||
| ) | [static] |
Definition at line 2459 of file sql_acl.cc.
References COL_ACLS, LEX_COLUMN::column, column_hash_search(), DBUG_ENTER, DBUG_RETURN, ER_NONEXISTING_TABLE_GRANT, error, st_table::field, st_table::file, fix_rights_for_column, get_rights_for_column, handler::ha_delete_row(), handler::ha_index_end(), handler::ha_index_init(), HA_READ_KEY_EXACT, handler::ha_update_row(), handler::ha_write_row(), GRANT_TABLE::hash_columns, hash_delete(), st_lex_user::host, HOSTNAME_LENGTH, handler::index_next(), handler::index_read(), key, key_cmp_if_same(), key_copy(), st_table::key_info, st_key::key_length, st_key::key_part, key_restore(), String::length(), LEX_STRING::length, MAX_KEY_LENGTH, my_error(), my_hash_insert(), MYF, NULL, handler::print_error(), String::ptr(), st_table::record, restore_record, GRANT_COLUMN::rights, Field::store(), st_key_part_info::store_length, store_record, LEX_STRING::str, strlen(), system_charset_info, TRUE, st_table::use_all_columns(), st_lex_user::user, Field::val_int(), and Field::val_str().
Referenced by mysql_revoke_all(), and mysql_table_grant().
02464 { 02465 int error=0,result=0; 02466 byte key[MAX_KEY_LENGTH]; 02467 uint key_prefix_length; 02468 KEY_PART_INFO *key_part= table->key_info->key_part; 02469 DBUG_ENTER("replace_column_table"); 02470 02471 table->use_all_columns(); 02472 table->field[0]->store(combo.host.str,combo.host.length, 02473 system_charset_info); 02474 table->field[1]->store(db,(uint) strlen(db), 02475 system_charset_info); 02476 table->field[2]->store(combo.user.str,combo.user.length, 02477 system_charset_info); 02478 table->field[3]->store(table_name,(uint) strlen(table_name), 02479 system_charset_info); 02480 02481 /* Get length of 3 first key parts */ 02482 key_prefix_length= (key_part[0].store_length + key_part[1].store_length + 02483 key_part[2].store_length + key_part[3].store_length); 02484 key_copy(key, table->record[0], table->key_info, key_prefix_length); 02485 02486 rights&= COL_ACLS; // Only ACL for columns 02487 02488 /* first fix privileges for all columns in column list */ 02489 02490 List_iterator <LEX_COLUMN> iter(columns); 02491 class LEX_COLUMN *column; 02492 table->file->ha_index_init(0, 1); 02493 while ((column= iter++)) 02494 { 02495 ulong privileges= column->rights; 02496 bool old_row_exists=0; 02497 byte user_key[MAX_KEY_LENGTH]; 02498 02499 key_restore(table->record[0],key,table->key_info, 02500 key_prefix_length); 02501 table->field[4]->store(column->column.ptr(), column->column.length(), 02502 system_charset_info); 02503 /* Get key for the first 4 columns */ 02504 key_copy(user_key, table->record[0], table->key_info, 02505 table->key_info->key_length); 02506 02507 if (table->file->index_read(table->record[0], user_key, 02508 table->key_info->key_length, 02509 HA_READ_KEY_EXACT)) 02510 { 02511 if (revoke_grant) 02512 { 02513 my_error(ER_NONEXISTING_TABLE_GRANT, MYF(0), 02514 combo.user.str, combo.host.str, 02515 table_name); /* purecov: inspected */ 02516 result= -1; /* purecov: inspected */ 02517 continue; /* purecov: inspected */ 02518 } 02519 old_row_exists = 0; 02520 restore_record(table, s->default_values); // Get empty record 02521 key_restore(table->record[0],key,table->key_info, 02522 key_prefix_length); 02523 table->field[4]->store(column->column.ptr(),column->column.length(), 02524 system_charset_info); 02525 } 02526 else 02527 { 02528 ulong tmp= (ulong) table->field[6]->val_int(); 02529 tmp=fix_rights_for_column(tmp); 02530 02531 if (revoke_grant) 02532 privileges = tmp & ~(privileges | rights); 02533 else 02534 privileges |= tmp; 02535 old_row_exists = 1; 02536 store_record(table,record[1]); // copy original row 02537 } 02538 02539 table->field[6]->store((longlong) get_rights_for_column(privileges), TRUE); 02540 02541 if (old_row_exists) 02542 { 02543 GRANT_COLUMN *grant_column; 02544 if (privileges) 02545 error=table->file->ha_update_row(table->record[1],table->record[0]); 02546 else 02547 error=table->file->ha_delete_row(table->record[1]); 02548 if (error) 02549 { 02550 table->file->print_error(error,MYF(0)); /* purecov: inspected */ 02551 result= -1; /* purecov: inspected */ 02552 goto end; /* purecov: inspected */ 02553 } 02554 grant_column= column_hash_search(g_t, column->column.ptr(), 02555 column->column.length()); 02556 if (grant_column) // Should always be true 02557 grant_column->rights= privileges; // Update hash 02558 } 02559 else // new grant 02560 { 02561 GRANT_COLUMN *grant_column; 02562 if ((error=table->file->ha_write_row(table->record[0]))) 02563 { 02564 table->file->print_error(error,MYF(0)); /* purecov: inspected */ 02565 result= -1; /* purecov: inspected */ 02566 goto end; /* purecov: inspected */ 02567 } 02568 grant_column= new GRANT_COLUMN(column->column,privileges); 02569 my_hash_insert(&g_t->hash_columns,(byte*) grant_column); 02570 } 02571 } 02572 02573 /* 02574 If revoke of privileges on the table level, remove all such privileges 02575 for all columns 02576 */ 02577 02578 if (revoke_grant) 02579 { 02580 byte user_key[MAX_KEY_LENGTH]; 02581 key_copy(user_key, table->record[0], table->key_info, 02582 key_prefix_length); 02583 02584 if (table->file->index_read(table->record[0], user_key, 02585 key_prefix_length, 02586 HA_READ_KEY_EXACT)) 02587 goto end; 02588 02589 /* Scan through all rows with the same host,db,user and table */ 02590 do 02591 { 02592 ulong privileges = (ulong) table->field[6]->val_int(); 02593 privileges=fix_rights_for_column(privileges); 02594 store_record(table,record[1]); 02595 02596 if (privileges & rights) // is in this record the priv to be revoked ?? 02597 { 02598 GRANT_COLUMN *grant_column = NULL; 02599 char colum_name_buf[HOSTNAME_LENGTH+1]; 02600 String column_name(colum_name_buf,sizeof(colum_name_buf), 02601 system_charset_info); 02602 02603 privileges&= ~rights; 02604 table->field[6]->store((longlong) 02605 get_rights_for_column(privileges), TRUE); 02606 table->field[4]->val_str(&column_name); 02607 grant_column = column_hash_search(g_t, 02608 column_name.ptr(), 02609 column_name.length()); 02610 if (privileges) 02611 { 02612 int tmp_error; 02613 if ((tmp_error=table->file->ha_update_row(table->record[1], 02614 table->record[0]))) 02615 { /* purecov: deadcode */ 02616 table->file->print_error(tmp_error,MYF(0)); /* purecov: deadcode */ 02617 result= -1; /* purecov: deadcode */ 02618 goto end; /* purecov: deadcode */ 02619 } 02620 if (grant_column) 02621 grant_column->rights = privileges; // Update hash 02622 } 02623 else 02624 { 02625 int tmp_error; 02626 if ((tmp_error = table->file->ha_delete_row(table->record[1]))) 02627 { /* purecov: deadcode */ 02628 table->file->print_error(tmp_error,MYF(0)); /* purecov: deadcode */ 02629 result= -1; /* purecov: deadcode */ 02630 goto end; /* purecov: deadcode */ 02631 } 02632 if (grant_column) 02633 hash_delete(&g_t->hash_columns,(byte*) grant_column); 02634 } 02635 } 02636 } while (!table->file->index_next(table->record[0]) && 02637 !key_cmp_if_same(table, key, 0, key_prefix_length)); 02638 } 02639 02640 end: 02641 table->file->ha_index_end(); 02642 DBUG_RETURN(result); 02643 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int replace_db_table | ( | TABLE * | table, | |
| const char * | db, | |||
| const LEX_USER & | combo, | |||
| ulong | rights, | |||
| bool | revoke_grant | |||
| ) | [static] |
Definition at line 2091 of file sql_acl.cc.
References abort(), acl_cache, acl_insert_db(), acl_update_db(), hash_filo::clear(), DBUG_ENTER, DBUG_RETURN, ER, ER_NONEXISTING_GRANT, ER_OPTION_PREVENTS_STATEMENT, ER_PASSWORD_NO_MATCH, error, FALSE, st_table::field, st_table_share::fields, st_table::file, find_acl_user(), fix_rights_for_db, get_access(), get_rights_for_db, HA_CHECK_DUP_KEY, handler::ha_delete_row(), HA_READ_KEY_EXACT, handler::ha_update_row(), handler::ha_write_row(), st_lex_user::host, handler::index_read_idx(), initialized, handler::is_fatal_error(), key_copy(), st_table::key_info, st_key::key_length, LEX_STRING::length, MAX_KEY_LENGTH, my_charset_latin1, my_error(), my_message(), MYF, handler::print_error(), st_table::record, restore_record, st_table::s, Field::store(), store_record, LEX_STRING::str, strlen(), system_charset_info, st_table::use_all_columns(), and st_lex_user::user.
Referenced by mysql_grant(), and mysql_revoke_all().
02094 { 02095 uint i; 02096 ulong priv,store_rights; 02097 bool old_row_exists=0; 02098 int error; 02099 char what= (revoke_grant) ? 'N' : 'Y'; 02100 byte user_key[MAX_KEY_LENGTH]; 02101 DBUG_ENTER("replace_db_table"); 02102 02103 if (!initialized) 02104 { 02105 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables"); 02106 DBUG_RETURN(-1); 02107 } 02108 02109 /* Check if there is such a user in user table in memory? */ 02110 if (!find_acl_user(combo.host.str,combo.user.str, FALSE)) 02111 { 02112 my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH), MYF(0)); 02113 DBUG_RETURN(-1); 02114 } 02115 02116 table->use_all_columns(); 02117 table->field[0]->store(combo.host.str,combo.host.length, 02118 system_charset_info); 02119 table->field[1]->store(db,(uint) strlen(db), system_charset_info); 02120 table->field[2]->store(combo.user.str,combo.user.length, 02121 system_charset_info); 02122 key_copy(user_key, table->record[0], table->key_info, 02123 table->key_info->key_length); 02124 02125 if (table->file->index_read_idx(table->record[0],0, 02126 user_key, table->key_info->key_length, 02127 HA_READ_KEY_EXACT)) 02128 { 02129 if (what == 'N') 02130 { // no row, no revoke 02131 my_error(ER_NONEXISTING_GRANT, MYF(0), combo.user.str, combo.host.str); 02132 goto abort; 02133 } 02134 old_row_exists = 0; 02135 restore_record(table, s->default_values); 02136 table->field[0]->store(combo.host.str,combo.host.length, 02137 system_charset_info); 02138 table->field[1]->store(db,(uint) strlen(db), system_charset_info); 02139 table->field[2]->store(combo.user.str,combo.user.length, 02140 system_charset_info); 02141 } 02142 else 02143 { 02144 old_row_exists = 1; 02145 store_record(table,record[1]); 02146 } 02147 02148 store_rights=get_rights_for_db(rights); 02149 for (i= 3, priv= 1; i < table->s->fields; i++, priv <<= 1) 02150 { 02151 if (priv & store_rights) // do it if priv is chosen 02152 table->field [i]->store(&what,1, &my_charset_latin1);// set requested privileges 02153 } 02154 rights=

