1 | #ifndef SQL_ACL_INCLUDED |
2 | #define SQL_ACL_INCLUDED |
3 | |
4 | /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. |
5 | Copyright (c) 2017, MariaDB Corporation. |
6 | |
7 | This program is free software; you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by |
9 | the Free Software Foundation; version 2 of the License. |
10 | |
11 | This program is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | GNU General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU General Public License |
17 | along with this program; if not, write to the Free Software |
18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
19 | |
20 | #include "violite.h" /* SSL_type */ |
21 | #include "sql_class.h" /* LEX_COLUMN */ |
22 | |
23 | #define SELECT_ACL (1UL << 0) |
24 | #define INSERT_ACL (1UL << 1) |
25 | #define UPDATE_ACL (1UL << 2) |
26 | #define DELETE_ACL (1UL << 3) |
27 | #define CREATE_ACL (1UL << 4) |
28 | #define DROP_ACL (1UL << 5) |
29 | #define RELOAD_ACL (1UL << 6) |
30 | #define SHUTDOWN_ACL (1UL << 7) |
31 | #define PROCESS_ACL (1UL << 8) |
32 | #define FILE_ACL (1UL << 9) |
33 | #define GRANT_ACL (1UL << 10) |
34 | #define REFERENCES_ACL (1UL << 11) |
35 | #define INDEX_ACL (1UL << 12) |
36 | #define ALTER_ACL (1UL << 13) |
37 | #define SHOW_DB_ACL (1UL << 14) |
38 | #define SUPER_ACL (1UL << 15) |
39 | #define CREATE_TMP_ACL (1UL << 16) |
40 | #define LOCK_TABLES_ACL (1UL << 17) |
41 | #define EXECUTE_ACL (1UL << 18) |
42 | #define REPL_SLAVE_ACL (1UL << 19) |
43 | #define REPL_CLIENT_ACL (1UL << 20) |
44 | #define CREATE_VIEW_ACL (1UL << 21) |
45 | #define SHOW_VIEW_ACL (1UL << 22) |
46 | #define CREATE_PROC_ACL (1UL << 23) |
47 | #define ALTER_PROC_ACL (1UL << 24) |
48 | #define CREATE_USER_ACL (1UL << 25) |
49 | #define EVENT_ACL (1UL << 26) |
50 | #define TRIGGER_ACL (1UL << 27) |
51 | #define CREATE_TABLESPACE_ACL (1UL << 28) |
52 | #define DELETE_HISTORY_ACL (1UL << 29) |
53 | /* |
54 | don't forget to update |
55 | 1. static struct show_privileges_st sys_privileges[] |
56 | 2. static const char *command_array[] and static uint command_lengths[] |
57 | 3. mysql_system_tables.sql and mysql_system_tables_fix.sql |
58 | 4. acl_init() or whatever - to define behaviour for old privilege tables |
59 | 5. sql_yacc.yy - for GRANT/REVOKE to work |
60 | */ |
61 | #define NO_ACCESS (1UL << 30) |
62 | #define DB_ACLS \ |
63 | (UPDATE_ACL | SELECT_ACL | INSERT_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \ |
64 | GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL | CREATE_TMP_ACL | \ |
65 | LOCK_TABLES_ACL | EXECUTE_ACL | CREATE_VIEW_ACL | SHOW_VIEW_ACL | \ |
66 | CREATE_PROC_ACL | ALTER_PROC_ACL | EVENT_ACL | TRIGGER_ACL | \ |
67 | DELETE_HISTORY_ACL) |
68 | |
69 | #define TABLE_ACLS \ |
70 | (SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \ |
71 | GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL | CREATE_VIEW_ACL | \ |
72 | SHOW_VIEW_ACL | TRIGGER_ACL | DELETE_HISTORY_ACL) |
73 | |
74 | #define COL_ACLS \ |
75 | (SELECT_ACL | INSERT_ACL | UPDATE_ACL | REFERENCES_ACL) |
76 | |
77 | #define PROC_ACLS \ |
78 | (ALTER_PROC_ACL | EXECUTE_ACL | GRANT_ACL) |
79 | |
80 | #define SHOW_PROC_ACLS \ |
81 | (ALTER_PROC_ACL | EXECUTE_ACL | CREATE_PROC_ACL) |
82 | |
83 | #define GLOBAL_ACLS \ |
84 | (SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \ |
85 | RELOAD_ACL | SHUTDOWN_ACL | PROCESS_ACL | FILE_ACL | GRANT_ACL | \ |
86 | REFERENCES_ACL | INDEX_ACL | ALTER_ACL | SHOW_DB_ACL | SUPER_ACL | \ |
87 | CREATE_TMP_ACL | LOCK_TABLES_ACL | REPL_SLAVE_ACL | REPL_CLIENT_ACL | \ |
88 | EXECUTE_ACL | CREATE_VIEW_ACL | SHOW_VIEW_ACL | CREATE_PROC_ACL | \ |
89 | ALTER_PROC_ACL | CREATE_USER_ACL | EVENT_ACL | TRIGGER_ACL | \ |
90 | CREATE_TABLESPACE_ACL | DELETE_HISTORY_ACL) |
91 | |
92 | #define DEFAULT_CREATE_PROC_ACLS \ |
93 | (ALTER_PROC_ACL | EXECUTE_ACL) |
94 | |
95 | #define SHOW_CREATE_TABLE_ACLS \ |
96 | (SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL | \ |
97 | CREATE_ACL | DROP_ACL | ALTER_ACL | INDEX_ACL | \ |
98 | TRIGGER_ACL | REFERENCES_ACL | GRANT_ACL | CREATE_VIEW_ACL | SHOW_VIEW_ACL) |
99 | |
100 | /** |
101 | Table-level privileges which are automatically "granted" to everyone on |
102 | existing temporary tables (CREATE_ACL is necessary for ALTER ... RENAME). |
103 | */ |
104 | #define TMP_TABLE_ACLS \ |
105 | (SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \ |
106 | INDEX_ACL | ALTER_ACL) |
107 | |
108 | /* |
109 | Defines to change the above bits to how things are stored in tables |
110 | This is needed as the 'host' and 'db' table is missing a few privileges |
111 | */ |
112 | |
113 | /* Privileges that needs to be reallocated (in continous chunks) */ |
114 | #define DB_CHUNK0 (SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL | \ |
115 | CREATE_ACL | DROP_ACL) |
116 | #define DB_CHUNK1 (GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL) |
117 | #define DB_CHUNK2 (CREATE_TMP_ACL | LOCK_TABLES_ACL) |
118 | #define DB_CHUNK3 (CREATE_VIEW_ACL | SHOW_VIEW_ACL | \ |
119 | CREATE_PROC_ACL | ALTER_PROC_ACL ) |
120 | #define DB_CHUNK4 (EXECUTE_ACL) |
121 | #define DB_CHUNK5 (EVENT_ACL | TRIGGER_ACL) |
122 | #define DB_CHUNK6 (DELETE_HISTORY_ACL) |
123 | |
124 | #define fix_rights_for_db(A) (((A) & DB_CHUNK0) | \ |
125 | (((A) << 4) & DB_CHUNK1) | \ |
126 | (((A) << 6) & DB_CHUNK2) | \ |
127 | (((A) << 9) & DB_CHUNK3) | \ |
128 | (((A) << 2) & DB_CHUNK4) | \ |
129 | (((A) << 9) & DB_CHUNK5) | \ |
130 | (((A) << 10) & DB_CHUNK6)) |
131 | #define get_rights_for_db(A) (((A) & DB_CHUNK0) | \ |
132 | (((A) & DB_CHUNK1) >> 4) | \ |
133 | (((A) & DB_CHUNK2) >> 6) | \ |
134 | (((A) & DB_CHUNK3) >> 9) | \ |
135 | (((A) & DB_CHUNK4) >> 2) | \ |
136 | (((A) & DB_CHUNK5) >> 9) | \ |
137 | (((A) & DB_CHUNK6) >> 10)) |
138 | #define TBL_CHUNK0 DB_CHUNK0 |
139 | #define TBL_CHUNK1 DB_CHUNK1 |
140 | #define TBL_CHUNK2 (CREATE_VIEW_ACL | SHOW_VIEW_ACL) |
141 | #define TBL_CHUNK3 TRIGGER_ACL |
142 | #define TBL_CHUNK4 (DELETE_HISTORY_ACL) |
143 | #define fix_rights_for_table(A) (((A) & TBL_CHUNK0) | \ |
144 | (((A) << 4) & TBL_CHUNK1) | \ |
145 | (((A) << 11) & TBL_CHUNK2) | \ |
146 | (((A) << 15) & TBL_CHUNK3) | \ |
147 | (((A) << 16) & TBL_CHUNK4)) |
148 | #define get_rights_for_table(A) (((A) & TBL_CHUNK0) | \ |
149 | (((A) & TBL_CHUNK1) >> 4) | \ |
150 | (((A) & TBL_CHUNK2) >> 11) | \ |
151 | (((A) & TBL_CHUNK3) >> 15) | \ |
152 | (((A) & TBL_CHUNK4) >> 16)) |
153 | #define fix_rights_for_column(A) (((A) & 7) | (((A) & ~7) << 8)) |
154 | #define get_rights_for_column(A) (((A) & 7) | ((A) >> 8)) |
155 | #define fix_rights_for_procedure(A) ((((A) << 18) & EXECUTE_ACL) | \ |
156 | (((A) << 23) & ALTER_PROC_ACL) | \ |
157 | (((A) << 8) & GRANT_ACL)) |
158 | #define get_rights_for_procedure(A) ((((A) & EXECUTE_ACL) >> 18) | \ |
159 | (((A) & ALTER_PROC_ACL) >> 23) | \ |
160 | (((A) & GRANT_ACL) >> 8)) |
161 | |
162 | enum mysql_db_table_field |
163 | { |
164 | MYSQL_DB_FIELD_HOST = 0, |
165 | MYSQL_DB_FIELD_DB, |
166 | MYSQL_DB_FIELD_USER, |
167 | MYSQL_DB_FIELD_SELECT_PRIV, |
168 | MYSQL_DB_FIELD_INSERT_PRIV, |
169 | MYSQL_DB_FIELD_UPDATE_PRIV, |
170 | MYSQL_DB_FIELD_DELETE_PRIV, |
171 | MYSQL_DB_FIELD_CREATE_PRIV, |
172 | MYSQL_DB_FIELD_DROP_PRIV, |
173 | MYSQL_DB_FIELD_GRANT_PRIV, |
174 | MYSQL_DB_FIELD_REFERENCES_PRIV, |
175 | MYSQL_DB_FIELD_INDEX_PRIV, |
176 | MYSQL_DB_FIELD_ALTER_PRIV, |
177 | MYSQL_DB_FIELD_CREATE_TMP_TABLE_PRIV, |
178 | MYSQL_DB_FIELD_LOCK_TABLES_PRIV, |
179 | MYSQL_DB_FIELD_CREATE_VIEW_PRIV, |
180 | MYSQL_DB_FIELD_SHOW_VIEW_PRIV, |
181 | MYSQL_DB_FIELD_CREATE_ROUTINE_PRIV, |
182 | MYSQL_DB_FIELD_ALTER_ROUTINE_PRIV, |
183 | MYSQL_DB_FIELD_EXECUTE_PRIV, |
184 | MYSQL_DB_FIELD_EVENT_PRIV, |
185 | MYSQL_DB_FIELD_TRIGGER_PRIV, |
186 | MYSQL_DB_FIELD_DELETE_VERSIONING_ROWS_PRIV, |
187 | MYSQL_DB_FIELD_COUNT |
188 | }; |
189 | |
190 | extern const TABLE_FIELD_DEF mysql_db_table_def; |
191 | extern bool mysql_user_table_is_in_short_password_format; |
192 | |
193 | extern LEX_CSTRING host_not_specified; |
194 | extern LEX_CSTRING current_user; |
195 | extern LEX_CSTRING current_role; |
196 | extern LEX_CSTRING current_user_and_current_role; |
197 | |
198 | |
199 | static inline int access_denied_error_code(int passwd_used) |
200 | { |
201 | #ifdef mysqld_error_find_printf_error_used |
202 | return 0; |
203 | #else |
204 | return passwd_used == 2 ? ER_ACCESS_DENIED_NO_PASSWORD_ERROR |
205 | : ER_ACCESS_DENIED_ERROR; |
206 | #endif |
207 | } |
208 | |
209 | /* prototypes */ |
210 | |
211 | bool hostname_requires_resolving(const char *hostname); |
212 | bool acl_init(bool dont_read_acl_tables); |
213 | bool acl_reload(THD *thd); |
214 | void acl_free(bool end=0); |
215 | ulong acl_get(const char *host, const char *ip, |
216 | const char *user, const char *db, my_bool db_is_pattern); |
217 | bool acl_authenticate(THD *thd, uint com_change_user_pkt_len); |
218 | bool acl_getroot(Security_context *sctx, const char *user, const char *host, |
219 | const char *ip, const char *db); |
220 | bool acl_check_host(const char *host, const char *ip); |
221 | bool check_change_password(THD *thd, LEX_USER *user); |
222 | bool change_password(THD *thd, LEX_USER *user); |
223 | |
224 | bool mysql_grant_role(THD *thd, List<LEX_USER> &user_list, bool revoke); |
225 | bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &user_list, |
226 | ulong rights, bool revoke, bool is_proxy); |
227 | int mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list, |
228 | List <LEX_COLUMN> &column_list, ulong rights, |
229 | bool revoke); |
230 | bool mysql_routine_grant(THD *thd, TABLE_LIST *table, const Sp_handler *sph, |
231 | List <LEX_USER> &user_list, ulong rights, |
232 | bool revoke, bool write_to_binlog); |
233 | bool grant_init(); |
234 | void grant_free(void); |
235 | bool grant_reload(THD *thd); |
236 | bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, |
237 | bool any_combination_will_do, uint number, bool no_errors); |
238 | bool check_grant_column (THD *thd, GRANT_INFO *grant, |
239 | const char *db_name, const char *table_name, |
240 | const char *name, size_t length, Security_context *sctx); |
241 | bool check_column_grant_in_table_ref(THD *thd, TABLE_LIST * table_ref, |
242 | const char *name, size_t length, Field *fld); |
243 | bool check_grant_all_columns(THD *thd, ulong want_access, |
244 | Field_iterator_table_ref *fields); |
245 | bool check_grant_routine(THD *thd, ulong want_access, |
246 | TABLE_LIST *procs, const Sp_handler *sph, |
247 | bool no_error); |
248 | bool check_grant_db(THD *thd,const char *db); |
249 | bool check_global_access(THD *thd, ulong want_access, bool no_errors= false); |
250 | bool check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, |
251 | GRANT_INTERNAL_INFO *grant_internal_info, |
252 | bool dont_check_global_grants, bool no_errors); |
253 | ulong get_table_grant(THD *thd, TABLE_LIST *table); |
254 | ulong get_column_grant(THD *thd, GRANT_INFO *grant, |
255 | const char *db_name, const char *table_name, |
256 | const char *field_name); |
257 | void mysql_show_grants_get_fields(THD *thd, List<Item> *fields, |
258 | const char *name, size_t length); |
259 | bool mysql_show_grants(THD *thd, LEX_USER *user); |
260 | bool mysql_show_create_user(THD *thd, LEX_USER *user); |
261 | int fill_schema_enabled_roles(THD *thd, TABLE_LIST *tables, COND *cond); |
262 | int fill_schema_applicable_roles(THD *thd, TABLE_LIST *tables, COND *cond); |
263 | void get_privilege_desc(char *to, uint max_length, ulong access); |
264 | void get_mqh(const char *user, const char *host, USER_CONN *uc); |
265 | bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role); |
266 | bool mysql_drop_user(THD *thd, List <LEX_USER> &list, bool handle_as_role); |
267 | bool mysql_rename_user(THD *thd, List <LEX_USER> &list); |
268 | int mysql_alter_user(THD *thd, List <LEX_USER> &list); |
269 | bool mysql_revoke_all(THD *thd, List <LEX_USER> &list); |
270 | void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, |
271 | const char *db, const char *table); |
272 | bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, |
273 | const Sp_handler *sph); |
274 | bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, |
275 | const Sp_handler *sph); |
276 | bool check_routine_level_acl(THD *thd, const char *db, const char *name, |
277 | const Sp_handler *sph); |
278 | bool is_acl_user(const char *host, const char *user); |
279 | int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond); |
280 | int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond); |
281 | int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond); |
282 | int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond); |
283 | int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr); |
284 | |
285 | /** |
286 | Result of an access check for an internal schema or table. |
287 | Internal ACL checks are always performed *before* using |
288 | the grant tables. |
289 | This mechanism enforces that the server implementation has full |
290 | control on its internal tables. |
291 | Depending on the internal check result, the server implementation |
292 | can choose to: |
293 | - always allow access, |
294 | - always deny access, |
295 | - delegate the decision to the database administrator, |
296 | by using the grant tables. |
297 | */ |
298 | enum ACL_internal_access_result |
299 | { |
300 | /** |
301 | Access granted for all the requested privileges, |
302 | do not use the grant tables. |
303 | This flag is used only for the INFORMATION_SCHEMA privileges, |
304 | for compatibility reasons. |
305 | */ |
306 | ACL_INTERNAL_ACCESS_GRANTED, |
307 | /** Access denied, do not use the grant tables. */ |
308 | ACL_INTERNAL_ACCESS_DENIED, |
309 | /** No decision yet, use the grant tables. */ |
310 | ACL_INTERNAL_ACCESS_CHECK_GRANT |
311 | }; |
312 | |
313 | /** |
314 | Per internal table ACL access rules. |
315 | This class is an interface. |
316 | Per table(s) specific access rule should be implemented in a subclass. |
317 | @sa ACL_internal_schema_access |
318 | */ |
319 | class ACL_internal_table_access |
320 | { |
321 | public: |
322 | ACL_internal_table_access() |
323 | {} |
324 | |
325 | virtual ~ACL_internal_table_access() |
326 | {} |
327 | |
328 | /** |
329 | Check access to an internal table. |
330 | When a privilege is granted, this method add the requested privilege |
331 | to save_priv. |
332 | @param want_access the privileges requested |
333 | @param [in, out] save_priv the privileges granted |
334 | @return |
335 | @retval ACL_INTERNAL_ACCESS_GRANTED All the requested privileges |
336 | are granted, and saved in save_priv. |
337 | @retval ACL_INTERNAL_ACCESS_DENIED At least one of the requested |
338 | privileges was denied. |
339 | @retval ACL_INTERNAL_ACCESS_CHECK_GRANT No requested privilege |
340 | was denied, and grant should be checked for at least one |
341 | privilege. Requested privileges that are granted, if any, are saved |
342 | in save_priv. |
343 | */ |
344 | virtual ACL_internal_access_result check(ulong want_access, |
345 | ulong *save_priv) const= 0; |
346 | }; |
347 | |
348 | /** |
349 | Per internal schema ACL access rules. |
350 | This class is an interface. |
351 | Each per schema specific access rule should be implemented |
352 | in a different subclass, and registered. |
353 | Per schema access rules can control: |
354 | - every schema privileges on schema.* |
355 | - every table privileges on schema.table |
356 | @sa ACL_internal_schema_registry |
357 | */ |
358 | class ACL_internal_schema_access |
359 | { |
360 | public: |
361 | ACL_internal_schema_access() |
362 | {} |
363 | |
364 | virtual ~ACL_internal_schema_access() |
365 | {} |
366 | |
367 | /** |
368 | Check access to an internal schema. |
369 | @param want_access the privileges requested |
370 | @param [in, out] save_priv the privileges granted |
371 | @return |
372 | @retval ACL_INTERNAL_ACCESS_GRANTED All the requested privileges |
373 | are granted, and saved in save_priv. |
374 | @retval ACL_INTERNAL_ACCESS_DENIED At least one of the requested |
375 | privileges was denied. |
376 | @retval ACL_INTERNAL_ACCESS_CHECK_GRANT No requested privilege |
377 | was denied, and grant should be checked for at least one |
378 | privilege. Requested privileges that are granted, if any, are saved |
379 | in save_priv. |
380 | */ |
381 | virtual ACL_internal_access_result check(ulong want_access, |
382 | ulong *save_priv) const= 0; |
383 | |
384 | /** |
385 | Search for per table ACL access rules by table name. |
386 | @param name the table name |
387 | @return per table access rules, or NULL |
388 | */ |
389 | virtual const ACL_internal_table_access *lookup(const char *name) const= 0; |
390 | }; |
391 | |
392 | /** |
393 | A registry for per internal schema ACL. |
394 | An 'internal schema' is a database schema maintained by the |
395 | server implementation, such as 'performance_schema' and 'INFORMATION_SCHEMA'. |
396 | */ |
397 | class ACL_internal_schema_registry |
398 | { |
399 | public: |
400 | static void register_schema(const LEX_CSTRING *name, |
401 | const ACL_internal_schema_access *access); |
402 | static const ACL_internal_schema_access *lookup(const char *name); |
403 | }; |
404 | |
405 | const ACL_internal_schema_access * |
406 | get_cached_schema_access(GRANT_INTERNAL_INFO *grant_internal_info, |
407 | const char *schema_name); |
408 | |
409 | const ACL_internal_table_access * |
410 | get_cached_table_access(GRANT_INTERNAL_INFO *grant_internal_info, |
411 | const char *schema_name, |
412 | const char *table_name); |
413 | |
414 | bool acl_check_proxy_grant_access (THD *thd, const char *host, const char *user, |
415 | bool with_grant); |
416 | int acl_setrole(THD *thd, const char *rolename, ulonglong access); |
417 | int acl_check_setrole(THD *thd, const char *rolename, ulonglong *access); |
418 | int acl_check_set_default_role(THD *thd, const char *host, const char *user); |
419 | int acl_set_default_role(THD *thd, const char *host, const char *user, |
420 | const char *rolename); |
421 | |
422 | extern SHOW_VAR acl_statistics[]; |
423 | |
424 | /* Check if a role is granted to a user/role. |
425 | |
426 | If hostname == NULL, search for a role as the starting grantee. |
427 | */ |
428 | bool check_role_is_granted(const char *username, |
429 | const char *hostname, |
430 | const char *rolename); |
431 | |
432 | #ifndef DBUG_OFF |
433 | extern ulong role_global_merges, role_db_merges, role_table_merges, |
434 | role_column_merges, role_routine_merges; |
435 | #endif |
436 | #endif /* SQL_ACL_INCLUDED */ |
437 | |