Commit 4b2dafcc authored by Tom Lane's avatar Tom Lane

Align GRANT/REVOKE behavior more closely with the SQL spec, per discussion

of bug report #1150.  Also, arrange that the object owner's irrevocable
grant-option permissions are handled implicitly by the system rather than
being listed in the ACL as self-granted rights (which was wrong anyway).
I did not take the further step of showing these permissions in an
explicit 'granted by _SYSTEM' ACL entry, as that seemed more likely to
bollix up existing clients than to do anything really useful.  It's still
a possible future direction, though.
parent f35e8d84
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/grant.sgml,v 1.39 2004/03/22 03:38:24 momjian Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/grant.sgml,v 1.40 2004/06/01 21:49:21 tgl Exp $
PostgreSQL documentation
-->
......@@ -67,9 +67,10 @@ GRANT { { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] }
<para>
If <literal>WITH GRANT OPTION</literal> is specified, the recipient
of the privilege may in turn grant it to others. By default this
is not allowed. Grant options can only be granted to individual
users, not to groups or <literal>PUBLIC</literal>.
of the privilege may in turn grant it to others. Without a grant
option, the recipient cannot do that. At present, grant options can
only be granted to individual users, not to groups or
<literal>PUBLIC</literal>.
</para>
<para>
......@@ -79,8 +80,8 @@ GRANT { { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] }
however, choose to revoke some of his own privileges for safety.)
The right to drop an object, or to alter its definition in any way is
not described by a grantable privilege; it is inherent in the owner,
and cannot be granted or revoked. It is not possible for the owner's
grant options to be revoked, either.
and cannot be granted or revoked. The owner implicitly has all grant
options for the object, too.
</para>
<para>
......@@ -150,7 +151,7 @@ GRANT { { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] }
<term>RULE</term>
<listitem>
<para>
Allows the creation of a rule on the table/view. (See <xref
Allows the creation of a rule on the table/view. (See the <xref
linkend="sql-createrule" endterm="sql-createrule-title"> statement.)
</para>
</listitem>
......@@ -171,7 +172,7 @@ GRANT { { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] }
<term>TRIGGER</term>
<listitem>
<para>
Allows the creation of a trigger on the specified table. (See
Allows the creation of a trigger on the specified table. (See the
<xref linkend="sql-createtrigger" endterm="sql-createtrigger-title"> statement.)
</para>
</listitem>
......@@ -234,7 +235,7 @@ GRANT { { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] }
<term>ALL PRIVILEGES</term>
<listitem>
<para>
Grant all of the privileges applicable to the object at once.
Grant all of the available privileges at once.
The <literal>PRIVILEGES</literal> key word is optional in
<productname>PostgreSQL</productname>, though it is required by
strict SQL.
......@@ -257,6 +258,20 @@ GRANT { { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] }
to revoke access privileges.
</para>
<para>
When a non-owner of an object attempts to <command>GRANT</> privileges
on the object, the command will fail outright if the user has no
privileges whatsoever on the object. As long as some privilege is
available, the command will proceed, but it will grant only those
privileges for which the user has grant options. The <command>GRANT ALL
PRIVILEGES</> forms will issue a warning message if no grant options are
held, while the other forms will issue a warning if grant options for
any of the privileges specifically named in the command are not held.
(In principle these statements apply to the object owner as well, but
since the owner is always treated as holding all grant options, the
cases can never occur.)
</para>
<para>
It should be noted that database superusers can access
all objects regardless of object privilege settings. This
......@@ -273,10 +288,10 @@ GRANT { { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] }
</para>
<para>
Currently, to grant privileges in <productname>PostgreSQL</productname>
to only a few columns, you must
create a view having the desired columns and then grant privileges
to that view.
Currently, <productname>PostgreSQL</productname> does not support
granting or revoking privileges for individual columns of a table.
One possible workaround is to create a view having just the desired
columns and then grant privileges to that view.
</para>
<para>
......@@ -286,9 +301,9 @@ GRANT { { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] }
=> \z mytable
Access privileges for database "lusitania"
Schema | Name | Type | Access privileges
--------+---------+-------+-----------------------------------------------------------------
public | mytable | table | {=r/postgres,miriam=arwdRxt/postgres,"group todos=arw/postgres"}
Schema | Name | Type | Access privileges
--------+---------+-------+------------------------------------------------------------
public | mytable | table | {miriam=arwdRxt/miriam,=r/miriam,"group todos=arw/miriam"}
(1 row)
</programlisting>
The entries shown by <command>\z</command> are interpreted thus:
......@@ -331,7 +346,14 @@ and may include some privileges for <literal>PUBLIC</> depending on the
object type, as explained above. The first <command>GRANT</> or
<command>REVOKE</> on an object
will instantiate the default privileges (producing, for example,
<literal>{=,miriam=arwdRxt}</>) and then modify them per the specified request.
<literal>{miriam=arwdRxt/miriam}</>) and then modify them per the
specified request.
</para>
<para>
Notice that the owner's implicit grant options are not marked in the
access privileges display. A <literal>*</> will appear only when
grant options have been explicitly granted to someone.
</para>
</refsect1>
......@@ -347,11 +369,17 @@ GRANT INSERT ON films TO PUBLIC;
</para>
<para>
Grant all privileges to user <literal>manuel</literal> on view <literal>kinds</literal>:
Grant all available privileges to user <literal>manuel</literal> on view
<literal>kinds</literal>:
<programlisting>
GRANT ALL PRIVILEGES ON kinds TO manuel;
</programlisting>
Note that while the above will indeed grant all privileges if executed by a
superuser or the owner of <literal>kinds</literal>, when executed by someone
else it will only grant those permissions for which the someone else has
grant options.
</para>
</refsect1>
......
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/revoke.sgml,v 1.29 2003/11/29 19:51:39 pgsql Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/revoke.sgml,v 1.30 2004/06/01 21:49:21 tgl Exp $
PostgreSQL documentation
-->
......@@ -81,6 +81,7 @@ REVOKE [ GRANT OPTION FOR ]
<para>
If <literal>GRANT OPTION FOR</literal> is specified, only the grant
option for the privilege is revoked, not the privilege itself.
Otherwise, both the privilege and the grant option are revoked.
</para>
<para>
......@@ -103,7 +104,7 @@ REVOKE [ GRANT OPTION FOR ]
<para>
Use <xref linkend="app-psql">'s <command>\z</command> command to
display the privileges granted on existing objects. See also <xref
display the privileges granted on existing objects. See <xref
linkend="sql-grant" endterm="sql-grant-title"> for information about the format.
</para>
......@@ -114,9 +115,25 @@ REVOKE [ GRANT OPTION FOR ]
C, then user A cannot revoke the privilege directly from C.
Instead, user A could revoke the grant option from user B and use
the <literal>CASCADE</literal> option so that the privilege is
automatically revoked from user C.
in turn revoked from user C. For another example, if both A and B
have granted the same privilege to C, A can revoke his own grant
but not B's grant, so C will still effectively have the privilege.
</para>
<para>
When a non-owner of an object attempts to <command>REVOKE</> privileges
on the object, the command will fail outright if the user has no
privileges whatsoever on the object. As long as some privilege is
available, the command will proceed, but it will revoke only those
privileges for which the user has grant options. The <command>REVOKE ALL
PRIVILEGES</> forms will issue a warning message if no grant options are
held, while the other forms will issue a warning if grant options for
any of the privileges specifically named in the command are not held.
(In principle these statements apply to the object owner as well, but
since the owner is always treated as holding all grant options, the
cases can never occur.)
</para>
<para>
If a superuser chooses to issue a <command>GRANT</> or <command>REVOKE</>
command, the command is performed as though it were issued by the
......@@ -140,11 +157,15 @@ REVOKE INSERT ON films FROM PUBLIC;
</para>
<para>
Revoke all privileges from user <literal>manuel</literal> on view <literal>kinds</literal>:
Revoke all privileges from user <literal>manuel</literal> on view
<literal>kinds</literal>:
<programlisting>
<programlisting>
REVOKE ALL PRIVILEGES ON kinds FROM manuel;
</programlisting>
Note that this actually means <quote>revoke all privileges that I
granted</>.
</para>
</refsect1>
......
This diff is collapsed.
This diff is collapsed.
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.69 2004/05/11 17:36:13 tgl Exp $
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.70 2004/06/01 21:49:22 tgl Exp $
*
* NOTES
* An ACL array is simply an array of AclItems, representing the union
......@@ -63,13 +63,16 @@ typedef struct AclItem
/*
* The AclIdType is stored in the top two bits of the ai_privs field
* of an AclItem. The middle 15 bits are the grant option markers,
* and the lower 15 bits are the actual privileges.
* and the lower 15 bits are the actual privileges. We use "rights"
* to mean the combined grant option and privilege bits fields.
*/
#define ACLITEM_GET_PRIVS(item) ((item).ai_privs & 0x7FFF)
#define ACLITEM_GET_GOPTIONS(item) (((item).ai_privs >> 15) & 0x7FFF)
#define ACLITEM_GET_RIGHTS(item) ((item).ai_privs & 0x3FFFFFFF)
#define ACLITEM_GET_IDTYPE(item) ((item).ai_privs >> 30)
#define ACL_GRANT_OPTION_FOR(privs) (((AclMode) (privs) & 0x7FFF) << 15)
#define ACL_OPTION_TO_PRIVS(privs) (((AclMode) (privs) >> 15) & 0x7FFF)
#define ACLITEM_SET_PRIVS(item,privs) \
((item).ai_privs = ((item).ai_privs & ~((AclMode) 0x7FFF)) | \
......@@ -77,6 +80,9 @@ typedef struct AclItem
#define ACLITEM_SET_GOPTIONS(item,goptions) \
((item).ai_privs = ((item).ai_privs & ~(((AclMode) 0x7FFF) << 15)) | \
(((AclMode) (goptions) & 0x7FFF) << 15))
#define ACLITEM_SET_RIGHTS(item,rights) \
((item).ai_privs = ((item).ai_privs & ~((AclMode) 0x3FFFFFFF)) | \
((AclMode) (rights) & 0x3FFFFFFF))
#define ACLITEM_SET_IDTYPE(item,idtype) \
((item).ai_privs = ((item).ai_privs & ~(((AclMode) 0x03) << 30)) | \
(((AclMode) (idtype) & 0x03) << 30))
......@@ -86,6 +92,8 @@ typedef struct AclItem
(((AclMode) (goption) & 0x7FFF) << 15) | \
((AclMode) (idtype) << 30))
#define ACLITEM_ALL_PRIV_BITS ((AclMode) 0x7FFF)
#define ACLITEM_ALL_GOPTION_BITS ((AclMode) 0x7FFF << 15)
/*
* Definitions for convenient access to Acl (array of AclItem) and IdList
......@@ -143,7 +151,7 @@ typedef ArrayType IdList;
/*
* ACL modification opcodes
* ACL modification opcodes for aclupdate
*/
#define ACL_MODECHG_ADD 1
#define ACL_MODECHG_DEL 2
......@@ -212,8 +220,10 @@ typedef enum AclObjectKind
* routines used internally
*/
extern Acl *acldefault(GrantObjectType objtype, AclId ownerid);
extern Acl *aclinsert3(const Acl *old_acl, const AclItem *mod_aip,
unsigned modechg, DropBehavior behavior);
extern Acl *aclupdate(const Acl *old_acl, const AclItem *mod_aip,
int modechg, AclId ownerid, DropBehavior behavior);
extern AclMode aclmask(const Acl *acl, AclId userid, AclId ownerid,
AclMode mask, AclMaskHow how);
/*
* SQL functions (from acl.c)
......
......@@ -11,7 +11,7 @@
*
* Copyright (c) 2003, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/include/utils/errcodes.h,v 1.11 2004/05/16 23:18:55 neilc Exp $
* $PostgreSQL: pgsql/src/include/utils/errcodes.h,v 1.12 2004/06/01 21:49:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -59,6 +59,8 @@
#define ERRCODE_WARNING_DYNAMIC_RESULT_SETS_RETURNED MAKE_SQLSTATE('0','1', '0','0','C')
#define ERRCODE_WARNING_IMPLICIT_ZERO_BIT_PADDING MAKE_SQLSTATE('0','1', '0','0','8')
#define ERRCODE_WARNING_NULL_VALUE_ELIMINATED_IN_SET_FUNCTION MAKE_SQLSTATE('0','1', '0','0','3')
#define ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED MAKE_SQLSTATE('0','1', '0','0','7')
#define ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED MAKE_SQLSTATE('0','1', '0','0','6')
#define ERRCODE_WARNING_STRING_DATA_RIGHT_TRUNCATION MAKE_SQLSTATE('0','1', '0','0','4')
#define ERRCODE_WARNING_DEPRECATED_FEATURE MAKE_SQLSTATE('0','1', 'P','0','1')
......
......@@ -89,7 +89,7 @@ ERROR: permission denied for relation atest2
COPY atest2 FROM stdin; -- fail
ERROR: permission denied for relation atest2
GRANT ALL ON atest1 TO PUBLIC; -- fail
ERROR: permission denied for relation atest1
WARNING: no privileges were granted
-- checks in subquery, both ok
SELECT * FROM atest1 WHERE ( b IN ( SELECT col1 FROM atest2 ) );
a | b
......@@ -225,7 +225,7 @@ GRANT USAGE ON LANGUAGE c TO PUBLIC; -- fail
ERROR: language "c" is not trusted
SET SESSION AUTHORIZATION regressuser1;
GRANT USAGE ON LANGUAGE sql TO regressuser2; -- fail
ERROR: permission denied for language sql
WARNING: no privileges were granted
CREATE FUNCTION testfunc1(int) RETURNS int AS 'select 2 * $1;' LANGUAGE sql;
CREATE FUNCTION testfunc2(int) RETURNS int AS 'select 3 * $1;' LANGUAGE sql;
REVOKE ALL ON FUNCTION testfunc1(int), testfunc2(int) FROM PUBLIC;
......@@ -550,7 +550,7 @@ ERROR: grant options can only be granted to individual users
SET SESSION AUTHORIZATION regressuser2;
GRANT SELECT ON atest4 TO regressuser3;
GRANT UPDATE ON atest4 TO regressuser3; -- fail
ERROR: permission denied for relation atest4
WARNING: no privileges were granted
SET SESSION AUTHORIZATION regressuser1;
REVOKE SELECT ON atest4 FROM regressuser3; -- does nothing
SELECT has_table_privilege('regressuser3', 'atest4', 'SELECT'); -- true
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment