File authenticate_context.cpp¶
File List > cubrid > src > object > authenticate_context.cpp
Go to the documentation of this file
/*
*
* 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_context.cpp -
*/
#include "authenticate_context.hpp"
#include "authenticate.h"
#include "authenticate_cache.hpp" /* init_caches */
#include "boot_cl.h" /* BOOT_IS_CLIENT_RESTARTED () */
#include "db.h"
#include "dbi.h"
#include "dbtype.h"
#include "error_manager.h"
#include "object_accessor.h" /* obj_ */
#include "object_primitive.h"
#include "schema_manager.h" /* sm_find_class() */
#include "schema_system_catalog_constants.h"
#include "locator_cl.h" /* locator_create_heap_if_needed () */
// static functions
static int au_add_method_check_authorization (void);
void
authenticate_context::reset (void)
{
root = nullptr;
root_class = nullptr;
authorization_class = nullptr;
user_class = nullptr;
password_class = nullptr;
current_user = nullptr;
public_user = nullptr;
dba_user = nullptr;
disable_auth_check = true;
ignore_passwords = false;
}
authenticate_context::authenticate_context (void) // au_init ()
: caches {}
{
init_ctx ();
}
authenticate_context::~authenticate_context ()
{
final_ctx ();
}
void
authenticate_context::init_ctx (void)
{
reset ();
caches.init ();
}
void
authenticate_context::final_ctx (void)
{
reset ();
/*
* could remove the static links here but it isn't necessary and
* we may need them again the next time we restart
*/
caches.flush ();
}
/*
* start - This is called during the bo_resteart initialization sequence
* after the database has been successfully opened
* return: error code
*
* Note: Here we initialize the authorization system by finding the system
* objects and validating the registered user.
*/
int
authenticate_context::start (void)
{
int error = NO_ERROR;
MOPLIST mops;
MOP class_mop;
/*
* NEED TO MAKE SURE THIS IS 1 IF THE SERVER CRASHED BECAUSE WE'RE
* GOING TO CALL db_ FUNCTIONS
*/
db_Connect_status = DB_CONNECTION_STATUS_CONNECTED;
/*
* It is important not to enable authorization until after the
* login is finished, otherwise the system will stop when it tries
* to validate the user when accessing the authorization objects.
*/
disable_auth_check = true;
/* locate the various system classes */
class_mop = sm_find_class (AU_ROOT_CLASS_NAME);
if (class_mop == NULL)
{
error = ER_AU_NO_AUTHORIZATION;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
return (error);
}
root_class = class_mop;
class_mop = sm_find_class (AU_AUTH_CLASS_NAME);
if (class_mop == NULL)
{
error = ER_AU_NO_AUTHORIZATION;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
return (error);
}
authorization_class = class_mop;
class_mop = sm_find_class (AU_USER_CLASS_NAME);
if (class_mop == NULL)
{
error = ER_AU_NO_AUTHORIZATION;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
return (error);
}
user_class = class_mop;
class_mop = sm_find_class (AU_PASSWORD_CLASS_NAME);
if (class_mop == NULL)
{
error = ER_AU_NO_AUTHORIZATION;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
return (error);
}
password_class = class_mop;
mops = db_get_all_objects (root_class);
if (mops == NULL)
{
error = ER_AU_NO_AUTHORIZATION;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
}
else
{
/* this shouldn't happen, not sure what to do */
if (mops->next != NULL)
{
error = ER_AU_MULTIPLE_ROOTS;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
}
root = mops->op;
db_objlist_free (mops);
public_user = au_find_user (AU_PUBLIC_USER_NAME);
dba_user = au_find_user (AU_DBA_USER_NAME);
if (public_user == NULL || dba_user == NULL)
{
error = er_errid ();
if (error != ER_LK_UNILATERALLY_ABORTED)
{
error = ER_AU_INCOMPLETE_AUTH;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
}
}
else
{
/*
* If you try to start the authorization system and
* there is no user logged in, you will automatically be logged in
* as "PUBLIC". Optionally, we could get a name from the
* cubrid.conf file or use the name of the current Unix user.
*/
if (strlen (user_name) == 0)
{
strcpy (user_name, AU_PUBLIC_USER_NAME);
}
error = perform_login (user_name, user_password_sha2_512, false);
}
}
/* make sure this is off */
disable_auth_check = false;
return (error);
}
/*
* login - Registers a user name and password for a database.
* return: error code
* name(in): user name
* password(in): password
* ignore_dba_privilege(in) : whether ignore DBA's privilege or not in login
*
* Note: If a database has already been restarted, the user will be validated
* immediately, otherwise the name and password are simply saved
* in global variables and the validation will ocurr the next time
* bo_restart is called.
*/
int
authenticate_context::login (const char *name, const char *password, bool ignore_dba_privilege)
{
int error = NO_ERROR;
int save;
/*
* because the database can be left open after authorization failure,
* checking Au_root for NULL isn't a reliable way to see of the database
* is in an "un-restarted" state. Instead, look at BOOT_IS_CLIENT_RESTARTED
* which is defined to return non-zero if a valid transaction is in
* progress.
*/
if (root == NULL || !BOOT_IS_CLIENT_RESTARTED ())
{
/*
* Save the name & password for later. Allow the name to be NULL
* and leave it unmodified.
*/
if (name != NULL)
{
if (strlen (name) >= DB_MAX_USER_LENGTH)
{
error = ER_USER_NAME_TOO_LONG;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
return error;
}
strcpy (user_name, name);
}
else
{
user_name[0] = '\0';
}
if (password == NULL || strlen (password) == 0)
{
strcpy (user_password_des_oldstyle, "");
strcpy (user_password_sha1, "");
strcpy (user_password_sha2_512, "");
}
else
{
/* store the password encrypted(DES and SHA1 both) so we don't have buffers lying around with the obvious
* passwords in it. */
encrypt_password (password, 1, user_password_des_oldstyle);
encrypt_password_sha1 (password, 1, user_password_sha1);
encrypt_password_sha2_512 (password, user_password_sha2_512);
}
}
else
{
/* Change users within an active database. */
AU_DISABLE (save);
error = perform_login (name, password, ignore_dba_privilege);
AU_ENABLE (save);
}
return (error);
}
/*
* au_install() - This is used to initialize the authorization system in a
* freshly created database.
* It should only be called within the createdb tool.
* return: error code
*/
int
authenticate_context::install (void)
{
MOP root_cls = NULL, user_cls = NULL, pass_cls = NULL, auth_cls = NULL;
SM_TEMPLATE *def;
AU_USER_CACHE *user_cache;
int exists, save, index;
AU_DISABLE (save);
/*
* create the system authorization objects, add attributes later since they
* have domain dependencies
*/
root_cls = db_create_class (AU_ROOT_CLASS_NAME);
user_cls = db_create_class (AU_USER_CLASS_NAME);
pass_cls = db_create_class (AU_PASSWORD_CLASS_NAME);
auth_cls = db_create_class (AU_AUTH_CLASS_NAME);
if (root_cls == NULL || user_cls == NULL || pass_cls == NULL || auth_cls == NULL)
{
goto exit_on_error;
}
sm_mark_system_class (root_cls, 1);
sm_mark_system_class (user_cls, 1);
sm_mark_system_class (pass_cls, 1);
sm_mark_system_class (auth_cls, 1);
/*
* db_root
*/
/*
* Authorization root, might not need this if we restrict the generation of
* user and group objects but could be useful in other ways.
*/
def = smt_edit_class_mop (root_cls, AU_ALTER);
if (def == NULL)
{
goto exit_on_error;
}
smt_add_attribute (def, "triggers", "sequence of (string, object)", (DB_DOMAIN *) 0);
smt_add_attribute (def, "charset", "integer", NULL);
smt_add_attribute (def, "lang", "string", NULL);
smt_add_attribute (def, "timezone_checksum", "string", NULL);
/* need signatures for these ! */
smt_add_class_method (def, "add_user", "au_add_user_method");
smt_add_class_method (def, "drop_user", "au_drop_user_method");
smt_add_class_method (def, "find_user", "au_find_user_method");
smt_assign_argument_domain (def, "find_user", true, NULL, 0, "string", (DB_DOMAIN *) 0);
smt_add_class_method (def, "print_authorizations", "au_describe_root_method");
smt_add_class_method (def, "info", "au_info_method");
smt_add_class_method (def, "change_owner", "au_change_owner_method");
smt_add_class_method (def, "change_trigger_owner", "au_change_trigger_owner_method");
smt_add_class_method (def, "get_owner", "au_get_owner_method");
smt_add_class_method (def, "change_sp_owner", "au_change_sp_owner_method");
if (sm_update_class (def, NULL) != NO_ERROR || locator_create_heap_if_needed (root_cls, false) == NULL)
{
goto exit_on_error;
}
/*
* db_user
*/
def = smt_edit_class_mop (user_cls, AU_ALTER);
if (def == NULL)
{
goto exit_on_error;
}
/* If the attribute configuration is changed, the CATCLS_USER_ATTR_IDX_NAME also be changed.
* - CATCLS_USER_ATTR_IDX_NAME is defined in the cubload::server_class_installer::locate_class () function.
*/
smt_add_attribute (def, "name", "string", (DB_DOMAIN *) 0);
smt_add_attribute (def, "id", "integer", (DB_DOMAIN *) 0);
smt_add_attribute (def, "password", AU_PASSWORD_CLASS_NAME, (DB_DOMAIN *) 0);
smt_add_attribute (def, "direct_groups", "set of (db_user)", (DB_DOMAIN *) 0);
smt_add_attribute (def, "groups", "set of (db_user)", (DB_DOMAIN *) 0);
smt_add_attribute (def, "authorization", AU_AUTH_CLASS_NAME, (DB_DOMAIN *) 0);
smt_add_attribute (def, "triggers", "sequence of object", (DB_DOMAIN *) 0);
smt_add_attribute (def, AU_USER_ATTR_IS_LOGINABLE, "integer", NULL);
smt_add_attribute (def, AU_USER_ATTR_IS_SYSTEM_CREATED, "integer", NULL);
smt_add_attribute (def, "comment", "varchar(1024)", NULL);
smt_add_attribute (def, "created_time", "datetime", NULL);
smt_add_attribute (def, "updated_time", "datetime", NULL);
/* need signatures for these */
smt_add_method (def, "set_password", "au_set_password_method");
smt_add_method (def, "set_password_encoded", "au_set_password_encoded_method");
smt_add_method (def, "set_password_encoded_sha1", "au_set_password_encoded_sha1_method");
smt_add_method (def, "add_member", "au_add_member_method");
smt_add_method (def, "drop_member", "au_drop_member_method");
smt_add_method (def, "print_authorizations", "au_describe_user_method");
smt_add_class_method (def, "add_user", "au_add_user_method");
smt_add_class_method (def, "drop_user", "au_drop_user_method");
smt_add_class_method (def, "find_user", "au_find_user_method");
smt_assign_argument_domain (def, "find_user", true, NULL, 0, "string", (DB_DOMAIN *) 0);
smt_add_class_method (def, "login", "au_login_method");
if (sm_update_class (def, NULL) != NO_ERROR || locator_create_heap_if_needed (user_cls, false) == NULL)
{
goto exit_on_error;
}
/* Add Unique Index */
{
const char *names[] = { "name", NULL };
if (db_add_constraint (user_cls, DB_CONSTRAINT_UNIQUE, NULL, names, 0) != NO_ERROR)
{
goto exit_on_error;
}
}
/*
* db_password
*/
def = smt_edit_class_mop (pass_cls, AU_ALTER);
if (def == NULL)
{
goto exit_on_error;
}
smt_add_attribute (def, "password", "string", (DB_DOMAIN *) 0);
if (sm_update_class (def, NULL) != NO_ERROR || locator_create_heap_if_needed (pass_cls, false) == NULL)
{
goto exit_on_error;
}
/*
* db_authorization
*/
/*
* Authorization object, the grant set could go directly in the user object
* but it might be better to keep it separate in order to use the special
* read-once lock for the authorization object only.
*/
def = smt_edit_class_mop (auth_cls, AU_ALTER);
if (def == NULL)
{
goto exit_on_error;
}
smt_add_attribute (def, "owner", AU_USER_CLASS_NAME, (DB_DOMAIN *) 0);
smt_add_attribute (def, "grants", "sequence", (DB_DOMAIN *) 0);
if (sm_update_class (def, NULL) != NO_ERROR || locator_create_heap_if_needed (auth_cls, false) == NULL)
{
goto exit_on_error;
}
/* Create the single authorization root object */
root = obj_create (root_cls);
if (root == NULL)
{
goto exit_on_error;
}
/* create the DBA user and assign ownership of the system classes */
dba_user = au_add_user (AU_DBA_USER_NAME, &exists);
if (dba_user == NULL)
{
goto exit_on_error;
}
/* establish the DBA as the current user */
user_cache = caches.find_user_cache_by_mop (dba_user);
if (user_cache == NULL)
{
user_cache = caches.make_user_cache (AU_DBA_USER_NAME, dba_user, false);
}
if (caches.get_user_cache_index (user_cache, &index) != NO_ERROR)
{
goto exit_on_error;
}
current_user = dba_user;
Au_cache.set_cache_index (index);
set_user (dba_user);
au_change_class_owner_including_partitions (root_cls, current_user);
au_change_class_owner_including_partitions (user_cls, current_user);
au_change_class_owner_including_partitions (pass_cls, current_user);
au_change_class_owner_including_partitions (auth_cls, current_user);
/* create the PUBLIC user */
public_user = au_add_user (AU_PUBLIC_USER_NAME, &exists);
if (public_user == NULL)
{
goto exit_on_error;
}
/*
* grant browser access to the authorization objects
* note that the password class cannot be read by anyone except the DBA
*/
au_grant (DB_OBJECT_CLASS, public_user, root_cls, (DB_AUTH) (AU_SELECT | AU_EXECUTE), false);
au_grant (DB_OBJECT_CLASS, public_user, user_cls, AU_SELECT, false);
au_grant (DB_OBJECT_CLASS, public_user, user_cls, (DB_AUTH) (AU_SELECT | AU_EXECUTE), false);
au_grant (DB_OBJECT_CLASS, public_user, auth_cls, AU_SELECT, false);
au_add_method_check_authorization ();
if (set_system_user() != NO_ERROR)
{
goto exit_on_error;
}
AU_ENABLE (save);
return NO_ERROR;
exit_on_error:
if (public_user != NULL)
{
au_drop_user (public_user);
public_user = NULL;
}
if (dba_user != NULL)
{
au_drop_user (dba_user);
dba_user = NULL;
}
if (root != NULL)
{
obj_delete (root);
root = NULL;
}
if (auth_cls != NULL)
{
db_drop_class (auth_cls);
}
if (pass_cls != NULL)
{
db_drop_class (pass_cls);
}
if (user_cls != NULL)
{
db_drop_class (user_cls);
}
if (root_cls != NULL)
{
db_drop_class (root_cls);
}
AU_ENABLE (save);
return (er_errid () == NO_ERROR ? ER_FAILED : er_errid ());
}
/*
* perform_login - This changes the current user using the supplied
* name & password.
* return: error code
* name(in): user name
* password(in): user password
*
* Note: It is called both by login() and start().
* Once the name/password have been validated, it calls au_set_user()
* to set the user object and calculate the authorization cache index.
* Assumes authorization has been disabled.
*/
int
authenticate_context::perform_login (const char *name, const char *password, bool ignore_dba_privilege)
{
int error = NO_ERROR;
MOP user;
DB_VALUE value;
const char *pass;
char *dbuser = NULL, *dbpassword = NULL;
dbuser = (char *) name;
dbpassword = (char *) password;
if (dbuser == NULL || strlen (dbuser) == 0)
{
error = ER_AU_NO_USER_LOGGED_IN;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 0);
}
else
{
public_user = au_find_user (AU_PUBLIC_USER_NAME);
dba_user = au_find_user (AU_DBA_USER_NAME);
if (public_user == NULL || dba_user == NULL)
{
error = er_errid ();
if (error != ER_LK_UNILATERALLY_ABORTED)
{
error = ER_AU_INCOMPLETE_AUTH;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
}
}
user = au_find_user (dbuser);
if (user == NULL)
{
error = er_errid ();
if (error != ER_LK_UNILATERALLY_ABORTED)
{
error = ER_AU_INVALID_USER;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, dbuser);
}
}
else
{
if (is_loginable_user (user) == false)
{
error = ER_AU_LOGIN_DISABLED;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, dbuser);
return error;
}
if (obj_get (user, "password", &value) != NO_ERROR)
{
error = ER_AU_CORRUPTED;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
}
else
{
/*
* hack, allow password checking to be turned off in certain
* cases, like the utility programs that will always run in DBA
* mode but don't want to have to enter a password, also
* if a sucessful DBA login ocurred, allow users to be
* changed without entering passwords
*/
if (!ignore_passwords && (!au_is_dba_group_member (current_user) || ignore_dba_privilege))
{
pass = NULL;
if (!DB_IS_NULL (&value) && db_get_object (&value) != NULL)
{
if (obj_get (db_get_object (&value), "password", &value))
{
assert (er_errid () != NO_ERROR);
return er_errid ();
}
if (DB_IS_STRING (&value))
{
if (DB_IS_NULL (&value))
{
pass = NULL;
}
else
{
pass = db_get_string (&value);
}
}
}
if (pass != NULL && strlen (pass))
{
/* the password is present and must match */
if ((dbpassword == NULL) || (strlen (dbpassword) == 0)
|| !match_password (dbpassword, db_get_string (&value)))
{
error = ER_AU_INVALID_PASSWORD;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
}
}
else
{
/*
* the password in the user object is effectively NULL,
* only accept the login if the user supplied an empty
* password.
* Formerly any password string was accepted
* if the stored password was NULL which is
* not quite right.
*/
if (dbpassword != NULL && strlen (dbpassword))
{
error = ER_AU_INVALID_PASSWORD;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
}
}
if (pass != NULL)
{
ws_free_string (db_get_string (&value));
}
}
if (error == NO_ERROR)
{
error = set_user (user);
/* necessary to invalidate vclass cache */
sm_bump_local_schema_version ();
}
}
}
}
return (error);
}
int
authenticate_context::set_user (MOP newuser)
{
int error = NO_ERROR;
int index;
AU_USER_CACHE *user_cache;
if (newuser != NULL && !ws_is_same_object (newuser, current_user))
{
user_cache = caches.find_user_cache_by_mop (newuser);
if (!user_cache)
{
const char *user_name = au_get_user_name (newuser);
if (user_name == nullptr)
{
error = ER_AU_INVALID_USER_NAME;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_AU_INVALID_USER_NAME, 1, "");
return (error);
}
user_cache = caches.make_user_cache (user_name, newuser, false);
ws_free_string (user_name);
}
if (user_cache)
{
if (caches.get_user_cache_index (user_cache, &index) == NO_ERROR)
{
current_user = newuser;
caches.set_cache_index (index);
/*
* it is important that we don't call sm_bump_local_schema_version() here
* because this function is called during the compilation of vclasses
*/
/*
* Entry-level SQL specifies that the schema name is the same as
* the current user authorization name. In any case, this is
* the place to set the current schema since the user just changed.
*/
error = sc_set_current_schema (current_user);
}
}
else
{
// you can guarantee that user cache is already created in au_find_user ()
assert (false);
}
}
return (error);
}
/*
* au_set_password_encrypt - Set the password string for a user.
* return: error code
* user(in): user object
* password(in): new password
*/
int
authenticate_context::set_password (MOP user, const char *password, int encode = 1,
char encrypt_prefix = ENCODE_PREFIX_SHA2_512)
{
return (au_set_password_internal (user, password, encode, encrypt_prefix));
}
/*
* au_set_password_encrypt - Set the password string for a user.
* return: error code
* user(in): user object
* password(in): new password
*/
int
authenticate_context::set_password (MOP user, const char *password)
{
return (au_set_password_internal (user, password, 1, ENCODE_PREFIX_SHA2_512));
}
/*
* au_disable_passwords -
* return: none
*/
void
authenticate_context::disable_passwords (void)
{
ignore_passwords = 1;
}
/*
* au_check_user - This is used to check for a currently valid user for some
* operations that are not strictly based on
* any particular class.
* return: error code
*/
int
authenticate_context::check_user (void)
{
int error = NO_ERROR;
if (current_user == NULL)
{
error = ER_AU_INVALID_USER;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
}
return (error);
}
bool
authenticate_context::has_user_name (void)
{
return current_user != NULL || strlen (user_name) > 0;
}
/*
* au_public_user
* return: Au_public_user
*/
MOP
authenticate_context::get_public_user (void)
{
return public_user;
}
/*
* au_public_user
* return: Au_public_user
*/
MOP
authenticate_context::get_dba_user (void)
{
return dba_user;
}
/*
* au_get_current_user_name - Returns the name of the current user, the string must be
* freed with ws_free_string (db_string_free).
* return: user name (NULL if error)
*
* Note: Note that this is what should always be used to get the active user.
* Au_user_name is only used as a temporary storage area during login.
* Once the database is open, the active user is determined by Au_user
* and Au_user_name doesn't necessarily track this.
*/
const char *
authenticate_context::get_current_user_name (void)
{
DB_VALUE value;
const char *name = NULL;
if (current_user == NULL)
{
/*
* Database hasn't been started yet, return the registered name
* if any.
*/
if (strlen (user_name) == 0)
{
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_AU_NO_USER_LOGGED_IN, 0);
}
else
{
name = ws_copy_string (user_name);
/*
* When this function is called before the workspace memory
* manager was not initialized in the case of client
* initialization(db_restart()), ws_copy_string() will return
* NULL.
*/
}
}
else
{
int save;
/*
* To reduce unnecessary code execution,
* the current schema name can be used instead of the current user name.
*
* Au_user_name cannot be used because it does not always store the current user name.
* When au_login_method () is called, Au_user_name is not changed.
*/
const char *sc_name = sc_current_schema_name ();
char upper_sc_name[DB_MAX_USER_LENGTH];
if (sc_name && sc_name[0] != '\0')
{
intl_identifier_upper (sc_name, upper_sc_name);
return ws_copy_string (upper_sc_name);
}
AU_DISABLE (save);
if (obj_get (current_user, "name", &value) == NO_ERROR)
{
if (!DB_IS_STRING (&value))
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_AU_CORRUPTED, 0);
pr_clear_value (&value);
}
else if (DB_IS_NULL (&value))
{
name = NULL;
}
else
{
name = db_get_string (&value);
name = ws_copy_string (name);
pr_clear_value (&value);
}
}
AU_ENABLE (save);
}
return name;
}
const char *
authenticate_context::get_public_user_name (void)
{
return AU_PUBLIC_USER_NAME;
}
const char *
authenticate_context::get_user_class_name (void)
{
return AU_USER_CLASS_NAME;
}
int
authenticate_context::push_user (MOP user)
{
MOP save_user = Au_user;
if (AU_SET_USER (user) == NO_ERROR)
{
user_stack.push (save_user);
return NO_ERROR;
}
else
{
return ER_FAILED;
}
}
int
authenticate_context::pop_user (void)
{
if (user_stack.size () == 0)
{
return ER_FAILED;
}
if (AU_SET_USER (user_stack.top ()) == NO_ERROR)
{
user_stack.pop ();
return NO_ERROR;
}
else
{
return ER_FAILED;
}
}
int
authenticate_context::set_system_user (void)
{
DB_VALUE value;
int error = NO_ERROR;
db_make_int (&value, true);
error = obj_set (Au_dba_user, AU_USER_ATTR_IS_SYSTEM_CREATED, &value);
if (error != NO_ERROR)
{
return error;
}
error = obj_set (Au_public_user, AU_USER_ATTR_IS_SYSTEM_CREATED, &value);
if (error != NO_ERROR)
{
return error;
}
return NO_ERROR;
}
int
authenticate_context::disable_login (MOP user)
{
DB_VALUE value;
int error = NO_ERROR;
db_make_int (&value, false);
error = obj_set (user, AU_USER_ATTR_IS_LOGINABLE, &value);
if (error != NO_ERROR)
{
return error;
}
return NO_ERROR;
}
int authenticate_context::is_loginable_user (MOP user)
{
DB_VALUE value;
if (obj_get (user, AU_USER_ATTR_IS_LOGINABLE, &value) == NO_ERROR &&
db_get_int (&value) == true)
{
return true;
}
return false;
}
//
// STATIC FUNCTIONS
//
/*
* au_add_method_check_authorization -
* return: error code
*/
static int
au_add_method_check_authorization (void)
{
MOP auth;
SM_TEMPLATE *def;
int save;
AU_DISABLE (save);
auth = db_find_class (AU_AUTH_CLASS_NAME);
if (auth == NULL)
{
goto exit_on_error;
}
def = smt_edit_class_mop (auth, AU_ALTER);
if (def == NULL)
{
goto exit_on_error;
}
smt_add_class_method (def, "check_authorization", "au_check_authorization_method");
smt_assign_argument_domain (def, "check_authorization", true, NULL, 0, "integer", (DB_DOMAIN *) 0);
smt_assign_argument_domain (def, "check_authorization", true, NULL, 1, "varchar(255)", (DB_DOMAIN *) 0);
smt_assign_argument_domain (def, "check_authorization", true, NULL, 2, "integer", (DB_DOMAIN *) 0);
sm_update_class (def, NULL);
au_grant (DB_OBJECT_CLASS, Au_public_user, auth, AU_EXECUTE, false);
AU_ENABLE (save);
return NO_ERROR;
exit_on_error:
AU_ENABLE (save);
return ER_FAILED;
}