diff options
Diffstat (limited to 'src/backend/commands/user.c')
-rw-r--r-- | src/backend/commands/user.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index ed243e3d141..e91fa4c78c9 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -1497,6 +1497,18 @@ AddRoleMems(const char *rolename, Oid roleid, } /* + * The charter of pg_database_owner is to have exactly one, implicit, + * situation-dependent member. There's no technical need for this + * restriction. (One could lift it and take the further step of making + * pg_database_ownercheck() equivalent to has_privs_of_role(roleid, + * DEFAULT_ROLE_DATABASE_OWNER), in which case explicit, + * situation-independent members could act as the owner of any database.) + */ + if (roleid == DEFAULT_ROLE_DATABASE_OWNER) + ereport(ERROR, + errmsg("role \"%s\" cannot have explicit members", rolename)); + + /* * The role membership grantor of record has little significance at * present. Nonetheless, inasmuch as users might look to it for a crude * audit trail, let only superusers impute the grant to a third party. @@ -1525,6 +1537,30 @@ AddRoleMems(const char *rolename, Oid roleid, bool new_record_repl[Natts_pg_auth_members]; /* + * pg_database_owner is never a role member. Lifting this restriction + * would require a policy decision about membership loops. One could + * prevent loops, which would include making "ALTER DATABASE x OWNER + * TO proposed_datdba" fail if is_member_of_role(pg_database_owner, + * proposed_datdba). Hence, gaining a membership could reduce what a + * role could do. Alternately, one could allow these memberships to + * complete loops. A role could then have actual WITH ADMIN OPTION on + * itself, prompting a decision about is_admin_of_role() treatment of + * the case. + * + * Lifting this restriction also has policy implications for ownership + * of shared objects (databases and tablespaces). We allow such + * ownership, but we might find cause to ban it in the future. + * Designing such a ban would more troublesome if the design had to + * address pg_database_owner being a member of role FOO that owns a + * shared object. (The effect of such ownership is that any owner of + * another database can act as the owner of affected shared objects.) + */ + if (memberid == DEFAULT_ROLE_DATABASE_OWNER) + ereport(ERROR, + errmsg("role \"%s\" cannot be a member of any role", + get_rolespec_name(memberRole))); + + /* * 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 |