1 #ifndef SQL_USER_CACHE_INCLUDED
2 #define SQL_USER_CACHE_INCLUDED
3 
4 /* Copyright (c) 2000, 2021, Oracle and/or its affiliates.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License, version 2.0,
8    as published by the Free Software Foundation.
9 
10    This program is also distributed with certain software (including
11    but not limited to OpenSSL) that is licensed under separate terms,
12    as designated in a particular file or component or in included license
13    documentation.  The authors of MySQL hereby grant you an additional
14    permission to link the program and your derivative works with the
15    separately licensed software that they have included with MySQL.
16 
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License, version 2.0, for more details.
21 
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software Foundation,
24    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
25 
26 #include "my_global.h"                  // NO_EMBEDDED_ACCESS_CHECKS
27 #include "my_sys.h"                     // wild_many, wild_one, wild_prefix
28 #include <string.h>                     // strchr
29 #include "mysql_com.h"                  // SCRAMBLE_LENGTH
30 #include "violite.h"                    // SSL_type
31 #include "hash_filo.h"                  // HASH, hash_filo
32 #include "records.h"                    // READ_RECORD
33 #include "partitioned_rwlock.h"         // Partitioned_rwlock
34 
35 #include "prealloced_array.h"
36 #include "log_event.h"
37 
38 /* Forward Declarations */
39 class String;
40 
41 /* Classes */
42 
43 class ACL_HOST_AND_IP
44 {
45   char *hostname;
46   size_t hostname_length;
47   long ip, ip_mask; // Used with masked ip:s
48 
49   const char *calc_ip(const char *ip_arg, long *val, char end);
50 
51 public:
get_host()52   const char *get_host() const { return hostname ? hostname : ""; }
get_host_len()53   size_t get_host_len() const { return hostname_length; }
54 
has_wildcard()55   bool has_wildcard()
56   {
57     return (strchr(hostname,wild_many) ||
58             strchr(hostname,wild_one)  || ip_mask );
59   }
60 
check_allow_all_hosts()61   bool check_allow_all_hosts()
62   {
63     return (!hostname ||
64             (hostname[0] == wild_many && !hostname[1]));
65   }
66 
67   void update_hostname(const char *host_arg);
68   bool compare_hostname(const char *host_arg, const char *ip_arg);
is_null()69   bool is_null() const { return hostname == NULL; }
70 };
71 
72 class ACL_ACCESS {
73 public:
74   ACL_HOST_AND_IP host;
75   ulong sort;
76   ulong access;
77 };
78 
79 /* ACL_HOST is used if no host is specified */
80 
81 class ACL_HOST :public ACL_ACCESS
82 {
83 public:
84   char *db;
85 };
86 
87 class ACL_USER :public ACL_ACCESS
88 {
89 public:
90   USER_RESOURCES user_resource;
91   char *user;
92   /**
93     The salt variable is used as the password hash for
94     native_password_authetication.
95   */
96   uint8 salt[SCRAMBLE_LENGTH + 1];       // scrambled password in binary form
97   /**
98     In the old protocol the salt_len indicated what type of autnetication
99     protocol was used: 0 - no password, 4 - 3.20, 8 - 4.0,  20 - 4.1.1
100   */
101   uint8 salt_len;
102   enum SSL_type ssl_type;
103   const char *ssl_cipher, *x509_issuer, *x509_subject;
104   LEX_CSTRING plugin;
105   LEX_STRING auth_string;
106   bool password_expired;
107   bool can_authenticate;
108   MYSQL_TIME password_last_changed;
109   uint password_lifetime;
110   bool use_default_password_lifetime;
111   /**
112     Specifies whether the user account is locked or unlocked.
113   */
114   bool account_locked;
115 
116   ACL_USER *copy(MEM_ROOT *root);
117 };
118 
119 class ACL_DB :public ACL_ACCESS
120 {
121 public:
122   char *user,*db;
123 };
124 
125 class ACL_PROXY_USER :public ACL_ACCESS
126 {
127   const char *user;
128   ACL_HOST_AND_IP proxied_host;
129   const char *proxied_user;
130   bool with_grant;
131 
132   typedef enum {
133     MYSQL_PROXIES_PRIV_HOST,
134     MYSQL_PROXIES_PRIV_USER,
135     MYSQL_PROXIES_PRIV_PROXIED_HOST,
136     MYSQL_PROXIES_PRIV_PROXIED_USER,
137     MYSQL_PROXIES_PRIV_WITH_GRANT,
138     MYSQL_PROXIES_PRIV_GRANTOR,
139     MYSQL_PROXIES_PRIV_TIMESTAMP } old_acl_proxy_users;
140 public:
ACL_PROXY_USER()141   ACL_PROXY_USER () {};
142 
143   void init(const char *host_arg, const char *user_arg,
144             const char *proxied_host_arg, const char *proxied_user_arg,
145             bool with_grant_arg);
146 
147   void init(MEM_ROOT *mem, const char *host_arg, const char *user_arg,
148             const char *proxied_host_arg, const char *proxied_user_arg,
149             bool with_grant_arg);
150 
151   void init(TABLE *table, MEM_ROOT *mem);
152 
get_with_grant()153   bool get_with_grant() { return with_grant; }
get_user()154   const char *get_user() { return user; }
get_proxied_user()155   const char *get_proxied_user() { return proxied_user; }
get_proxied_host()156   const char *get_proxied_host() { return proxied_host.get_host(); }
set_user(MEM_ROOT * mem,const char * user_arg)157   void set_user(MEM_ROOT *mem, const char *user_arg)
158   {
159     user= user_arg && *user_arg ? strdup_root(mem, user_arg) : NULL;
160   }
161 
162   void check_validity(bool check_no_resolve);
163 
164   bool matches(const char *host_arg, const char *user_arg, const char *ip_arg,
165                 const char *proxied_user_arg, bool any_proxy_user);
166 
auth_element_equals(const char * a,const char * b)167   inline static bool auth_element_equals(const char *a, const char *b)
168   {
169     return (a == b || (a != NULL && b != NULL && !strcmp(a,b)));
170   }
171 
172 
173   bool pk_equals(ACL_PROXY_USER *grant);
174 
granted_on(const char * host_arg,const char * user_arg)175   bool granted_on(const char *host_arg, const char *user_arg)
176   {
177     return (((!user && (!user_arg || !user_arg[0])) ||
178              (user && user_arg && !strcmp(user, user_arg))) &&
179             ((host.is_null() && (!host_arg || !host_arg[0])) ||
180              (!host.is_null() && host_arg && !strcmp(host.get_host(), host_arg))));
181   }
182 
183 
184   void print_grant(THD *thd, String *str);
185 
set_data(ACL_PROXY_USER * grant)186   void set_data(ACL_PROXY_USER *grant)
187   {
188     with_grant= grant->with_grant;
189   }
190 
191   static int store_pk(TABLE *table,
192                       const LEX_CSTRING &host,
193                       const LEX_CSTRING &user,
194                       const LEX_CSTRING &proxied_host,
195                       const LEX_CSTRING &proxied_user);
196 
197   static int store_with_grant(TABLE * table,
198                               bool with_grant);
199 
200   static int store_data_record(TABLE *table,
201                                const LEX_CSTRING &host,
202                                const LEX_CSTRING &user,
203                                const LEX_CSTRING &proxied_host,
204                                const LEX_CSTRING &proxied_user,
205                                bool with_grant,
206                                const char *grantor);
207 
get_user_length()208   size_t get_user_length() const { return user ? strlen(user) : 0; }
209 
get_proxied_user_length()210   size_t get_proxied_user_length() const {
211     return proxied_user ? strlen(proxied_user) : 0;
212   }
213 };
214 
215 #ifndef NO_EMBEDDED_ACCESS_CHECKS
216 
217 class acl_entry :public hash_filo_element
218 {
219 public:
220   ulong access;
221   uint16 length;
222   char key[1];                          // Key will be stored here
223 };
224 
225 
226 class GRANT_COLUMN :public Sql_alloc
227 {
228 public:
229   char *column;
230   ulong rights;
231   size_t key_length;
232   GRANT_COLUMN(String &c,  ulong y);
233 };
234 
235 
236 class GRANT_NAME :public Sql_alloc
237 {
238 public:
239   ACL_HOST_AND_IP host;
240   char *db, *user, *tname, *hash_key;
241   ulong privs;
242   ulong sort;
243   size_t key_length;
244   GRANT_NAME(const char *h, const char *d,const char *u,
245              const char *t, ulong p, bool is_routine);
246   GRANT_NAME (TABLE *form, bool is_routine);
~GRANT_NAME()247   virtual ~GRANT_NAME() {};
ok()248   virtual bool ok() { return privs != 0; }
249   void set_user_details(const char *h, const char *d,
250                         const char *u, const char *t,
251                         bool is_routine);
252 };
253 
254 
255 class GRANT_TABLE :public GRANT_NAME
256 {
257 public:
258   ulong cols;
259   HASH hash_columns;
260 
261   GRANT_TABLE(const char *h, const char *d,const char *u,
262               const char *t, ulong p, ulong c);
263   explicit GRANT_TABLE(TABLE *form);
264   bool init(TABLE *col_privs);
265   ~GRANT_TABLE();
ok()266   bool ok() { return privs != 0 || cols != 0; }
267 };
268 
269 
270 #endif /* NO_EMBEDDED_ACCESS_CHECKS */
271 
272 
273 /* Data Structures */
274 
275 #ifndef NO_EMBEDDED_ACCESS_CHECKS
276 extern MEM_ROOT global_acl_memory;
277 extern MEM_ROOT memex;
278 extern bool initialized;
279 const size_t ACL_PREALLOC_SIZE = 10U;
280 extern Prealloced_array<ACL_USER, ACL_PREALLOC_SIZE> *acl_users;
281 extern Prealloced_array<ACL_PROXY_USER, ACL_PREALLOC_SIZE> *acl_proxy_users;
282 extern Prealloced_array<ACL_DB, ACL_PREALLOC_SIZE> *acl_dbs;
283 extern Prealloced_array<ACL_HOST_AND_IP, ACL_PREALLOC_SIZE> *acl_wild_hosts;
284 extern HASH column_priv_hash, proc_priv_hash, func_priv_hash;
285 extern hash_filo *acl_cache;
286 extern HASH acl_check_hosts;
287 extern bool allow_all_hosts;
288 extern uint grant_version; /* Version of priv tables */
289 extern Partitioned_rwlock LOCK_grant;
290 
291 GRANT_NAME *name_hash_search(HASH *name_hash,
292                              const char *host,const char* ip,
293                              const char *db,
294                              const char *user, const char *tname,
295                              bool exact, bool name_tolower);
296 
routine_hash_search(const char * host,const char * ip,const char * db,const char * user,const char * tname,bool proc,bool exact)297 inline GRANT_NAME * routine_hash_search(const char *host, const char *ip,
298                                         const char *db, const char *user,
299                                         const char *tname, bool proc,
300                                         bool exact)
301 {
302   return (GRANT_TABLE*)
303     name_hash_search(proc ? &proc_priv_hash : &func_priv_hash,
304                      host, ip, db, user, tname, exact, TRUE);
305 }
306 
table_hash_search(const char * host,const char * ip,const char * db,const char * user,const char * tname,bool exact)307 inline GRANT_TABLE * table_hash_search(const char *host, const char *ip,
308                                        const char *db, const char *user,
309                                        const char *tname, bool exact)
310 {
311   return (GRANT_TABLE*) name_hash_search(&column_priv_hash, host, ip, db,
312                                          user, tname, exact, FALSE);
313 }
314 
column_hash_search(GRANT_TABLE * t,const char * cname,size_t length)315 inline GRANT_COLUMN * column_hash_search(GRANT_TABLE *t, const char *cname,
316                                          size_t length)
317 {
318   return (GRANT_COLUMN*) my_hash_search(&t->hash_columns,
319                                         (uchar*) cname, length);
320 }
321 
322 extern ACL_USER acl_utility_user;
323 
324 #endif /* NO_EMBEDDED_ACCESS_CHECKS */
325 
326 #endif /* SQL_USER_CACHE_INCLUDED */
327