Disregard superuserness when checking to see if a role GRANT would
authorTom Lane <[email protected]>
Fri, 4 Nov 2005 17:25:15 +0000 (17:25 +0000)
committerTom Lane <[email protected]>
Fri, 4 Nov 2005 17:25:15 +0000 (17:25 +0000)
create circularity of role memberships.  This is a minimum-impact fix
for the problem reported by Florian Pflug.  I thought about removing
the superuser_arg test from is_member_of_role() altogether, as it seems
redundant for many of the callers --- but not all, and it's way too late
in the 8.1 cycle to be making large changes.  Perhaps reconsider this
later.

src/backend/commands/user.c
src/backend/utils/adt/acl.c
src/include/utils/acl.h

index 0cbe8252cf6512b3ab0d5c754e79e25c3228d8c7..a06b338ff2684607d8331a9ca2b309a1d12a5027 100644 (file)
@@ -1214,9 +1214,10 @@ AddRoleMems(const char *rolename, Oid roleid,
                 * Refuse creation of membership loops, including the trivial case
                 * where a role is made a member of itself.  We do this by checking to
                 * see if the target role is already a member of the proposed member
-                * role.
+                * role.  We have to ignore possible superuserness, however, else we
+                * could never grant membership in a superuser-privileged role.
                 */
-               if (is_member_of_role(roleid, memberid))
+               if (is_member_of_role_nosuper(roleid, memberid))
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_GRANT_OPERATION),
                                         (errmsg("role \"%s\" is a member of role \"%s\"",
index f770f80e9db19bf7738fe529e18905a1390e0f04..ff3b9676c4359c94888534af6a98792b60698157 100644 (file)
@@ -3067,6 +3067,26 @@ check_is_member_of_role(Oid member, Oid role)
                                                GetUserNameFromId(role))));
 }
 
+/*
+ * Is member a member of role, not considering superuserness?
+ *
+ * This is identical to is_member_of_role except we ignore superuser
+ * status.
+ */
+bool
+is_member_of_role_nosuper(Oid member, Oid role)
+{
+       /* Fast path for simple case */
+       if (member == role)
+               return true;
+
+       /*
+        * Find all the roles that member is a member of, including multi-level
+        * recursion, then see if target role is any one of them.
+        */
+       return list_member_oid(roles_is_member_of(member), role);
+}
+
 
 /*
  * Is member an admin of role (directly or indirectly)?  That is, is it
index 55b9efe3c399dc1a3abc62dc5a88de34c2b6742d..9e0e0d05b080945bb68de0022f5e577975e88fd8 100644 (file)
@@ -212,6 +212,7 @@ extern int  aclmembers(const Acl *acl, Oid **roleids);
 
 extern bool has_privs_of_role(Oid member, Oid role);
 extern bool is_member_of_role(Oid member, Oid role);
+extern bool is_member_of_role_nosuper(Oid member, Oid role);
 extern bool is_admin_of_role(Oid member, Oid role);
 extern void check_is_member_of_role(Oid member, Oid role);