|
From: <rom...@us...> - 2014-07-08 07:35:38
|
Revision: 59840
http://sourceforge.net/p/firebird/code/59840
Author: roman-simakov
Date: 2014-07-08 07:35:27 +0000 (Tue, 08 Jul 2014)
Log Message:
-----------
Fixed CORE-735: User rights for metadata changes.
We check DDL in DDL nodes and skip at vio level. vio level still exists for direct metadata editing.
Modified Paths:
--------------
firebird/trunk/lang_helpers/gds_codes.ftn
firebird/trunk/lang_helpers/gds_codes.pas
firebird/trunk/src/dsql/DdlNodes.epp
firebird/trunk/src/dsql/DdlNodes.h
firebird/trunk/src/dsql/Nodes.h
firebird/trunk/src/dsql/PackageNodes.epp
firebird/trunk/src/dsql/PackageNodes.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/ids.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/jrd/Database.h
firebird/trunk/src/jrd/acl.h
firebird/trunk/src/jrd/constants.h
firebird/trunk/src/jrd/drq.h
firebird/trunk/src/jrd/filters.cpp
firebird/trunk/src/jrd/grant.epp
firebird/trunk/src/jrd/ini.epp
firebird/trunk/src/jrd/intl.h
firebird/trunk/src/jrd/jrd.h
firebird/trunk/src/jrd/met.epp
firebird/trunk/src/jrd/obj.h
firebird/trunk/src/jrd/relations.h
firebird/trunk/src/jrd/scl.epp
firebird/trunk/src/jrd/scl.h
firebird/trunk/src/jrd/scl_proto.h
firebird/trunk/src/jrd/vio.cpp
firebird/trunk/src/msgs/facilities2.sql
firebird/trunk/src/msgs/messages2.sql
firebird/trunk/src/msgs/system_errors2.sql
Added Paths:
-----------
firebird/trunk/doc/sql.extensions/README.ddl_access.txt
Added: firebird/trunk/doc/sql.extensions/README.ddl_access.txt
===================================================================
--- firebird/trunk/doc/sql.extensions/README.ddl_access.txt (rev 0)
+++ firebird/trunk/doc/sql.extensions/README.ddl_access.txt 2014-07-08 07:35:27 UTC (rev 59840)
@@ -0,0 +1,35 @@
+SQL Language Extension: GRANT/REVOKE permissions on DDL operations
+
+ Implements capability to manage permissions on DDL operations.
+
+Author:
+ Red Soft Corporation, roman.simakov(at)red-soft.biz
+
+Syntax is:
+
+GRANT CREATE <OBJECT> TO USER|ROLE [with grant option];
+GRANT ALTER ANY <OBJECT> TO USER|ROLE [with grant option];
+GRANT DROP ANY <OBJECT> TO USER|ROLE [with grant option];
+
+REVOKE [grant option for] CREATE <OBJECT> FROM USER|ROLE;
+REVOKE [grant option for] ALTER ANY <OBJECT> FROM USER|ROLE;
+REVOKE [grant option for] DROP ANY <OBJECT> FROM USER|ROLE;
+
+Where <OBJECT> could be:
+TABLE, VIEW, PROCEDURE, FUNCTION, PACKAGE, GENERATOR, SEQUENCE, DOMAIN,
+EXCEPTION, ROLE, SHADOW, DATABASE, CHARACTER SET, COLLATION, FILTER
+
+Description:
+
+Makes it possible to grant and revoke privileges on DDL operations.
+
+DDL operations for managing triggers and indices re-use table privileges.
+
+If ANY keyword is used a user will be able to perform operation on any object. Otherwise only on object which he owns.
+If ANY keyword was used due GRANT operation it also must be used in according REVOKE operation.
+
+Sample:
+
+GRANT CREATE TABLE TO Joe;
+GRANT ALTER ANY TABLE TO Joe;
+REVOKE CREATE TABLE FROM Joe;
Property changes on: firebird/trunk/doc/sql.extensions/README.ddl_access.txt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Rev URL
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: firebird/trunk/lang_helpers/gds_codes.ftn
===================================================================
--- firebird/trunk/lang_helpers/gds_codes.ftn 2014-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/lang_helpers/gds_codes.ftn 2014-07-08 07:35:27 UTC (rev 59840)
@@ -1598,6 +1598,10 @@
PARAMETER (GDS__cursor_not_positioned = 335545092)
INTEGER*4 GDS__dup_attribute
PARAMETER (GDS__dup_attribute = 335545093)
+ INTEGER*4 GDS__dyn_no_priv
+ PARAMETER (GDS__dyn_no_priv = 335545094)
+ INTEGER*4 GDS__dsql_cant_grant_option
+ PARAMETER (GDS__dsql_cant_grant_option = 335545095)
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-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/lang_helpers/gds_codes.pas 2014-07-08 07:35:27 UTC (rev 59840)
@@ -806,6 +806,8 @@
gds_set_invalid_role = 335545091;
gds_cursor_not_positioned = 335545092;
gds_dup_attribute = 335545093;
+ gds_dyn_no_priv = 335545094;
+ gds_dsql_cant_grant_option = 335545095;
gds_gfix_db_name = 335740929;
gds_gfix_invalid_sw = 335740930;
gds_gfix_incmp_sw = 335740932;
Modified: firebird/trunk/src/dsql/DdlNodes.epp
===================================================================
--- firebird/trunk/src/dsql/DdlNodes.epp 2014-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/dsql/DdlNodes.epp 2014-07-08 07:35:27 UTC (rev 59840)
@@ -747,7 +747,16 @@
//----------------------
+SecureDdlNodeExecute::SecureDdlNodeExecute(thread_db* tdbb, DdlNode* ddlNode,
+ DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction): _tdbb(tdbb)
+{
+ if (ddlNode->checkPermission(tdbb, transaction))
+ tdbb->tdbb_flags |= TDBB_trusted_ddl;
+ ddlNode->execute(tdbb, dsqlScratch, transaction);
+}
+
+
// Delete a security class.
bool DdlNode::deleteSecurityClass(thread_db* tdbb, jrd_tra* transaction,
const MetaName& secClass)
@@ -962,6 +971,12 @@
charSet.c_str(), defaultCollation.c_str());
}
+bool AlterCharSetNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_charset(tdbb, charSet, SCL_alter);
+ return true;
+}
+
void AlterCharSetNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -1030,6 +1045,13 @@
objType, objName.c_str(), this->text.c_str());
}
+bool CommentOnNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ //DDL_TODO
+ // Probably requires migration code from execute with caching some query results for reuse in execute later.
+ return false;
+}
+
// select rdb$relation_name from rdb$relation_fields where rdb$field_name = 'RDB$DESCRIPTION';
// gives the list of objects that accept descriptions. At FB2 time, the only
// subobjects with descriptions are relation's fields and procedure's parameters.
@@ -1357,6 +1379,17 @@
return DdlNode::dsqlPass(dsqlScratch);
}
+bool CreateAlterFunctionNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ dsc dscName;
+ dscName.makeText(name.length(), CS_METADATA, (UCHAR*)name.c_str());
+ if (alter)
+ SCL_check_function(tdbb, &dscName, SCL_alter);
+ else
+ SCL_check_create_access(tdbb, SCL_object_function);
+ return true;
+}
+
void CreateAlterFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -1975,6 +2008,14 @@
name.c_str(), clauses.name.c_str(), clauses.udfModule.c_str());
}
+bool AlterExternalFunctionNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ dsc dscName;
+ dscName.makeText(name.length(), CS_METADATA, (UCHAR*)name.c_str());
+ SCL_check_function(tdbb, &dscName, SCL_alter);
+ return true;
+}
+
// Allow changing the entry point and/or the module name of a UDF.
void AlterExternalFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
@@ -2092,6 +2133,14 @@
return DdlNode::dsqlPass(dsqlScratch);
}
+bool DropFunctionNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ dsc dscName;
+ dscName.makeText(name.length(), CS_METADATA, (UCHAR*)name.c_str());
+ SCL_check_function(tdbb, &dscName, SCL_drop);
+ return true;
+}
+
void DropFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -2277,6 +2326,17 @@
return DdlNode::dsqlPass(dsqlScratch);
}
+bool CreateAlterProcedureNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ dsc dscName;
+ dscName.makeText(name.length(), CS_METADATA, (UCHAR*)name.c_str());
+ if (alter)
+ SCL_check_procedure(tdbb, &dscName, SCL_alter);
+ else
+ SCL_check_create_access(tdbb, SCL_object_procedure);
+ return true;
+}
+
void CreateAlterProcedureNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -2820,6 +2880,14 @@
return DdlNode::dsqlPass(dsqlScratch);
}
+bool DropProcedureNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ dsc dscName;
+ dscName.makeText(name.length(), CS_METADATA, (UCHAR*)name.c_str());
+ SCL_check_procedure(tdbb, &dscName, SCL_drop);
+ return true;
+}
+
void DropProcedureNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -3075,6 +3143,14 @@
return DdlNode::dsqlPass(dsqlScratch);
}
+bool CreateAlterTriggerNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ dsc dscName;
+ dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*)relationName.c_str());
+ SCL_check_relation(tdbb, &dscName, SCL_alter);
+ return true;
+}
+
void CreateAlterTriggerNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -3082,9 +3158,6 @@
Attachment* const attachment = transaction->getAttachment();
- if (relationName.isEmpty() && !attachment->locksmith())
- status_exception::raise(Arg::Gds(isc_adm_task_denied));
-
source.ltrim("\n\r\t ");
// run all statements under savepoint control
@@ -3248,6 +3321,32 @@
return DdlNode::dsqlPass(dsqlScratch);
}
+bool DropTriggerNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ dsc dscName;
+ MetaName relationName;
+
+ AutoCacheRequest request(tdbb, drq_l_trigger_relname, DYN_REQUESTS);
+
+ FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ X IN RDB$TRIGGERS
+ WITH X.RDB$TRIGGER_NAME EQ name.c_str()
+ {
+ relationName = X.RDB$RELATION_NAME;
+ }
+ END_FOR
+
+ if (relationName.isEmpty())
+ {
+ // msg 48: "Index not found"
+ status_exception::raise(Arg::PrivateDyn(48));
+ }
+
+ dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*)relationName.c_str());
+ SCL_check_relation(tdbb, &dscName, SCL_alter);
+ return true;
+}
+
void DropTriggerNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -3371,6 +3470,12 @@
attributesOn, attributesOff);
}
+bool CreateCollationNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_create_access(tdbb, SCL_object_collation);
+ return true;
+}
+
void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -3583,6 +3688,12 @@
name.c_str());
}
+bool DropCollationNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_collation(tdbb, name, SCL_drop);
+ return true;
+}
+
void DropCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -3732,6 +3843,12 @@
" " + nameTypeStr + "\n";
}
+bool CreateDomainNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_create_access(tdbb, SCL_object_domain);
+ return true;
+}
+
void CreateDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -4250,6 +4367,12 @@
" %s\n", name.c_str());
}
+bool AlterDomainNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_domain(tdbb, name, SCL_alter);
+ return true;
+}
+
void AlterDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -4266,6 +4389,7 @@
WITH FLD.RDB$FIELD_NAME EQ name.c_str()
{
found = true;
+
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
DDL_TRIGGER_ALTER_DOMAIN, name);
@@ -4565,6 +4689,12 @@
name.c_str());
}
+bool DropDomainNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_domain(tdbb, name, SCL_drop);
+ return true;
+}
+
void DropDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -4685,6 +4815,15 @@
name.c_str(), create, alter, message.c_str());
}
+bool CreateAlterExceptionNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ if (alter)
+ SCL_check_exception(tdbb, name, SCL_alter);
+ else
+ SCL_check_create_access(tdbb, SCL_object_exception);
+ return true;
+}
+
void CreateAlterExceptionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -4720,7 +4859,6 @@
{
Attachment* const attachment = transaction->getAttachment();
const string& userName = attachment->att_user->usr_user_name;
-
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
DDL_TRIGGER_CREATE_EXCEPTION, name);
@@ -4811,6 +4949,12 @@
name.c_str());
}
+bool DropExceptionNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_exception(tdbb, name, SCL_drop);
+ return true;
+}
+
void DropExceptionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -4869,6 +5013,15 @@
name.c_str());
}
+bool CreateAlterSequenceNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ if (alter)
+ SCL_check_generator(tdbb, name, SCL_alter);
+ else
+ SCL_check_create_access(tdbb, SCL_object_generator);
+ return true;
+}
+
void CreateAlterSequenceNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -5116,6 +5269,12 @@
name.c_str());
}
+bool DropSequenceNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_generator(tdbb, name, SCL_drop);
+ return true;
+}
+
void DropSequenceNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
// run all statements under savepoint control
@@ -6552,6 +6711,12 @@
name.c_str());
}
+bool CreateRelationNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_create_access(tdbb, SCL_object_table);
+ return true;
+}
+
void CreateRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -6676,11 +6841,30 @@
name.c_str());
}
+bool AlterRelationNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ dsc dscName;
+ dscName.makeText(name.length(), CS_METADATA, (UCHAR*)name.c_str());
+ SCL_check_relation(tdbb, &dscName, SCL_alter);
+ return true;
+}
+
void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
saveRelation(tdbb, dsqlScratch, name, false, false);
+ dsql_rel* relation;
+ relation = METD_get_relation(dsqlScratch->getTransaction(), dsqlScratch, name);
+
+ if (!relation || (relation && (relation->rel_flags & REL_view)))
+ {
+ status_exception::raise(
+ Arg::Gds(isc_sqlerr) << Arg::Num(-607) <<
+ Arg::Gds(isc_dsql_command_err) <<
+ Arg::Gds(isc_dsql_table_not_found) << name);
+ }
+
if (!dsqlScratch->relation)
{
//// TODO: <Missing arg #1 - possibly status vector overflow>
@@ -7353,6 +7537,17 @@
name.c_str());
}
+bool DropRelationNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ dsc dscName;
+ dscName.makeText(name.length(), CS_METADATA, (UCHAR*)name.c_str());
+ if (view)
+ SCL_check_view(tdbb, &dscName, SCL_drop);
+ else
+ SCL_check_relation(tdbb, &dscName, SCL_drop);
+ return true;
+}
+
void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -7587,6 +7782,17 @@
return DdlNode::dsqlPass(dsqlScratch);
}
+bool CreateAlterViewNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ dsc dscName;
+ dscName.makeText(name.length(), CS_METADATA, (UCHAR*)name.c_str());
+ if (alter)
+ SCL_check_view(tdbb, &dscName, SCL_alter);
+ else
+ SCL_check_create_access(tdbb, SCL_object_view);
+ return true;
+}
+
void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -7642,7 +7848,6 @@
REL.RDB$VIEW_BLR NOT MISSING
{
found = true;
-
MODIFY REL
attachment->storeMetaDataBlob(tdbb, transaction, &REL.RDB$VIEW_SOURCE, source);
attachment->storeBinaryBlob(tdbb, transaction, &REL.RDB$VIEW_BLR,
@@ -8709,6 +8914,15 @@
name.c_str());
}
+bool CreateIndexNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ dsc dscName;
+ const MetaName &relationName = relation->dsqlName;
+ dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*)relationName.c_str());
+ SCL_check_relation(tdbb, &dscName, SCL_alter);
+ return true;
+}
+
// Define an index.
void CreateIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
@@ -8768,6 +8982,32 @@
name.c_str(), active);
}
+bool AlterIndexNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ dsc dscName;
+ MetaName relationName;
+
+ AutoCacheRequest request(tdbb, drq_l_index_relname, DYN_REQUESTS);
+
+ FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ IDX IN RDB$INDICES
+ WITH IDX.RDB$INDEX_NAME EQ name.c_str()
+ {
+ relationName = IDX.RDB$RELATION_NAME;
+ }
+ END_FOR
+
+ if (relationName.isEmpty())
+ {
+ // msg 48: "Index not found"
+ status_exception::raise(Arg::PrivateDyn(48));
+ }
+
+ dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*)relationName.c_str());
+ SCL_check_relation(tdbb, &dscName, SCL_alter);
+ return true;
+}
+
void AlterIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
// run all statements under savepoint control
@@ -8814,6 +9054,32 @@
name.c_str());
}
+bool SetStatisticsNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ dsc dscName;
+ MetaName relationName;
+
+ AutoCacheRequest request(tdbb, drq_l_index_relname, DYN_REQUESTS);
+
+ FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ IDX IN RDB$INDICES
+ WITH IDX.RDB$INDEX_NAME EQ name.c_str()
+ {
+ relationName = IDX.RDB$RELATION_NAME;
+ }
+ END_FOR
+
+ if (relationName.isEmpty())
+ {
+ // msg 48: "Index not found"
+ status_exception::raise(Arg::PrivateDyn(48));
+ }
+
+ dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*)relationName.c_str());
+ SCL_check_relation(tdbb, &dscName, SCL_alter);
+ return true;
+}
+
void SetStatisticsNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
// run all statements under savepoint control
@@ -8879,6 +9145,32 @@
name.c_str());
}
+bool DropIndexNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ dsc dscName;
+ MetaName relationName;
+
+ AutoCacheRequest request(tdbb, drq_l_index_relname, DYN_REQUESTS);
+
+ FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ IDX IN RDB$INDICES
+ WITH IDX.RDB$INDEX_NAME EQ name.c_str()
+ {
+ relationName = IDX.RDB$RELATION_NAME;
+ }
+ END_FOR
+
+ if (relationName.isEmpty())
+ {
+ // msg 48: "Index not found"
+ status_exception::raise(Arg::PrivateDyn(48));
+ }
+
+ dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*)relationName.c_str());
+ SCL_check_relation(tdbb, &dscName, SCL_alter);
+ return true;
+}
+
void DropIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
// run all statements under savepoint control
@@ -8929,6 +9221,12 @@
name.c_str());
}
+bool CreateFilterNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_create_access(tdbb, SCL_object_filter);
+ return true;
+}
+
// Define a blob filter.
void CreateFilterNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScratch*/, jrd_tra* transaction)
{
@@ -8994,6 +9292,12 @@
name.c_str());
}
+bool DropFilterNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_filter(tdbb, name, SCL_drop);
+ return true;
+}
+
void DropFilterNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScratch*/, jrd_tra* transaction)
{
// run all statements under savepoint control
@@ -9032,11 +9336,14 @@
number);
}
+bool CreateShadowNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_database(tdbb, SCL_alter);
+ return true;
+}
+
void CreateShadowNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScratch*/, jrd_tra* transaction)
{
- if (!tdbb->getAttachment()->locksmith())
- status_exception::raise(Arg::Gds(isc_adm_task_denied));
-
// Should be caught by the parser.
if (number == 0)
{
@@ -9097,11 +9404,14 @@
number);
}
+bool DropShadowNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_database(tdbb, SCL_alter);
+ return true;
+}
+
void DropShadowNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScratch*/, jrd_tra* transaction)
{
- if (!tdbb->getAttachment()->locksmith())
- status_exception::raise(Arg::Gds(isc_adm_task_denied));
-
// run all statements under savepoint control
AutoSavePoint savePoint(tdbb, transaction);
@@ -9132,6 +9442,12 @@
name.c_str());
}
+bool CreateRoleNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_create_access(tdbb, SCL_object_role);
+ return true;
+}
+
void CreateRoleNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
MetaName ownerName(tdbb->getAttachment()->att_user->usr_user_name);
@@ -9269,6 +9585,12 @@
ddl += '"';
}
+bool MappingNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ //DDL_TODO
+ return false;
+}
+
// It's purpose is to add/drop mapping from any security name to DB security object.
void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
@@ -9660,6 +9982,12 @@
name.c_str());
}
+bool DropRoleNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_role(tdbb, name, SCL_drop);
+ return true;
+}
+
void DropRoleNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
MetaName user(tdbb->getAttachment()->att_user->usr_user_name);
@@ -9678,7 +10006,7 @@
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
DDL_TRIGGER_DROP_ROLE, name);
- const MetaName roleOwner(ROL.RDB$OWNER_NAME);
+
if (ROL.RDB$SYSTEM_FLAG != 0)
{
@@ -9686,29 +10014,22 @@
status_exception::raise(Arg::PrivateDyn(284) << name);
}
- if (tdbb->getAttachment()->locksmith() || roleOwner == user)
- {
- AutoCacheRequest request2(tdbb, drq_del_role_1, DYN_REQUESTS);
+
+ AutoCacheRequest request2(tdbb, drq_del_role_1, DYN_REQUESTS);
- // The first OR clause finds all members of the role.
- // The 2nd OR clause finds all privileges granted to the role
- FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
- PRIV IN RDB$USER_PRIVILEGES
- WITH (PRIV.RDB$RELATION_NAME EQ name.c_str() AND PRIV.RDB$OBJECT_TYPE = obj_sql_role) OR
- (PRIV.RDB$USER EQ name.c_str() AND PRIV.RDB$USER_TYPE = obj_sql_role)
- {
- ERASE PRIV;
- }
- END_FOR
-
- ERASE ROL;
- }
- else
+ // The first OR clause finds all members of the role.
+ // The 2nd OR clause finds all privileges granted to the role
+ FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
+ PRIV IN RDB$USER_PRIVILEGES
+ WITH (PRIV.RDB$RELATION_NAME EQ name.c_str() AND PRIV.RDB$OBJECT_TYPE = obj_sql_role) OR
+ (PRIV.RDB$USER EQ name.c_str() AND PRIV.RDB$USER_TYPE = obj_sql_role)
{
- // msg 191: "only owner of SQL role or USR_locksmith could drop SQL role"
- status_exception::raise(Arg::PrivateDyn(191));
+ ERASE PRIV;
}
+ END_FOR
+ ERASE ROL;
+
found = true;
}
END_FOR
@@ -9759,6 +10080,13 @@
}
+bool CreateAlterUserNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ //DDL_TODO
+ return false;
+}
+
+
void CreateAlterUserNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
if (mode != USER_ADD && !password && !firstName && !middleName && !lastName &&
@@ -9872,6 +10200,12 @@
name.c_str());
}
+bool DropUserNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ //DDL_TODO
+ return false;
+}
+
void DropUserNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
// run all statements under savepoint control
@@ -9912,6 +10246,12 @@
isGrant);
}
+bool GrantRevokeNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ // GRANT OPTION will be checked in grantRevoke method
+ return false;
+}
+
void GrantRevokeNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
// run all statements under savepoint control
@@ -10033,6 +10373,26 @@
break;
}
+ if (options == 1) { // with grant option
+ switch (userType) {
+ case obj_procedure: {
+ ERRD_post(Arg::Gds(isc_dsql_cant_grant_option) << Arg::Str("procedures"));
+ break;
+ }
+ case obj_trigger: {
+ ERRD_post(Arg::Gds(isc_dsql_cant_grant_option) << Arg::Str("triggers"));
+ break;
+ }
+ case obj_view: {
+ ERRD_post(Arg::Gds(isc_dsql_cant_grant_option) << Arg::Str("views"));
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ }
+
MetaName grantorRevoker(grantor ?
*grantor : tdbb->getAttachment()->att_user->usr_user_name);
@@ -10171,6 +10531,10 @@
tdbb->getAttachment()->att_user->usr_user_name.c_str(), priv, objName,
field, true);
}
+ else if (objType >= obj_database) {
+ checkGrantorCanGrantDdl(tdbb, transaction,
+ tdbb->getAttachment()->att_user->usr_user_name.c_str(), priv, objName);
+ }
}
storePrivilege(tdbb, transaction, objName, user, field, pr, userType, objType,
@@ -10506,6 +10870,35 @@
}
}
+// Check if the grantor has grant option on DDL privilege
+void GrantRevokeNode::checkGrantorCanGrantDdl(thread_db* tdbb, jrd_tra* transaction,
+ const Firebird::MetaName& grantor, const char* privilege, const Firebird::MetaName& objName)
+{
+ if (tdbb->getAttachment()->locksmith())
+ return;
+
+ AutoCacheRequest request(tdbb, drq_l_grant_option, DYN_REQUESTS);
+ bool grantable = false;
+
+ FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ PRV IN RDB$USER_PRIVILEGES WITH
+ PRV.RDB$USER = UPPERCASE(grantor.c_str()) AND
+ PRV.RDB$USER_TYPE = obj_user AND
+ PRV.RDB$RELATION_NAME EQ objName.c_str() AND
+ PRV.RDB$OBJECT_TYPE >= obj_database AND
+ PRV.RDB$PRIVILEGE EQ privilege
+ {
+ grantable = PRV.RDB$GRANT_OPTION == 1;
+ }
+ END_FOR
+
+ if (!grantable)
+ {
+ // no .. privilege with grant option on DDL ..
+ status_exception::raise(Arg::PrivateDyn(174) << privilege << objName.c_str());
+ }
+}
+
void GrantRevokeNode::storePrivilege(thread_db* tdbb, jrd_tra* transaction, const MetaName& object,
const MetaName& user, const MetaName& field, const TEXT* privilege, SSHORT userType,
SSHORT objType, int option, const MetaName& grantor)
@@ -10582,6 +10975,12 @@
"AlterDatabaseNode\n");
}
+bool AlterDatabaseNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_database(tdbb, SCL_alter);
+ return true;
+}
+
void AlterDatabaseNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
Modified: firebird/trunk/src/dsql/DdlNodes.h
===================================================================
--- firebird/trunk/src/dsql/DdlNodes.h 2014-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/dsql/DdlNodes.h 2014-07-08 07:35:27 UTC (rev 59840)
@@ -153,6 +153,11 @@
text.printf("RecreateNode\n");
}
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction)
+ {
+ return dropNode.checkPermission(tdbb, transaction) && createNode->checkPermission(tdbb, transaction);
+ }
+
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
// run all statements under savepoint control
@@ -196,6 +201,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -226,6 +232,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -275,6 +282,7 @@
public:
virtual void print(Firebird::string& text) const;
virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -334,6 +342,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -366,6 +375,7 @@
public:
virtual void print(Firebird::string& text) const;
virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -410,6 +420,7 @@
public:
virtual void print(Firebird::string& text) const;
virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -467,6 +478,7 @@
public:
virtual void print(Firebird::string& text) const;
virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -551,6 +563,7 @@
public:
virtual void print(Firebird::string& text) const;
virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -624,6 +637,7 @@
public:
virtual void print(Firebird::string& text) const;
virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -663,6 +677,7 @@
public:
virtual void print(Firebird::string& text) const;
virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
void setAttribute(USHORT attribute)
@@ -721,6 +736,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -747,6 +763,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -785,6 +802,7 @@
const Firebird::MetaName& newFieldName);
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -822,6 +840,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -853,6 +872,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -889,6 +909,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -940,6 +961,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
@@ -982,6 +1004,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1335,6 +1358,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1362,6 +1386,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1392,6 +1417,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1429,6 +1455,7 @@
public:
virtual void print(Firebird::string& text) const;
virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1510,6 +1537,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1540,6 +1568,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1565,6 +1594,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1593,6 +1623,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1640,6 +1671,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1668,6 +1700,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1695,6 +1728,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1723,6 +1757,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1747,6 +1782,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1787,6 +1823,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1825,6 +1862,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1857,6 +1895,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1915,6 +1954,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1942,12 +1982,14 @@
object(NULL),
users(p),
grantAdminOption(false),
- grantor(NULL)
+ grantor(NULL),
+ isDdl(false)
{
}
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -1966,6 +2008,8 @@
const Firebird::MetaName& fieldName, bool topLevel);
static void checkGrantorCanGrantRole(thread_db* tdbb, jrd_tra* transaction,
const Firebird::MetaName& grantor, const Firebird::MetaName& roleName);
+ static void checkGrantorCanGrantDdl(thread_db* tdbb, jrd_tra* transaction,
+ const Firebird::MetaName& grantor, const char* privilege, const Firebird::MetaName& objName);
static void storePrivilege(thread_db* tdbb, jrd_tra* transaction,
const Firebird::MetaName& object, const Firebird::MetaName& user,
const Firebird::MetaName& field, const TEXT* privilege, SSHORT userType,
@@ -1987,6 +2031,10 @@
case 'G': return "Usage";
case 'M': return "Role";
case 'R': return "Reference";
+ //ddl
+ case 'C': return "Create";
+ case 'L': return "Alter";
+ case 'O': return "DROP";
}
return "<Unknown>";
@@ -2000,6 +2048,8 @@
Firebird::Array<GranteeClause> users;
bool grantAdminOption;
NestConst<Firebird::MetaName> grantor;
+ // ddl rights
+ bool isDdl;
};
@@ -2038,6 +2088,7 @@
}
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
Modified: firebird/trunk/src/dsql/Nodes.h
===================================================================
--- firebird/trunk/src/dsql/Nodes.h 2014-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/dsql/Nodes.h 2014-07-08 07:35:27 UTC (rev 59840)
@@ -152,6 +152,23 @@
};
+class DdlNode;
+
+class SecureDdlNodeExecute
+{
+public:
+ explicit SecureDdlNodeExecute(thread_db* tdbb, DdlNode* ddlNode,
+ DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+
+ ~SecureDdlNodeExecute()
+ {
+ _tdbb->tdbb_flags &= ~TDBB_trusted_ddl;
+ }
+
+private:
+ thread_db* _tdbb;
+};
+
class DdlNode : public Node
{
public:
@@ -167,6 +184,11 @@
const Firebird::MetaName& name, int type, const char* privileges);
public:
+ // Check permission on DDL operation. Return true if everything is OK.
+ // Raise an exception for bad permission.
+ // If returns false permissions will be check in old style at vio level as well as while direct RDB$ tables modify.
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction) = 0;
+
// Set the scratch's transaction when executing a node. Fact of accessing the scratch during
// execution is a hack.
void executeDdl(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
@@ -175,7 +197,7 @@
if (dsqlScratch)
dsqlScratch->setTransaction(transaction);
- execute(tdbb, dsqlScratch, transaction);
+ SecureDdlNodeExecute(tdbb, this, dsqlScratch, transaction);
}
virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
Modified: firebird/trunk/src/dsql/PackageNodes.epp
===================================================================
--- firebird/trunk/src/dsql/PackageNodes.epp 2014-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/dsql/PackageNodes.epp 2014-07-08 07:35:27 UTC (rev 59840)
@@ -34,6 +34,7 @@
#include "../dsql/pass1_proto.h"
#include "../common/StatusArg.h"
#include "../jrd/Attachment.h"
+#include "../jrd/scl_proto.h"
using namespace Firebird;
@@ -458,6 +459,18 @@
}
+bool CreateAlterPackageNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ dsc dscName;
+ dscName.makeText(name.length(), CS_METADATA, (UCHAR*)name.c_str());
+ if (alter)
+ SCL_check_package(tdbb, &dscName, SCL_alter);
+ else
+ SCL_check_create_access(tdbb, SCL_object_package);
+ return true;
+}
+
+
void CreateAlterPackageNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -619,6 +632,15 @@
}
+bool DropPackageNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ dsc dscName;
+ dscName.makeText(name.length(), CS_METADATA, (UCHAR*)name.c_str());
+ SCL_check_package(tdbb, &dscName, SCL_drop);
+ return true;
+}
+
+
void DropPackageNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -838,6 +860,13 @@
}
+bool CreatePackageBodyNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_create_access(tdbb, SCL_object_package);
+ return true;
+}
+
+
void CreatePackageBodyNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
@@ -1063,6 +1092,15 @@
}
+bool DropPackageBodyNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ dsc dscName;
+ dscName.makeText(name.length(), CS_METADATA, (UCHAR*)name.c_str());
+ SCL_check_package(tdbb, &dscName, SCL_drop);
+ return true;
+}
+
+
void DropPackageBodyNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{
Modified: firebird/trunk/src/dsql/PackageNodes.h
===================================================================
--- firebird/trunk/src/dsql/PackageNodes.h 2014-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/dsql/PackageNodes.h 2014-07-08 07:35:27 UTC (rev 59840)
@@ -84,6 +84,7 @@
public:
virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -126,6 +127,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -160,6 +162,7 @@
public:
virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
@@ -191,6 +194,7 @@
public:
virtual void print(Firebird::string& text) const;
+ virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
Modified: firebird/trunk/src/dsql/parse.y
===================================================================
--- firebird/trunk/src/dsql/parse.y 2014-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/dsql/parse.y 2014-07-08 07:35:27 UTC (rev 59840)
@@ -838,6 +838,14 @@
$node->grantAdminOption = $7;
$node->grantor = $8;
}
+ | ddl_privileges(NOTRIAL(&$node->privileges)) object
+ TO non_role_grantee_list(NOTRIAL(&$node->users)) grant_option granted_by
+ {
+ $node->object = $2;
+ $node->grantAdminOption = $5;
+ $node->grantor = $6;
+ $node->isDdl = true;
+ }
| role_name_list(NOTRIAL(&$node->roles)) TO role_grantee_list(NOTRIAL(&$node->users))
role_admin_option granted_by
{
@@ -846,6 +854,39 @@
}
;
+%type <granteeClause> object
+object : TABLE
+ { $$ = newNode<GranteeClause>(obj_relations, get_object_name(obj_relations)); }
+ | VIEW
+ { $$ = newNode<GranteeClause>(obj_views, get_object_name(obj_views)); }
+ | PROCEDURE
+ { $$ = newNode<GranteeClause>(obj_procedures, get_object_name(obj_procedures)); }
+ | FUNCTION
+ { $$ = newNode<GranteeClause>(obj_functions, get_object_name(obj_functions)); }
+ | PACKAGE
+ { $$ = newNode<GranteeClause>(obj_packages, get_object_name(obj_packages)); }
+ | GENERATOR
+ { $$ = newNode<GranteeClause>(obj_generators, get_object_name(obj_generators)); }
+ | SEQUENCE
+ { $$ = newNode<GranteeClause>(obj_generators, get_object_name(obj_generators)); }
+ | KW_DOMAIN
+ { $$ = newNode<GranteeClause>(obj_domains, get_object_name(obj_domains)); }
+ | EXCEPTION
+ { $$ = newNode<GranteeClause>(obj_exceptions, get_object_name(obj_exceptions)); }
+ | ROLE
+ { $$ = newNode<GranteeClause>(obj_roles, get_object_name(obj_roles)); }
+ | SHADOW
+ { $$ = newNode<GranteeClause>(obj_shadows, get_object_name(obj_shadows)); }
+ | DATABASE
+ { $$ = newNode<GranteeClause>(obj_database, get_object_name(obj_database)); }
+ | CHARACTER SET
+ { $$ = newNode<GranteeClause>(obj_charsets, get_object_name(obj_charsets)); }
+ | COLLATION
+ { $$ = newNode<GranteeClause>(obj_collations, get_object_name(obj_collations)); }
+ | FILTER
+ { $$ = newNode<GranteeClause>(obj_filters, get_object_name(obj_filters)); }
+ ;
+
table_noise
: // nothing
| TABLE
@@ -872,7 +913,6 @@
%type usage_privilege(<privilegeArray>)
usage_privilege($privilegeArray)
: USAGE { $privilegeArray->add(PrivilegeClause('G', NULL)); }
- ;
%type privilege(<privilegeArray>)
privilege($privilegeArray)
@@ -883,6 +923,26 @@
| REFERENCES column_parens_opt { $privilegeArray->add(PrivilegeClause('R', $2)); }
;
+%type ddl_privileges(<privilegeArray>)
+ddl_privileges($privilegeArray)
+ : ALL { $privilegeArray->add(PrivilegeClause('C', NULL)); $privilegeArray->add(PrivilegeClause('L', NULL)); $privilegeArray->add(PrivilegeClause('O', NULL)); }
+ | ALL PRIVILEGES { $privilegeArray->add(PrivilegeClause('C', NULL)); $privilegeArray->add(PrivilegeClause('L', NULL)); $privilegeArray->add(PrivilegeClause('O', NULL)); }
+ | ddl_privilege_list($privilegeArray)
+ ;
+
+%type ddl_privilege_list(<privilegeArray>)
+ddl_privilege_list($privilegeArray)
+ : ddl_privilege($privilegeArray)
+ | ddl_privilege_list ',' ddl_privilege($privilegeArray)
+ ;
+
+%type ddl_privilege(<privilegeArray>)
+ddl_privilege($privilegeArray)
+ : CREATE { $privilegeArray->add(PrivilegeClause('C', NULL)); }
+ | ALTER ANY { $privilegeArray->add(PrivilegeClause('L', NULL)); }
+ | DROP ANY { $privilegeArray->add(PrivilegeClause('O', NULL)); }
+ ;
+
%type <boolVal> grant_option
grant_option
: /* nothing */ { $$ = false; }
@@ -996,6 +1056,14 @@
$node->grantAdminOption = $1;
$node->grantor = $8;
}
+ | rev_grant_option ddl_privileges(NOTRIAL(&$node->privileges)) object
+ FROM non_role_grantee_list(NOTRIAL(&$node->users)) granted_by
+ {
+ $node->object = $3;
+ $node->grantAdminOption = $1;
+ $node->grantor = $6;
+ $node->isDdl = true;
+ }
| rev_admin_option role_name_list(NOTRIAL(&$node->roles))
FROM role_grantee_list(NOTRIAL(&$node->users)) granted_by
{
Modified: firebird/trunk/src/include/gen/codetext.h
===================================================================
--- firebird/trunk/src/include/gen/codetext.h 2014-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/include/gen/codetext.h 2014-07-08 07:35:27 UTC (rev 59840)
@@ -795,6 +795,8 @@
{"set_invalid_role", 335545091},
{"cursor_not_positioned", 335545092},
{"dup_attribute", 335545093},
+ {"dyn_no_priv", 335545094},
+ {"dsql_cant_grant_option", 335545095},
{"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-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/include/gen/iberror.h 2014-07-08 07:35:27 UTC (rev 59840)
@@ -829,6 +829,8 @@
const ISC_STATUS isc_set_invalid_role = 335545091L;
const ISC_STATUS isc_cursor_not_positioned = 335545092L;
const ISC_STATUS isc_dup_attribute = 335545093L;
+const ISC_STATUS isc_dyn_no_priv = 335545094L;
+const ISC_STATUS isc_dsql_cant_grant_option = 335545095L;
const ISC_STATUS isc_gfix_db_name = 335740929L;
const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
const ISC_STATUS isc_gfix_incmp_sw = 335740932L;
@@ -1287,7 +1289,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 = 1231;
+const ISC_STATUS isc_err_max = 1233;
#else /* c definitions */
@@ -2086,6 +2088,8 @@
#define isc_set_invalid_role 335545091L
#define isc_cursor_not_positioned 335545092L
#define isc_dup_attribute 335545093L
+#define isc_dyn_no_priv 335545094L
+#define isc_dsql_cant_grant_option 335545095L
#define isc_gfix_db_name 335740929L
#define isc_gfix_invalid_sw 335740930L
#define isc_gfix_incmp_sw 335740932L
@@ -2544,7 +2548,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 1231
+#define isc_err_max 1233
#endif
Modified: firebird/trunk/src/include/gen/ids.h
===================================================================
--- firebird/trunk/src/include/gen/ids.h 2014-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/include/gen/ids.h 2014-07-08 07:35:27 UTC (rev 59840)
@@ -277,6 +277,7 @@
const USHORT f_flt_input = 4;
const USHORT f_flt_output = 5;
const USHORT f_flt_sys_flag = 6;
+ const USHORT f_flt_class = 7;
// Relation 17 (RDB$TRIGGER_MESSAGES)
@@ -449,6 +450,7 @@
const USHORT f_rol_owner = 1;
const USHORT f_rol_desc = 2;
const USHORT f_rol_sys_flag = 3;
+ const USHORT f_rol_class = 4;
// Relation 32 (RDB$BACKUP_HISTORY)
Modified: firebird/trunk/src/include/gen/msgs.h
===================================================================
--- firebird/trunk/src/include/gen/msgs.h 2014-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/include/gen/msgs.h 2014-07-08 07:35:27 UTC (rev 59840)
@@ -798,6 +798,8 @@
{335545091, "Role @1 is invalid or unavailable"}, /* set_invalid_role */
{335545092, "Cursor @1 is not positioned in a valid record"}, /* cursor_not_positioned */
{335545093, "Duplicated user attribute @1"}, /* dup_attribute */
+ {335545094, "There is no privilege for this operation"}, /* dyn_no_priv */
+ {335545095, "Using GRANT OPTION on @1 not allowed"}, /* dsql_cant_grant_option */
{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-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/include/gen/sql_code.h 2014-07-08 07:35:27 UTC (rev 59840)
@@ -794,6 +794,8 @@
{335545091, -901}, /* 771 set_invalid_role */
{335545092, -596}, /* 772 cursor_not_positioned */
{335545093, -901}, /* 773 dup_attribute */
+ {335545094, -901}, /* 774 dyn_no_priv */
+ {335545095, -901}, /* 775 dsql_cant_grant_option */
{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-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/include/gen/sql_state.h 2014-07-08 07:35:27 UTC (rev 59840)
@@ -794,6 +794,8 @@
{335545091, "0P000"}, // 771 set_invalid_role
{335545092, "HY109"}, // 772 cursor_not_positioned
{335545093, "42702"}, // 773 dup_attribute
+ {335545094, "42000"}, // 774 dyn_no_priv
+ {335545095, "42000"}, // 775 dsql_cant_grant_option
{335740929, "00000"}, // 1 gfix_db_name
{335740930, "00000"}, // 2 gfix_invalid_sw
{335740932, "00000"}, // 4 gfix_incmp_sw
Modified: firebird/trunk/src/jrd/Database.h
===================================================================
--- firebird/trunk/src/jrd/Database.h 2014-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/jrd/Database.h 2014-07-08 07:35:27 UTC (rev 59840)
@@ -411,7 +411,6 @@
Firebird::PathName dbb_filename; // filename string
Firebird::PathName dbb_database_name; // database ID (file name or alias)
-
Firebird::MetaName dbb_owner; // database owner
Firebird::SyncObject dbb_pools_sync;
@@ -494,6 +493,7 @@
dbb_modules(*p),
dbb_extManager(*p),
dbb_filename(*p),
+ dbb_owner(*p),
dbb_database_name(*p),
dbb_pools(*p, 4),
dbb_sort_buffers(*p),
Modified: firebird/trunk/src/jrd/acl.h
===================================================================
--- firebird/trunk/src/jrd/acl.h 2014-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/jrd/acl.h 2014-07-08 07:35:27 UTC (rev 59840)
@@ -50,7 +50,10 @@
const int priv_execute = 11; // EXECUTE (procedure, function, package)
// New in FB3
const int priv_usage = 12; // USAGE (domain, exception, sequence, collation)
-const int priv_max = 13;
+const int priv_create = 13; // Create object
+const int priv_alter_any = 14; // Alter any object
+const int priv_drop_any = 15; // Drop any object
+const int priv_max = 16;
// Identification criterias
@@ -69,7 +72,8 @@
// New in FB3
const int id_package = 12; // Package name
const int id_function = 13; // Function name
-const int id_max = 14;
+const int id_filter = 14; // Filter name
+const int id_max = 15;
/* Format of access control list:
Modified: firebird/trunk/src/jrd/constants.h
===================================================================
--- firebird/trunk/src/jrd/constants.h 2014-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/jrd/constants.h 2014-07-08 07:35:27 UTC (rev 59840)
@@ -132,6 +132,8 @@
const int SQL_SECCLASS_PREFIX_LEN = 4;
const char* const SQL_FLD_SECCLASS_PREFIX = "SQL$GRANT";
const int SQL_FLD_SECCLASS_PREFIX_LEN = 9;
+const char* const GEN_SECCLASS_PREFIX = "GEN$";
+const int GEN_SECCLASS_PREFIX_LEN = 4;
// Automatically created check constraints for unnamed PRIMARY and UNIQUE declarations.
const char* const IMPLICIT_INTEGRITY_PREFIX = "INTEG_";
Modified: firebird/trunk/src/jrd/drq.h
===================================================================
--- firebird/trunk/src/jrd/drq.h 2014-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/jrd/drq.h 2014-07-08 07:35:27 UTC (rev 59840)
@@ -232,6 +232,9 @@
drq_e_gen_prvs, // erase generator privileges
drq_e_gfld_prvs, // erase domain privileges
drq_g_nxt_nbakhist_id, // generate next history ID for nbackup
+ drq_l_index_relname, // lookup relation name for index
+ drq_l_trigger_relname, // loopup relation name for trigger
+ drq_l_grant_option, // loopup grant option for privilege
drq_MAX
};
Modified: firebird/trunk/src/jrd/filters.cpp
===================================================================
--- firebird/trunk/src/jrd/filters.cpp 2014-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/jrd/filters.cpp 2014-07-08 07:35:27 UTC (rev 59840)
@@ -94,7 +94,10 @@
"update",
"references",
"execute",
- "usage"
+ "usage",
+ "create",
+ "alter_any",
+ "drop_any"
};
static const TEXT* acl_ids[id_max] =
Modified: firebird/trunk/src/jrd/grant.epp
===================================================================
--- firebird/trunk/src/jrd/grant.epp 2014-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/jrd/grant.epp 2014-07-08 07:35:27 UTC (rev 59840)
@@ -141,7 +141,11 @@
break;
default:
- break;
+ if (id >= obj_database &&
+ id < obj_type_MAX)
+ {
+ priv = OWNER_PRIVS;
+ }
}
grant_user(acl, owner, obj_user, priv);
@@ -472,6 +476,20 @@
}
END_FOR
}
+ else if (obj_type == obj_database)
+ {
+ s_class = attachment->att_security_class->scl_name;
+ default_class = "";
+ owner = tdbb->getDatabase()->dbb_owner;
+ view = false;
+ }
+ else
+ {
+ s_class = get_object_name(obj_type);
+ default_class = "";
+ owner = tdbb->getDatabase()->dbb_owner;
+ view = false;
+ }
}
@@ -882,6 +900,15 @@
case 'G':
priv |= SCL_usage;
break;
+ case 'C':
+ priv |= SCL_create;
+ break;
+ case 'L':
+ priv |= SCL_alter;
+ break;
+ case 'O':
+ priv |= SCL_drop;
+ break;
}
return priv;
Modified: firebird/trunk/src/jrd/ini.epp
===================================================================
--- firebird/trunk/src/jrd/ini.epp 2014-07-08 00:52:54 UTC (rev 59839)
+++ firebird/trunk/src/jrd/ini.epp 2014-07-08 07:35:27 UTC (rev 59840)
@@ -72,6 +72,7 @@
static void add_index_set(thread_db*);
static void add_security_to_sys_obj(thread_db*, const MetaName&, USHORT, const MetaName&,
USHORT = 0, const UCHAR* = NULL);
+static void add_security_class(thread_db* tdbb, const MetaName& class_name, USHORT acl_length, const UCHAR* acl);
static void add_security_to_sys_rel(thread_db*, const MetaName&,
const TEXT*, const USHORT, const UCHAR*);
static void store_generator(thread_db*, const gen*, AutoRequest&, const MetaName&);
@@ -477,6 +478,13 @@
add_security_to_sys_obj(tdbb, ownerName, obj_collation, collation->name, length, buffer);
}
+ for (int ddl_obj = obj_database + 1; ddl_obj < obj_type_MAX; ddl_obj++)
+ {
+ add_security_class(tdbb, get_object_name(ddl_obj), length, buffer);
+ }
+
+ add_security_to_sys_obj(tdbb, ownerName, obj_database, "", length, buffer);
+
// Add security on system tables
const UCHAR REL_OWNER_ACL[] =
@@ -1137,6 +1145,17 @@
}
END_FOR
}
+ else if (obj_type == obj_database)
+ {
+ FOR(REQUEST_HANDLE handle) DB IN RDB$DATABASE
+ {
+ MODIFY DB USING
+ DB.RDB$SECURITY_CLASS.NULL = FALSE;
+ PAD(security_class.c_str(), DB.RDB$SECURITY_CLASS);
+ END_MODIFY
+ }
+ END_FOR
+ }
handle.reset();
@@ -1155,6 +1174,30 @@
}
+// Add security class.
+static void add_security_class(thread_db* tdbb, const MetaName& class_name, USHORT acl_length, const UCHAR* acl)
+{
+ SET_TDBB(tdbb);
+ Jrd::Attachment* const attachment = tdbb->getAttachment();
+
+ bid blob_id;
+ attachment->storeBinaryBlob(td...
[truncated message content] |