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, 2020, 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-1335  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 
access_denied_error_code(int passwd_used)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 bool get_show_user(THD *thd, LEX_USER *lex_user, const char **username,
258                    const char **hostname, const char **rolename);
259 void mysql_show_grants_get_fields(THD *thd, List<Item> *fields,
260                                   const char *name, size_t length);
261 bool mysql_show_grants(THD *thd, LEX_USER *user);
262 bool mysql_show_create_user(THD *thd, LEX_USER *user);
263 int fill_schema_enabled_roles(THD *thd, TABLE_LIST *tables, COND *cond);
264 int fill_schema_applicable_roles(THD *thd, TABLE_LIST *tables, COND *cond);
265 void get_privilege_desc(char *to, uint max_length, ulong access);
266 void get_mqh(const char *user, const char *host, USER_CONN *uc);
267 bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role);
268 bool mysql_drop_user(THD *thd, List <LEX_USER> &list, bool handle_as_role);
269 bool mysql_rename_user(THD *thd, List <LEX_USER> &list);
270 int mysql_alter_user(THD *thd, List <LEX_USER> &list);
271 bool mysql_revoke_all(THD *thd, List <LEX_USER> &list);
272 void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant,
273                                      const char *db, const char *table);
274 bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name,
275                           const Sp_handler *sph);
276 bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
277                          const Sp_handler *sph);
278 bool check_routine_level_acl(THD *thd, const char *db, const char *name,
279                              const Sp_handler *sph);
280 bool is_acl_user(const char *host, const char *user);
281 int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
282 int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
283 int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
284 int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
285 int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr);
286 
287 /**
288   Result of an access check for an internal schema or table.
289   Internal ACL checks are always performed *before* using
290   the grant tables.
291   This mechanism enforces that the server implementation has full
292   control on its internal tables.
293   Depending on the internal check result, the server implementation
294   can choose to:
295   - always allow access,
296   - always deny access,
297   - delegate the decision to the database administrator,
298   by using the grant tables.
299 */
300 enum ACL_internal_access_result
301 {
302   /**
303     Access granted for all the requested privileges,
304     do not use the grant tables.
305     This flag is used only for the INFORMATION_SCHEMA privileges,
306     for compatibility reasons.
307   */
308   ACL_INTERNAL_ACCESS_GRANTED,
309   /** Access denied, do not use the grant tables. */
310   ACL_INTERNAL_ACCESS_DENIED,
311   /** No decision yet, use the grant tables. */
312   ACL_INTERNAL_ACCESS_CHECK_GRANT
313 };
314 
315 /**
316   Per internal table ACL access rules.
317   This class is an interface.
318   Per table(s) specific access rule should be implemented in a subclass.
319   @sa ACL_internal_schema_access
320 */
321 class ACL_internal_table_access
322 {
323 public:
ACL_internal_table_access()324   ACL_internal_table_access()
325   {}
326 
~ACL_internal_table_access()327   virtual ~ACL_internal_table_access()
328   {}
329 
330   /**
331     Check access to an internal table.
332     When a privilege is granted, this method add the requested privilege
333     to save_priv.
334     @param want_access the privileges requested
335     @param [in, out] save_priv the privileges granted
336     @return
337       @retval ACL_INTERNAL_ACCESS_GRANTED All the requested privileges
338       are granted, and saved in save_priv.
339       @retval ACL_INTERNAL_ACCESS_DENIED At least one of the requested
340       privileges was denied.
341       @retval ACL_INTERNAL_ACCESS_CHECK_GRANT No requested privilege
342       was denied, and grant should be checked for at least one
343       privilege. Requested privileges that are granted, if any, are saved
344       in save_priv.
345   */
346   virtual ACL_internal_access_result check(ulong want_access,
347                                            ulong *save_priv) const= 0;
348 };
349 
350 /**
351   Per internal schema ACL access rules.
352   This class is an interface.
353   Each per schema specific access rule should be implemented
354   in a different subclass, and registered.
355   Per schema access rules can control:
356   - every schema privileges on schema.*
357   - every table privileges on schema.table
358   @sa ACL_internal_schema_registry
359 */
360 class ACL_internal_schema_access
361 {
362 public:
ACL_internal_schema_access()363   ACL_internal_schema_access()
364   {}
365 
~ACL_internal_schema_access()366   virtual ~ACL_internal_schema_access()
367   {}
368 
369   /**
370     Check access to an internal schema.
371     @param want_access the privileges requested
372     @param [in, out] save_priv the privileges granted
373     @return
374       @retval ACL_INTERNAL_ACCESS_GRANTED All the requested privileges
375       are granted, and saved in save_priv.
376       @retval ACL_INTERNAL_ACCESS_DENIED At least one of the requested
377       privileges was denied.
378       @retval ACL_INTERNAL_ACCESS_CHECK_GRANT No requested privilege
379       was denied, and grant should be checked for at least one
380       privilege. Requested privileges that are granted, if any, are saved
381       in save_priv.
382   */
383   virtual ACL_internal_access_result check(ulong want_access,
384                                            ulong *save_priv) const= 0;
385 
386   /**
387     Search for per table ACL access rules by table name.
388     @param name the table name
389     @return per table access rules, or NULL
390   */
391   virtual const ACL_internal_table_access *lookup(const char *name) const= 0;
392 };
393 
394 /**
395   A registry for per internal schema ACL.
396   An 'internal schema' is a database schema maintained by the
397   server implementation, such as 'performance_schema' and 'INFORMATION_SCHEMA'.
398 */
399 class ACL_internal_schema_registry
400 {
401 public:
402   static void register_schema(const LEX_CSTRING *name,
403                               const ACL_internal_schema_access *access);
404   static const ACL_internal_schema_access *lookup(const char *name);
405 };
406 
407 const ACL_internal_schema_access *
408 get_cached_schema_access(GRANT_INTERNAL_INFO *grant_internal_info,
409                          const char *schema_name);
410 
411 const ACL_internal_table_access *
412 get_cached_table_access(GRANT_INTERNAL_INFO *grant_internal_info,
413                         const char *schema_name,
414                         const char *table_name);
415 
416 bool acl_check_proxy_grant_access (THD *thd, const char *host, const char *user,
417                                    bool with_grant);
418 int acl_setrole(THD *thd, const char *rolename, ulonglong access);
419 int acl_check_setrole(THD *thd, const char *rolename, ulonglong *access);
420 int acl_check_set_default_role(THD *thd, const char *host, const char *user,
421                                const char *role);
422 int acl_set_default_role(THD *thd, const char *host, const char *user,
423                          const char *rolename);
424 
425 extern SHOW_VAR acl_statistics[];
426 
427 /* Check if a role is granted to a user/role.
428 
429    If hostname == NULL, search for a role as the starting grantee.
430 */
431 bool check_role_is_granted(const char *username,
432                            const char *hostname,
433                            const char *rolename);
434 
435 #ifndef DBUG_OFF
436 extern ulong role_global_merges, role_db_merges, role_table_merges,
437              role_column_merges, role_routine_merges;
438 #endif
439 #endif /* SQL_ACL_INCLUDED */
440