1 /* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
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
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #define MYSQL_SERVER  "We need security context"
24 
25 #include <sql_class.h>                      /* THD, Security context */
26 #include <sql_acl.h>                        /* SUPER_ACL */
27 
28 #include "security_context_wrapper.h"
29 
30 namespace connection_control
31 {
32   /**
33     Security_context_wrapper constructor.
34 
35     @param [in] thd    Handle to THD
36 
37     Get security context from thd.
38   */
Security_context_wrapper(MYSQL_THD thd)39   Security_context_wrapper::Security_context_wrapper(MYSQL_THD thd)
40   {
41     m_valid= thd->security_ctx ? true : false;
42     m_thd= thd;
43   }
44 
45 
46   /**
47     Get value for given property from security context
48 
49     @param [in] property    Property to be checked
50     @param [out] value      Value of the property
51 
52     @returns status of property check
53       @retval true Error fetching property value
54       @retval false value contains valid value for given property
55   */
56 
57   bool
get_property(const char * property,LEX_CSTRING * value)58   Security_context_wrapper::get_property(const char *property, LEX_CSTRING *value)
59   {
60     value->length=0;
61     value->str= 0;
62 
63     if (!m_valid || !property)
64       return true;
65     else
66     {
67       if (!strcmp(property, "priv_user"))
68       {
69         compile_time_assert (sizeof(m_thd->security_ctx->priv_user) / sizeof(void*) > 1);
70         value->str= m_thd->security_ctx->priv_user;
71         value->length= strlen(value->str);
72       }
73       else if (!strcmp(property, "priv_host"))
74       {
75         compile_time_assert (sizeof(m_thd->security_ctx->priv_host) / sizeof(void*) > 1);
76         value->str= m_thd->security_ctx->priv_host;
77         value->length= strlen(value->str);
78       }
79       else if (!strcmp(property, "user"))
80       {
81         if (m_thd->security_ctx->user)
82         {
83           value->str= m_thd->security_ctx->user;
84           value->length= strlen(value->str);
85         }
86       }
87       else if (!strcmp(property, "proxy_user"))
88       {
89         compile_time_assert (sizeof(m_thd->security_ctx->proxy_user) / sizeof(void*) > 1);
90         value->str= m_thd->security_ctx->proxy_user;
91         value->length= strlen(value->str);
92       }
93       else if (!strcmp(property, "host"))
94       {
95         if (m_thd->security_ctx->get_host()->length())
96         {
97           value->str= m_thd->security_ctx->get_host()->c_ptr();
98           value->length= strlen(value->str);
99         }
100       }
101       else if (!strcmp(property, "ip"))
102       {
103         if (m_thd->security_ctx->get_ip()->length())
104         {
105           value->str= m_thd->security_ctx->get_ip()->c_ptr();
106           value->length= strlen(value->str);
107         }
108       }
109       else
110       {
111         return true;
112       }
113     }
114     return false;
115   }
116 
117 
118   /**  Get proxy user information from security context */
119 
120   const char *
get_proxy_user()121     Security_context_wrapper::get_proxy_user()
122   {
123     LEX_CSTRING proxy_user;
124     if (get_property("proxy_user", &proxy_user))
125       return 0;
126     return proxy_user.str;
127   }
128 
129 
130   /** Get priv user information from security context */
131 
132   const char *
get_priv_user()133     Security_context_wrapper::get_priv_user()
134   {
135     LEX_CSTRING priv_user;
136     if (get_property("priv_user", &priv_user))
137       return 0;
138     return priv_user.str;
139   }
140 
141 
142   /** Get priv host information from security context */
143 
144   const char *
get_priv_host()145     Security_context_wrapper::get_priv_host()
146   {
147     LEX_CSTRING priv_host;
148     if (get_property("priv_host", &priv_host))
149       return 0;
150     return priv_host.str;
151   }
152 
153 
154   /** Get connected user information from security context */
155 
156   const char *
get_user()157     Security_context_wrapper::get_user()
158   {
159     LEX_CSTRING user;
160     if (get_property("user", &user))
161       return 0;
162     return user.str;
163   }
164 
165 
166   /** Get connected host information from security context */
167 
168   const char *
get_host()169     Security_context_wrapper::get_host()
170   {
171     /*
172       We can't use thd->security_ctx->priv_host_name()
173       because it returns "%" if hostname is empty.
174       However, thd->security_ctx->proxy_user won't have
175       "%" if hostname was empty.
176 
177       To be consistent, we will always use
178       'user'@'host'/''@'host'/''@'' type of representation.
179     */
180     LEX_CSTRING host;
181     if (get_property("host", &host))
182       return 0;
183     return host.str;
184   }
185 
186 
187   /** Get connected ip information from security context */
188 
189   const char *
get_ip()190     Security_context_wrapper::get_ip()
191   {
192     LEX_CSTRING ip;
193     if (get_property("ip", &ip))
194       return 0;
195     return ip.str;
196   }
197 
198 
199   /** Check if valid security context exists for give THD or not */
200 
201   bool
security_context_exists()202     Security_context_wrapper::security_context_exists()
203   {
204     return m_valid;
205   }
206 
207 
208   /** Check whether user has requried privilege or not */
209 
210   bool
is_super_user()211     Security_context_wrapper::is_super_user()
212   {
213     if (!m_valid)
214       return false;
215 
216     bool has_super= ((m_thd->security_ctx->master_access & SUPER_ACL) == SUPER_ACL);
217 
218     return has_super;
219   }
220 }
221