|
From: <ale...@us...> - 2014-04-30 15:12:16
|
Revision: 59508
http://sourceforge.net/p/firebird/code/59508
Author: alexpeshkoff
Date: 2014-04-30 15:12:12 +0000 (Wed, 30 Apr 2014)
Log Message:
-----------
Implemented CORE-1377: Add an ability to change role without reconnecting to database
Modified Paths:
--------------
firebird/trunk/lang_helpers/gds_codes.ftn
firebird/trunk/lang_helpers/gds_codes.pas
firebird/trunk/src/dsql/StmtNodes.cpp
firebird/trunk/src/dsql/StmtNodes.h
firebird/trunk/src/dsql/dsql.cpp
firebird/trunk/src/dsql/dsql.h
firebird/trunk/src/dsql/parse.y
firebird/trunk/src/include/gen/codetext.h
firebird/trunk/src/include/gen/iberror.h
firebird/trunk/src/include/gen/msgs.h
firebird/trunk/src/include/gen/sql_code.h
firebird/trunk/src/include/gen/sql_state.h
firebird/trunk/src/isql/isql.epp
firebird/trunk/src/jrd/irq.h
firebird/trunk/src/jrd/jrd.cpp
firebird/trunk/src/jrd/scl.epp
firebird/trunk/src/jrd/scl.h
firebird/trunk/src/jrd/scl_proto.h
firebird/trunk/src/msgs/facilities2.sql
firebird/trunk/src/msgs/messages2.sql
firebird/trunk/src/msgs/system_errors2.sql
firebird/trunk/src/yvalve/keywords.cpp
Modified: firebird/trunk/lang_helpers/gds_codes.ftn
===================================================================
--- firebird/trunk/lang_helpers/gds_codes.ftn 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/lang_helpers/gds_codes.ftn 2014-04-30 15:12:12 UTC (rev 59508)
@@ -1590,6 +1590,10 @@
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
Modified: firebird/trunk/lang_helpers/gds_codes.pas
===================================================================
--- firebird/trunk/lang_helpers/gds_codes.pas 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/lang_helpers/gds_codes.pas 2014-04-30 15:12:12 UTC (rev 59508)
@@ -802,6 +802,8 @@
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;
Modified: firebird/trunk/src/dsql/StmtNodes.cpp
===================================================================
--- firebird/trunk/src/dsql/StmtNodes.cpp 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/dsql/StmtNodes.cpp 2014-04-30 15:12:12 UTC (rev 59508)
@@ -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 @@
//--------------------
+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?
Modified: firebird/trunk/src/dsql/StmtNodes.h
===================================================================
--- firebird/trunk/src/dsql/StmtNodes.h 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/dsql/StmtNodes.h 2014-04-30 15:12:12 UTC (rev 59508)
@@ -1509,6 +1509,42 @@
};
+// 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:
Modified: firebird/trunk/src/dsql/dsql.cpp
===================================================================
--- firebird/trunk/src/dsql/dsql.cpp 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/dsql/dsql.cpp 2014-04-30 15:12:12 UTC (rev 59508)
@@ -1822,6 +1822,7 @@
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:
Modified: firebird/trunk/src/dsql/dsql.h
===================================================================
--- firebird/trunk/src/dsql/dsql.h 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/dsql/dsql.h 2014-04-30 15:12:12 UTC (rev 59508)
@@ -429,7 +429,7 @@
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.
Modified: firebird/trunk/src/dsql/parse.y
===================================================================
--- firebird/trunk/src/dsql/parse.y 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/dsql/parse.y 2014-04-30 15:12:12 UTC (rev 59508)
@@ -569,6 +569,7 @@
%token <metaNamePtr> PLUGIN
%token <metaNamePtr> SERVERWIDE
%token <metaNamePtr> INCREMENT
+%token <metaNamePtr> TRUSTED
// precedence declarations for expression evaluation
@@ -697,6 +698,7 @@
Jrd::CreateAlterUserNode* createAlterUserNode;
Jrd::MappingNode* mappingNode;
Jrd::MappingNode::OP mappingOp;
+ Jrd::SetRoleNode* setRoleNode;
}
%include types.y
@@ -749,6 +751,7 @@
: set_transaction { $$ = $1; }
| commit { $$ = $1; }
| rollback { $$ = $1; }
+ | set_role { $$ = $1; }
;
@@ -4468,6 +4471,14 @@
{ $$ = $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 @@
| PLUGIN
| SERVERWIDE
| INCREMENT
+ | TRUSTED
;
%%
Modified: firebird/trunk/src/include/gen/codetext.h
===================================================================
--- firebird/trunk/src/include/gen/codetext.h 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/include/gen/codetext.h 2014-04-30 15:12:12 UTC (rev 59508)
@@ -791,6 +791,8 @@
{"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},
Modified: firebird/trunk/src/include/gen/iberror.h
===================================================================
--- firebird/trunk/src/include/gen/iberror.h 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/include/gen/iberror.h 2014-04-30 15:12:12 UTC (rev 59508)
@@ -825,6 +825,8 @@
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_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 @@
#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 @@
#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
Modified: firebird/trunk/src/include/gen/msgs.h
===================================================================
--- firebird/trunk/src/include/gen/msgs.h 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/include/gen/msgs.h 2014-04-30 15:12:12 UTC (rev 59508)
@@ -794,6 +794,8 @@
{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 */
Modified: firebird/trunk/src/include/gen/sql_code.h
===================================================================
--- firebird/trunk/src/include/gen/sql_code.h 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/include/gen/sql_code.h 2014-04-30 15:12:12 UTC (rev 59508)
@@ -790,6 +790,8 @@
{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 */
Modified: firebird/trunk/src/include/gen/sql_state.h
===================================================================
--- firebird/trunk/src/include/gen/sql_state.h 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/include/gen/sql_state.h 2014-04-30 15:12:12 UTC (rev 59508)
@@ -790,6 +790,8 @@
{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
Modified: firebird/trunk/src/isql/isql.epp
===================================================================
--- firebird/trunk/src/isql/isql.epp 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/isql/isql.epp 2014-04-30 15:12:12 UTC (rev 59508)
@@ -4918,7 +4918,7 @@
//#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 @@
{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 @@
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 @@
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;
Modified: firebird/trunk/src/jrd/irq.h
===================================================================
--- firebird/trunk/src/jrd/irq.h 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/jrd/irq.h 2014-04-30 15:12:12 UTC (rev 59508)
@@ -103,6 +103,8 @@
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).
Modified: firebird/trunk/src/jrd/jrd.cpp
===================================================================
--- firebird/trunk/src/jrd/jrd.cpp 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/jrd/jrd.cpp 2014-04-30 15:12:12 UTC (rev 59508)
@@ -1223,6 +1223,87 @@
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,83 +1586,9 @@
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;
- }
+ makeRoleName(dbb, userId.usr_sql_role_name, options);
+ makeRoleName(dbb, userId.usr_trusted_role, options);
- 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;
- }
- }
-
options.dpb_sql_dialect = 0;
SCL_init(tdbb, false, userId);
@@ -7126,10 +7133,9 @@
{
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;
}
}
Modified: firebird/trunk/src/jrd/scl.epp
===================================================================
--- firebird/trunk/src/jrd/scl.epp 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/jrd/scl.epp 2014-04-30 15:12:12 UTC (rev 59508)
@@ -804,6 +804,91 @@
}
+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 @@
* 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 @@
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,51 +934,17 @@
// 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;
+ if (!SCL_role_granted(tdbb, tempId, sql_role))
+ sql_role = NULL;
+ }
- AutoCacheRequest request(tdbb, irq_verify_role_name, IRQ_REQUESTS);
+ if (!sql_role)
+ sql_role = tempId.usr_trusted_role.nullStr();
- // 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.
+ MetaName role_name(sql_role ? sql_role : NULL_ROLE);
- 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 (sql_role)
- {
- if (role_name != NULL_ROLE)
- role_name = sql_role;
- }
- else
- role_name = NULL_ROLE;
-
MemoryPool& pool = *attachment->att_pool;
UserId* const user = FB_NEW(pool) UserId(pool, tempId);
user->usr_sql_role_name = role_name.c_str();
@@ -903,9 +952,9 @@
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 @@
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 @@
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 @@
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];
Modified: firebird/trunk/src/jrd/scl.h
===================================================================
--- firebird/trunk/src/jrd/scl.h 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/jrd/scl.h 2014-04-30 15:12:12 UTC (rev 59508)
@@ -84,14 +84,13 @@
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 @@
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 @@
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 @@
{
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;
Modified: firebird/trunk/src/jrd/scl_proto.h
===================================================================
--- firebird/trunk/src/jrd/scl_proto.h 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/jrd/scl_proto.h 2014-04-30 15:12:12 UTC (rev 59508)
@@ -51,6 +51,8 @@
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;
Modified: firebird/trunk/src/msgs/facilities2.sql
===================================================================
--- firebird/trunk/src/msgs/facilities2.sql 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/msgs/facilities2.sql 2014-04-30 15:12:12 UTC (rev 59508)
@@ -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)
Modified: firebird/trunk/src/msgs/messages2.sql
===================================================================
--- firebird/trunk/src/msgs/messages2.sql 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/msgs/messages2.sql 2014-04-30 15:12:12 UTC (rev 59508)
@@ -877,6 +877,8 @@
('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);
Modified: firebird/trunk/src/msgs/system_errors2.sql
===================================================================
--- firebird/trunk/src/msgs/system_errors2.sql 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/msgs/system_errors2.sql 2014-04-30 15:12:12 UTC (rev 59508)
@@ -776,6 +776,8 @@
(-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)
Modified: firebird/trunk/src/yvalve/keywords.cpp
===================================================================
--- firebird/trunk/src/yvalve/keywords.cpp 2014-04-30 12:20:59 UTC (rev 59507)
+++ firebird/trunk/src/yvalve/keywords.cpp 2014-04-30 15:12:12 UTC (rev 59508)
@@ -407,6 +407,7 @@
{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},
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|