8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-02-02 10:40:38 +01:00

Implemented CORE-1377: Add an ability to change role without reconnecting to database

This commit is contained in:
alexpeshkoff 2014-04-30 15:12:12 +00:00
parent 235fb16aa9
commit 9bd0939f09
22 changed files with 326 additions and 153 deletions

View File

@ -1590,6 +1590,10 @@ C --
PARAMETER (GDS__map_nodb = 335545088)
INTEGER*4 GDS__map_notable
PARAMETER (GDS__map_notable = 335545089)
INTEGER*4 GDS__miss_trusted_role
PARAMETER (GDS__miss_trusted_role = 335545090)
INTEGER*4 GDS__set_invalid_role
PARAMETER (GDS__set_invalid_role = 335545091)
INTEGER*4 GDS__gfix_db_name
PARAMETER (GDS__gfix_db_name = 335740929)
INTEGER*4 GDS__gfix_invalid_sw

View File

@ -802,6 +802,8 @@ const
gds_baddpb_temp_buffers = 335545087;
gds_map_nodb = 335545088;
gds_map_notable = 335545089;
gds_miss_trusted_role = 335545090;
gds_set_invalid_role = 335545091;
gds_gfix_db_name = 335740929;
gds_gfix_invalid_sw = 335740930;
gds_gfix_incmp_sw = 335740932;

View File

@ -49,6 +49,7 @@
#include "../jrd/par_proto.h"
#include "../jrd/rlck_proto.h"
#include "../jrd/tra_proto.h"
#include "../jrd/scl_proto.h"
#include "../dsql/ddl_proto.h"
#include "../dsql/metd_proto.h"
#include "../jrd/vio_proto.h"
@ -7593,6 +7594,45 @@ void SetTransactionNode::genTableLock(DsqlCompilerScratch* dsqlScratch,
//--------------------
SetRoleNode* SetRoleNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_SET_ROLE);
return this;
}
void SetRoleNode::execute(thread_db* tdbb, dsql_req* request, jrd_tra** transaction) const
{
SET_TDBB(tdbb);
Attachment* const attachment = tdbb->getAttachment();
UserId* user = attachment->att_user;
fb_assert(user);
if (trusted)
{
if (!user->usr_trusted_role.hasData())
Arg::Gds(isc_miss_trusted_role).raise();
user->usr_sql_role_name = user->usr_trusted_role;
}
else
{
if (!SCL_role_granted(tdbb, *user, roleName.c_str()))
(Arg::Gds(isc_set_invalid_role) << roleName).raise();
user->usr_sql_role_name = roleName.c_str();
}
if (SCL_admin_role(tdbb, user->usr_sql_role_name.c_str()))
user->usr_flags |= USR_dba;
else
user->usr_flags &= ~USR_dba;
SCL_release_all(attachment->att_security_classes);
}
//--------------------
StmtNode* UpdateOrInsertNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
thread_db* tdbb = JRD_get_thread_data(); // necessary?

View File

@ -1509,6 +1509,42 @@ public:
};
// This node should better be session management node,
// but as long as we do not have other session management and
// node is rather similiar internally to transaction management
// let it for now be transaction management node.
class SetRoleNode : public TransactionNode
{
public:
explicit SetRoleNode(MemoryPool& pool)
: TransactionNode(pool),
trusted(true),
roleName(pool)
{
}
SetRoleNode(MemoryPool& pool, Firebird::MetaName* name)
: TransactionNode(pool),
trusted(false),
roleName(pool, *name)
{
}
public:
virtual void print(Firebird::string& text) const
{
text = "SetRoleNode";
}
virtual SetRoleNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
virtual void execute(thread_db* tdbb, dsql_req* request, jrd_tra** transaction) const;
public:
bool trusted;
Firebird::MetaName roleName;
};
class UpdateOrInsertNode : public TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_UPDATE_OR_INSERT>
{
public:

View File

@ -1822,6 +1822,7 @@ static void sql_info(thread_db* tdbb,
break;
case DsqlCompiledStatement::TYPE_CREATE_DB:
case DsqlCompiledStatement::TYPE_DDL:
case DsqlCompiledStatement::TYPE_SET_ROLE:
number = isc_info_sql_stmt_ddl;
break;
case DsqlCompiledStatement::TYPE_COMMIT:

View File

@ -429,7 +429,7 @@ public:
TYPE_SELECT, TYPE_SELECT_UPD, TYPE_INSERT, TYPE_DELETE, TYPE_UPDATE, TYPE_UPDATE_CURSOR,
TYPE_DELETE_CURSOR, TYPE_COMMIT, TYPE_ROLLBACK, TYPE_CREATE_DB, TYPE_DDL, TYPE_START_TRANS,
TYPE_EXEC_PROCEDURE, TYPE_COMMIT_RETAIN, TYPE_ROLLBACK_RETAIN, TYPE_SET_GENERATOR,
TYPE_SAVEPOINT, TYPE_EXEC_BLOCK, TYPE_SELECT_BLOCK
TYPE_SAVEPOINT, TYPE_EXEC_BLOCK, TYPE_SELECT_BLOCK, TYPE_SET_ROLE
};
// Statement flags.

View File

@ -569,6 +569,7 @@ using namespace Firebird;
%token <metaNamePtr> PLUGIN
%token <metaNamePtr> SERVERWIDE
%token <metaNamePtr> INCREMENT
%token <metaNamePtr> TRUSTED
// precedence declarations for expression evaluation
@ -697,6 +698,7 @@ using namespace Firebird;
Jrd::CreateAlterUserNode* createAlterUserNode;
Jrd::MappingNode* mappingNode;
Jrd::MappingNode::OP mappingOp;
Jrd::SetRoleNode* setRoleNode;
}
%include types.y
@ -749,6 +751,7 @@ tra_statement
: set_transaction { $$ = $1; }
| commit { $$ = $1; }
| rollback { $$ = $1; }
| set_role { $$ = $1; }
;
@ -4468,6 +4471,14 @@ set_transaction
{ $$ = $3; }
;
%type <setRoleNode> set_role
set_role
: SET ROLE valid_symbol_name
{ $$ = newNode<SetRoleNode>($3); }
| SET TRUSTED ROLE
{ $$ = newNode<SetRoleNode>(); }
;
%type tran_option_list_opt(<setTransactionNode>)
tran_option_list_opt($setTransactionNode)
: // nothing
@ -7373,6 +7384,7 @@ non_reserved_word
| PLUGIN
| SERVERWIDE
| INCREMENT
| TRUSTED
;
%%

View File

@ -791,6 +791,8 @@ static const struct {
{"baddpb_temp_buffers", 335545087},
{"map_nodb", 335545088},
{"map_notable", 335545089},
{"miss_trusted_role", 335545090},
{"set_invalid_role", 335545091},
{"gfix_db_name", 335740929},
{"gfix_invalid_sw", 335740930},
{"gfix_incmp_sw", 335740932},

View File

@ -825,6 +825,8 @@ const ISC_STATUS isc_baddpb_buffers_range = 335545086L;
const ISC_STATUS isc_baddpb_temp_buffers = 335545087L;
const ISC_STATUS isc_map_nodb = 335545088L;
const ISC_STATUS isc_map_notable = 335545089L;
const ISC_STATUS isc_miss_trusted_role = 335545090L;
const ISC_STATUS isc_set_invalid_role = 335545091L;
const ISC_STATUS isc_gfix_db_name = 335740929L;
const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
const ISC_STATUS isc_gfix_incmp_sw = 335740932L;
@ -1278,7 +1280,7 @@ const ISC_STATUS isc_trace_switch_user_only = 337182757L;
const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
const ISC_STATUS isc_err_max = 1222;
const ISC_STATUS isc_err_max = 1224;
#else /* c definitions */
@ -2073,6 +2075,8 @@ const ISC_STATUS isc_err_max = 1222;
#define isc_baddpb_temp_buffers 335545087L
#define isc_map_nodb 335545088L
#define isc_map_notable 335545089L
#define isc_miss_trusted_role 335545090L
#define isc_set_invalid_role 335545091L
#define isc_gfix_db_name 335740929L
#define isc_gfix_invalid_sw 335740930L
#define isc_gfix_incmp_sw 335740932L
@ -2526,7 +2530,7 @@ const ISC_STATUS isc_err_max = 1222;
#define isc_trace_switch_param_miss 337182758L
#define isc_trace_param_act_notcompat 337182759L
#define isc_trace_mandatory_switch_miss 337182760L
#define isc_err_max 1222
#define isc_err_max 1224
#endif

View File

@ -794,6 +794,8 @@ Data source : @4"}, /* eds_statement */
{335545087, "Attempt to temporarily set number of buffers less than @1"}, /* baddpb_temp_buffers */
{335545088, "Global mapping is not available when database @1 is not present"}, /* map_nodb */
{335545089, "Global mapping is not available when table RDB$MAP is not present in database @1"}, /* map_notable */
{335545090, "Your attachment has no trusted role"}, /* miss_trusted_role */
{335545091, "Role @1 is invalid or unavailable"}, /* set_invalid_role */
{335740929, "data base file name (@1) already given"}, /* gfix_db_name */
{335740930, "invalid switch @1"}, /* gfix_invalid_sw */
{335740932, "incompatible switch combination"}, /* gfix_incmp_sw */

View File

@ -790,6 +790,8 @@ static const struct {
{335545087, -924}, /* 767 baddpb_temp_buffers */
{335545088, -901}, /* 768 map_nodb */
{335545089, -901}, /* 769 map_notable */
{335545090, -901}, /* 770 miss_trusted_role */
{335545091, -901}, /* 771 set_invalid_role */
{335740929, -901}, /* 1 gfix_db_name */
{335740930, -901}, /* 2 gfix_invalid_sw */
{335740932, -901}, /* 4 gfix_incmp_sw */

View File

@ -790,6 +790,8 @@ static const struct {
{335545087, "HY000"}, // 767 baddpb_temp_buffers
{335545088, "0A000"}, // 768 map_nodb
{335545089, "0A000"}, // 769 map_notable
{335545090, "0P000"}, // 770 miss_trusted_role
{335545091, "0P000"}, // 771 set_invalid_role
{335740929, "00000"}, // 1 gfix_db_name
{335740930, "00000"}, // 2 gfix_invalid_sw
{335740932, "00000"}, // 4 gfix_incmp_sw

View File

@ -4918,7 +4918,7 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
//#ifdef DEV_BUILD
sqlda_display,
//#endif
sql, warning, generator, statistics, heading, bail,
sql, warning, sqlCont, heading, bail,
bulk_insert, maxrows, wrong
};
SetOptions(const optionsMap* inmap, size_t insize, int wrongval)
@ -4948,13 +4948,15 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
{SetOptions::sql, "SQL", 0},
{SetOptions::warning, "WARNINGS", 7},
{SetOptions::warning, "WNG", 0},
{SetOptions::generator, "GENERATOR", 0},
{SetOptions::statistics, "STATISTICS", 0},
{SetOptions::sqlCont, "GENERATOR", 0},
{SetOptions::sqlCont, "STATISTICS", 0},
{SetOptions::heading, "HEADING", 0},
{SetOptions::bail, "BAIL", 0},
{SetOptions::bulk_insert, "BULK_INSERT", 0},
{SetOptions::maxrows, "ROWCOUNT", 0}, // legacy, compatible with FB2.5
{SetOptions::maxrows, "MAXROWS", 0},
{SetOptions::sqlCont, "ROLE", 0},
{SetOptions::sqlCont, "TRUSTED", 0}, // TRUSTED ROLE, will get DSQL error other case
};
// Display current set options
@ -4965,6 +4967,10 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
const SetOptions setoptions(options, FB_NELEM(options), SetOptions::wrong);
switch (setoptions.getCommand(parms[1]))
{
case SetOptions::sqlCont:
ret = CONT;
break;
case SetOptions::stat:
ret = do_set_command(parms[2], &Stats);
break;
@ -5082,11 +5088,6 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
ret = do_set_command (parms[2], &Warnings);
break;
case SetOptions::generator:
case SetOptions::statistics:
ret = CONT;
break;
case SetOptions::heading:
ret = do_set_command(parms[2], &Heading);
break;

View File

@ -103,6 +103,8 @@ enum irq_type_t
irq_c_trg_perm, // check if trig can ignore perm. checks
irq_get_role_mem, // get SQL role membership
irq_get_role_name, // get SQL role name
irq_is_admin_role, // check is current role admin or not
irq_get_att_class, // get security class for current attachment
irq_format6, // make a new format for a record
irq_r_gen_id_num, // lookup generator by ID.
irq_upd_gen_id_step, // update the STEP of a generator (only for legacy code).

View File

@ -1223,6 +1223,87 @@ jrd_tra* JAttachment::getEngineTransaction(IStatus* status, ITransaction* tra)
return getTransactionInterface(status, tra)->getHandle();
}
static void makeRoleName(Database* dbb, string& userIdRole, DatabaseOptions& options)
{
if (userIdRole.hasData())
{
switch (options.dpb_sql_dialect)
{
case 0:
// V6 Client --> V6 Server, dummy client SQL dialect 0 was passed
// It means that client SQL dialect was not set by user
// and takes DB SQL dialect as client SQL dialect
if (dbb->dbb_flags & DBB_DB_SQL_dialect_3)
{
// DB created in IB V6.0 by client SQL dialect 3
options.dpb_sql_dialect = SQL_DIALECT_V6;
}
else
{
// old DB was gbaked in IB V6.0
options.dpb_sql_dialect = SQL_DIALECT_V5;
}
break;
case 99:
// V5 Client --> V6 Server, old client has no concept of dialect
options.dpb_sql_dialect = SQL_DIALECT_V5;
break;
default:
// V6 Client --> V6 Server, but client SQL dialect was set
// by user and was passed.
break;
}
CharSet* utf8CharSet = IntlUtil::getUtf8CharSet();
switch (options.dpb_sql_dialect)
{
case SQL_DIALECT_V5:
{
strip_quotes(userIdRole);
IntlUtil::toUpper(utf8CharSet, userIdRole);
}
break;
case SQL_DIALECT_V6_TRANSITION:
case SQL_DIALECT_V6:
{
if (userIdRole.hasData() && (userIdRole[0] == DBL_QUOTE || userIdRole[0] == SINGLE_QUOTE))
{
const char end_quote = userIdRole[0];
// remove the delimited quotes and escape quote
// from ROLE name
userIdRole.erase(0, 1);
for (string::iterator p = userIdRole.begin(); p < userIdRole.end(); ++p)
{
if (*p == end_quote)
{
if (++p < userIdRole.end() && *p == end_quote)
{
// skip the escape quote here
userIdRole.erase(p--);
}
else
{
// delimited done
userIdRole.erase(--p, userIdRole.end());
}
}
}
}
else
IntlUtil::toUpper(utf8CharSet, userIdRole);
}
break;
default:
break;
}
}
}
JAttachment* FB_CARG JProvider::attachDatabase(IStatus* user_status, const char* filename,
unsigned int dpb_length, const unsigned char* dpb)
{
@ -1505,82 +1586,8 @@ JAttachment* FB_CARG JProvider::attachDatabase(IStatus* user_status, const char*
Arg::Gds(isc_valid_client_dialects) << Arg::Str("1, 2 or 3"));
}
if (userId.usr_sql_role_name.hasData())
{
switch (options.dpb_sql_dialect)
{
case 0:
// V6 Client --> V6 Server, dummy client SQL dialect 0 was passed
// It means that client SQL dialect was not set by user
// and takes DB SQL dialect as client SQL dialect
if (dbb->dbb_flags & DBB_DB_SQL_dialect_3)
{
// DB created in IB V6.0 by client SQL dialect 3
options.dpb_sql_dialect = SQL_DIALECT_V6;
}
else
{
// old DB was gbaked in IB V6.0
options.dpb_sql_dialect = SQL_DIALECT_V5;
}
break;
case 99:
// V5 Client --> V6 Server, old client has no concept of dialect
options.dpb_sql_dialect = SQL_DIALECT_V5;
break;
default:
// V6 Client --> V6 Server, but client SQL dialect was set
// by user and was passed.
break;
}
CharSet* utf8CharSet = IntlUtil::getUtf8CharSet();
switch (options.dpb_sql_dialect)
{
case SQL_DIALECT_V5:
{
strip_quotes(userId.usr_sql_role_name);
IntlUtil::toUpper(utf8CharSet, userId.usr_sql_role_name);
}
break;
case SQL_DIALECT_V6_TRANSITION:
case SQL_DIALECT_V6:
{
string& role = userId.usr_sql_role_name;
if (role.hasData() && (role[0] == DBL_QUOTE || role[0] == SINGLE_QUOTE))
{
const char end_quote = role[0];
// remove the delimited quotes and escape quote
// from ROLE name
role.erase(0, 1);
for (string::iterator p = role.begin(); p < role.end(); ++p)
{
if (*p == end_quote)
{
if (++p < role.end() && *p == end_quote)
{
// skip the escape quote here
role.erase(p--);
}
else
{
// delimited done
role.erase(--p, role.end());
}
}
}
}
else
IntlUtil::toUpper(utf8CharSet, role);
}
break;
default:
break;
}
}
makeRoleName(dbb, userId.usr_sql_role_name, options);
makeRoleName(dbb, userId.usr_trusted_role, options);
options.dpb_sql_dialect = 0;
@ -7126,10 +7133,9 @@ static void getUserInfo(UserId& user, const DatabaseOptions& options,
{
user.usr_sql_role_name = options.dpb_role_name;
}
else if (trusted_role.hasData())
if (trusted_role.hasData())
{
user.usr_sql_role_name = trusted_role;
user.usr_flags |= USR_trole;
user.usr_trusted_role = trusted_role;
}
}

View File

@ -804,6 +804,91 @@ SecurityClass::flags_t SCL_get_mask(thread_db* tdbb, const TEXT* relation_name,
}
bool SCL_role_granted(thread_db* tdbb, const UserId& usr, const TEXT* sql_role)
{
/**************************************
*
* S C L _ r o l e _ g r a n t e d
*
**************************************
*
* Functional description
* Check is sql_role granted to the user.
*
**************************************/
SET_TDBB(tdbb);
Jrd::Attachment* const attachment = tdbb->getAttachment();
if (!strcmp(sql_role, NULL_ROLE))
{
return true;
}
Firebird::string loginName(usr.usr_user_name);
loginName.upper();
const TEXT* login_name = loginName.c_str();
bool found = false;
AutoCacheRequest request(tdbb, irq_verify_role_name, IRQ_REQUESTS);
// CVC: The caller has hopefully uppercased the role or stripped quotes. Of course,
// uppercase-UPPER7 should only happen if the role wasn't enclosed in quotes.
// Shortsighted developers named the field rdb$relation_name instead of rdb$object_name.
// This request is not exactly the same than irq_get_role_mem, sorry, I can't reuse that.
// If you think that an unknown role cannot be granted, think again: someone made sure
// in DYN that SYSDBA can do almost anything, including invalid grants.
FOR (REQUEST_HANDLE request) FIRST 1 RR IN RDB$ROLES
CROSS UU IN RDB$USER_PRIVILEGES
WITH RR.RDB$ROLE_NAME EQ sql_role
AND RR.RDB$ROLE_NAME EQ UU.RDB$RELATION_NAME
AND UU.RDB$OBJECT_TYPE EQ obj_sql_role
AND (UU.RDB$USER EQ login_name
OR UU.RDB$USER EQ "PUBLIC")
AND UU.RDB$USER_TYPE EQ obj_user
AND UU.RDB$PRIVILEGE EQ "M"
{
if (!UU.RDB$USER.NULL)
found = true;
}
END_FOR
return found;
}
bool SCL_admin_role(thread_db* tdbb, const TEXT* sql_role)
{
/**************************************
*
* S C L _ a d m i n _ r o l e
*
**************************************
*
* Functional description
* Check is sql_role is an admin role.
*
**************************************/
SET_TDBB(tdbb);
Jrd::Attachment* const attachment = tdbb->getAttachment();
bool adminRole = false;
AutoCacheRequest request(tdbb, irq_is_admin_role, IRQ_REQUESTS);
FOR(REQUEST_HANDLE request) R IN RDB$ROLES
WITH R.RDB$ROLE_NAME EQ sql_role
{
if (R.RDB$SYSTEM_FLAG & ROLE_FLAG_DBO)
adminRole = true;
}
END_FOR
return adminRole;
}
void SCL_init(thread_db* tdbb, bool create, const UserId& tempId)
{
/**************************************
@ -815,10 +900,8 @@ void SCL_init(thread_db* tdbb, bool create, const UserId& tempId)
* Functional description
* Check database access control list.
*
* Checks the userinfo database to get the
* password and other stuff about the specified
* user. Compares the password to that passed
* in, encrypting if necessary.
* Finally fills UserId information
* (role, flags, etc.).
*
**************************************/
SET_TDBB(tdbb);
@ -826,17 +909,17 @@ void SCL_init(thread_db* tdbb, bool create, const UserId& tempId)
Jrd::Attachment* const attachment = tdbb->getAttachment();
const TEXT* sql_role = tempId.usr_sql_role_name.nullStr();
Firebird::string loginName(tempId.usr_user_name);
loginName.upper();
const TEXT* login_name = loginName.c_str();
Firebird::MetaName role_name;
// CVC: We'll verify the role and wipe it out when it doesn't exist
if (strlen(login_name) != 0)
if (tempId.usr_user_name.hasData())
{
if (!create)
{
Firebird::string loginName(tempId.usr_user_name);
loginName.upper();
const TEXT* login_name = loginName.c_str();
AutoCacheRequest request(tdbb, irq_get_role_name, IRQ_REQUESTS);
FOR(REQUEST_HANDLE request) X IN RDB$ROLES
@ -851,50 +934,16 @@ void SCL_init(thread_db* tdbb, bool create, const UserId& tempId)
// CVC: If we aren't creating a db and sql_role was specified,
// then verify it against rdb$roles and rdb$user_privileges
if (!create && sql_role && *sql_role && strcmp(sql_role, NULL_ROLE))
if (!create && sql_role && *sql_role)
{
bool found = false;
AutoCacheRequest request(tdbb, irq_verify_role_name, IRQ_REQUESTS);
// CVC: The caller has hopefully uppercased the role or stripped quotes. Of course,
// uppercase-UPPER7 should only happen if the role wasn't enclosed in quotes.
// Shortsighted developers named the field rdb$relation_name instead of rdb$object_name.
// This request is not exactly the same than irq_get_role_mem, sorry, I can't reuse that.
// If you think that an unknown role cannot be granted, think again: someone made sure
// in DYN that SYSDBA can do almost anything, including invalid grants.
if (!(tempId.usr_flags & USR_trole))
{
FOR (REQUEST_HANDLE request) FIRST 1 RR IN RDB$ROLES
CROSS UU IN RDB$USER_PRIVILEGES
WITH RR.RDB$ROLE_NAME EQ sql_role
AND RR.RDB$ROLE_NAME EQ UU.RDB$RELATION_NAME
AND UU.RDB$OBJECT_TYPE EQ obj_sql_role
AND (UU.RDB$USER EQ login_name
OR UU.RDB$USER EQ "PUBLIC")
AND UU.RDB$USER_TYPE EQ obj_user
AND UU.RDB$PRIVILEGE EQ "M"
{
if (!UU.RDB$USER.NULL)
found = true;
}
END_FOR
}
else
found = true;
if (!found)
role_name = NULL_ROLE;
if (!SCL_role_granted(tdbb, tempId, sql_role))
sql_role = NULL;
}
if (sql_role)
{
if (role_name != NULL_ROLE)
role_name = sql_role;
}
else
role_name = NULL_ROLE;
if (!sql_role)
sql_role = tempId.usr_trusted_role.nullStr();
MetaName role_name(sql_role ? sql_role : NULL_ROLE);
MemoryPool& pool = *attachment->att_pool;
UserId* const user = FB_NEW(pool) UserId(pool, tempId);
@ -903,9 +952,9 @@ void SCL_init(thread_db* tdbb, bool create, const UserId& tempId)
if (!create)
{
AutoRequest handle, handle1, handle2;
AutoCacheRequest request(tdbb, irq_get_att_class, IRQ_REQUESTS);
FOR(REQUEST_HANDLE handle) X IN RDB$DATABASE
FOR(REQUEST_HANDLE request) X IN RDB$DATABASE
{
if (!X.RDB$SECURITY_CLASS.NULL)
attachment->att_security_class = SCL_get_class(tdbb, X.RDB$SECURITY_CLASS);
@ -914,7 +963,9 @@ void SCL_init(thread_db* tdbb, bool create, const UserId& tempId)
if (dbb->dbb_owner.isEmpty())
{
FOR(REQUEST_HANDLE handle1)
AutoRequest request;
FOR(REQUEST_HANDLE request)
FIRST 1 REL IN RDB$RELATIONS
WITH REL.RDB$RELATION_NAME EQ "RDB$DATABASE"
{
@ -927,13 +978,8 @@ void SCL_init(thread_db* tdbb, bool create, const UserId& tempId)
if (dbb->dbb_owner == user->usr_user_name)
user->usr_flags |= USR_owner;
FOR(REQUEST_HANDLE handle2) R IN RDB$ROLES
WITH R.RDB$ROLE_NAME EQ role_name.c_str()
{
if (R.RDB$SYSTEM_FLAG & ROLE_FLAG_DBO)
user->usr_flags |= USR_dba;
}
END_FOR
if (sql_role && SCL_admin_role(tdbb, role_name.c_str()))
user->usr_flags |= USR_dba;
}
else
{
@ -1294,6 +1340,8 @@ static SecurityClass::flags_t walk_acl(thread_db* tdbb,
case id_sql_role:
if (!role_name || check_string(a, role_name))
hit = false;
else if (user.usr_sql_role_name == user.usr_trusted_role)
hit = true;
else
{
TEXT login_name[129];

View File

@ -84,14 +84,13 @@ const SecurityClass::flags_t SCL_usage = 2048; // USAGE access
const USHORT USR_locksmith = 1; // User has great karma
const USHORT USR_dba = 2; // User has DBA privileges
const USHORT USR_owner = 4; // User owns database
const USHORT USR_trole = 8; // Role was set by trusted auth
class UserId
{
public:
Firebird::string usr_user_name; // User name
Firebird::string usr_sql_role_name; // Role name
Firebird::string usr_trusted_role; // Trusted role if set
Firebird::string usr_project_name; // Project name
Firebird::string usr_org_name; // Organization name
Firebird::string usr_auth_method; // Authentication method
@ -112,6 +111,7 @@ public:
UserId(Firebird::MemoryPool& p, const UserId& ui)
: usr_user_name(p, ui.usr_user_name),
usr_sql_role_name(p, ui.usr_sql_role_name),
usr_trusted_role(p, ui.usr_trusted_role),
usr_project_name(p, ui.usr_project_name),
usr_org_name(p, ui.usr_org_name),
usr_auth_method(p, ui.usr_auth_method),
@ -126,6 +126,7 @@ public:
UserId(const UserId& ui)
: usr_user_name(ui.usr_user_name),
usr_sql_role_name(ui.usr_sql_role_name),
usr_trusted_role(ui.usr_trusted_role),
usr_project_name(ui.usr_project_name),
usr_org_name(ui.usr_org_name),
usr_auth_method(ui.usr_auth_method),
@ -140,6 +141,7 @@ public:
{
usr_user_name = ui.usr_user_name;
usr_sql_role_name = ui.usr_sql_role_name;
usr_trusted_role = ui.usr_trusted_role;
usr_project_name = ui.usr_project_name;
usr_org_name = ui.usr_org_name;
usr_auth_method = ui.usr_auth_method;

View File

@ -51,6 +51,8 @@ Jrd::SecurityClass::flags_t SCL_get_mask(Jrd::thread_db* tdbb, const TEXT*, cons
void SCL_init(Jrd::thread_db* tdbb, bool, const Jrd::UserId& tempId);
Jrd::SecurityClass* SCL_recompute_class(Jrd::thread_db*, const TEXT*);
void SCL_release_all(Jrd::SecurityClassList*&);
bool SCL_role_granted(Jrd::thread_db* tdbb, const Jrd::UserId& usr, const TEXT* sql_role);
bool SCL_admin_role(Jrd::thread_db* tdbb, const TEXT* sql_role);
namespace Jrd {
typedef Firebird::Array<UCHAR> Acl;

View File

@ -1,7 +1,7 @@
/* MAX_NUMBER is the next number to be used, always one more than the highest message number. */
set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES (?, ?, ?, ?);
--
('2014-04-18 19:01:37', 'JRD', 0, 770)
('2014-04-30 18:55:42', 'JRD', 0, 772)
('2012-01-23 20:10:30', 'QLI', 1, 532)
('2013-11-13 15:59:10', 'GFIX', 3, 122)
('1996-11-07 13:39:40', 'GPRE', 4, 1)

View File

@ -877,6 +877,8 @@ Data source : @4', NULL, NULL)
('baddpb_temp_buffers', 'DatabaseOptions::get', 'jrd.cpp', NULL, 0, 767, NULL, 'Attempt to temporarily set number of buffers less than @1', NULL, NULL);
('map_nodb', 'MappingList::getList', 'Mapping.cpp', NULL, 0, 768, NULL, 'Global mapping is not available when database @1 is not present', NULL, NULL);
('map_notable', 'MappingList::getList', 'Mapping.cpp', NULL, 0, 769, NULL, 'Global mapping is not available when table RDB$MAP is not present in database @1', NULL, NULL);
('miss_trusted_role', 'SetRoleNode::execute', 'StmtNodes.cpp', NULL, 0, 770, NULL, 'Your attachment has no trusted role', NULL, NULL);
('set_invalid_role', 'SetRoleNode::execute', 'StmtNodes.cpp', NULL, 0, 771, NULL, 'Role @1 is invalid or unavailable', NULL, NULL);
-- QLI
(NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL);
(NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL);

View File

@ -776,6 +776,8 @@ set bulk_insert INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, FA
(-924, 'HY', '000', 0, 767, 'baddpb_temp_buffers', NULL, NULL);
(-901, '0A', '000', 0, 768, 'map_nodb', NULL, NULL);
(-901, '0A', '000', 0, 769, 'map_notable', NULL, NULL);
(-901, '0P', '000', 0, 770, 'miss_trusted_role', NULL, NULL);
(-901, '0P', '000', 0, 771, 'set_invalid_role', NULL, NULL);
-- GFIX
(-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL)
(-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL)

View File

@ -407,6 +407,7 @@ static const TOK tokens[] =
{TRIM, "TRIM", 2, false},
{KW_TRUE, "TRUE", 2, false},
{TRUNC, "TRUNC", 2, false},
{TRUSTED, "TRUSTED", 2, false},
{TWO_PHASE, "TWO_PHASE", 2, true},
{KW_TYPE, "TYPE", 2, true},
{UNCOMMITTED, "UNCOMMITTED", 1, false},