/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SQL_SECURITY_CTX_SERVICE_INCLUDED #define SQL_SECURITY_CTX_SERVICE_INCLUDED #ifndef NO_EMBEDDED_ACCESS_CHECKS #include "auth_common.h" #include "sql_class.h" #include #define MY_SVC_TRUE 1 #define MY_SVC_FALSE 0 /** Gets the security context for the thread. @param[in] thd The thread to get the context from @param[out] out_ctx placeholder for the security context handle @retval true failure @retval false success */ my_svc_bool thd_get_security_context(MYSQL_THD _thd, MYSQL_SECURITY_CONTEXT *out_ctx) { THD *thd= dynamic_cast(_thd); try { if (out_ctx) *out_ctx= thd->security_context(); else return MY_SVC_TRUE; return MY_SVC_FALSE; } catch (...) { return MY_SVC_FALSE; } } /** Sets a new security context for the thread. @param[in] thd The thread to set the context to @param[in] ctx The handle of the new security context @retval true failure @retval false success */ my_svc_bool thd_set_security_context(MYSQL_THD _thd, MYSQL_SECURITY_CONTEXT in_ctx) { THD *thd= dynamic_cast(_thd); try { if (in_ctx) thd->set_security_context(in_ctx); return MY_SVC_FALSE; } catch (...) { return MY_SVC_TRUE; } } /** Creates a new security context and initializes it with the defaults (no access, no user etc). @param[out] out_ctx placeholder for the newly created security context handle @retval true failure @retval false success */ my_svc_bool security_context_create(MYSQL_SECURITY_CONTEXT *out_ctx) { try { if (out_ctx) *out_ctx= new Security_context(); return MY_SVC_FALSE; } catch (...) { return MY_SVC_TRUE; } } /** Deallocates a security context. @param[in] ctx The handle of the security context to destroy @retval true failure @retval false success */ my_svc_bool security_context_destroy(MYSQL_SECURITY_CONTEXT ctx) { try { delete ctx; return MY_SVC_FALSE; } catch (...) { return MY_SVC_TRUE; } } /** Duplicates a security context. @param[in] ctx The handle of the security context to copy @param[out] out_ctx placeholder for the handle of the copied security context @retval true failure @retval false success */ my_svc_bool security_context_copy(MYSQL_SECURITY_CONTEXT in_ctx, MYSQL_SECURITY_CONTEXT *out_ctx) { try { if (out_ctx) { *out_ctx= new Security_context(); if (in_ctx) **out_ctx= *in_ctx; } return MY_SVC_FALSE; } catch (...) { return MY_SVC_TRUE; } } /** Looks up in the defined user accounts an account based on the user@host[ip] combo supplied and checks if the user has access to the database requested. The lookup is done in exactly the same way as at login time. @param[in] ctx The handle of the security context to update @param[in] user The user name to look up @param[in] host The host name to look up @param[in] ip The ip of the incoming connection @param[in] db The database to check access to @retval true failure @retval false success */ my_svc_bool security_context_lookup(MYSQL_SECURITY_CONTEXT ctx, const char *user, const char *host, const char *ip, const char *db) { return acl_getroot(ctx, (char *) user, (char *) host, (char *) ip, db) ? TRUE : FALSE; } /** Reads a named security context attribute and retuns its value. Currently defined names are: user MYSQL_LEX_CSTRING * login user (a.k.a. the user's part of USER()) host MYSQL_LEX_CSTRING * login host (a.k.a. the host's part of USER()) ip MYSQL_LEX_CSTRING * login client ip host_or_ip MYSQL_LEX_CSTRING * host, if present, ip if not. priv_user MYSQL_LEX_CSTRING * authenticated user (a.k.a. the user's part of CURRENT_USER()) priv_host MYSQL_LEX_CSTRING * authenticated host (a.k.a. the host's part of CURRENT_USER()) proxy_user MYSQL_LEX_CSTRING * the proxy user used in authenticating privilege_super my_svc_bool * 1 if the user account has supper privilege, 0 otherwise privilege_execute my_svc_bool * 1 if the user account has execute privilege, 0 otherwise @param[in] ctx The handle of the security context to read from @param[in] name The option name to read @param[out] value The value of the option. Type depens on the name. @retval true failure @retval false success */ my_svc_bool security_context_get_option(MYSQL_SECURITY_CONTEXT ctx, const char *name, void *inout_pvalue) { try { if (inout_pvalue) { if (!strcmp(name, "user")) { *((MYSQL_LEX_CSTRING *)inout_pvalue)= ctx->user(); } else if (!strcmp(name, "host")) { *((MYSQL_LEX_CSTRING *) inout_pvalue)= ctx->host(); } else if (!strcmp(name, "ip")) { *((MYSQL_LEX_CSTRING *) inout_pvalue)= ctx->ip(); } else if (!strcmp(name, "host_or_ip")) { *((MYSQL_LEX_CSTRING *) inout_pvalue)= ctx->host_or_ip(); } else if (!strcmp(name, "priv_user")) { *((MYSQL_LEX_CSTRING *) inout_pvalue)= ctx->priv_user(); } else if (!strcmp(name, "priv_host")) { *((MYSQL_LEX_CSTRING *) inout_pvalue)= ctx->priv_host(); } else if (!strcmp(name, "proxy_user")) { *((MYSQL_LEX_CSTRING *) inout_pvalue)= ctx->proxy_user(); } else if (!strcmp(name, "external_user")) { *((MYSQL_LEX_CSTRING *) inout_pvalue)= ctx->external_user(); } else if (!strcmp(name, "privilege_super")) { bool checked= ctx->check_access(SUPER_ACL); *((my_svc_bool *) inout_pvalue)= checked ? MY_SVC_TRUE : MY_SVC_FALSE; } else if (!strcmp(name, "privilege_execute")) { bool checked= ctx->check_access(EXECUTE_ACL); *((my_svc_bool *) inout_pvalue)= checked ? MY_SVC_TRUE : MY_SVC_FALSE; } else return MY_SVC_TRUE; /** invalid option */ } return MY_SVC_FALSE; } catch (...) { return MY_SVC_TRUE; } } /** Sets a value for a named security context attribute Currently defined names are: user MYSQL_LEX_CSTRING * login user (a.k.a. the user's part of USER()) host MYSQL_LEX_CSTRING * login host (a.k.a. the host's part of USER()) ip MYSQL_LEX_CSTRING * login client ip priv_user MYSQL_LEX_CSTRING * authenticated user (a.k.a. the user's part of CURRENT_USER()) priv_host MYSQL_LEX_CSTRING * authenticated host (a.k.a. the host's part of CURRENT_USER()) proxy_user MYSQL_LEX_CSTRING * the proxy user used in authenticating privilege_super my_svc_bool * 1 if the user account has supper privilege, 0 otherwise privilege_execute my_svc_bool * 1 if the user account has execute privilege, 0 otherwise @param[in] ctx The handle of the security context to set into @param[in] name The option name to set @param[in] value The value of the option. Type depens on the name. @retval true failure @retval false success */ my_svc_bool security_context_set_option(MYSQL_SECURITY_CONTEXT ctx, const char *name, void *pvalue) { try { if (!strcmp(name, "user")) { LEX_CSTRING *value= (LEX_CSTRING *) pvalue; ctx->assign_user(value->str, value->length); } else if (!strcmp(name, "host")) { LEX_CSTRING *value= (LEX_CSTRING *) pvalue; ctx->assign_host(value->str, value->length); } else if (!strcmp(name, "ip")) { LEX_CSTRING *value= (LEX_CSTRING *) pvalue; ctx->assign_ip(value->str, value->length); } else if (!strcmp(name, "priv_user")) { LEX_CSTRING *value= (LEX_CSTRING *) pvalue; ctx->assign_priv_user(value->str, value->length); } else if (!strcmp(name, "priv_host")) { LEX_CSTRING *value= (LEX_CSTRING *) pvalue; ctx->assign_priv_host(value->str, value->length); } else if (!strcmp(name, "proxy_user")) { LEX_CSTRING *value= (LEX_CSTRING *) pvalue; ctx->assign_proxy_user(value->str, value->length); } else if (!strcmp(name, "privilege_super")) { my_svc_bool value= *(my_svc_bool *) pvalue; if (value) ctx->set_master_access(ctx->master_access() | (SUPER_ACL)); else ctx->set_master_access(ctx->master_access() & ~(SUPER_ACL)); } else if (!strcmp(name, "privilege_execute")) { my_svc_bool value= *(my_svc_bool *) pvalue; if (value) ctx->set_master_access(ctx->master_access() | (EXECUTE_ACL)); else ctx->set_master_access(ctx->master_access() & ~(EXECUTE_ACL)); } else return MY_SVC_TRUE; /** invalid option */ return MY_SVC_FALSE; } catch (...) { return MY_SVC_TRUE; } } #endif /* !NO_EMBEDDED_ACCESS_CHECKS */ #endif /* !SQL_SECURITY_CTX_SERVICE_INCLUDED */