| 3831 | */ |
| 3832 | |
| 3833 | privilege_t acl_get(const char *host, const char *ip, |
| 3834 | const char *user, const char *db, my_bool db_is_pattern) |
| 3835 | { |
| 3836 | privilege_t host_access(ALL_KNOWN_ACL), db_access(NO_ACL); |
| 3837 | uint i; |
| 3838 | const char *tmp_db; |
| 3839 | acl_entry *entry; |
| 3840 | DBUG_ENTER("acl_get"); |
| 3841 | |
| 3842 | // Key length, without the trailing '\0' byte |
| 3843 | constexpr size_t key_data_size= IP_ADDR_STRLEN + 1/*'\0'*/ + |
| 3844 | USERNAME_LENGTH + 1/*'\0'*/ + |
| 3845 | NAME_LEN/*database*/; |
| 3846 | /* |
| 3847 | Let's reserve extra MY_CS_MBMAXLEN bytes in the buffer. |
| 3848 | This is to catch cases when a too long database name gets truncated: |
| 3849 | key.length() will return a length in the range: |
| 3850 | [key_data_size + 1, key_data_size + MY_CS_MBMAXLEN]. |
| 3851 | */ |
| 3852 | CharBuffer<key_data_size + MY_CS_MBMAXLEN> key; |
| 3853 | key.append(Lex_cstring_strlen(safe_str(ip))).append_char('\0') |
| 3854 | .append(Lex_cstring_strlen(user)).append_char('\0'); |
| 3855 | tmp_db= key.end(); |
| 3856 | key.append_opt_casedn(files_charset_info, Lex_cstring_strlen(db), |
| 3857 | lower_case_table_names); |
| 3858 | db= tmp_db; |
| 3859 | |
| 3860 | if (key.length() > key_data_size) // db name was truncated |
| 3861 | DBUG_RETURN(NO_ACL); // no privileges for an invalid db name |
| 3862 | |
| 3863 | mysql_mutex_lock(&acl_cache->lock); |
| 3864 | if (!db_is_pattern && |
| 3865 | (entry= acl_cache->search((uchar*) key.ptr(), key.length()))) |
| 3866 | { |
| 3867 | db_access=entry->access; |
| 3868 | mysql_mutex_unlock(&acl_cache->lock); |
| 3869 | DBUG_PRINT("exit", ("access: 0x%llx", (longlong) db_access)); |
| 3870 | DBUG_RETURN(db_access); |
| 3871 | } |
| 3872 | |
| 3873 | /* |
| 3874 | Check if there are some access rights for database and user |
| 3875 | */ |
| 3876 | if (ACL_DB *acl_db= acl_db_find(db,user, host, ip, db_is_pattern)) |
| 3877 | { |
| 3878 | db_access= acl_db->access; |
| 3879 | if (acl_db->host.hostname) |
| 3880 | goto exit; // Fully specified. Take it |
| 3881 | /* the host table is not used for roles */ |
| 3882 | if ((!host || !host[0]) && !acl_db->host.hostname && |
| 3883 | find_acl_role(Lex_cstring_strlen(user), false)) |
| 3884 | goto exit; |
| 3885 | } |
| 3886 | |
| 3887 | if (!db_access) |
| 3888 | goto exit; // Can't be better |
| 3889 | |
| 3890 | /* |
no test coverage detected