1 /* Copyright (c) 2010, 2021, Oracle and/or its affiliates.
2 
3   This program is free software; you can redistribute it and/or modify
4   it under the terms of the GNU General Public License, version 2.0,
5   as published by the Free Software Foundation.
6 
7   This program is also distributed with certain software (including
8   but not limited to OpenSSL) that is licensed under separate terms,
9   as designated in a particular file or component or in included license
10   documentation.  The authors of MySQL hereby grant you an additional
11   permission to link the program and your derivative works with the
12   separately licensed software that they have included with MySQL.
13 
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License, version 2.0, for more details.
18 
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software Foundation,
21   51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22 
23 /**
24   @file storage/perfschema/pfs_setup_actor.cc
25   Performance schema setup actor (implementation).
26 */
27 
28 #include "my_global.h"
29 #include "my_sys.h"
30 #include "my_base.h"
31 #include "pfs.h"
32 #include "pfs_stat.h"
33 #include "pfs_instr.h"
34 #include "pfs_setup_actor.h"
35 #include "pfs_account.h"
36 #include "pfs_global.h"
37 #include "pfs_buffer_container.h"
38 
39 /**
40   @addtogroup Performance_schema_buffers
41   @{
42 */
43 
44 /** Hash table for setup_actor records. */
45 LF_HASH setup_actor_hash;
46 /** True if @c setup_actor_hash is initialized. */
47 static bool setup_actor_hash_inited= false;
48 
49 /**
50   Initialize the setup actor buffers.
51   @param param                        sizing parameters
52   @return 0 on success
53 */
init_setup_actor(const PFS_global_param * param)54 int init_setup_actor(const PFS_global_param *param)
55 {
56   return global_setup_actor_container.init(param->m_setup_actor_sizing);
57 }
58 
59 /** Cleanup all the setup actor buffers. */
cleanup_setup_actor(void)60 void cleanup_setup_actor(void)
61 {
62   global_setup_actor_container.cleanup();
63 }
64 
65 C_MODE_START
setup_actor_hash_get_key(const uchar * entry,size_t * length,my_bool)66 static uchar *setup_actor_hash_get_key(const uchar *entry, size_t *length,
67                                        my_bool)
68 {
69   const PFS_setup_actor * const *typed_entry;
70   const PFS_setup_actor *setup_actor;
71   const void *result;
72   typed_entry= reinterpret_cast<const PFS_setup_actor* const *> (entry);
73   assert(typed_entry != NULL);
74   setup_actor= *typed_entry;
75   assert(setup_actor != NULL);
76   *length= setup_actor->m_key.m_key_length;
77   result= setup_actor->m_key.m_hash_key;
78   return const_cast<uchar*> (reinterpret_cast<const uchar*> (result));
79 }
80 C_MODE_END
81 
82 /**
83   Initialize the setup actor hash.
84   @return 0 on success
85 */
init_setup_actor_hash(const PFS_global_param * param)86 int init_setup_actor_hash(const PFS_global_param *param)
87 {
88   if ((! setup_actor_hash_inited) && (param->m_setup_actor_sizing != 0))
89   {
90     lf_hash_init(&setup_actor_hash, sizeof(PFS_setup_actor*), LF_HASH_UNIQUE,
91                  0, 0, setup_actor_hash_get_key, &my_charset_bin);
92     /* setup_actor_hash.size= param->m_setup_actor_sizing; */
93     setup_actor_hash_inited= true;
94   }
95   return 0;
96 }
97 
98 /** Cleanup the setup actor hash. */
cleanup_setup_actor_hash(void)99 void cleanup_setup_actor_hash(void)
100 {
101   if (setup_actor_hash_inited)
102   {
103     lf_hash_destroy(&setup_actor_hash);
104     setup_actor_hash_inited= false;
105   }
106 }
107 
get_setup_actor_hash_pins(PFS_thread * thread)108 static LF_PINS* get_setup_actor_hash_pins(PFS_thread *thread)
109 {
110   if (unlikely(thread->m_setup_actor_hash_pins == NULL))
111   {
112     if (! setup_actor_hash_inited)
113       return NULL;
114     thread->m_setup_actor_hash_pins= lf_hash_get_pins(&setup_actor_hash);
115   }
116   return thread->m_setup_actor_hash_pins;
117 }
118 
set_setup_actor_key(PFS_setup_actor_key * key,const char * user,uint user_length,const char * host,uint host_length,const char * role,uint role_length)119 static void set_setup_actor_key(PFS_setup_actor_key *key,
120                                 const char *user, uint user_length,
121                                 const char *host, uint host_length,
122                                 const char *role, uint role_length)
123 {
124   assert(user_length <= USERNAME_LENGTH);
125   assert(host_length <= HOSTNAME_LENGTH);
126 
127   char *ptr= &key->m_hash_key[0];
128   memcpy(ptr, user, user_length);
129   ptr+= user_length;
130   ptr[0]= 0;
131   ptr++;
132   memcpy(ptr, host, host_length);
133   ptr+= host_length;
134   ptr[0]= 0;
135   ptr++;
136   memcpy(ptr, role, role_length);
137   ptr+= role_length;
138   ptr[0]= 0;
139   ptr++;
140   key->m_key_length= ptr - &key->m_hash_key[0];
141 }
142 
insert_setup_actor(const String * user,const String * host,const String * role,bool enabled,bool history)143 int insert_setup_actor(const String *user, const String *host, const String *role,
144                        bool enabled, bool history)
145 {
146   PFS_thread *thread= PFS_thread::get_current_thread();
147   if (unlikely(thread == NULL))
148     return HA_ERR_OUT_OF_MEM;
149 
150   LF_PINS *pins= get_setup_actor_hash_pins(thread);
151   if (unlikely(pins == NULL))
152     return HA_ERR_OUT_OF_MEM;
153 
154   PFS_setup_actor *pfs;
155   pfs_dirty_state dirty_state;
156 
157   pfs= global_setup_actor_container.allocate(& dirty_state);
158   if (pfs != NULL)
159   {
160     set_setup_actor_key(&pfs->m_key,
161                         user->ptr(), user->length(),
162                         host->ptr(), host->length(),
163                         role->ptr(), role->length());
164     pfs->m_username= &pfs->m_key.m_hash_key[0];
165     pfs->m_username_length= user->length();
166     pfs->m_hostname= pfs->m_username + pfs->m_username_length + 1;
167     pfs->m_hostname_length= host->length();
168     pfs->m_rolename= pfs->m_hostname + pfs->m_hostname_length + 1;
169     pfs->m_rolename_length= role->length();
170     pfs->m_enabled= enabled;
171     pfs->m_history= history;
172 
173     int res;
174     pfs->m_lock.dirty_to_allocated(& dirty_state);
175     res= lf_hash_insert(&setup_actor_hash, pins, &pfs);
176     if (likely(res == 0))
177     {
178       update_setup_actors_derived_flags();
179       return 0;
180     }
181 
182     global_setup_actor_container.deallocate(pfs);
183 
184     if (res > 0)
185       return HA_ERR_FOUND_DUPP_KEY;
186     return HA_ERR_OUT_OF_MEM;
187   }
188 
189   return HA_ERR_RECORD_FILE_FULL;
190 }
191 
delete_setup_actor(const String * user,const String * host,const String * role)192 int delete_setup_actor(const String *user, const String *host, const String *role)
193 {
194   PFS_thread *thread= PFS_thread::get_current_thread();
195   if (unlikely(thread == NULL))
196     return HA_ERR_OUT_OF_MEM;
197 
198   LF_PINS* pins= get_setup_actor_hash_pins(thread);
199   if (unlikely(pins == NULL))
200     return HA_ERR_OUT_OF_MEM;
201 
202   PFS_setup_actor_key key;
203   set_setup_actor_key(&key,
204                       user->ptr(), user->length(),
205                       host->ptr(), host->length(),
206                       role->ptr(), role->length());
207 
208   PFS_setup_actor **entry;
209   entry= reinterpret_cast<PFS_setup_actor**>
210     (lf_hash_search(&setup_actor_hash, pins, key.m_hash_key, key.m_key_length));
211 
212   if (entry && (entry != MY_ERRPTR))
213   {
214     PFS_setup_actor *pfs= *entry;
215     lf_hash_delete(&setup_actor_hash, pins, key.m_hash_key, key.m_key_length);
216     global_setup_actor_container.deallocate(pfs);
217   }
218 
219   lf_hash_search_unpin(pins);
220 
221   update_setup_actors_derived_flags();
222 
223   return 0;
224 }
225 
226 class Proc_reset_setup_actor
227   : public PFS_buffer_processor<PFS_setup_actor>
228 {
229 public:
Proc_reset_setup_actor(LF_PINS * pins)230   Proc_reset_setup_actor(LF_PINS* pins)
231     : m_pins(pins)
232   {}
233 
operator ()(PFS_setup_actor * pfs)234   virtual void operator()(PFS_setup_actor *pfs)
235   {
236     lf_hash_delete(&setup_actor_hash, m_pins,
237                    pfs->m_key.m_hash_key, pfs->m_key.m_key_length);
238 
239     global_setup_actor_container.deallocate(pfs);
240   }
241 
242 private:
243   LF_PINS* m_pins;
244 };
245 
reset_setup_actor()246 int reset_setup_actor()
247 {
248   PFS_thread *thread= PFS_thread::get_current_thread();
249   if (unlikely(thread == NULL))
250     return HA_ERR_OUT_OF_MEM;
251 
252   LF_PINS* pins= get_setup_actor_hash_pins(thread);
253   if (unlikely(pins == NULL))
254     return HA_ERR_OUT_OF_MEM;
255 
256   Proc_reset_setup_actor proc(pins);
257   // FIXME: delete helper instead
258   global_setup_actor_container.apply(proc);
259 
260   update_setup_actors_derived_flags();
261 
262   return 0;
263 }
264 
setup_actor_count()265 long setup_actor_count()
266 {
267   return setup_actor_hash.count;
268 }
269 
270 /*
271   - '%' should be replaced by NULL in table SETUP_ACTOR
272   - add an ENABLED column to include/exclude patterns, more flexible
273   - the principle is similar to SETUP_OBJECTS
274 */
lookup_setup_actor(PFS_thread * thread,const char * user,uint user_length,const char * host,uint host_length,bool * enabled,bool * history)275 void lookup_setup_actor(PFS_thread *thread,
276                         const char *user, uint user_length,
277                         const char *host, uint host_length,
278                         bool *enabled, bool *history)
279 {
280   PFS_setup_actor_key key;
281   PFS_setup_actor **entry;
282   int i;
283 
284   LF_PINS* pins= get_setup_actor_hash_pins(thread);
285   if (unlikely(pins == NULL))
286   {
287     *enabled= false;
288     *history= false;
289     return;
290   }
291 
292   for (i= 1; i<=4; i++)
293   {
294     /*
295       WL#988 Roles is not implemented, so we do not have a role name.
296       Looking up "%" in SETUP_ACTORS.ROLE.
297     */
298     switch(i)
299     {
300     case 1:
301       set_setup_actor_key(&key, user, user_length, host, host_length, "%", 1);
302       break;
303     case 2:
304       set_setup_actor_key(&key, user, user_length, "%", 1, "%", 1);
305       break;
306     case 3:
307       set_setup_actor_key(&key, "%", 1, host, host_length, "%", 1);
308       break;
309     case 4:
310       set_setup_actor_key(&key, "%", 1, "%", 1, "%", 1);
311       break;
312     }
313     entry= reinterpret_cast<PFS_setup_actor**>
314       (lf_hash_search(&setup_actor_hash, pins, key.m_hash_key, key.m_key_length));
315 
316     if (entry && (entry != MY_ERRPTR))
317     {
318       PFS_setup_actor *pfs= *entry;
319       lf_hash_search_unpin(pins);
320       *enabled= pfs->m_enabled;
321       *history= pfs->m_history;
322       return;
323     }
324 
325     lf_hash_search_unpin(pins);
326   }
327   *enabled= false;
328   *history= false;
329   return;
330 }
331 
update_setup_actors_derived_flags()332 int update_setup_actors_derived_flags()
333 {
334   PFS_thread *thread= PFS_thread::get_current_thread();
335   if (unlikely(thread == NULL))
336     return HA_ERR_OUT_OF_MEM;
337 
338   update_accounts_derived_flags(thread);
339   return 0;
340 }
341 
342 /** @} */
343