Refactor some bits in aclchk.c in order to reduce code duplication.
This commit is contained in:
parent
164442fe7f
commit
7415e083e4
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.122 2005/11/22 18:17:07 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.123 2005/12/01 02:03:00 alvherre Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* See acl.h.
|
* See acl.h.
|
||||||
@ -42,28 +42,22 @@
|
|||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
|
|
||||||
static void ExecGrant_Relation(bool is_grant, List *objects, bool all_privs,
|
static void ExecGrant_Relation(InternalGrant *grantStmt);
|
||||||
AclMode privileges, List *grantees, bool grant_option,
|
static void ExecGrant_Database(InternalGrant *grantStmt);
|
||||||
DropBehavior behavior);
|
static void ExecGrant_Function(InternalGrant *grantStmt);
|
||||||
static void ExecGrant_Database(bool is_grant, List *objects, bool all_privs,
|
static void ExecGrant_Language(InternalGrant *grantStmt);
|
||||||
AclMode privileges, List *grantees, bool grant_option,
|
static void ExecGrant_Namespace(InternalGrant *grantStmt);
|
||||||
DropBehavior behavior);
|
static void ExecGrant_Tablespace(InternalGrant *grantStmt);
|
||||||
static void ExecGrant_Function(bool is_grant, List *objects, bool all_privs,
|
|
||||||
AclMode privileges, List *grantees, bool grant_option,
|
|
||||||
DropBehavior behavior);
|
|
||||||
static void ExecGrant_Language(bool is_grant, List *objects, bool all_privs,
|
|
||||||
AclMode privileges, List *grantees, bool grant_option,
|
|
||||||
DropBehavior behavior);
|
|
||||||
static void ExecGrant_Namespace(bool is_grant, List *objects, bool all_privs,
|
|
||||||
AclMode privileges, List *grantees, bool grant_option,
|
|
||||||
DropBehavior behavior);
|
|
||||||
static void ExecGrant_Tablespace(bool is_grant, List *objects, bool all_privs,
|
|
||||||
AclMode privileges, List *grantees, bool grant_option,
|
|
||||||
DropBehavior behavior);
|
|
||||||
static List *objectNamesToOids(GrantObjectType objtype, List *objnames);
|
|
||||||
|
|
||||||
|
static List *objectNamesToOids(GrantObjectType objtype, List *objnames);
|
||||||
static AclMode string_to_privilege(const char *privname);
|
static AclMode string_to_privilege(const char *privname);
|
||||||
static const char *privilege_to_string(AclMode privilege);
|
static const char *privilege_to_string(AclMode privilege);
|
||||||
|
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions,
|
||||||
|
bool all_privs, AclMode privileges,
|
||||||
|
Oid objectId, Oid grantorId,
|
||||||
|
AclObjectKind objkind, char *objname);
|
||||||
|
static AclMode pg_aclmask(AclObjectKind objkind, Oid table_oid, Oid roleid,
|
||||||
|
AclMode mask, AclMaskHow how);
|
||||||
|
|
||||||
|
|
||||||
#ifdef ACLDEBUG
|
#ifdef ACLDEBUG
|
||||||
@ -153,6 +147,91 @@ merge_acl_with_grant(Acl *old_acl, bool is_grant,
|
|||||||
return new_acl;
|
return new_acl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restrict the privileges to what we can actually grant, and emit
|
||||||
|
* the standards-mandated warning and error messages.
|
||||||
|
*/
|
||||||
|
static AclMode
|
||||||
|
restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
|
||||||
|
AclMode privileges, Oid objectId, Oid grantorId,
|
||||||
|
AclObjectKind objkind, char *objname)
|
||||||
|
{
|
||||||
|
AclMode this_privileges;
|
||||||
|
AclMode whole_mask;
|
||||||
|
|
||||||
|
switch (objkind)
|
||||||
|
{
|
||||||
|
case ACL_KIND_CLASS:
|
||||||
|
whole_mask = ACL_ALL_RIGHTS_RELATION;
|
||||||
|
break;
|
||||||
|
case ACL_KIND_DATABASE:
|
||||||
|
whole_mask = ACL_ALL_RIGHTS_DATABASE;
|
||||||
|
break;
|
||||||
|
case ACL_KIND_PROC:
|
||||||
|
whole_mask = ACL_ALL_RIGHTS_FUNCTION;
|
||||||
|
break;
|
||||||
|
case ACL_KIND_LANGUAGE:
|
||||||
|
whole_mask = ACL_ALL_RIGHTS_LANGUAGE;
|
||||||
|
break;
|
||||||
|
case ACL_KIND_NAMESPACE:
|
||||||
|
whole_mask = ACL_ALL_RIGHTS_NAMESPACE;
|
||||||
|
break;
|
||||||
|
case ACL_KIND_TABLESPACE:
|
||||||
|
whole_mask = ACL_ALL_RIGHTS_TABLESPACE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
elog(ERROR, "unrecognized object kind: %d", objkind);
|
||||||
|
/* not reached, but keep compiler quiet */
|
||||||
|
return ACL_NO_RIGHTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we found no grant options, consider whether to issue a hard
|
||||||
|
* error. Per spec, having any privilege at all on the object will
|
||||||
|
* get you by here.
|
||||||
|
*/
|
||||||
|
if (avail_goptions == ACL_NO_RIGHTS)
|
||||||
|
{
|
||||||
|
if (pg_aclmask(objkind, objectId, grantorId,
|
||||||
|
whole_mask | ACL_GRANT_OPTION_FOR(whole_mask),
|
||||||
|
ACLMASK_ANY) == ACL_NO_RIGHTS)
|
||||||
|
aclcheck_error(ACLCHECK_NO_PRIV, objkind, objname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restrict the operation to what we can actually grant or revoke, and
|
||||||
|
* issue a warning if appropriate. (For REVOKE this isn't quite what
|
||||||
|
* the spec says to do: the spec seems to want a warning only if no
|
||||||
|
* privilege bits actually change in the ACL. In practice that
|
||||||
|
* behavior seems much too noisy, as well as inconsistent with the
|
||||||
|
* GRANT case.)
|
||||||
|
*/
|
||||||
|
this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions);
|
||||||
|
if (is_grant)
|
||||||
|
{
|
||||||
|
if (this_privileges == 0)
|
||||||
|
ereport(WARNING,
|
||||||
|
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
|
||||||
|
errmsg("no privileges were granted")));
|
||||||
|
else if (!all_privs && this_privileges != privileges)
|
||||||
|
ereport(WARNING,
|
||||||
|
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
|
||||||
|
errmsg("not all privileges were granted")));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (this_privileges == 0)
|
||||||
|
ereport(WARNING,
|
||||||
|
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
|
||||||
|
errmsg("no privileges could be revoked")));
|
||||||
|
else if (!all_privs && this_privileges != privileges)
|
||||||
|
ereport(WARNING,
|
||||||
|
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
|
||||||
|
errmsg("not all privileges could be revoked")));
|
||||||
|
}
|
||||||
|
|
||||||
|
return this_privileges;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called to execute the utility commands GRANT and REVOKE
|
* Called to execute the utility commands GRANT and REVOKE
|
||||||
@ -160,13 +239,24 @@ merge_acl_with_grant(Acl *old_acl, bool is_grant,
|
|||||||
void
|
void
|
||||||
ExecuteGrantStmt(GrantStmt *stmt)
|
ExecuteGrantStmt(GrantStmt *stmt)
|
||||||
{
|
{
|
||||||
List *objects;
|
InternalGrant istmt;
|
||||||
List *grantees = NIL;
|
|
||||||
AclMode privileges;
|
|
||||||
ListCell *cell;
|
ListCell *cell;
|
||||||
bool all_privs;
|
char *errormsg;
|
||||||
AclMode all_privileges = (AclMode) 0;
|
AclMode all_privileges;
|
||||||
char *errormsg = NULL;
|
|
||||||
|
/*
|
||||||
|
* Turn the regular GrantStmt into the InternalGrant form.
|
||||||
|
*/
|
||||||
|
istmt.is_grant = stmt->is_grant;
|
||||||
|
istmt.objtype = stmt->objtype;
|
||||||
|
istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects);
|
||||||
|
/* all_privs to be filled below */
|
||||||
|
/* privileges to be filled below */
|
||||||
|
istmt.grantees = NIL;
|
||||||
|
/* filled below */
|
||||||
|
istmt.grant_option = stmt->grant_option;
|
||||||
|
istmt.behavior = stmt->behavior;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert the PrivGrantee list into an Oid list. Note that at this point
|
* Convert the PrivGrantee list into an Oid list. Note that at this point
|
||||||
@ -180,15 +270,15 @@ ExecuteGrantStmt(GrantStmt *stmt)
|
|||||||
PrivGrantee *grantee = (PrivGrantee *) lfirst(cell);
|
PrivGrantee *grantee = (PrivGrantee *) lfirst(cell);
|
||||||
|
|
||||||
if (grantee->rolname == NULL)
|
if (grantee->rolname == NULL)
|
||||||
grantees = lappend_oid(grantees, ACL_ID_PUBLIC);
|
istmt.grantees = lappend_oid(istmt.grantees, ACL_ID_PUBLIC);
|
||||||
else
|
else
|
||||||
grantees = lappend_oid(grantees,
|
istmt.grantees =
|
||||||
get_roleid_checked(grantee->rolname));
|
lappend_oid(istmt.grantees,
|
||||||
|
get_roleid_checked(grantee->rolname));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert stmt->privileges, a textual list, into an AclMode bitmask
|
* Convert stmt->privileges, a textual list, into an AclMode bitmask.
|
||||||
* appropiate for the given object class.
|
|
||||||
*/
|
*/
|
||||||
switch (stmt->objtype)
|
switch (stmt->objtype)
|
||||||
{
|
{
|
||||||
@ -217,19 +307,26 @@ ExecuteGrantStmt(GrantStmt *stmt)
|
|||||||
errormsg = _("invalid privilege type %s for tablespace");
|
errormsg = _("invalid privilege type %s for tablespace");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
/* keep compiler quiet */
|
||||||
|
all_privileges = ACL_NO_RIGHTS;
|
||||||
|
errormsg = NULL;
|
||||||
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
|
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
|
||||||
(int) stmt->objtype);
|
(int) stmt->objtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stmt->privileges == NIL)
|
if (stmt->privileges == NIL)
|
||||||
{
|
{
|
||||||
all_privs = true;
|
istmt.all_privs = true;
|
||||||
privileges = all_privileges;
|
/*
|
||||||
|
* will be turned into ACL_ALL_RIGHTS_* by the internal routines
|
||||||
|
* depending on the object type
|
||||||
|
*/
|
||||||
|
istmt.privileges = ACL_NO_RIGHTS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
all_privs = false;
|
istmt.all_privs = false;
|
||||||
privileges = ACL_NO_RIGHTS;
|
istmt.privileges = ACL_NO_RIGHTS;
|
||||||
foreach(cell, stmt->privileges)
|
foreach(cell, stmt->privileges)
|
||||||
{
|
{
|
||||||
char *privname = strVal(lfirst(cell));
|
char *privname = strVal(lfirst(cell));
|
||||||
@ -241,61 +338,44 @@ ExecuteGrantStmt(GrantStmt *stmt)
|
|||||||
errmsg(errormsg,
|
errmsg(errormsg,
|
||||||
privilege_to_string(priv))));
|
privilege_to_string(priv))));
|
||||||
|
|
||||||
privileges |= priv;
|
istmt.privileges |= priv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Turn the list of object names into an Oid list */
|
ExecGrantStmt_oids(&istmt);
|
||||||
objects = objectNamesToOids(stmt->objtype, stmt->objects);
|
|
||||||
|
|
||||||
ExecGrantStmt_oids(stmt->is_grant, stmt->objtype, objects, all_privs,
|
|
||||||
privileges, grantees, stmt->grant_option,
|
|
||||||
stmt->behavior);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ExecGrantStmt_oids
|
* ExecGrantStmt_oids
|
||||||
*
|
*
|
||||||
* "Internal" entrypoint for granting and revoking privileges. The arguments
|
* "Internal" entrypoint for granting and revoking privileges.
|
||||||
* it receives are lists of Oids or have been otherwise converted from text
|
|
||||||
* format to internal format.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ExecGrantStmt_oids(bool is_grant, GrantObjectType objtype, List *objects,
|
ExecGrantStmt_oids(InternalGrant *istmt)
|
||||||
bool all_privs, AclMode privileges, List *grantees,
|
|
||||||
bool grant_option, DropBehavior behavior)
|
|
||||||
{
|
{
|
||||||
switch (objtype)
|
switch (istmt->objtype)
|
||||||
{
|
{
|
||||||
case ACL_OBJECT_RELATION:
|
case ACL_OBJECT_RELATION:
|
||||||
ExecGrant_Relation(is_grant, objects, all_privs, privileges,
|
ExecGrant_Relation(istmt);
|
||||||
grantees, grant_option, behavior);
|
|
||||||
break;
|
break;
|
||||||
case ACL_OBJECT_DATABASE:
|
case ACL_OBJECT_DATABASE:
|
||||||
ExecGrant_Database(is_grant, objects, all_privs, privileges,
|
ExecGrant_Database(istmt);
|
||||||
grantees, grant_option, behavior);
|
|
||||||
break;
|
break;
|
||||||
case ACL_OBJECT_FUNCTION:
|
case ACL_OBJECT_FUNCTION:
|
||||||
ExecGrant_Function(is_grant, objects, all_privs, privileges,
|
ExecGrant_Function(istmt);
|
||||||
grantees, grant_option, behavior);
|
|
||||||
break;
|
break;
|
||||||
case ACL_OBJECT_LANGUAGE:
|
case ACL_OBJECT_LANGUAGE:
|
||||||
ExecGrant_Language(is_grant, objects, all_privs, privileges,
|
ExecGrant_Language(istmt);
|
||||||
grantees, grant_option, behavior);
|
|
||||||
break;
|
break;
|
||||||
case ACL_OBJECT_NAMESPACE:
|
case ACL_OBJECT_NAMESPACE:
|
||||||
ExecGrant_Namespace(is_grant, objects, all_privs,
|
ExecGrant_Namespace(istmt);
|
||||||
privileges, grantees, grant_option,
|
|
||||||
behavior);
|
|
||||||
break;
|
break;
|
||||||
case ACL_OBJECT_TABLESPACE:
|
case ACL_OBJECT_TABLESPACE:
|
||||||
ExecGrant_Tablespace(is_grant, objects, all_privs,
|
ExecGrant_Tablespace(istmt);
|
||||||
privileges, grantees, grant_option,
|
|
||||||
behavior);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
|
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
|
||||||
(int) objtype);
|
(int) istmt->objtype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,19 +524,17 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ExecGrant_Relation(bool is_grant, List *objects, bool all_privs,
|
ExecGrant_Relation(InternalGrant *istmt)
|
||||||
AclMode privileges, List *grantees, bool grant_option,
|
|
||||||
DropBehavior behavior)
|
|
||||||
{
|
{
|
||||||
Relation relation;
|
Relation relation;
|
||||||
ListCell *cell;
|
ListCell *cell;
|
||||||
|
|
||||||
if (all_privs && privileges == ACL_NO_RIGHTS)
|
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
|
||||||
privileges = ACL_ALL_RIGHTS_RELATION;
|
istmt->privileges = ACL_ALL_RIGHTS_RELATION;
|
||||||
|
|
||||||
relation = heap_open(RelationRelationId, RowExclusiveLock);
|
relation = heap_open(RelationRelationId, RowExclusiveLock);
|
||||||
|
|
||||||
foreach(cell, objects)
|
foreach(cell, istmt->objects)
|
||||||
{
|
{
|
||||||
Oid relOid = lfirst_oid(cell);
|
Oid relOid = lfirst_oid(cell);
|
||||||
Datum aclDatum;
|
Datum aclDatum;
|
||||||
@ -512,56 +590,19 @@ ExecGrant_Relation(bool is_grant, List *objects, bool all_privs,
|
|||||||
old_acl = DatumGetAclPCopy(aclDatum);
|
old_acl = DatumGetAclPCopy(aclDatum);
|
||||||
|
|
||||||
/* Determine ID to do the grant as, and available grant options */
|
/* Determine ID to do the grant as, and available grant options */
|
||||||
select_best_grantor(GetUserId(), privileges,
|
select_best_grantor(GetUserId(), istmt->privileges,
|
||||||
old_acl, ownerId,
|
old_acl, ownerId,
|
||||||
&grantorId, &avail_goptions);
|
&grantorId, &avail_goptions);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we found no grant options, consider whether to issue a hard
|
* Restrict the privileges to what we can actually grant, and emit
|
||||||
* error. Per spec, having any privilege at all on the object will
|
* the standards-mandated warning and error messages.
|
||||||
* get you by here.
|
|
||||||
*/
|
*/
|
||||||
if (avail_goptions == ACL_NO_RIGHTS)
|
this_privileges =
|
||||||
{
|
restrict_and_check_grant(istmt->is_grant, avail_goptions,
|
||||||
if (pg_class_aclmask(relOid,
|
istmt->all_privs, istmt->privileges,
|
||||||
grantorId,
|
relOid, grantorId, ACL_KIND_CLASS,
|
||||||
ACL_ALL_RIGHTS_RELATION | ACL_GRANT_OPTION_FOR(ACL_ALL_RIGHTS_RELATION),
|
NameStr(pg_class_tuple->relname));
|
||||||
ACLMASK_ANY) == ACL_NO_RIGHTS)
|
|
||||||
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS,
|
|
||||||
NameStr(pg_class_tuple->relname));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Restrict the operation to what we can actually grant or revoke, and
|
|
||||||
* issue a warning if appropriate. (For REVOKE this isn't quite what
|
|
||||||
* the spec says to do: the spec seems to want a warning only if no
|
|
||||||
* privilege bits actually change in the ACL. In practice that
|
|
||||||
* behavior seems much too noisy, as well as inconsistent with the
|
|
||||||
* GRANT case.)
|
|
||||||
*/
|
|
||||||
this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions);
|
|
||||||
if (is_grant)
|
|
||||||
{
|
|
||||||
if (this_privileges == 0)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
|
|
||||||
errmsg("no privileges were granted")));
|
|
||||||
else if (!all_privs && this_privileges != privileges)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
|
|
||||||
errmsg("not all privileges were granted")));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (this_privileges == 0)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
|
|
||||||
errmsg("no privileges could be revoked")));
|
|
||||||
else if (!all_privs && this_privileges != privileges)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
|
|
||||||
errmsg("not all privileges could be revoked")));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate new ACL.
|
* Generate new ACL.
|
||||||
@ -571,9 +612,9 @@ ExecGrant_Relation(bool is_grant, List *objects, bool all_privs,
|
|||||||
*/
|
*/
|
||||||
noldmembers = aclmembers(old_acl, &oldmembers);
|
noldmembers = aclmembers(old_acl, &oldmembers);
|
||||||
|
|
||||||
new_acl = merge_acl_with_grant(old_acl, is_grant,
|
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
|
||||||
grant_option, behavior,
|
istmt->grant_option, istmt->behavior,
|
||||||
grantees, this_privileges,
|
istmt->grantees, this_privileges,
|
||||||
grantorId, ownerId);
|
grantorId, ownerId);
|
||||||
|
|
||||||
nnewmembers = aclmembers(new_acl, &newmembers);
|
nnewmembers = aclmembers(new_acl, &newmembers);
|
||||||
@ -595,7 +636,7 @@ ExecGrant_Relation(bool is_grant, List *objects, bool all_privs,
|
|||||||
|
|
||||||
/* Update the shared dependency ACL info */
|
/* Update the shared dependency ACL info */
|
||||||
updateAclDependencies(RelationRelationId, relOid,
|
updateAclDependencies(RelationRelationId, relOid,
|
||||||
ownerId, is_grant,
|
ownerId, istmt->is_grant,
|
||||||
noldmembers, oldmembers,
|
noldmembers, oldmembers,
|
||||||
nnewmembers, newmembers);
|
nnewmembers, newmembers);
|
||||||
|
|
||||||
@ -611,19 +652,17 @@ ExecGrant_Relation(bool is_grant, List *objects, bool all_privs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ExecGrant_Database(bool is_grant, List *objects, bool all_privs,
|
ExecGrant_Database(InternalGrant *istmt)
|
||||||
AclMode privileges, List *grantees, bool grant_option,
|
|
||||||
DropBehavior behavior)
|
|
||||||
{
|
{
|
||||||
Relation relation;
|
Relation relation;
|
||||||
ListCell *cell;
|
ListCell *cell;
|
||||||
|
|
||||||
if (all_privs && privileges == ACL_NO_RIGHTS)
|
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
|
||||||
privileges = ACL_ALL_RIGHTS_DATABASE;
|
istmt->privileges = ACL_ALL_RIGHTS_DATABASE;
|
||||||
|
|
||||||
relation = heap_open(DatabaseRelationId, RowExclusiveLock);
|
relation = heap_open(DatabaseRelationId, RowExclusiveLock);
|
||||||
|
|
||||||
foreach(cell, objects)
|
foreach(cell, istmt->objects)
|
||||||
{
|
{
|
||||||
Oid datId = lfirst_oid(cell);
|
Oid datId = lfirst_oid(cell);
|
||||||
Form_pg_database pg_database_tuple;
|
Form_pg_database pg_database_tuple;
|
||||||
@ -675,56 +714,19 @@ ExecGrant_Database(bool is_grant, List *objects, bool all_privs,
|
|||||||
old_acl = DatumGetAclPCopy(aclDatum);
|
old_acl = DatumGetAclPCopy(aclDatum);
|
||||||
|
|
||||||
/* Determine ID to do the grant as, and available grant options */
|
/* Determine ID to do the grant as, and available grant options */
|
||||||
select_best_grantor(GetUserId(), privileges,
|
select_best_grantor(GetUserId(), istmt->privileges,
|
||||||
old_acl, ownerId,
|
old_acl, ownerId,
|
||||||
&grantorId, &avail_goptions);
|
&grantorId, &avail_goptions);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we found no grant options, consider whether to issue a hard
|
* Restrict the privileges to what we can actually grant, and emit
|
||||||
* error. Per spec, having any privilege at all on the object will
|
* the standards-mandated warning and error messages.
|
||||||
* get you by here.
|
|
||||||
*/
|
*/
|
||||||
if (avail_goptions == ACL_NO_RIGHTS)
|
this_privileges =
|
||||||
{
|
restrict_and_check_grant(istmt->is_grant, avail_goptions,
|
||||||
if (pg_database_aclmask(HeapTupleGetOid(tuple),
|
istmt->all_privs, istmt->privileges,
|
||||||
grantorId,
|
datId, grantorId, ACL_KIND_DATABASE,
|
||||||
ACL_ALL_RIGHTS_DATABASE | ACL_GRANT_OPTION_FOR(ACL_ALL_RIGHTS_DATABASE),
|
NameStr(pg_database_tuple->datname));
|
||||||
ACLMASK_ANY) == ACL_NO_RIGHTS)
|
|
||||||
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_DATABASE,
|
|
||||||
NameStr(pg_database_tuple->datname));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Restrict the operation to what we can actually grant or revoke, and
|
|
||||||
* issue a warning if appropriate. (For REVOKE this isn't quite what
|
|
||||||
* the spec says to do: the spec seems to want a warning only if no
|
|
||||||
* privilege bits actually change in the ACL. In practice that
|
|
||||||
* behavior seems much too noisy, as well as inconsistent with the
|
|
||||||
* GRANT case.)
|
|
||||||
*/
|
|
||||||
this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions);
|
|
||||||
if (is_grant)
|
|
||||||
{
|
|
||||||
if (this_privileges == 0)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
|
|
||||||
errmsg("no privileges were granted")));
|
|
||||||
else if (!all_privs && this_privileges != privileges)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
|
|
||||||
errmsg("not all privileges were granted")));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (this_privileges == 0)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
|
|
||||||
errmsg("no privileges could be revoked")));
|
|
||||||
else if (!all_privs && this_privileges != privileges)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
|
|
||||||
errmsg("not all privileges could be revoked")));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate new ACL.
|
* Generate new ACL.
|
||||||
@ -734,9 +736,9 @@ ExecGrant_Database(bool is_grant, List *objects, bool all_privs,
|
|||||||
*/
|
*/
|
||||||
noldmembers = aclmembers(old_acl, &oldmembers);
|
noldmembers = aclmembers(old_acl, &oldmembers);
|
||||||
|
|
||||||
new_acl = merge_acl_with_grant(old_acl, is_grant,
|
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
|
||||||
grant_option, behavior,
|
istmt->grant_option, istmt->behavior,
|
||||||
grantees, this_privileges,
|
istmt->grantees, this_privileges,
|
||||||
grantorId, ownerId);
|
grantorId, ownerId);
|
||||||
|
|
||||||
nnewmembers = aclmembers(new_acl, &newmembers);
|
nnewmembers = aclmembers(new_acl, &newmembers);
|
||||||
@ -759,7 +761,7 @@ ExecGrant_Database(bool is_grant, List *objects, bool all_privs,
|
|||||||
|
|
||||||
/* Update the shared dependency ACL info */
|
/* Update the shared dependency ACL info */
|
||||||
updateAclDependencies(DatabaseRelationId, HeapTupleGetOid(tuple),
|
updateAclDependencies(DatabaseRelationId, HeapTupleGetOid(tuple),
|
||||||
ownerId, is_grant,
|
ownerId, istmt->is_grant,
|
||||||
noldmembers, oldmembers,
|
noldmembers, oldmembers,
|
||||||
nnewmembers, newmembers);
|
nnewmembers, newmembers);
|
||||||
|
|
||||||
@ -775,19 +777,17 @@ ExecGrant_Database(bool is_grant, List *objects, bool all_privs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ExecGrant_Function(bool is_grant, List *objects, bool all_privs,
|
ExecGrant_Function(InternalGrant *istmt)
|
||||||
AclMode privileges, List *grantees, bool grant_option,
|
|
||||||
DropBehavior behavior)
|
|
||||||
{
|
{
|
||||||
Relation relation;
|
Relation relation;
|
||||||
ListCell *cell;
|
ListCell *cell;
|
||||||
|
|
||||||
if (all_privs && privileges == ACL_NO_RIGHTS)
|
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
|
||||||
privileges = ACL_ALL_RIGHTS_FUNCTION;
|
istmt->privileges = ACL_ALL_RIGHTS_FUNCTION;
|
||||||
|
|
||||||
relation = heap_open(ProcedureRelationId, RowExclusiveLock);
|
relation = heap_open(ProcedureRelationId, RowExclusiveLock);
|
||||||
|
|
||||||
foreach(cell, objects)
|
foreach(cell, istmt->objects)
|
||||||
{
|
{
|
||||||
Oid funcId = lfirst_oid(cell);
|
Oid funcId = lfirst_oid(cell);
|
||||||
Form_pg_proc pg_proc_tuple;
|
Form_pg_proc pg_proc_tuple;
|
||||||
@ -830,56 +830,19 @@ ExecGrant_Function(bool is_grant, List *objects, bool all_privs,
|
|||||||
old_acl = DatumGetAclPCopy(aclDatum);
|
old_acl = DatumGetAclPCopy(aclDatum);
|
||||||
|
|
||||||
/* Determine ID to do the grant as, and available grant options */
|
/* Determine ID to do the grant as, and available grant options */
|
||||||
select_best_grantor(GetUserId(), privileges,
|
select_best_grantor(GetUserId(), istmt->privileges,
|
||||||
old_acl, ownerId,
|
old_acl, ownerId,
|
||||||
&grantorId, &avail_goptions);
|
&grantorId, &avail_goptions);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we found no grant options, consider whether to issue a hard
|
* Restrict the privileges to what we can actually grant, and emit
|
||||||
* error. Per spec, having any privilege at all on the object will
|
* the standards-mandated warning and error messages.
|
||||||
* get you by here.
|
|
||||||
*/
|
*/
|
||||||
if (avail_goptions == ACL_NO_RIGHTS)
|
this_privileges =
|
||||||
{
|
restrict_and_check_grant(istmt->is_grant, avail_goptions,
|
||||||
if (pg_proc_aclmask(funcId,
|
istmt->all_privs, istmt->privileges,
|
||||||
grantorId,
|
funcId, grantorId, ACL_KIND_PROC,
|
||||||
ACL_ALL_RIGHTS_FUNCTION | ACL_GRANT_OPTION_FOR(ACL_ALL_RIGHTS_FUNCTION),
|
NameStr(pg_proc_tuple->proname));
|
||||||
ACLMASK_ANY) == ACL_NO_RIGHTS)
|
|
||||||
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_PROC,
|
|
||||||
NameStr(pg_proc_tuple->proname));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Restrict the operation to what we can actually grant or revoke, and
|
|
||||||
* issue a warning if appropriate. (For REVOKE this isn't quite what
|
|
||||||
* the spec says to do: the spec seems to want a warning only if no
|
|
||||||
* privilege bits actually change in the ACL. In practice that
|
|
||||||
* behavior seems much too noisy, as well as inconsistent with the
|
|
||||||
* GRANT case.)
|
|
||||||
*/
|
|
||||||
this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions);
|
|
||||||
if (is_grant)
|
|
||||||
{
|
|
||||||
if (this_privileges == 0)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
|
|
||||||
errmsg("no privileges were granted")));
|
|
||||||
else if (!all_privs && this_privileges != privileges)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
|
|
||||||
errmsg("not all privileges were granted")));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (this_privileges == 0)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
|
|
||||||
errmsg("no privileges could be revoked")));
|
|
||||||
else if (!all_privs && this_privileges != privileges)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
|
|
||||||
errmsg("not all privileges could be revoked")));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate new ACL.
|
* Generate new ACL.
|
||||||
@ -889,9 +852,9 @@ ExecGrant_Function(bool is_grant, List *objects, bool all_privs,
|
|||||||
*/
|
*/
|
||||||
noldmembers = aclmembers(old_acl, &oldmembers);
|
noldmembers = aclmembers(old_acl, &oldmembers);
|
||||||
|
|
||||||
new_acl = merge_acl_with_grant(old_acl, is_grant,
|
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
|
||||||
grant_option, behavior,
|
istmt->grant_option, istmt->behavior,
|
||||||
grantees, this_privileges,
|
istmt->grantees, this_privileges,
|
||||||
grantorId, ownerId);
|
grantorId, ownerId);
|
||||||
|
|
||||||
nnewmembers = aclmembers(new_acl, &newmembers);
|
nnewmembers = aclmembers(new_acl, &newmembers);
|
||||||
@ -914,7 +877,7 @@ ExecGrant_Function(bool is_grant, List *objects, bool all_privs,
|
|||||||
|
|
||||||
/* Update the shared dependency ACL info */
|
/* Update the shared dependency ACL info */
|
||||||
updateAclDependencies(ProcedureRelationId, funcId,
|
updateAclDependencies(ProcedureRelationId, funcId,
|
||||||
ownerId, is_grant,
|
ownerId, istmt->is_grant,
|
||||||
noldmembers, oldmembers,
|
noldmembers, oldmembers,
|
||||||
nnewmembers, newmembers);
|
nnewmembers, newmembers);
|
||||||
|
|
||||||
@ -930,21 +893,19 @@ ExecGrant_Function(bool is_grant, List *objects, bool all_privs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ExecGrant_Language(bool is_grant, List *objects, bool all_privs,
|
ExecGrant_Language(InternalGrant *istmt)
|
||||||
AclMode privileges, List *grantees, bool grant_option,
|
|
||||||
DropBehavior behavior)
|
|
||||||
{
|
{
|
||||||
Relation relation;
|
Relation relation;
|
||||||
ListCell *cell;
|
ListCell *cell;
|
||||||
|
|
||||||
if (all_privs && privileges == ACL_NO_RIGHTS)
|
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
|
||||||
privileges = ACL_ALL_RIGHTS_LANGUAGE;
|
istmt->privileges = ACL_ALL_RIGHTS_LANGUAGE;
|
||||||
|
|
||||||
relation = heap_open(LanguageRelationId, RowExclusiveLock);
|
relation = heap_open(LanguageRelationId, RowExclusiveLock);
|
||||||
|
|
||||||
foreach(cell, objects)
|
foreach(cell, istmt->objects)
|
||||||
{
|
{
|
||||||
Oid langid = lfirst_oid(cell);
|
Oid langId = lfirst_oid(cell);
|
||||||
Form_pg_language pg_language_tuple;
|
Form_pg_language pg_language_tuple;
|
||||||
Datum aclDatum;
|
Datum aclDatum;
|
||||||
bool isNull;
|
bool isNull;
|
||||||
@ -965,10 +926,10 @@ ExecGrant_Language(bool is_grant, List *objects, bool all_privs,
|
|||||||
Oid *newmembers;
|
Oid *newmembers;
|
||||||
|
|
||||||
tuple = SearchSysCache(LANGOID,
|
tuple = SearchSysCache(LANGOID,
|
||||||
ObjectIdGetDatum(langid),
|
ObjectIdGetDatum(langId),
|
||||||
0, 0, 0);
|
0, 0, 0);
|
||||||
if (!HeapTupleIsValid(tuple))
|
if (!HeapTupleIsValid(tuple))
|
||||||
elog(ERROR, "cache lookup failed for language %u", langid);
|
elog(ERROR, "cache lookup failed for language %u", langId);
|
||||||
|
|
||||||
pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
|
pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
|
||||||
|
|
||||||
@ -995,56 +956,19 @@ ExecGrant_Language(bool is_grant, List *objects, bool all_privs,
|
|||||||
old_acl = DatumGetAclPCopy(aclDatum);
|
old_acl = DatumGetAclPCopy(aclDatum);
|
||||||
|
|
||||||
/* Determine ID to do the grant as, and available grant options */
|
/* Determine ID to do the grant as, and available grant options */
|
||||||
select_best_grantor(GetUserId(), privileges,
|
select_best_grantor(GetUserId(), istmt->privileges,
|
||||||
old_acl, ownerId,
|
old_acl, ownerId,
|
||||||
&grantorId, &avail_goptions);
|
&grantorId, &avail_goptions);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we found no grant options, consider whether to issue a hard
|
* Restrict the privileges to what we can actually grant, and emit
|
||||||
* error. Per spec, having any privilege at all on the object will
|
* the standards-mandated warning and error messages.
|
||||||
* get you by here.
|
|
||||||
*/
|
*/
|
||||||
if (avail_goptions == ACL_NO_RIGHTS)
|
this_privileges =
|
||||||
{
|
restrict_and_check_grant(istmt->is_grant, avail_goptions,
|
||||||
if (pg_language_aclmask(HeapTupleGetOid(tuple),
|
istmt->all_privs, istmt->privileges,
|
||||||
grantorId,
|
langId, grantorId, ACL_KIND_LANGUAGE,
|
||||||
ACL_ALL_RIGHTS_LANGUAGE | ACL_GRANT_OPTION_FOR(ACL_ALL_RIGHTS_LANGUAGE),
|
NameStr(pg_language_tuple->lanname));
|
||||||
ACLMASK_ANY) == ACL_NO_RIGHTS)
|
|
||||||
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_LANGUAGE,
|
|
||||||
NameStr(pg_language_tuple->lanname));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Restrict the operation to what we can actually grant or revoke, and
|
|
||||||
* issue a warning if appropriate. (For REVOKE this isn't quite what
|
|
||||||
* the spec says to do: the spec seems to want a warning only if no
|
|
||||||
* privilege bits actually change in the ACL. In practice that
|
|
||||||
* behavior seems much too noisy, as well as inconsistent with the
|
|
||||||
* GRANT case.)
|
|
||||||
*/
|
|
||||||
this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions);
|
|
||||||
if (is_grant)
|
|
||||||
{
|
|
||||||
if (this_privileges == 0)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
|
|
||||||
errmsg("no privileges were granted")));
|
|
||||||
else if (!all_privs && this_privileges != privileges)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
|
|
||||||
errmsg("not all privileges were granted")));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (this_privileges == 0)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
|
|
||||||
errmsg("no privileges could be revoked")));
|
|
||||||
else if (!all_privs && this_privileges != privileges)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
|
|
||||||
errmsg("not all privileges could be revoked")));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate new ACL.
|
* Generate new ACL.
|
||||||
@ -1054,9 +978,9 @@ ExecGrant_Language(bool is_grant, List *objects, bool all_privs,
|
|||||||
*/
|
*/
|
||||||
noldmembers = aclmembers(old_acl, &oldmembers);
|
noldmembers = aclmembers(old_acl, &oldmembers);
|
||||||
|
|
||||||
new_acl = merge_acl_with_grant(old_acl, is_grant,
|
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
|
||||||
grant_option, behavior,
|
istmt->grant_option, istmt->behavior,
|
||||||
grantees, this_privileges,
|
istmt->grantees, this_privileges,
|
||||||
grantorId, ownerId);
|
grantorId, ownerId);
|
||||||
|
|
||||||
nnewmembers = aclmembers(new_acl, &newmembers);
|
nnewmembers = aclmembers(new_acl, &newmembers);
|
||||||
@ -1079,7 +1003,7 @@ ExecGrant_Language(bool is_grant, List *objects, bool all_privs,
|
|||||||
|
|
||||||
/* Update the shared dependency ACL info */
|
/* Update the shared dependency ACL info */
|
||||||
updateAclDependencies(LanguageRelationId, HeapTupleGetOid(tuple),
|
updateAclDependencies(LanguageRelationId, HeapTupleGetOid(tuple),
|
||||||
ownerId, is_grant,
|
ownerId, istmt->is_grant,
|
||||||
noldmembers, oldmembers,
|
noldmembers, oldmembers,
|
||||||
nnewmembers, newmembers);
|
nnewmembers, newmembers);
|
||||||
|
|
||||||
@ -1095,19 +1019,17 @@ ExecGrant_Language(bool is_grant, List *objects, bool all_privs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ExecGrant_Namespace(bool is_grant, List *objects, bool all_privs,
|
ExecGrant_Namespace(InternalGrant *istmt)
|
||||||
AclMode privileges, List *grantees, bool grant_option,
|
|
||||||
DropBehavior behavior)
|
|
||||||
{
|
{
|
||||||
Relation relation;
|
Relation relation;
|
||||||
ListCell *cell;
|
ListCell *cell;
|
||||||
|
|
||||||
if (all_privs && privileges == ACL_NO_RIGHTS)
|
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
|
||||||
privileges = ACL_ALL_RIGHTS_NAMESPACE;
|
istmt->privileges = ACL_ALL_RIGHTS_NAMESPACE;
|
||||||
|
|
||||||
relation = heap_open(NamespaceRelationId, RowExclusiveLock);
|
relation = heap_open(NamespaceRelationId, RowExclusiveLock);
|
||||||
|
|
||||||
foreach(cell, objects)
|
foreach(cell, istmt->objects)
|
||||||
{
|
{
|
||||||
Oid nspid = lfirst_oid(cell);
|
Oid nspid = lfirst_oid(cell);
|
||||||
Form_pg_namespace pg_namespace_tuple;
|
Form_pg_namespace pg_namespace_tuple;
|
||||||
@ -1151,56 +1073,19 @@ ExecGrant_Namespace(bool is_grant, List *objects, bool all_privs,
|
|||||||
old_acl = DatumGetAclPCopy(aclDatum);
|
old_acl = DatumGetAclPCopy(aclDatum);
|
||||||
|
|
||||||
/* Determine ID to do the grant as, and available grant options */
|
/* Determine ID to do the grant as, and available grant options */
|
||||||
select_best_grantor(GetUserId(), privileges,
|
select_best_grantor(GetUserId(), istmt->privileges,
|
||||||
old_acl, ownerId,
|
old_acl, ownerId,
|
||||||
&grantorId, &avail_goptions);
|
&grantorId, &avail_goptions);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we found no grant options, consider whether to issue a hard
|
* Restrict the privileges to what we can actually grant, and emit
|
||||||
* error. Per spec, having any privilege at all on the object will
|
* the standards-mandated warning and error messages.
|
||||||
* get you by here.
|
|
||||||
*/
|
*/
|
||||||
if (avail_goptions == ACL_NO_RIGHTS)
|
this_privileges =
|
||||||
{
|
restrict_and_check_grant(istmt->is_grant, avail_goptions,
|
||||||
if (pg_namespace_aclmask(HeapTupleGetOid(tuple),
|
istmt->all_privs, istmt->privileges,
|
||||||
grantorId,
|
nspid, grantorId, ACL_KIND_NAMESPACE,
|
||||||
ACL_ALL_RIGHTS_NAMESPACE | ACL_GRANT_OPTION_FOR(ACL_ALL_RIGHTS_NAMESPACE),
|
NameStr(pg_namespace_tuple->nspname));
|
||||||
ACLMASK_ANY) == ACL_NO_RIGHTS)
|
|
||||||
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_NAMESPACE,
|
|
||||||
NameStr(pg_namespace_tuple->nspname));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Restrict the operation to what we can actually grant or revoke, and
|
|
||||||
* issue a warning if appropriate. (For REVOKE this isn't quite what
|
|
||||||
* the spec says to do: the spec seems to want a warning only if no
|
|
||||||
* privilege bits actually change in the ACL. In practice that
|
|
||||||
* behavior seems much too noisy, as well as inconsistent with the
|
|
||||||
* GRANT case.)
|
|
||||||
*/
|
|
||||||
this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions);
|
|
||||||
if (is_grant)
|
|
||||||
{
|
|
||||||
if (this_privileges == 0)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
|
|
||||||
errmsg("no privileges were granted")));
|
|
||||||
else if (!all_privs && this_privileges != privileges)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
|
|
||||||
errmsg("not all privileges were granted")));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (this_privileges == 0)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
|
|
||||||
errmsg("no privileges could be revoked")));
|
|
||||||
else if (!all_privs && this_privileges != privileges)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
|
|
||||||
errmsg("not all privileges could be revoked")));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate new ACL.
|
* Generate new ACL.
|
||||||
@ -1210,9 +1095,9 @@ ExecGrant_Namespace(bool is_grant, List *objects, bool all_privs,
|
|||||||
*/
|
*/
|
||||||
noldmembers = aclmembers(old_acl, &oldmembers);
|
noldmembers = aclmembers(old_acl, &oldmembers);
|
||||||
|
|
||||||
new_acl = merge_acl_with_grant(old_acl, is_grant,
|
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
|
||||||
grant_option, behavior,
|
istmt->grant_option, istmt->behavior,
|
||||||
grantees, this_privileges,
|
istmt->grantees, this_privileges,
|
||||||
grantorId, ownerId);
|
grantorId, ownerId);
|
||||||
|
|
||||||
nnewmembers = aclmembers(new_acl, &newmembers);
|
nnewmembers = aclmembers(new_acl, &newmembers);
|
||||||
@ -1235,7 +1120,7 @@ ExecGrant_Namespace(bool is_grant, List *objects, bool all_privs,
|
|||||||
|
|
||||||
/* Update the shared dependency ACL info */
|
/* Update the shared dependency ACL info */
|
||||||
updateAclDependencies(NamespaceRelationId, HeapTupleGetOid(tuple),
|
updateAclDependencies(NamespaceRelationId, HeapTupleGetOid(tuple),
|
||||||
ownerId, is_grant,
|
ownerId, istmt->is_grant,
|
||||||
noldmembers, oldmembers,
|
noldmembers, oldmembers,
|
||||||
nnewmembers, newmembers);
|
nnewmembers, newmembers);
|
||||||
|
|
||||||
@ -1251,19 +1136,17 @@ ExecGrant_Namespace(bool is_grant, List *objects, bool all_privs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ExecGrant_Tablespace(bool is_grant, List *objects, bool all_privs,
|
ExecGrant_Tablespace(InternalGrant *istmt)
|
||||||
AclMode privileges, List *grantees, bool grant_option,
|
|
||||||
DropBehavior behavior)
|
|
||||||
{
|
{
|
||||||
Relation relation;
|
Relation relation;
|
||||||
ListCell *cell;
|
ListCell *cell;
|
||||||
|
|
||||||
if (all_privs && privileges == ACL_NO_RIGHTS)
|
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
|
||||||
privileges = ACL_ALL_RIGHTS_TABLESPACE;
|
istmt->privileges = ACL_ALL_RIGHTS_TABLESPACE;
|
||||||
|
|
||||||
relation = heap_open(TableSpaceRelationId, RowExclusiveLock);
|
relation = heap_open(TableSpaceRelationId, RowExclusiveLock);
|
||||||
|
|
||||||
foreach(cell, objects)
|
foreach(cell, istmt->objects)
|
||||||
{
|
{
|
||||||
Oid tblId = lfirst_oid(cell);
|
Oid tblId = lfirst_oid(cell);
|
||||||
Form_pg_tablespace pg_tablespace_tuple;
|
Form_pg_tablespace pg_tablespace_tuple;
|
||||||
@ -1313,56 +1196,19 @@ ExecGrant_Tablespace(bool is_grant, List *objects, bool all_privs,
|
|||||||
old_acl = DatumGetAclPCopy(aclDatum);
|
old_acl = DatumGetAclPCopy(aclDatum);
|
||||||
|
|
||||||
/* Determine ID to do the grant as, and available grant options */
|
/* Determine ID to do the grant as, and available grant options */
|
||||||
select_best_grantor(GetUserId(), privileges,
|
select_best_grantor(GetUserId(), istmt->privileges,
|
||||||
old_acl, ownerId,
|
old_acl, ownerId,
|
||||||
&grantorId, &avail_goptions);
|
&grantorId, &avail_goptions);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we found no grant options, consider whether to issue a hard
|
* Restrict the privileges to what we can actually grant, and emit
|
||||||
* error. Per spec, having any privilege at all on the object will
|
* the standards-mandated warning and error messages.
|
||||||
* get you by here.
|
|
||||||
*/
|
*/
|
||||||
if (avail_goptions == ACL_NO_RIGHTS)
|
this_privileges =
|
||||||
{
|
restrict_and_check_grant(istmt->is_grant, avail_goptions,
|
||||||
if (pg_tablespace_aclmask(HeapTupleGetOid(tuple),
|
istmt->all_privs, istmt->privileges,
|
||||||
grantorId,
|
tblId, grantorId, ACL_KIND_TABLESPACE,
|
||||||
ACL_ALL_RIGHTS_TABLESPACE | ACL_GRANT_OPTION_FOR(ACL_ALL_RIGHTS_TABLESPACE),
|
NameStr(pg_tablespace_tuple->spcname));
|
||||||
ACLMASK_ANY) == ACL_NO_RIGHTS)
|
|
||||||
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE,
|
|
||||||
NameStr(pg_tablespace_tuple->spcname));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Restrict the operation to what we can actually grant or revoke, and
|
|
||||||
* issue a warning if appropriate. (For REVOKE this isn't quite what
|
|
||||||
* the spec says to do: the spec seems to want a warning only if no
|
|
||||||
* privilege bits actually change in the ACL. In practice that
|
|
||||||
* behavior seems much too noisy, as well as inconsistent with the
|
|
||||||
* GRANT case.)
|
|
||||||
*/
|
|
||||||
this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions);
|
|
||||||
if (is_grant)
|
|
||||||
{
|
|
||||||
if (this_privileges == 0)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
|
|
||||||
errmsg("no privileges were granted")));
|
|
||||||
else if (!all_privs && this_privileges != privileges)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
|
|
||||||
errmsg("not all privileges were granted")));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (this_privileges == 0)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
|
|
||||||
errmsg("no privileges could be revoked")));
|
|
||||||
else if (!all_privs && this_privileges != privileges)
|
|
||||||
ereport(WARNING,
|
|
||||||
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
|
|
||||||
errmsg("not all privileges could be revoked")));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate new ACL.
|
* Generate new ACL.
|
||||||
@ -1372,9 +1218,9 @@ ExecGrant_Tablespace(bool is_grant, List *objects, bool all_privs,
|
|||||||
*/
|
*/
|
||||||
noldmembers = aclmembers(old_acl, &oldmembers);
|
noldmembers = aclmembers(old_acl, &oldmembers);
|
||||||
|
|
||||||
new_acl = merge_acl_with_grant(old_acl, is_grant,
|
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
|
||||||
grant_option, behavior,
|
istmt->grant_option, istmt->behavior,
|
||||||
grantees, this_privileges,
|
istmt->grantees, this_privileges,
|
||||||
grantorId, ownerId);
|
grantorId, ownerId);
|
||||||
|
|
||||||
nnewmembers = aclmembers(new_acl, &newmembers);
|
nnewmembers = aclmembers(new_acl, &newmembers);
|
||||||
@ -1397,7 +1243,7 @@ ExecGrant_Tablespace(bool is_grant, List *objects, bool all_privs,
|
|||||||
|
|
||||||
/* Update the shared dependency ACL info */
|
/* Update the shared dependency ACL info */
|
||||||
updateAclDependencies(TableSpaceRelationId, tblId,
|
updateAclDependencies(TableSpaceRelationId, tblId,
|
||||||
ownerId, is_grant,
|
ownerId, istmt->is_grant,
|
||||||
noldmembers, oldmembers,
|
noldmembers, oldmembers,
|
||||||
nnewmembers, newmembers);
|
nnewmembers, newmembers);
|
||||||
|
|
||||||
@ -1583,6 +1429,34 @@ has_rolcatupdate(Oid roleid)
|
|||||||
return rolcatupdate;
|
return rolcatupdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Relay for the various pg_*_mask routines depending on object kind
|
||||||
|
*/
|
||||||
|
static AclMode
|
||||||
|
pg_aclmask(AclObjectKind objkind, Oid table_oid, Oid roleid,
|
||||||
|
AclMode mask, AclMaskHow how)
|
||||||
|
{
|
||||||
|
switch (objkind)
|
||||||
|
{
|
||||||
|
case ACL_KIND_CLASS:
|
||||||
|
return pg_class_aclmask(table_oid, roleid, mask, how);
|
||||||
|
case ACL_KIND_DATABASE:
|
||||||
|
return pg_database_aclmask(table_oid, roleid, mask, how);
|
||||||
|
case ACL_KIND_PROC:
|
||||||
|
return pg_proc_aclmask(table_oid, roleid, mask, how);
|
||||||
|
case ACL_KIND_LANGUAGE:
|
||||||
|
return pg_language_aclmask(table_oid, roleid, mask, how);
|
||||||
|
case ACL_KIND_NAMESPACE:
|
||||||
|
return pg_namespace_aclmask(table_oid, roleid, mask, how);
|
||||||
|
case ACL_KIND_TABLESPACE:
|
||||||
|
return pg_tablespace_aclmask(table_oid, roleid, mask, how);
|
||||||
|
default:
|
||||||
|
elog(ERROR, "unrecognized objkind: %d",
|
||||||
|
(int) objkind);
|
||||||
|
/* not reached, but keep compiler quiet */
|
||||||
|
return ACL_NO_RIGHTS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exported routine for examining a user's privileges for a table
|
* Exported routine for examining a user's privileges for a table
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.5 2005/11/22 18:17:08 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.6 2005/12/01 02:03:00 alvherre Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1122,6 +1122,7 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
|
|||||||
{
|
{
|
||||||
ObjectAddress obj;
|
ObjectAddress obj;
|
||||||
GrantObjectType objtype;
|
GrantObjectType objtype;
|
||||||
|
InternalGrant istmt;
|
||||||
|
|
||||||
/* Shouldn't happen */
|
/* Shouldn't happen */
|
||||||
case SHARED_DEPENDENCY_PIN:
|
case SHARED_DEPENDENCY_PIN:
|
||||||
@ -1132,22 +1133,22 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
|
|||||||
switch (sdepForm->classid)
|
switch (sdepForm->classid)
|
||||||
{
|
{
|
||||||
case RelationRelationId:
|
case RelationRelationId:
|
||||||
objtype = ACL_OBJECT_RELATION;
|
istmt.objtype = ACL_OBJECT_RELATION;
|
||||||
break;
|
break;
|
||||||
case DatabaseRelationId:
|
case DatabaseRelationId:
|
||||||
objtype = ACL_OBJECT_DATABASE;
|
istmt.objtype = ACL_OBJECT_DATABASE;
|
||||||
break;
|
break;
|
||||||
case ProcedureRelationId:
|
case ProcedureRelationId:
|
||||||
objtype = ACL_OBJECT_FUNCTION;
|
istmt.objtype = ACL_OBJECT_FUNCTION;
|
||||||
break;
|
break;
|
||||||
case LanguageRelationId:
|
case LanguageRelationId:
|
||||||
objtype = ACL_OBJECT_LANGUAGE;
|
istmt.objtype = ACL_OBJECT_LANGUAGE;
|
||||||
break;
|
break;
|
||||||
case NamespaceRelationId:
|
case NamespaceRelationId:
|
||||||
objtype = ACL_OBJECT_NAMESPACE;
|
istmt.objtype = ACL_OBJECT_NAMESPACE;
|
||||||
break;
|
break;
|
||||||
case TableSpaceRelationId:
|
case TableSpaceRelationId:
|
||||||
objtype = ACL_OBJECT_TABLESPACE;
|
istmt.objtype = ACL_OBJECT_TABLESPACE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
elog(ERROR, "unexpected object type %d",
|
elog(ERROR, "unexpected object type %d",
|
||||||
@ -1156,11 +1157,15 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
|
|||||||
objtype = (GrantObjectType) 0;
|
objtype = (GrantObjectType) 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
istmt.is_grant = false;
|
||||||
|
istmt.objects = list_make1_oid(sdepForm->objid);
|
||||||
|
istmt.all_privs = true;
|
||||||
|
istmt.privileges = ACL_NO_RIGHTS;
|
||||||
|
istmt.grantees = list_make1_oid(roleid);
|
||||||
|
istmt.grant_option = false;
|
||||||
|
istmt.behavior = DROP_CASCADE;
|
||||||
|
|
||||||
ExecGrantStmt_oids(false, objtype,
|
ExecGrantStmt_oids(&istmt);
|
||||||
list_make1_oid(sdepForm->objid), true,
|
|
||||||
ACL_NO_RIGHTS, list_make1_oid(roleid),
|
|
||||||
false, DROP_CASCADE);
|
|
||||||
break;
|
break;
|
||||||
case SHARED_DEPENDENCY_OWNER:
|
case SHARED_DEPENDENCY_OWNER:
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.90 2005/11/22 18:17:31 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.91 2005/12/01 02:03:01 alvherre Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* An ACL array is simply an array of AclItems, representing the union
|
* An ACL array is simply an array of AclItems, representing the union
|
||||||
@ -181,6 +181,26 @@ typedef enum AclObjectKind
|
|||||||
MAX_ACL_KIND /* MUST BE LAST */
|
MAX_ACL_KIND /* MUST BE LAST */
|
||||||
} AclObjectKind;
|
} AclObjectKind;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The information about one Grant/Revoke statement, in internal format: object
|
||||||
|
* and grantees names have been turned into Oids, the privilege list is an
|
||||||
|
* AclMode bitmask. If 'privileges' is ACL_NO_RIGHTS (the 0 value) and
|
||||||
|
* all_privs is true, it will be internally turned into the right kind of
|
||||||
|
* ACL_ALL_RIGHTS_*, depending on the object type (NB - this will modify the
|
||||||
|
* InternalGrant struct!)
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
bool is_grant;
|
||||||
|
GrantObjectType objtype;
|
||||||
|
List *objects;
|
||||||
|
bool all_privs;
|
||||||
|
AclMode privileges;
|
||||||
|
List *grantees;
|
||||||
|
bool grant_option;
|
||||||
|
DropBehavior behavior;
|
||||||
|
} InternalGrant;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* routines used internally
|
* routines used internally
|
||||||
*/
|
*/
|
||||||
@ -221,9 +241,7 @@ extern Datum hash_aclitem(PG_FUNCTION_ARGS);
|
|||||||
* prototypes for functions in aclchk.c
|
* prototypes for functions in aclchk.c
|
||||||
*/
|
*/
|
||||||
extern void ExecuteGrantStmt(GrantStmt *stmt);
|
extern void ExecuteGrantStmt(GrantStmt *stmt);
|
||||||
extern void ExecGrantStmt_oids(bool is_grant, GrantObjectType objtype,
|
extern void ExecGrantStmt_oids(InternalGrant *istmt);
|
||||||
List *objects, bool all_privs, AclMode privileges,
|
|
||||||
List *grantees, bool grant_option, DropBehavior behavior);
|
|
||||||
|
|
||||||
extern AclMode pg_class_aclmask(Oid table_oid, Oid roleid,
|
extern AclMode pg_class_aclmask(Oid table_oid, Oid roleid,
|
||||||
AclMode mask, AclMaskHow how);
|
AclMode mask, AclMaskHow how);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user