示例#1
0
/*
 * updateAclDependencies
 *		Update the pg_shdepend info for an object's ACL during GRANT/REVOKE.
 *
 * classId, objectId: identify the object whose ACL this is
 * ownerId: role owning the object
 * isGrant: are we adding or removing ACL entries?
 * noldmembers, oldmembers: array of roleids appearing in old ACL
 * nnewmembers, newmembers: array of roleids appearing in new ACL
 *
 * We calculate the difference between the new and old lists of roles,
 * and then insert (if it's a grant) or delete (if it's a revoke) from
 * pg_shdepend as appropiate.
 *
 * Note that we can't insert blindly at grant, because we would end up with
 * duplicate registered dependencies.  We could check for existence of the
 * tuple before inserting, but that seems to be more expensive than what we are
 * doing now.  On the other hand, we can't just delete the tuples blindly at
 * revoke, because the user may still have other privileges.
 *
 * NOTE: Both input arrays must be sorted and de-duped.  They are pfreed
 * before return.
 */
void
updateAclDependencies(Oid classId, Oid objectId, Oid ownerId, bool isGrant,
					  int noldmembers, Oid *oldmembers,
					  int nnewmembers, Oid *newmembers)
{
	Relation	sdepRel;
	Oid		   *diff;
	int			ndiff,
				i;

	/*
	 * Calculate the differences between the old and new lists.
	 */
	if (isGrant)
		ndiff = getOidListDiff(newmembers, nnewmembers,
							   oldmembers, noldmembers, &diff);
	else
		ndiff = getOidListDiff(oldmembers, noldmembers,
							   newmembers, nnewmembers, &diff);

	if (ndiff > 0)
	{
		sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock);

		/* Add or drop the respective dependency */
		for (i = 0; i < ndiff; i++)
		{
			Oid			roleid = diff[i];

			/*
			 * Skip the owner: he has an OWNER shdep entry instead. (This is
			 * not just a space optimization; it makes ALTER OWNER easier. See
			 * notes in changeDependencyOnOwner.)
			 */
			if (roleid == ownerId)
				continue;

			/* Skip pinned roles */
			if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
				continue;

			if (isGrant)
				shdepAddDependency(sdepRel, classId, objectId,
								   AuthIdRelationId, roleid,
								   SHARED_DEPENDENCY_ACL);
			else
				shdepDropDependency(sdepRel, classId, objectId,
									AuthIdRelationId, roleid,
									SHARED_DEPENDENCY_ACL);
		}

		heap_close(sdepRel, RowExclusiveLock);
	}

	pfree(diff);
}
示例#2
0
/*
 * changeDependencyOnOwner
 *
 * Update the shared dependencies to account for the new owner.
 *
 * Note: we don't need an objsubid argument because only whole objects
 * have owners.
 */
void
changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
{
	Relation	sdepRel;

	sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock);

	/* Adjust the SHARED_DEPENDENCY_OWNER entry */
	shdepChangeDep(sdepRel,
				   classId, objectId, 0,
				   AuthIdRelationId, newOwnerId,
				   SHARED_DEPENDENCY_OWNER);

	/*----------
	 * There should never be a SHARED_DEPENDENCY_ACL entry for the owner,
	 * so get rid of it if there is one.  This can happen if the new owner
	 * was previously granted some rights to the object.
	 *
	 * This step is analogous to aclnewowner's removal of duplicate entries
	 * in the ACL.  We have to do it to handle this scenario:
	 *		A grants some rights on an object to B
	 *		ALTER OWNER changes the object's owner to B
	 *		ALTER OWNER changes the object's owner to C
	 * The third step would remove all mention of B from the object's ACL,
	 * but we'd still have a SHARED_DEPENDENCY_ACL for B if we did not do
	 * things this way.
	 *
	 * The rule against having a SHARED_DEPENDENCY_ACL entry for the owner
	 * allows us to fix things up in just this one place, without having
	 * to make the various ALTER OWNER routines each know about it.
	 *----------
	 */
	shdepDropDependency(sdepRel, classId, objectId, 0, true,
						AuthIdRelationId, newOwnerId,
						SHARED_DEPENDENCY_ACL);

	heap_close(sdepRel, RowExclusiveLock);
}
示例#3
0
/*
 * updateAclDependencies
 *		Update the pg_shdepend info for an object's ACL during GRANT/REVOKE.
 *
 * classId, objectId, objsubId: identify the object whose ACL this is
 * ownerId: role owning the object
 * noldmembers, oldmembers: array of roleids appearing in old ACL
 * nnewmembers, newmembers: array of roleids appearing in new ACL
 *
 * We calculate the differences between the new and old lists of roles,
 * and then insert or delete from pg_shdepend as appropriate.
 *
 * Note that we can't just insert all referenced roles blindly during GRANT,
 * because we would end up with duplicate registered dependencies.  We could
 * check for existence of the tuples before inserting, but that seems to be
 * more expensive than what we are doing here.  Likewise we can't just delete
 * blindly during REVOKE, because the user may still have other privileges.
 * It is also possible that REVOKE actually adds dependencies, due to
 * instantiation of a formerly implicit default ACL (although at present,
 * all such dependencies should be for the owning role, which we ignore here).
 *
 * NOTE: Both input arrays must be sorted and de-duped.  (Typically they
 * are extracted from an ACL array by aclmembers(), which takes care of
 * both requirements.)	The arrays are pfreed before return.
 */
void
updateAclDependencies(Oid classId, Oid objectId, int32 objsubId,
					  Oid ownerId,
					  int noldmembers, Oid *oldmembers,
					  int nnewmembers, Oid *newmembers)
{
	Relation	sdepRel;
	int			i;

	/*
	 * Remove entries that are common to both lists; those represent existing
	 * dependencies we don't need to change.
	 *
	 * OK to overwrite the inputs since we'll pfree them anyway.
	 */
	getOidListDiff(oldmembers, &noldmembers, newmembers, &nnewmembers);

	if (noldmembers > 0 || nnewmembers > 0)
	{
		sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock);

		/* Add new dependencies that weren't already present */
		for (i = 0; i < nnewmembers; i++)
		{
			Oid			roleid = newmembers[i];

			/*
			 * Skip the owner: he has an OWNER shdep entry instead. (This is
			 * not just a space optimization; it makes ALTER OWNER easier. See
			 * notes in changeDependencyOnOwner.)
			 */
			if (roleid == ownerId)
				continue;

			/* Skip pinned roles; they don't need dependency entries */
			if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
				continue;

			shdepAddDependency(sdepRel, classId, objectId, objsubId,
							   AuthIdRelationId, roleid,
							   SHARED_DEPENDENCY_ACL);
		}

		/* Drop no-longer-used old dependencies */
		for (i = 0; i < noldmembers; i++)
		{
			Oid			roleid = oldmembers[i];

			/* Skip the owner, same as above */
			if (roleid == ownerId)
				continue;

			/* Skip pinned roles */
			if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
				continue;

			shdepDropDependency(sdepRel, classId, objectId, objsubId,
								false,	/* exact match on objsubId */
								AuthIdRelationId, roleid,
								SHARED_DEPENDENCY_ACL);
		}

		heap_close(sdepRel, RowExclusiveLock);
	}

	if (oldmembers)
		pfree(oldmembers);
	if (newmembers)
		pfree(newmembers);
}