8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 12:43:03 +01:00

Backport of fixed CORE-5861: GRANT OPTION is not checked for new object.

Also now GRANT OPTION can be checked for roles too.
This commit is contained in:
Roman Simakov 2018-06-26 16:44:32 +03:00
parent d41875903e
commit 1dfb1d2095
2 changed files with 59 additions and 39 deletions

View File

@ -11394,8 +11394,11 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
break;
}
case obj_procedure:
case obj_udf:
case obj_exception:
case obj_generator:
case obj_package_header:
{
checkGrantorCanGrantObject(tdbb, transaction,
tdbb->getAttachment()->att_user->usr_user_name.c_str(), priv, objName, objType);
@ -11519,6 +11522,8 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
const char* grantor, const char* privilege, const MetaName& relationName,
const MetaName& fieldName, bool topLevel)
{
const Attachment* attachment = tdbb->getAttachment();
// Verify that the input relation exists.
AutoCacheRequest request(tdbb, drq_gcg4, DYN_REQUESTS);
@ -11569,7 +11574,7 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
// If the current user is locksmith - allow all grants to occur
if (tdbb->getAttachment()->locksmith())
if (attachment->locksmith())
return;
// If this is a non-sql table, then the owner will probably not have any
@ -11604,34 +11609,36 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
request.reset(tdbb, drq_gcg1, DYN_REQUESTS);
const char* roleName = attachment->att_user->usr_sql_role_name.c_str();
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
PRV IN RDB$USER_PRIVILEGES WITH
PRV.RDB$USER = UPPERCASE(grantor) AND
PRV.RDB$USER_TYPE = obj_user AND
PRV IN RDB$USER_PRIVILEGES
WITH ((PRV.RDB$USER = UPPERCASE(grantor) AND PRV.RDB$USER_TYPE = obj_user) OR
(PRV.RDB$USER = UPPERCASE(roleName) AND (PRV.RDB$USER_TYPE = obj_sql_role))) AND
PRV.RDB$RELATION_NAME = relationName.c_str() AND
PRV.RDB$OBJECT_TYPE = obj_relation AND
PRV.RDB$PRIVILEGE = privilege
{
const bool hasGrantOption = !PRV.RDB$GRANT_OPTION.NULL && PRV.RDB$GRANT_OPTION;
if (PRV.RDB$FIELD_NAME.NULL)
{
if (PRV.RDB$GRANT_OPTION.NULL || !PRV.RDB$GRANT_OPTION)
goRel = 0;
else if (goRel)
if (goRel == -1)
goRel = hasGrantOption ? 1 : 0;
else if ((goRel == 0) && hasGrantOption)
goRel = 1;
}
else
{
if (PRV.RDB$GRANT_OPTION.NULL || !PRV.RDB$GRANT_OPTION)
{
if (fieldName.hasData() && fieldName == PRV.RDB$FIELD_NAME)
goFld = 0;
}
else
{
if (fieldName.hasData() && fieldName == PRV.RDB$FIELD_NAME)
if (goFld == -1)
goFld = hasGrantOption ? 1 : 0;
else if ((goFld == 0) && hasGrantOption)
goFld = 1;
}
}
if ( (goRel > 0) && (goFld > 0 || !fieldName.hasData()) )
break; // We've found a privilege with grant option and can break the loop
}
END_FOR
@ -11641,7 +11648,7 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
{
// no grant option for privilege .. on column .. of [base] table/view ..
status_exception::raise(Arg::PrivateDyn(topLevel ? 167 : 168) <<
privilege << fieldName.c_str() << relationName.c_str());
privilegeName(*privilege) << fieldName.c_str() << relationName.c_str());
}
if (goFld == -1)
@ -11650,14 +11657,14 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
{
// no grant option for privilege .. on [base] table/view .. (for column ..)
status_exception::raise(Arg::PrivateDyn(topLevel ? 169 : 170) <<
privilege << relationName.c_str() << fieldName.c_str());
privilegeName(*privilege) << relationName.c_str() << fieldName.c_str());
}
if (goRel == -1)
{
// no .. privilege with grant option on [base] table/view .. (for column ..)
status_exception::raise(Arg::PrivateDyn(topLevel ? 171 : 172) <<
privilege << relationName.c_str() << fieldName.c_str());
privilegeName(*privilege) << relationName.c_str() << fieldName.c_str());
}
}
}
@ -11666,13 +11673,13 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
if (goRel == 0)
{
// no grant option for privilege .. on table/view ..
status_exception::raise(Arg::PrivateDyn(173) << privilege << relationName.c_str());
status_exception::raise(Arg::PrivateDyn(173) << privilegeName(*privilege) << relationName.c_str());
}
if (goRel == -1)
{
// no .. privilege with grant option on table/view ..
status_exception::raise(Arg::PrivateDyn(174) << privilege << relationName.c_str());
status_exception::raise(Arg::PrivateDyn(174) << privilegeName(*privilege) << relationName.c_str());
}
}
@ -11763,29 +11770,35 @@ void GrantRevokeNode::checkGrantorCanGrantRole(thread_db* tdbb, jrd_tra* transac
void GrantRevokeNode::checkGrantorCanGrantDdl(thread_db* tdbb, jrd_tra* transaction,
const MetaName& grantor, const char* privilege, const MetaName& objName)
{
if (tdbb->getAttachment()->locksmith())
Attachment* attachment = tdbb->getAttachment();
if (attachment->locksmith())
return;
AutoCacheRequest request(tdbb, drq_l_grant_option, DYN_REQUESTS);
bool grantable = false;
const char* roleName = attachment->att_user->usr_sql_role_name.c_str();
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
WITH ((PRV.RDB$USER = UPPERCASE(grantor.c_str()) AND PRV.RDB$USER_TYPE = obj_user) OR
(PRV.RDB$USER = UPPERCASE(roleName) AND (PRV.RDB$USER_TYPE = obj_sql_role))) AND
PRV.RDB$RELATION_NAME EQ objName.c_str() AND
PRV.RDB$OBJECT_TYPE >= obj_database AND
PRV.RDB$PRIVILEGE EQ privilege
{
if (PRV.RDB$GRANT_OPTION == 1)
{
grantable = true;
break; // We've found a privilege with grant option and can break the loop
}
}
END_FOR
if (!grantable)
{
// no @1 privilege with grant option on DDL @2
status_exception::raise(Arg::PrivateDyn(299) << privilege << objName.c_str());
status_exception::raise(Arg::PrivateDyn(299) << privilegeName(*privilege) << objName.c_str());
}
}
@ -11794,28 +11807,35 @@ void GrantRevokeNode::checkGrantorCanGrantDdl(thread_db* tdbb, jrd_tra* transact
void GrantRevokeNode::checkGrantorCanGrantObject(thread_db* tdbb, jrd_tra* transaction, const char* grantor,
const char* privilege, const Firebird::MetaName& objName, SSHORT objType)
{
if (tdbb->getAttachment()->locksmith())
Attachment* attachment = tdbb->getAttachment();
if (attachment->locksmith())
return;
AutoCacheRequest request(tdbb, drq_l_grant_object, DYN_REQUESTS);
bool grantable = false;
const char* roleName = attachment->att_user->usr_sql_role_name.c_str();
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
PRV IN RDB$USER_PRIVILEGES
WITH (PRV.RDB$USER = UPPERCASE(grantor) AND PRV.RDB$USER_TYPE = obj_user) AND
WITH ((PRV.RDB$USER = UPPERCASE(grantor) AND PRV.RDB$USER_TYPE = obj_user) OR
(PRV.RDB$USER = UPPERCASE(roleName) AND (PRV.RDB$USER_TYPE = obj_sql_role))) AND
PRV.RDB$RELATION_NAME EQ objName.c_str() AND
PRV.RDB$OBJECT_TYPE >= obj_database AND
PRV.RDB$OBJECT_TYPE = objType AND
PRV.RDB$PRIVILEGE EQ privilege
{
if (PRV.RDB$GRANT_OPTION == 1)
{
grantable = true;
break; // We've found a privilege with grant option and can break the loop
}
}
END_FOR
if (!grantable)
{
// no @1 privilege with grant option on object @2
status_exception::raise(Arg::PrivateDyn(300) << privilege << objName.c_str());
status_exception::raise(Arg::PrivateDyn(300) << privilegeName(*privilege) << objName.c_str());
}
}

View File

@ -2166,19 +2166,19 @@ private:
{
switch (UPPER7(symbol))
{
case 'A': return "All";
case 'I': return "Insert";
case 'U': return "Update";
case 'D': return "Delete";
case 'S': return "Select";
case 'X': return "Execute";
case 'G': return "Usage";
case 'M': return "Role";
case 'R': return "Reference";
case 'A': return "ALL";
case 'I': return "INSERT";
case 'U': return "UPDATE";
case 'D': return "DELETE";
case 'S': return "SELECT";
case 'X': return "EXECUTE";
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";
case 'C': return "CREATE";
case 'L': return "ALTER";
case 'O': return "DROP";
}
return "<Unknown>";