File authenticate.c¶
File List > cubrid > src > object > authenticate.c
Go to the documentation of this file
/*
* Copyright 2008 Search Solution Corporation
* Copyright 2016 CUBRID Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/*
* authenticate.c - Authorization manager
*/
#ident "$Id$"
/*
* Note:
* Need to remove calls to the db_ layer since there are some
* nasty dependency problems during restart and when the server
* crashes since we need to touch objects before the database is
* officially open.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <stack>
#include "porting.h"
#include "misc_string.h"
#include "memory_alloc.h"
#include "dbtype.h"
#include "error_manager.h"
#include "work_space.h"
#include "object_primitive.h"
#include "class_object.h"
#include "schema_manager.h"
#include "authenticate.h"
#include "object_accessor.h"
#include "encryption.h"
#include "crypt_opfunc.h"
#include "message_catalog.h"
#include "string_opfunc.h"
#include "transaction_cl.h"
#include "db.h"
#include "transform.h"
#include "schema_system_catalog_constants.h"
#include "environment_variable.h"
#include "object_print.h"
#include "optimizer.h"
#include "network_interface_cl.h"
#include "printer.hpp"
#include "authenticate_access_auth.hpp"
#include "authenticate_cache.hpp"
#include "authenticate_grant.hpp"
#if defined (SUPPRESS_STRLEN_WARNING)
#define strlen(s1) ((int) strlen(s1))
#endif /* defined (SUPPRESS_STRLEN_WARNING) */
#if defined(SA_MODE)
#include "catalog_class.h"
#endif /* SA_MODE */
/* Macro to determine if a name is system catalog class */
/*
*
*
*
*/
static authenticate_context *au_ctx_obj = nullptr;
int
au_login (const char *name, const char *password, bool ignore_dba_privilege)
{
return au_ctx ()->login (name, password, ignore_dba_privilege);
}
authenticate_context *
au_ctx (void)
{
if (au_ctx_obj == nullptr)
{
au_ctx_obj = new authenticate_context ();
}
return au_ctx_obj;
}
/*
* DB_ EXTENSION FUNCTIONS
*/
/*
* au_get_set
* return: error code
* obj(in):
* attname(in):
* set(in):
*/
int
au_get_set (MOP obj, const char *attname, DB_SET ** set)
{
int error = NO_ERROR;
DB_VALUE value;
*set = NULL;
error = obj_get (obj, attname, &value);
if (error == NO_ERROR)
{
if (!TP_IS_SET_TYPE (DB_VALUE_TYPE (&value)))
{
error = ER_OBJ_DOMAIN_CONFLICT;
}
else
{
if (DB_IS_NULL (&value))
{
*set = NULL;
}
else
{
*set = db_get_set (&value);
}
/*
* since we almost ALWAYS end up iterating through the sets fetching
* objects, do a vector fetch immediately to avoid
* multiple server calls.
* Should have a sub db_ function for doing this.
*/
if (*set != NULL)
{
error = db_fetch_set (*set, DB_FETCH_READ, 0);
if (error == NO_ERROR)
{
error = set_filter (*set);
}
/*
* shoudl be detecting the filtered elements and marking the
* object dirty if possible
*/
}
}
}
return (error);
}
/*
* au_get_object
* return: error code
* obj(in):
* attname(in):
* mop_ptr(in):
*/
int
au_get_object (MOP obj, const char *attname, MOP * mop_ptr)
{
int error = NO_ERROR;
DB_VALUE value;
*mop_ptr = NULL;
error = obj_get (obj, attname, &value);
if (error == NO_ERROR)
{
if (DB_VALUE_TYPE (&value) != DB_TYPE_OBJECT)
{
error = ER_OBJ_DOMAIN_CONFLICT;
}
else
{
if (DB_IS_NULL (&value))
{
*mop_ptr = NULL;
}
else
{
*mop_ptr = db_get_object (&value);
}
}
}
return (error);
}
/*
* au_set_get_obj -
* return: error code
* set(in):
* index(in):
* obj(out):
*/
int
au_set_get_obj (DB_SET * set, int index, MOP * obj)
{
int error = NO_ERROR;
DB_VALUE value;
*obj = NULL;
error = set_get_element (set, index, &value);
if (error == NO_ERROR)
{
if (DB_VALUE_TYPE (&value) != DB_TYPE_OBJECT)
{
error = ER_OBJ_DOMAIN_CONFLICT;
}
else
{
if (DB_IS_NULL (&value))
{
*obj = NULL;
}
else
{
*obj = db_get_object (&value);
}
}
}
return error;
}
/*
* au_dump_auth() - Prints authorization info for all users.
* return: none
* fp(in): output file
*
* Note: The db_root class used to have a user attribute which was a set
* containing the object-id for all users. The users attribute has been
* eliminated for performance reasons. A query on the db_user class is
* new used to find all users.
*/
void
au_dump_auth (FILE * fp)
{
MOP user, auth;
char *query;
DB_QUERY_RESULT *query_result;
DB_QUERY_ERROR query_error;
int error;
DB_VALUE user_val;
const char *qp1 = "select [%s] from [%s];";
query = (char *) malloc (strlen (qp1) + strlen (AU_USER_CLASS_NAME) * 2);
if (query)
{
sprintf (query, qp1, AU_USER_CLASS_NAME, AU_USER_CLASS_NAME);
error = db_compile_and_execute_local (query, &query_result, &query_error);
/* error is row count if not negative. */
if (error > 0)
{
while (db_query_next_tuple (query_result) == DB_CURSOR_SUCCESS)
{
if (db_query_get_tuple_value (query_result, 0, &user_val) == NO_ERROR)
{
user = db_get_object (&user_val);
if (au_get_object (user, "authorization", &auth) == NO_ERROR)
{
au_print_grants (auth, fp);
}
}
}
}
if (error >= 0)
{
db_query_end (query_result);
}
free_and_init (query);
}
}
/*
* au_dump_user() - Dumps authorization information for a
* particular user to a file.
* return: none
* user(in): user object
* fp(in): file pointer
*/
void
au_dump_user (MOP user, FILE * fp)
{
DB_VALUE value;
DB_SET *groups = NULL;
MOP auth;
int i, card;
if (obj_get (user, "name", &value) == NO_ERROR)
{
fprintf (fp, msgcat_message (MSGCAT_CATALOG_CUBRID, MSGCAT_SET_AUTHORIZATION, MSGCAT_AUTH_USER_NAME),
db_get_string (&value));
pr_clear_value (&value);
}
groups = NULL;
if (au_get_set (user, "direct_groups", &groups) == NO_ERROR)
{
fprintf (fp, msgcat_message (MSGCAT_CATALOG_CUBRID, MSGCAT_SET_AUTHORIZATION, MSGCAT_AUTH_USER_DIRECT_GROUPS));
card = set_cardinality (groups);
for (i = 0; i < card; i++)
{
if (set_get_element (groups, i, &value) == NO_ERROR)
{
if (obj_get (db_get_object (&value), "name", &value) == NO_ERROR)
{
fprintf (fp, "%s ", db_get_string (&value));
pr_clear_value (&value);
}
}
}
fprintf (fp, "\n");
set_free (groups);
}
groups = NULL;
if (au_get_set (user, "groups", &groups) == NO_ERROR)
{
fprintf (fp, msgcat_message (MSGCAT_CATALOG_CUBRID, MSGCAT_SET_AUTHORIZATION, MSGCAT_AUTH_USER_GROUPS));
card = set_cardinality (groups);
for (i = 0; i < card; i++)
{
if (set_get_element (groups, i, &value) == NO_ERROR)
{
if (obj_get (db_get_object (&value), "name", &value) == NO_ERROR)
{
fprintf (fp, "%s ", db_get_string (&value));
pr_clear_value (&value);
}
}
}
fprintf (fp, "\n");
set_free (groups);
}
/* dump local grants */
if (au_get_object (user, "authorization", &auth) == NO_ERROR)
{
au_print_grants (auth, fp);
}
/*
* need to do a walk back through the group hierarchy and collect all
* inherited grants and their origins
*/
}
/*
* au_dump_to_file() - Dump all authorization information including
* user/group hierarchy.
* return: none
* fp(in): file pointer
*
* Note: The db_root class used to have a user attribute which was a set
* containing the object-id for all users. The users attribute has been
* eliminated for performance reasons. A query on the db_user class is
* new used to find all users.
*/
void
au_dump_to_file (FILE * fp)
{
MOP user;
DB_VALUE value;
char *query = NULL;
DB_QUERY_RESULT *query_result = NULL;
DB_QUERY_ERROR query_error;
int error = NO_ERROR;
DB_VALUE user_val;
const char *qp1 = "select [%s] from [%s];";
/* NOTE: We should be getting the real user name here ! */
fprintf (fp, msgcat_message (MSGCAT_CATALOG_CUBRID, MSGCAT_SET_AUTHORIZATION, MSGCAT_AUTH_CURRENT_USER),
Au_user_name);
query = (char *) malloc (strlen (qp1) + strlen (AU_USER_CLASS_NAME) * 2);
if (query)
{
sprintf (query, qp1, AU_USER_CLASS_NAME, AU_USER_CLASS_NAME);
error = db_compile_and_execute_local (query, &query_result, &query_error);
/* error is row count if not negative. */
if (error > 0)
{
fprintf (fp, msgcat_message (MSGCAT_CATALOG_CUBRID, MSGCAT_SET_AUTHORIZATION, MSGCAT_AUTH_ROOT_USERS));
while (db_query_next_tuple (query_result) == DB_CURSOR_SUCCESS)
{
if (db_query_get_tuple_value (query_result, 0, &user_val) == NO_ERROR)
{
user = db_get_object (&user_val);
if (obj_get (user, "name", &value) == NO_ERROR)
{
fprintf (fp, "%s ", db_get_string (&value));
pr_clear_value (&value);
}
}
}
fprintf (fp, "\n");
if (db_query_first_tuple (query_result) == DB_CURSOR_SUCCESS)
{
do
{
if (db_query_get_tuple_value (query_result, 0, &user_val) == NO_ERROR)
{
user = db_get_object (&user_val);
au_dump_user (user, fp);
}
}
while (db_query_next_tuple (query_result) == DB_CURSOR_SUCCESS);
}
fprintf (fp, "\n");
}
}
if (error >= 0 && query)
{
db_query_end (query_result);
}
if (query)
{
free_and_init (query);
}
fprintf (fp, msgcat_message (MSGCAT_CATALOG_CUBRID, MSGCAT_SET_AUTHORIZATION, MSGCAT_AUTH_AUTH_TITLE));
au_dump_auth (fp);
}
/*
* au_dump() -
* return: none
*/
void
au_dump (void)
{
au_dump_to_file (stdout);
}
/*
* au_check_serial_authorization - check whether the current user is able to
* modify serial object or not
* return: NO_ERROR if available, otherwise error code
* serial_object(in): serial object pointer
*/
int
au_check_serial_authorization (MOP serial_object)
{
DB_VALUE creator_val;
int ret_val;
ret_val = db_get (serial_object, "owner", &creator_val);
if (ret_val != NO_ERROR)
{
return ret_val;
}
assert (!DB_IS_NULL (&creator_val));
ret_val = au_check_owner (&creator_val);
if (ret_val != NO_ERROR)
{
ret_val = ER_QPROC_CANNOT_UPDATE_SERIAL;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ret_val, 0);
}
pr_clear_value (&creator_val);
return ret_val;
}
int
au_check_server_authorization (MOP server_object)
{
DB_VALUE creator_val;
int ret_val;
ret_val = db_get (server_object, "owner", &creator_val);
if (ret_val != NO_ERROR || DB_IS_NULL (&creator_val))
{
return ret_val;
}
ret_val = au_check_owner (&creator_val);
if (ret_val != NO_ERROR)
{
ret_val = ER_DBLINK_CANNOT_UPDATE_SERVER;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ret_val, 0);
}
pr_clear_value (&creator_val);
return ret_val;
}
bool
au_is_server_authorized_user (DB_VALUE * owner_val)
{
return (au_check_owner (owner_val) == NO_ERROR);
}
void
au_disable_passwords (void)
{
AU_DISABLE_PASSWORDS ();
}