Privileges on functions and procedural languages
This commit is contained in:
parent
5e03503126
commit
8adf56f77a
@ -1,6 +1,6 @@
|
||||
<!--
|
||||
Documentation of the system catalogs, directed toward PostgreSQL developers
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.29 2001/11/21 05:53:40 thomas Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.30 2002/02/18 23:10:59 petere Exp $
|
||||
-->
|
||||
|
||||
<chapter id="catalogs">
|
||||
@ -1261,6 +1261,13 @@
|
||||
<entry></entry>
|
||||
<entry>not currently used</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>lanacl</entry>
|
||||
<entry><type>aclitem[]</type></entry>
|
||||
<entry></entry>
|
||||
<entry>Access permissions</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
@ -1699,6 +1706,13 @@
|
||||
Again, the interpretation is language-specific.
|
||||
</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>proacl</entry>
|
||||
<entry><type>aclitem[]</type></entry>
|
||||
<entry></entry>
|
||||
<entry>Access permissions</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.30 2001/12/08 03:24:34 thomas Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.31 2002/02/18 23:11:02 petere Exp $
|
||||
-->
|
||||
|
||||
<refentry id="SQL-CREATEFUNCTION">
|
||||
@ -270,6 +270,17 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
|
||||
definition without breaking objects that refer to the function.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To be able to define a function, the user must have the
|
||||
<literal>USAGE</literal> privilege on the language.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
By default, only the owner (creator) of the function has the right
|
||||
to execute it. Other users must be granted the
|
||||
<literal>EXECUTE</literal> privilege on the function to be able to
|
||||
use it.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
||||
@ -369,7 +380,9 @@ Point * complex_to_point (Complex *z)
|
||||
|
||||
<para>
|
||||
<xref linkend="sql-dropfunction">,
|
||||
<xref linkend="sql-grant">,
|
||||
<xref linkend="sql-load">,
|
||||
<xref linkend="sql-revoke">,
|
||||
<citetitle>PostgreSQL Programmer's Guide</citetitle>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_language.sgml,v 1.20 2001/12/08 03:24:34 thomas Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_language.sgml,v 1.21 2002/02/18 23:11:02 petere Exp $
|
||||
PostgreSQL documentation
|
||||
-->
|
||||
|
||||
@ -203,8 +203,8 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable
|
||||
lanname | lanispl | lanpltrusted | lanplcallfoid | lancompiler
|
||||
-------------+---------+--------------+---------------+-------------
|
||||
internal | f | f | 0 | n/a
|
||||
C | f | f | 0 | /bin/cc
|
||||
sql | f | f | 0 | postgres
|
||||
c | f | f | 0 | /bin/cc
|
||||
sql | f | t | 0 | postgres
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
@ -212,6 +212,13 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable
|
||||
At present, the definition of a procedural language cannot be
|
||||
changed once it has been created.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To be able to use a procedural language, a user must be granted the
|
||||
<literal>USAGE</literal> privilege. The
|
||||
<command>createlang</command> program automatically grants
|
||||
permissions to everyone if the language is known to be trusted.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="sql-createlanguage-examples">
|
||||
@ -257,6 +264,8 @@ CREATE LANGUAGE plsample
|
||||
<member><xref linkend="sql-createfunction"></member>
|
||||
<member><xref linkend="app-droplang"></member>
|
||||
<member><xref linkend="sql-droplanguage"></member>
|
||||
<member><xref linkend="sql-grant"></member>
|
||||
<member><xref linkend="sql-revoke"></member>
|
||||
<member><citetitle>PostgreSQL Programmer's Guide</citetitle></member>
|
||||
</simplelist>
|
||||
</para>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/grant.sgml,v 1.19 2002/01/20 22:19:57 petere Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/grant.sgml,v 1.20 2002/02/18 23:11:02 petere Exp $
|
||||
PostgreSQL documentation
|
||||
-->
|
||||
|
||||
@ -19,6 +19,14 @@ PostgreSQL documentation
|
||||
GRANT { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER } [,...] | ALL [ PRIVILEGES ] }
|
||||
ON [ TABLE ] <replaceable class="PARAMETER">objectname</replaceable> [, ...]
|
||||
TO { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC } [, ...]
|
||||
|
||||
GRANT { EXECUTE | ALL [ PRIVILEGES ] }
|
||||
ON FUNCTION <replaceable>funcname</replaceable> ([<replaceable>type</replaceable>, ...]) [, ...]
|
||||
TO { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC } [, ...]
|
||||
|
||||
GRANT { USAGE | ALL [ PRIVILEGES ] }
|
||||
ON LANGUAGE <replaceable>langname</replaceable> [, ...]
|
||||
TO { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC } [, ...]
|
||||
</synopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@ -27,8 +35,9 @@ GRANT { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER } [,..
|
||||
|
||||
<para>
|
||||
The <command>GRANT</command> command gives specific permissions on
|
||||
an object (table, view, sequence) to one or more users or groups of users.
|
||||
These permissions are added to those already granted, if any.
|
||||
an object (table, view, sequence, function, procedural language) to
|
||||
one or more users or groups of users. These permissions are added
|
||||
to those already granted, if any.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -134,14 +143,36 @@ GRANT { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER } [,..
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>EXECUTE</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Allows the use of the specified function and the use of any
|
||||
operators that are implemented on top of the function. This is
|
||||
the only type of privilege that is applicable to functions.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>USAGE</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Allows the use of the specified procedural language for the
|
||||
creation of functions in that language. This is the only type
|
||||
of privilege that is applicable to procedural languages.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>ALL PRIVILEGES</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Grant all of the above privileges at once. The
|
||||
<literal>PRIVILEGES</literal> key word is optional in
|
||||
<productname>PostgreSQL</productname>, though it is
|
||||
required by strict SQL.
|
||||
Grant all of the privileges applicable to the object at once.
|
||||
The <literal>PRIVILEGES</literal> key word is optional in
|
||||
<productname>PostgreSQL</productname>, though it is required by
|
||||
strict SQL.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/revoke.sgml,v 1.19 2001/12/08 03:24:39 thomas Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/revoke.sgml,v 1.20 2002/02/18 23:11:03 petere Exp $
|
||||
PostgreSQL documentation
|
||||
-->
|
||||
|
||||
@ -19,6 +19,14 @@ PostgreSQL documentation
|
||||
REVOKE { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER } [,...] | ALL [ PRIVILEGES ] }
|
||||
ON [ TABLE ] <replaceable class="PARAMETER">object</replaceable> [, ...]
|
||||
FROM { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC } [, ...]
|
||||
|
||||
REVOKE { EXECUTE | ALL [ PRIVILEGES ] }
|
||||
ON FUNCTION <replaceable>funcname</replaceable> ([<replaceable>type</replaceable>, ...]) [, ...]
|
||||
FROM { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC } [, ...]
|
||||
|
||||
REVOKE { USAGE | ALL [ PRIVILEGES ] }
|
||||
ON LANGUAGE <replaceable>langname</replaceable> [, ...]
|
||||
FROM { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC } [, ...]
|
||||
</synopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
|
@ -1,10 +1,35 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.115 2002/01/31 21:20:03 momjian Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.116 2002/02/18 23:11:00 petere Exp $
|
||||
-->
|
||||
|
||||
<appendix id="release">
|
||||
<title>Release Notes</title>
|
||||
|
||||
<sect1 id="release-devel">
|
||||
<title>&version; Development Branch</title>
|
||||
|
||||
<para>
|
||||
Below is a subset of the changes that have gone into the
|
||||
development branch of PostgreSQL since version 7.2. For a complete
|
||||
list of changes, consult the CVS logs.
|
||||
</para>
|
||||
|
||||
<!--
|
||||
Developers: When you add a feature, mention it here. This avoids
|
||||
lossiness when digging out the information from the CVS logs, and
|
||||
furthermore it advertises your feature to external parties at the
|
||||
earliest possible moment.
|
||||
|
||||
CDATA means the content is "SGML-free", so you can write without
|
||||
worries about funny characters.
|
||||
-->
|
||||
<literallayout><![CDATA[
|
||||
Access privileges on functions
|
||||
Access privileges on procedural languages
|
||||
]]></literallayout>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="release-7-2">
|
||||
<title>Release 7.2</title>
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.53 2001/11/05 17:46:24 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.54 2002/02/18 23:11:07 petere Exp $
|
||||
*
|
||||
* NOTES
|
||||
* See acl.h.
|
||||
@ -18,22 +18,35 @@
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/heapam.h"
|
||||
#include "access/transam.h"
|
||||
#include "catalog/catalog.h"
|
||||
#include "catalog/catname.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/pg_aggregate.h"
|
||||
#include "catalog/pg_group.h"
|
||||
#include "catalog/pg_language.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_shadow.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "miscadmin.h"
|
||||
#include "nodes/parsenodes.h"
|
||||
#include "parser/keywords.h"
|
||||
#include "parser/parse.h"
|
||||
#include "parser/parse_agg.h"
|
||||
#include "parser/parse_func.h"
|
||||
#include "parser/parse_expr.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/temprel.h"
|
||||
|
||||
|
||||
static void ExecuteGrantStmt_Table(GrantStmt *stmt);
|
||||
static void ExecuteGrantStmt_Function(GrantStmt *stmt);
|
||||
static void ExecuteGrantStmt_Lang(GrantStmt *stmt);
|
||||
|
||||
static const char *privilege_token_string(int token);
|
||||
|
||||
static int32 aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode);
|
||||
|
||||
/* warning messages, now more explicit. */
|
||||
@ -64,19 +77,128 @@ dumpacl(Acl *acl)
|
||||
#endif /* ACLDEBUG */
|
||||
|
||||
|
||||
/*
|
||||
* If is_grant is true, adds the given privileges for the list of
|
||||
* grantees to the existing old_acl. If is_grant is false, the
|
||||
* privileges for the given grantees are removed from old_acl.
|
||||
*/
|
||||
static Acl*
|
||||
merge_acl_with_grant(Acl *old_acl, bool is_grant, List *grantees, char *privileges)
|
||||
{
|
||||
List *j;
|
||||
Acl *new_acl;
|
||||
|
||||
#ifdef ACLDEBUG
|
||||
dumpacl(old_acl);
|
||||
#endif
|
||||
new_acl = old_acl;
|
||||
|
||||
foreach(j, grantees)
|
||||
{
|
||||
PrivGrantee *grantee = (PrivGrantee *) lfirst(j);
|
||||
char *granteeString;
|
||||
char *aclString;
|
||||
AclItem aclitem;
|
||||
unsigned modechg;
|
||||
|
||||
if (grantee->username)
|
||||
granteeString = aclmakeuser("U", grantee->username);
|
||||
else if (grantee->groupname)
|
||||
granteeString = aclmakeuser("G", grantee->groupname);
|
||||
else
|
||||
granteeString = aclmakeuser("A", "");
|
||||
|
||||
aclString = makeAclString(privileges, granteeString,
|
||||
is_grant ? '+' : '-');
|
||||
|
||||
/* Convert string ACL spec into internal form */
|
||||
aclparse(aclString, &aclitem, &modechg);
|
||||
new_acl = aclinsert3(new_acl, &aclitem, modechg);
|
||||
|
||||
#ifdef ACLDEBUG
|
||||
dumpacl(new_acl);
|
||||
#endif
|
||||
}
|
||||
|
||||
return new_acl;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called to execute the utility commands GRANT and REVOKE
|
||||
*/
|
||||
void
|
||||
ExecuteGrantStmt(GrantStmt *stmt)
|
||||
{
|
||||
List *i;
|
||||
List *j;
|
||||
|
||||
/* see comment in pg_type.h */
|
||||
Assert(ACLITEMSIZE == sizeof(AclItem));
|
||||
|
||||
foreach(i, stmt->relnames)
|
||||
switch(stmt->objtype)
|
||||
{
|
||||
case TABLE:
|
||||
ExecuteGrantStmt_Table(stmt);
|
||||
break;
|
||||
case FUNCTION:
|
||||
ExecuteGrantStmt_Function(stmt);
|
||||
break;
|
||||
case LANGUAGE:
|
||||
ExecuteGrantStmt_Lang(stmt);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "bogus GrantStmt.objtype %d", stmt->objtype);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ExecuteGrantStmt_Table(GrantStmt *stmt)
|
||||
{
|
||||
List *i;
|
||||
char *privstring;
|
||||
|
||||
if (lfirsti(stmt->privileges) == ALL)
|
||||
privstring = aclmakepriv(ACL_MODE_STR, 0);
|
||||
else
|
||||
{
|
||||
privstring = "";
|
||||
foreach(i, stmt->privileges)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
switch(lfirsti(i))
|
||||
{
|
||||
case SELECT:
|
||||
c = ACL_MODE_SELECT_CHR;
|
||||
break;
|
||||
case INSERT:
|
||||
c = ACL_MODE_INSERT_CHR;
|
||||
break;
|
||||
case UPDATE:
|
||||
c = ACL_MODE_UPDATE_CHR;
|
||||
break;
|
||||
case DELETE:
|
||||
c = ACL_MODE_DELETE_CHR;
|
||||
break;
|
||||
case RULE:
|
||||
c = ACL_MODE_RULE_CHR;
|
||||
break;
|
||||
case REFERENCES:
|
||||
c = ACL_MODE_REFERENCES_CHR;
|
||||
break;
|
||||
case TRIGGER:
|
||||
c = ACL_MODE_TRIGGER_CHR;
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "invalid privilege type %s for table object",
|
||||
privilege_token_string(lfirsti(i)));
|
||||
}
|
||||
|
||||
privstring = aclmakepriv(privstring, c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach(i, stmt->objects)
|
||||
{
|
||||
char *relname = strVal(lfirst(i));
|
||||
Relation relation;
|
||||
@ -120,41 +242,13 @@ ExecuteGrantStmt(GrantStmt *stmt)
|
||||
aclDatum = SysCacheGetAttr(RELNAME, tuple, Anum_pg_class_relacl,
|
||||
&isNull);
|
||||
if (isNull)
|
||||
old_acl = acldefault(relname, pg_class_tuple->relowner);
|
||||
old_acl = acldefault(pg_class_tuple->relowner);
|
||||
else
|
||||
/* get a detoasted copy of the rel's ACL */
|
||||
old_acl = DatumGetAclPCopy(aclDatum);
|
||||
|
||||
#ifdef ACLDEBUG
|
||||
dumpacl(old_acl);
|
||||
#endif
|
||||
new_acl = old_acl;
|
||||
|
||||
foreach(j, stmt->grantees)
|
||||
{
|
||||
PrivGrantee *grantee = (PrivGrantee *) lfirst(j);
|
||||
char *granteeString;
|
||||
char *aclString;
|
||||
AclItem aclitem;
|
||||
unsigned modechg;
|
||||
|
||||
if (grantee->username)
|
||||
granteeString = aclmakeuser("U", grantee->username);
|
||||
else if (grantee->groupname)
|
||||
granteeString = aclmakeuser("G", grantee->groupname);
|
||||
else
|
||||
granteeString = aclmakeuser("A", "");
|
||||
|
||||
aclString = makeAclString(stmt->privileges, granteeString,
|
||||
stmt->is_grant ? '+' : '-');
|
||||
|
||||
/* Convert string ACL spec into internal form */
|
||||
aclparse(aclString, &aclitem, &modechg);
|
||||
new_acl = aclinsert3(new_acl, &aclitem, modechg);
|
||||
#ifdef ACLDEBUG
|
||||
dumpacl(new_acl);
|
||||
#endif
|
||||
}
|
||||
new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
|
||||
stmt->grantees, privstring);
|
||||
|
||||
/* finished building new ACL value, now insert it */
|
||||
for (i = 0; i < Natts_pg_class; ++i)
|
||||
@ -190,6 +284,267 @@ ExecuteGrantStmt(GrantStmt *stmt)
|
||||
}
|
||||
|
||||
|
||||
static Oid
|
||||
find_function_with_arglist(char *name, List *arguments)
|
||||
{
|
||||
Oid oid;
|
||||
Oid argoids[FUNC_MAX_ARGS];
|
||||
int i;
|
||||
int16 argcount;
|
||||
|
||||
MemSet(argoids, 0, FUNC_MAX_ARGS * sizeof(Oid));
|
||||
argcount = length(arguments);
|
||||
if (argcount > FUNC_MAX_ARGS)
|
||||
elog(ERROR, "functions cannot have more than %d arguments",
|
||||
FUNC_MAX_ARGS);
|
||||
|
||||
for (i = 0; i < argcount; i++)
|
||||
{
|
||||
TypeName *t = (TypeName *) lfirst(arguments);
|
||||
char *typnam = TypeNameToInternalName(t);
|
||||
|
||||
arguments = lnext(arguments);
|
||||
|
||||
if (strcmp(typnam, "opaque") == 0)
|
||||
argoids[i] = InvalidOid;
|
||||
else
|
||||
{
|
||||
argoids[i] = GetSysCacheOid(TYPENAME,
|
||||
PointerGetDatum(typnam),
|
||||
0, 0, 0);
|
||||
if (!OidIsValid(argoids[i]))
|
||||
elog(ERROR, "type '%s' not found", typnam);
|
||||
}
|
||||
}
|
||||
|
||||
oid = GetSysCacheOid(PROCNAME,
|
||||
PointerGetDatum(name),
|
||||
Int16GetDatum(argcount),
|
||||
PointerGetDatum(argoids),
|
||||
0);
|
||||
|
||||
if (!OidIsValid(oid))
|
||||
func_error(NULL, name, argcount, argoids, NULL);
|
||||
|
||||
return oid;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ExecuteGrantStmt_Function(GrantStmt *stmt)
|
||||
{
|
||||
List *i;
|
||||
char *privstring = NULL;
|
||||
|
||||
if (lfirsti(stmt->privileges) == ALL)
|
||||
privstring = aclmakepriv("", ACL_MODE_SELECT_CHR);
|
||||
else
|
||||
{
|
||||
foreach(i, stmt->privileges)
|
||||
{
|
||||
if (lfirsti(i) != EXECUTE)
|
||||
elog(ERROR, "invalid privilege type %s for function object",
|
||||
privilege_token_string(lfirsti(i)));
|
||||
}
|
||||
|
||||
privstring = aclmakepriv("", ACL_MODE_SELECT_CHR);
|
||||
}
|
||||
|
||||
foreach(i, stmt->objects)
|
||||
{
|
||||
FuncWithArgs *func = (FuncWithArgs *) lfirst(i);
|
||||
Oid oid;
|
||||
Relation relation;
|
||||
HeapTuple tuple;
|
||||
Form_pg_proc pg_proc_tuple;
|
||||
Datum aclDatum;
|
||||
bool isNull;
|
||||
Acl *old_acl;
|
||||
Acl *new_acl;
|
||||
unsigned i;
|
||||
HeapTuple newtuple;
|
||||
Datum values[Natts_pg_proc];
|
||||
char nulls[Natts_pg_proc];
|
||||
char replaces[Natts_pg_proc];
|
||||
|
||||
oid = find_function_with_arglist(func->funcname, func->funcargs);
|
||||
relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
|
||||
tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(oid), 0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
{
|
||||
heap_close(relation, RowExclusiveLock);
|
||||
elog(ERROR, "function %u not found", oid);
|
||||
}
|
||||
pg_proc_tuple = (Form_pg_proc) GETSTRUCT(tuple);
|
||||
|
||||
if (pg_proc_tuple->proowner != GetUserId())
|
||||
elog(ERROR, "permission denied");
|
||||
|
||||
/*
|
||||
* If there's no ACL, create a default using the pg_proc.proowner
|
||||
* field.
|
||||
*/
|
||||
aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
|
||||
&isNull);
|
||||
if (isNull)
|
||||
old_acl = acldefault(pg_proc_tuple->proowner);
|
||||
else
|
||||
/* get a detoasted copy of the rel's ACL */
|
||||
old_acl = DatumGetAclPCopy(aclDatum);
|
||||
|
||||
new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
|
||||
stmt->grantees, privstring);
|
||||
|
||||
/* finished building new ACL value, now insert it */
|
||||
for (i = 0; i < Natts_pg_proc; ++i)
|
||||
{
|
||||
replaces[i] = ' ';
|
||||
nulls[i] = ' '; /* ignored if replaces[i]==' ' anyway */
|
||||
values[i] = (Datum) NULL; /* ignored if replaces[i]==' '
|
||||
* anyway */
|
||||
}
|
||||
replaces[Anum_pg_proc_proacl - 1] = 'r';
|
||||
values[Anum_pg_proc_proacl - 1] = PointerGetDatum(new_acl);
|
||||
newtuple = heap_modifytuple(tuple, relation, values, nulls, replaces);
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
simple_heap_update(relation, &newtuple->t_self, newtuple);
|
||||
|
||||
{
|
||||
/* keep the catalog indexes up to date */
|
||||
Relation idescs[Num_pg_proc_indices];
|
||||
|
||||
CatalogOpenIndices(Num_pg_proc_indices, Name_pg_proc_indices,
|
||||
idescs);
|
||||
CatalogIndexInsert(idescs, Num_pg_proc_indices, relation, newtuple);
|
||||
CatalogCloseIndices(Num_pg_proc_indices, idescs);
|
||||
}
|
||||
|
||||
pfree(old_acl);
|
||||
pfree(new_acl);
|
||||
|
||||
heap_close(relation, RowExclusiveLock);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ExecuteGrantStmt_Lang(GrantStmt *stmt)
|
||||
{
|
||||
List *i;
|
||||
char *privstring = NULL;
|
||||
|
||||
if (lfirsti(stmt->privileges) == ALL)
|
||||
privstring = aclmakepriv("", ACL_MODE_SELECT_CHR);
|
||||
else
|
||||
{
|
||||
foreach(i, stmt->privileges)
|
||||
{
|
||||
if (lfirsti(i) != USAGE)
|
||||
elog(ERROR, "invalid privilege type %s for language object",
|
||||
privilege_token_string(lfirsti(i)));
|
||||
}
|
||||
|
||||
privstring = aclmakepriv("", ACL_MODE_SELECT_CHR);
|
||||
}
|
||||
|
||||
foreach(i, stmt->objects)
|
||||
{
|
||||
char *langname = strVal(lfirst(i));
|
||||
Relation relation;
|
||||
HeapTuple tuple;
|
||||
Form_pg_language pg_language_tuple;
|
||||
Datum aclDatum;
|
||||
bool isNull;
|
||||
Acl *old_acl;
|
||||
Acl *new_acl;
|
||||
unsigned i;
|
||||
HeapTuple newtuple;
|
||||
Datum values[Natts_pg_language];
|
||||
char nulls[Natts_pg_language];
|
||||
char replaces[Natts_pg_language];
|
||||
|
||||
if (!superuser())
|
||||
elog(ERROR, "permission denied");
|
||||
|
||||
relation = heap_openr(LanguageRelationName, RowExclusiveLock);
|
||||
tuple = SearchSysCache(LANGNAME, PointerGetDatum(langname), 0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
{
|
||||
heap_close(relation, RowExclusiveLock);
|
||||
elog(ERROR, "language \"%s\" not found", langname);
|
||||
}
|
||||
pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
|
||||
|
||||
if (!pg_language_tuple->lanpltrusted)
|
||||
{
|
||||
heap_close(relation, RowExclusiveLock);
|
||||
elog(ERROR, "language \"%s\" is not trusted", langname);
|
||||
}
|
||||
|
||||
/*
|
||||
* If there's no ACL, create a default.
|
||||
*/
|
||||
aclDatum = SysCacheGetAttr(LANGNAME, tuple, Anum_pg_language_lanacl,
|
||||
&isNull);
|
||||
if (isNull)
|
||||
old_acl = acldefault(InvalidOid);
|
||||
else
|
||||
/* get a detoasted copy of the rel's ACL */
|
||||
old_acl = DatumGetAclPCopy(aclDatum);
|
||||
|
||||
new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
|
||||
stmt->grantees, privstring);
|
||||
|
||||
/* finished building new ACL value, now insert it */
|
||||
for (i = 0; i < Natts_pg_language; ++i)
|
||||
{
|
||||
replaces[i] = ' ';
|
||||
nulls[i] = ' '; /* ignored if replaces[i]==' ' anyway */
|
||||
values[i] = (Datum) NULL; /* ignored if replaces[i]==' '
|
||||
* anyway */
|
||||
}
|
||||
replaces[Anum_pg_language_lanacl - 1] = 'r';
|
||||
values[Anum_pg_language_lanacl - 1] = PointerGetDatum(new_acl);
|
||||
newtuple = heap_modifytuple(tuple, relation, values, nulls, replaces);
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
simple_heap_update(relation, &newtuple->t_self, newtuple);
|
||||
|
||||
{
|
||||
/* keep the catalog indexes up to date */
|
||||
Relation idescs[Num_pg_language_indices];
|
||||
|
||||
CatalogOpenIndices(Num_pg_language_indices, Name_pg_language_indices,
|
||||
idescs);
|
||||
CatalogIndexInsert(idescs, Num_pg_language_indices, relation, newtuple);
|
||||
CatalogCloseIndices(Num_pg_language_indices, idescs);
|
||||
}
|
||||
|
||||
pfree(old_acl);
|
||||
pfree(new_acl);
|
||||
|
||||
heap_close(relation, RowExclusiveLock);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char *
|
||||
privilege_token_string(int token)
|
||||
{
|
||||
const char *s = TokenString(token);
|
||||
|
||||
if (s)
|
||||
return s;
|
||||
else
|
||||
elog(ERROR, "privilege_token_string: invalid token number");
|
||||
return NULL; /* appease compiler */
|
||||
}
|
||||
|
||||
|
||||
|
||||
AclId
|
||||
get_grosysid(char *groname)
|
||||
@ -483,7 +838,7 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode)
|
||||
AclId ownerId;
|
||||
|
||||
ownerId = ((Form_pg_class) GETSTRUCT(tuple))->relowner;
|
||||
acl = acldefault(relname, ownerId);
|
||||
acl = acldefault(ownerId);
|
||||
aclDatum = (Datum) 0;
|
||||
}
|
||||
else
|
||||
@ -721,3 +1076,142 @@ pg_aggr_ownercheck(Oid userid,
|
||||
|
||||
return userid == owner_id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Exported routine for checking a user's access privileges to a function
|
||||
*
|
||||
* Returns an ACLCHECK_* result code.
|
||||
*/
|
||||
int32
|
||||
pg_proc_aclcheck(Oid proc_oid, Oid userid)
|
||||
{
|
||||
int32 result;
|
||||
HeapTuple tuple;
|
||||
Datum aclDatum;
|
||||
bool isNull;
|
||||
Acl *acl;
|
||||
|
||||
if (superuser_arg(userid))
|
||||
return ACLCHECK_OK;
|
||||
|
||||
/*
|
||||
* Validate userid
|
||||
*/
|
||||
tuple = SearchSysCache(SHADOWSYSID,
|
||||
ObjectIdGetDatum(userid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "pg_proc_aclcheck: invalid user id %u",
|
||||
(unsigned) userid);
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
/*
|
||||
* Normal case: get the function's ACL from pg_proc
|
||||
*/
|
||||
tuple = SearchSysCache(PROCOID,
|
||||
ObjectIdGetDatum(proc_oid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "pg_proc_aclcheck: function %u not found", proc_oid);
|
||||
|
||||
aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
|
||||
&isNull);
|
||||
if (isNull)
|
||||
{
|
||||
/* No ACL, so build default ACL */
|
||||
AclId ownerId;
|
||||
|
||||
ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;
|
||||
acl = acldefault(ownerId);
|
||||
aclDatum = (Datum) 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* detoast ACL if necessary */
|
||||
acl = DatumGetAclP(aclDatum);
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions only have one kind of privilege, which is encoded as
|
||||
* "SELECT" here.
|
||||
*/
|
||||
result = aclcheck(acl, userid, (AclIdType) ACL_IDTYPE_UID, ACL_SELECT);
|
||||
|
||||
/* if we have a detoasted copy, free it */
|
||||
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
|
||||
pfree(acl);
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Exported routine for checking a user's access privileges to a language
|
||||
*
|
||||
* Returns an ACLCHECK_* result code.
|
||||
*/
|
||||
int32
|
||||
pg_language_aclcheck(Oid lang_oid, Oid userid)
|
||||
{
|
||||
int32 result;
|
||||
HeapTuple tuple;
|
||||
Datum aclDatum;
|
||||
bool isNull;
|
||||
Acl *acl;
|
||||
|
||||
if (superuser_arg(userid))
|
||||
return ACLCHECK_OK;
|
||||
|
||||
/*
|
||||
* Validate userid
|
||||
*/
|
||||
tuple = SearchSysCache(SHADOWSYSID,
|
||||
ObjectIdGetDatum(userid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "pg_language_aclcheck: invalid user id %u",
|
||||
(unsigned) userid);
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
/*
|
||||
* Normal case: get the function's ACL from pg_language
|
||||
*/
|
||||
tuple = SearchSysCache(LANGOID,
|
||||
ObjectIdGetDatum(lang_oid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "pg_language_aclcheck: language %u not found", lang_oid);
|
||||
|
||||
aclDatum = SysCacheGetAttr(LANGOID, tuple, Anum_pg_language_lanacl,
|
||||
&isNull);
|
||||
if (isNull)
|
||||
{
|
||||
/* No ACL, so build default ACL */
|
||||
acl = acldefault(InvalidOid);
|
||||
aclDatum = (Datum) 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* detoast ACL if necessary */
|
||||
acl = DatumGetAclP(aclDatum);
|
||||
}
|
||||
|
||||
/*
|
||||
* Languages only have one kind of privilege, which is encoded as
|
||||
* "SELECT" here.
|
||||
*/
|
||||
result = aclcheck(acl, userid, (AclIdType) ACL_IDTYPE_UID, ACL_SELECT);
|
||||
|
||||
/* if we have a detoasted copy, free it */
|
||||
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
|
||||
pfree(acl);
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.63 2001/11/05 17:46:24 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.64 2002/02/18 23:11:08 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -44,7 +44,7 @@ ProcedureCreate(char *procedureName,
|
||||
bool replace,
|
||||
bool returnsSet,
|
||||
char *returnTypeName,
|
||||
char *languageName,
|
||||
Oid languageObjectId,
|
||||
char *prosrc,
|
||||
char *probin,
|
||||
bool trusted,
|
||||
@ -65,7 +65,6 @@ ProcedureCreate(char *procedureName,
|
||||
char nulls[Natts_pg_proc];
|
||||
Datum values[Natts_pg_proc];
|
||||
char replaces[Natts_pg_proc];
|
||||
Oid languageObjectId;
|
||||
Oid typeObjectId;
|
||||
List *x;
|
||||
List *querytree_list;
|
||||
@ -82,12 +81,6 @@ ProcedureCreate(char *procedureName,
|
||||
Assert(PointerIsValid(prosrc));
|
||||
Assert(PointerIsValid(probin));
|
||||
|
||||
languageObjectId = GetSysCacheOid(LANGNAME,
|
||||
PointerGetDatum(languageName),
|
||||
0, 0, 0);
|
||||
if (!OidIsValid(languageObjectId))
|
||||
elog(ERROR, "language '%s' does not exist", languageName);
|
||||
|
||||
parameterCount = 0;
|
||||
MemSet(typev, 0, FUNC_MAX_ARGS * sizeof(Oid));
|
||||
foreach(x, argList)
|
||||
@ -320,6 +313,9 @@ ProcedureCreate(char *procedureName,
|
||||
elog(ERROR, "ProcedureCreate: cannot change return type of existing function."
|
||||
"\n\tUse DROP FUNCTION first.");
|
||||
|
||||
/* do not change existing permissions */
|
||||
replaces[Anum_pg_proc_proacl-1] = ' ';
|
||||
|
||||
/* Okay, do it... */
|
||||
tup = heap_modifytuple(oldtup, rel, values, nulls, replaces);
|
||||
simple_heap_update(rel, &tup->t_self, tup);
|
||||
@ -329,6 +325,10 @@ ProcedureCreate(char *procedureName,
|
||||
else
|
||||
{
|
||||
/* Creating a new procedure */
|
||||
|
||||
/* start out with empty permissions */
|
||||
nulls[Anum_pg_proc_proacl-1] = 'n';
|
||||
|
||||
tup = heap_formtuple(tupDesc, values, nulls);
|
||||
heap_insert(rel, tup);
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.64 2001/10/28 06:25:42 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.65 2002/02/18 23:11:10 petere Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
@ -50,6 +50,7 @@
|
||||
#include "miscadmin.h"
|
||||
#include "optimizer/cost.h"
|
||||
#include "parser/parse_expr.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
@ -60,22 +61,18 @@ static int defGetTypeLength(DefElem *def);
|
||||
#define DEFAULT_TYPDELIM ','
|
||||
|
||||
|
||||
/*
|
||||
* Translate the input language name to lower case.
|
||||
*/
|
||||
static void
|
||||
case_translate_language_name(const char *input, char *output)
|
||||
{
|
||||
/*
|
||||
* Translate the input language name to lower case, except if it's "C",
|
||||
* translate to upper case.
|
||||
*/
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NAMEDATALEN - 1 && input[i]; ++i)
|
||||
output[i] = tolower((unsigned char) input[i]);
|
||||
|
||||
output[i] = '\0';
|
||||
|
||||
if (strcmp(output, "c") == 0)
|
||||
output[0] = 'C';
|
||||
}
|
||||
|
||||
|
||||
@ -175,12 +172,12 @@ compute_full_attributes(List *parameters,
|
||||
*/
|
||||
|
||||
static void
|
||||
interpret_AS_clause(const char *languageName, const List *as,
|
||||
interpret_AS_clause(Oid languageOid, const char *languageName, const List *as,
|
||||
char **prosrc_str_p, char **probin_str_p)
|
||||
{
|
||||
Assert(as != NIL);
|
||||
|
||||
if (strcmp(languageName, "C") == 0)
|
||||
if (languageOid == ClanguageId)
|
||||
{
|
||||
/*
|
||||
* For "C" language, store the file name in probin and, when
|
||||
@ -213,29 +210,16 @@ interpret_AS_clause(const char *languageName, const List *as,
|
||||
void
|
||||
CreateFunction(ProcedureStmt *stmt)
|
||||
{
|
||||
char *probin_str;
|
||||
|
||||
/* pathname of executable file that executes this function, if any */
|
||||
|
||||
char *prosrc_str;
|
||||
|
||||
char *probin_str;
|
||||
/* SQL that executes this function, if any */
|
||||
|
||||
char *prorettype;
|
||||
|
||||
char *prosrc_str;
|
||||
/* Type of return value (or member of set of values) from function */
|
||||
|
||||
char *prorettype;
|
||||
/* name of language of function, with case adjusted */
|
||||
char languageName[NAMEDATALEN];
|
||||
|
||||
/*
|
||||
* name of language of function, with case adjusted: "C", "internal",
|
||||
* "sql", etc.
|
||||
*/
|
||||
|
||||
bool returnsSet;
|
||||
|
||||
/* The function returns a set of values, as opposed to a singleton. */
|
||||
|
||||
bool returnsSet;
|
||||
/*
|
||||
* The following are optional user-supplied attributes of the
|
||||
* function.
|
||||
@ -247,62 +231,28 @@ CreateFunction(ProcedureStmt *stmt)
|
||||
bool canCache,
|
||||
isStrict;
|
||||
|
||||
HeapTuple languageTuple;
|
||||
Form_pg_language languageStruct;
|
||||
Oid languageOid;
|
||||
|
||||
/* Convert language name to canonical case */
|
||||
case_translate_language_name(stmt->language, languageName);
|
||||
|
||||
/*
|
||||
* Apply appropriate security checks depending on language.
|
||||
*/
|
||||
if (strcmp(languageName, "C") == 0 ||
|
||||
strcmp(languageName, "internal") == 0)
|
||||
{
|
||||
if (!superuser())
|
||||
elog(ERROR,
|
||||
"Only users with Postgres superuser privilege are "
|
||||
"permitted to create a function in the '%s' language.\n\t"
|
||||
"Others may use the 'sql' language "
|
||||
"or the created procedural languages.",
|
||||
languageName);
|
||||
}
|
||||
else if (strcmp(languageName, "sql") == 0)
|
||||
{
|
||||
/* No security check needed for SQL functions */
|
||||
}
|
||||
else
|
||||
{
|
||||
HeapTuple languageTuple;
|
||||
Form_pg_language languageStruct;
|
||||
languageTuple = SearchSysCache(LANGNAME,
|
||||
PointerGetDatum(languageName),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(languageTuple))
|
||||
elog(ERROR, "language \"%s\" does not exist", languageName);
|
||||
|
||||
/* Lookup the language in the system cache */
|
||||
languageTuple = SearchSysCache(LANGNAME,
|
||||
PointerGetDatum(languageName),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(languageTuple))
|
||||
elog(ERROR,
|
||||
"Unrecognized language specified in a CREATE FUNCTION: "
|
||||
"'%s'.\n\tPre-installed languages are SQL, C, and "
|
||||
"internal.\n\tAdditional languages may be installed "
|
||||
"using 'createlang'.",
|
||||
languageName);
|
||||
languageOid = languageTuple->t_data->t_oid;
|
||||
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
|
||||
|
||||
/* Check that this language is a PL */
|
||||
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
|
||||
if (!languageStruct->lanispl)
|
||||
elog(ERROR,
|
||||
"Language '%s' isn't defined as PL", languageName);
|
||||
if (!((languageStruct->lanpltrusted
|
||||
&& pg_language_aclcheck(languageOid, GetUserId()) == ACLCHECK_OK)
|
||||
|| superuser()))
|
||||
elog(ERROR, "permission denied");
|
||||
|
||||
/*
|
||||
* Functions in untrusted procedural languages are restricted to
|
||||
* be defined by postgres superusers only
|
||||
*/
|
||||
if (!languageStruct->lanpltrusted && !superuser())
|
||||
elog(ERROR, "Only users with Postgres superuser privilege "
|
||||
"are permitted to create a function in the '%s' "
|
||||
"language.",
|
||||
languageName);
|
||||
|
||||
ReleaseSysCache(languageTuple);
|
||||
}
|
||||
ReleaseSysCache(languageTuple);
|
||||
|
||||
/*
|
||||
* Convert remaining parameters of CREATE to form wanted by
|
||||
@ -316,7 +266,7 @@ CreateFunction(ProcedureStmt *stmt)
|
||||
&byte_pct, &perbyte_cpu, &percall_cpu,
|
||||
&outin_ratio, &canCache, &isStrict);
|
||||
|
||||
interpret_AS_clause(languageName, stmt->as, &prosrc_str, &probin_str);
|
||||
interpret_AS_clause(languageOid, languageName, stmt->as, &prosrc_str, &probin_str);
|
||||
|
||||
/*
|
||||
* And now that we have all the parameters, and know we're permitted
|
||||
@ -326,7 +276,7 @@ CreateFunction(ProcedureStmt *stmt)
|
||||
stmt->replace,
|
||||
returnsSet,
|
||||
prorettype,
|
||||
languageName,
|
||||
languageOid,
|
||||
prosrc_str, /* converted to text later */
|
||||
probin_str, /* converted to text later */
|
||||
true, /* (obsolete "trusted") */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.28 2001/06/13 21:44:40 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.29 2002/02/18 23:11:11 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -27,22 +27,18 @@
|
||||
#include "utils/syscache.h"
|
||||
|
||||
|
||||
/*
|
||||
* Translate the input language name to lower case.
|
||||
*/
|
||||
static void
|
||||
case_translate_language_name(const char *input, char *output)
|
||||
{
|
||||
/*-------------------------------------------------------------------------
|
||||
Translate the input language name to lower case, except if it's C,
|
||||
translate to upper case.
|
||||
--------------------------------------------------------------------------*/
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NAMEDATALEN && input[i]; ++i)
|
||||
output[i] = tolower((unsigned char) input[i]);
|
||||
|
||||
output[i] = '\0';
|
||||
|
||||
if (strcmp(output, "c") == 0)
|
||||
output[0] = 'C';
|
||||
}
|
||||
|
||||
|
||||
@ -116,6 +112,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
|
||||
values[i++] = ObjectIdGetDatum(procTup->t_data->t_oid);
|
||||
values[i++] = DirectFunctionCall1(textin,
|
||||
CStringGetDatum(stmt->plcompiler));
|
||||
nulls[i] = 'n'; /* lanacl */
|
||||
|
||||
ReleaseSysCache(procTup);
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.89 2001/10/25 05:49:27 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.90 2002/02/18 23:11:13 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -658,6 +658,9 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
|
||||
bool hasSetArg;
|
||||
int i;
|
||||
|
||||
if (!fcache->permission_ok)
|
||||
elog(ERROR, "permission denied");
|
||||
|
||||
/*
|
||||
* arguments is a list of expressions to evaluate before passing to
|
||||
* the function manager. We skip the evaluation if it was already
|
||||
|
@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.160 2001/11/05 05:00:14 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.161 2002/02/18 23:11:14 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1893,9 +1893,9 @@ _copyGrantStmt(GrantStmt *from)
|
||||
GrantStmt *newnode = makeNode(GrantStmt);
|
||||
|
||||
newnode->is_grant = from->is_grant;
|
||||
Node_Copy(from, newnode, relnames);
|
||||
if (from->privileges)
|
||||
newnode->privileges = pstrdup(from->privileges);
|
||||
newnode->objtype = from->objtype;
|
||||
Node_Copy(from, newnode, objects);
|
||||
Node_Copy(from, newnode, privileges);
|
||||
Node_Copy(from, newnode, grantees);
|
||||
|
||||
return newnode;
|
||||
@ -1914,6 +1914,20 @@ _copyPrivGrantee(PrivGrantee *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static FuncWithArgs *
|
||||
_copyFuncWithArgs(FuncWithArgs *from)
|
||||
{
|
||||
FuncWithArgs *newnode = makeNode(FuncWithArgs);
|
||||
|
||||
if (from->funcname)
|
||||
newnode->funcname = pstrdup(from->funcname);
|
||||
else
|
||||
newnode->funcname = NULL;
|
||||
Node_Copy(from, newnode, funcargs);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static ClosePortalStmt *
|
||||
_copyClosePortalStmt(ClosePortalStmt *from)
|
||||
{
|
||||
@ -2971,6 +2985,9 @@ copyObject(void *from)
|
||||
case T_PrivGrantee:
|
||||
retval = _copyPrivGrantee(from);
|
||||
break;
|
||||
case T_FuncWithArgs:
|
||||
retval = _copyFuncWithArgs(from);
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "copyObject: don't know how to copy node type %d",
|
||||
|
@ -20,7 +20,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.108 2001/11/05 05:00:14 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.109 2002/02/18 23:11:14 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -758,9 +758,11 @@ _equalGrantStmt(GrantStmt *a, GrantStmt *b)
|
||||
{
|
||||
if (a->is_grant != b->is_grant)
|
||||
return false;
|
||||
if (!equal(a->relnames, b->relnames))
|
||||
if (a->objtype != b->objtype)
|
||||
return false;
|
||||
if (!equalstr(a->privileges, b->privileges))
|
||||
if (!equal(a->objects, b->objects))
|
||||
return false;
|
||||
if (!equal(a->privileges, b->privileges))
|
||||
return false;
|
||||
if (!equal(a->grantees, b->grantees))
|
||||
return false;
|
||||
@ -775,6 +777,13 @@ _equalPrivGrantee(PrivGrantee *a, PrivGrantee *b)
|
||||
&& equalstr(a->groupname, b->groupname);
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalFuncWithArgs(FuncWithArgs *a, FuncWithArgs *b)
|
||||
{
|
||||
return equalstr(a->funcname, b->funcname)
|
||||
&& equal(a->funcargs, b->funcargs);
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalClosePortalStmt(ClosePortalStmt *a, ClosePortalStmt *b)
|
||||
{
|
||||
@ -2122,6 +2131,9 @@ equal(void *a, void *b)
|
||||
case T_PrivGrantee:
|
||||
retval = _equalPrivGrantee(a, b);
|
||||
break;
|
||||
case T_FuncWithArgs:
|
||||
retval = _equalFuncWithArgs(a, b);
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(NOTICE, "equal: don't know whether nodes of type %d are equal",
|
||||
|
@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.277 2002/02/18 06:49:20 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.278 2002/02/18 23:11:17 petere Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@ -56,7 +56,6 @@
|
||||
#include "nodes/parsenodes.h"
|
||||
#include "parser/gramparse.h"
|
||||
#include "storage/lmgr.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/numeric.h"
|
||||
#include "utils/datetime.h"
|
||||
|
||||
@ -122,6 +121,7 @@ static void doNegateFloat(Value *v);
|
||||
A_Indices *aind;
|
||||
ResTarget *target;
|
||||
ParamNo *paramno;
|
||||
PrivTarget *privtarget;
|
||||
|
||||
VersionStmt *vstmt;
|
||||
DefineStmt *dstmt;
|
||||
@ -182,10 +182,14 @@ static void doNegateFloat(Value *v);
|
||||
OptUseOp, opt_class, SpecialRuleRelation
|
||||
|
||||
%type <str> opt_level, opt_encoding
|
||||
%type <str> privileges, operation_commalist
|
||||
%type <node> grantee
|
||||
%type <list> grantee_list
|
||||
%type <chr> operation, TriggerOneEvent
|
||||
%type <ival> privilege
|
||||
%type <list> privileges, privilege_list
|
||||
%type <privtarget> privilege_target
|
||||
%type <node> function_with_argtypes
|
||||
%type <list> function_with_argtypes_list
|
||||
%type <chr> TriggerOneEvent
|
||||
|
||||
%type <list> stmtblock, stmtmulti,
|
||||
into_clause, OptTempTableName, relation_name_list,
|
||||
@ -323,7 +327,7 @@ static void doNegateFloat(Value *v);
|
||||
SCHEMA, SCROLL, SECOND_P, SELECT, SESSION, SESSION_USER, SET, SOME, SUBSTRING,
|
||||
TABLE, TEMPORARY, THEN, TIME, TIMESTAMP,
|
||||
TO, TRAILING, TRANSACTION, TRIM, TRUE_P,
|
||||
UNENCRYPTED, UNION, UNIQUE, UNKNOWN, UPDATE, USER, USING,
|
||||
UNENCRYPTED, UNION, UNIQUE, UNKNOWN, UPDATE, USAGE, USER, USING,
|
||||
VALUES, VARCHAR, VARYING, VIEW,
|
||||
WHEN, WHERE, WITH, WORK, YEAR_P, ZONE
|
||||
|
||||
@ -2327,73 +2331,94 @@ from_in: IN
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* GRANT privileges ON [TABLE] relation_name_list TO [GROUP] grantee, ...
|
||||
* GRANT and REVOKE statements
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
GrantStmt: GRANT privileges ON opt_table relation_name_list TO grantee_list opt_with_grant
|
||||
GrantStmt: GRANT privileges ON privilege_target TO grantee_list opt_grant_grant_option
|
||||
{
|
||||
GrantStmt *n = makeNode(GrantStmt);
|
||||
n->is_grant = true;
|
||||
n->relnames = $5;
|
||||
n->privileges = $2;
|
||||
n->grantees = $7;
|
||||
n->objtype = ($4)->objtype;
|
||||
n->objects = ($4)->objs;
|
||||
n->grantees = $6;
|
||||
$$ = (Node*)n;
|
||||
}
|
||||
;
|
||||
|
||||
privileges: ALL PRIVILEGES
|
||||
RevokeStmt: REVOKE opt_revoke_grant_option privileges ON privilege_target FROM grantee_list
|
||||
{
|
||||
$$ = aclmakepriv(ACL_MODE_STR,0);
|
||||
}
|
||||
| ALL
|
||||
{
|
||||
$$ = aclmakepriv(ACL_MODE_STR,0);
|
||||
}
|
||||
| operation_commalist
|
||||
{
|
||||
$$ = $1;
|
||||
GrantStmt *n = makeNode(GrantStmt);
|
||||
n->is_grant = false;
|
||||
n->privileges = $3;
|
||||
n->objtype = ($5)->objtype;
|
||||
n->objects = ($5)->objs;
|
||||
n->grantees = $7;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
;
|
||||
|
||||
operation_commalist: operation
|
||||
|
||||
/* either ALL [PRIVILEGES] or a list of individual privileges */
|
||||
privileges: privilege_list { $$ = $1; }
|
||||
| ALL { $$ = makeListi1(ALL); }
|
||||
| ALL PRIVILEGES { $$ = makeListi1(ALL); }
|
||||
;
|
||||
|
||||
privilege_list: privilege { $$ = makeListi1($1); }
|
||||
| privilege_list ',' privilege { $$ = lappendi($1, $3); }
|
||||
;
|
||||
|
||||
/* Not all of these privilege types apply to all objects, but that
|
||||
gets sorted out later. */
|
||||
privilege: SELECT { $$ = SELECT; }
|
||||
| INSERT { $$ = INSERT; }
|
||||
| UPDATE { $$ = UPDATE; }
|
||||
| DELETE { $$ = DELETE; }
|
||||
| RULE { $$ = RULE; }
|
||||
| REFERENCES { $$ = REFERENCES; }
|
||||
| TRIGGER { $$ = TRIGGER; }
|
||||
| EXECUTE { $$ = EXECUTE; }
|
||||
| USAGE { $$ = USAGE; }
|
||||
;
|
||||
|
||||
|
||||
/* Don't bother trying to fold the first two rules into one using
|
||||
opt_table. You're going to get conflicts. */
|
||||
privilege_target: relation_name_list
|
||||
{
|
||||
$$ = aclmakepriv("",$1);
|
||||
PrivTarget *n = makeNode(PrivTarget);
|
||||
n->objtype = TABLE;
|
||||
n->objs = $1;
|
||||
$$ = n;
|
||||
}
|
||||
| operation_commalist ',' operation
|
||||
| TABLE relation_name_list
|
||||
{
|
||||
$$ = aclmakepriv($1,$3);
|
||||
PrivTarget *n = makeNode(PrivTarget);
|
||||
n->objtype = TABLE;
|
||||
n->objs = $2;
|
||||
$$ = n;
|
||||
}
|
||||
| FUNCTION function_with_argtypes_list
|
||||
{
|
||||
PrivTarget *n = makeNode(PrivTarget);
|
||||
n->objtype = FUNCTION;
|
||||
n->objs = $2;
|
||||
$$ = n;
|
||||
}
|
||||
| LANGUAGE name_list
|
||||
{
|
||||
PrivTarget *n = makeNode(PrivTarget);
|
||||
n->objtype = LANGUAGE;
|
||||
n->objs = $2;
|
||||
$$ = n;
|
||||
}
|
||||
;
|
||||
|
||||
operation: SELECT
|
||||
{
|
||||
$$ = ACL_MODE_SELECT_CHR;
|
||||
}
|
||||
| INSERT
|
||||
{
|
||||
$$ = ACL_MODE_INSERT_CHR;
|
||||
}
|
||||
| UPDATE
|
||||
{
|
||||
$$ = ACL_MODE_UPDATE_CHR;
|
||||
}
|
||||
| DELETE
|
||||
{
|
||||
$$ = ACL_MODE_DELETE_CHR;
|
||||
}
|
||||
| RULE
|
||||
{
|
||||
$$ = ACL_MODE_RULE_CHR;
|
||||
}
|
||||
| REFERENCES
|
||||
{
|
||||
$$ = ACL_MODE_REFERENCES_CHR;
|
||||
}
|
||||
| TRIGGER
|
||||
{
|
||||
$$ = ACL_MODE_TRIGGER_CHR;
|
||||
}
|
||||
|
||||
grantee_list: grantee { $$ = makeList1($1); }
|
||||
| grantee_list ',' grantee { $$ = lappend($1, $3); }
|
||||
;
|
||||
|
||||
grantee: PUBLIC
|
||||
@ -2419,31 +2444,33 @@ grantee: PUBLIC
|
||||
}
|
||||
;
|
||||
|
||||
grantee_list: grantee { $$ = makeList1($1); }
|
||||
| grantee_list ',' grantee { $$ = lappend($1, $3); }
|
||||
|
||||
|
||||
opt_with_grant: WITH GRANT OPTION
|
||||
opt_grant_grant_option: WITH GRANT OPTION
|
||||
{
|
||||
elog(ERROR,"WITH GRANT OPTION is not supported. Only relation owners can set privileges");
|
||||
}
|
||||
elog(ERROR, "grant options are not implemented");
|
||||
}
|
||||
| /*EMPTY*/
|
||||
;
|
||||
|
||||
opt_revoke_grant_option: GRANT OPTION FOR
|
||||
{
|
||||
elog(ERROR, "grant options are not implemented");
|
||||
}
|
||||
| /*EMPTY*/
|
||||
;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* REVOKE privileges ON [TABLE] relation_name_list FROM user, ...
|
||||
*
|
||||
*****************************************************************************/
|
||||
function_with_argtypes_list: function_with_argtypes
|
||||
{ $$ = makeList1($1); }
|
||||
| function_with_argtypes_list ',' function_with_argtypes
|
||||
{ $$ = lappend($1, $3); }
|
||||
;
|
||||
|
||||
RevokeStmt: REVOKE privileges ON opt_table relation_name_list FROM grantee_list
|
||||
function_with_argtypes: func_name func_args
|
||||
{
|
||||
GrantStmt *n = makeNode(GrantStmt);
|
||||
n->is_grant = false;
|
||||
n->relnames = $5;
|
||||
n->privileges = $2;
|
||||
n->grantees = $7;
|
||||
FuncWithArgs *n = makeNode(FuncWithArgs);
|
||||
n->funcname = $1;
|
||||
n->funcargs = $2;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
;
|
||||
@ -5876,6 +5903,7 @@ unreserved_keyword:
|
||||
| UNLISTEN { $$ = "unlisten"; }
|
||||
| UNTIL { $$ = "until"; }
|
||||
| UPDATE { $$ = "update"; }
|
||||
| USAGE { $$ = "usage"; }
|
||||
| VACUUM { $$ = "vacuum"; }
|
||||
| VALID { $$ = "valid"; }
|
||||
| VALUES { $$ = "values"; }
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.99 2001/10/10 00:02:42 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.100 2002/02/18 23:11:18 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -269,6 +269,7 @@ static ScanKeyword ScanKeywords[] = {
|
||||
{"unlisten", UNLISTEN},
|
||||
{"until", UNTIL},
|
||||
{"update", UPDATE},
|
||||
{"usage", USAGE},
|
||||
{"user", USER},
|
||||
{"using", USING},
|
||||
{"vacuum", VACUUM},
|
||||
@ -354,3 +355,36 @@ ScanKeywordLookup(char *text)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This does the reverse mapping from token number to string.
|
||||
*/
|
||||
const char *
|
||||
TokenString(int token)
|
||||
{
|
||||
int i = 0;
|
||||
static char buf[NAMEDATALEN];
|
||||
|
||||
while (i < sizeof(ScanKeywords))
|
||||
{
|
||||
if (ScanKeywords[i].value == token)
|
||||
{
|
||||
int k;
|
||||
|
||||
/* uppercase */
|
||||
for (k = 0; k < NAMEDATALEN; k++)
|
||||
if (ScanKeywords[i].name[k] >= 'a'
|
||||
&& ScanKeywords[i].name[k] <= 'z')
|
||||
buf[k] = ScanKeywords[i].name[k] + ('A' - 'a');
|
||||
else
|
||||
buf[k] = ScanKeywords[i].name[k];
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
#
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh,v 1.20 2001/05/22 12:06:51 momjian Exp $
|
||||
# $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh,v 1.21 2002/02/18 23:11:20 petere Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@ -164,7 +164,7 @@ FuNkYfMgRsTuFf
|
||||
tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' < $RAWFILE | \
|
||||
$AWK '
|
||||
BEGIN { OFS = ""; }
|
||||
{ if (seenit[$(NF-1)]++ == 0) print "#define F_", $(NF-1), " ", $1; }' >> "$$-$OIDSFILE"
|
||||
{ if (seenit[$(NF-2)]++ == 0) print "#define F_", $(NF-2), " ", $1; }' >> "$$-$OIDSFILE"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
cleanup
|
||||
@ -209,7 +209,7 @@ cat > "$$-$TABLEFILE" <<FuNkYfMgRtAbStUfF
|
||||
|
||||
FuNkYfMgRtAbStUfF
|
||||
|
||||
$AWK '{ print "extern Datum", $(NF-1), "(PG_FUNCTION_ARGS);"; }' $RAWFILE >> "$$-$TABLEFILE"
|
||||
$AWK '{ print "extern Datum", $(NF-2), "(PG_FUNCTION_ARGS);"; }' $RAWFILE >> "$$-$TABLEFILE"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
cleanup
|
||||
@ -232,7 +232,7 @@ $AWK 'BEGIN {
|
||||
Bool["f"] = "false"
|
||||
}
|
||||
{ printf (" { %d, \"%s\", %d, %s, %s, %s },\n"), \
|
||||
$1, $(NF-1), $9, Bool[$8], Bool[$10], $(NF-1)
|
||||
$1, $(NF-2), $9, Bool[$8], Bool[$10], $(NF-2)
|
||||
}' $RAWFILE >> "$$-$TABLEFILE"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.66 2001/11/16 23:30:35 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.67 2002/02/18 23:11:22 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -373,7 +373,7 @@ aclitemgt(const AclItem *a1, const AclItem *a2)
|
||||
* newly-created tables (or any table with a NULL acl entry in pg_class)
|
||||
*/
|
||||
Acl *
|
||||
acldefault(const char *relname, AclId ownerid)
|
||||
acldefault(AclId ownerid)
|
||||
{
|
||||
Acl *acl;
|
||||
AclItem *aip;
|
||||
@ -381,16 +381,18 @@ acldefault(const char *relname, AclId ownerid)
|
||||
#define ACL_WORLD_DEFAULT (ACL_NO)
|
||||
#define ACL_OWNER_DEFAULT (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_RULE|ACL_REFERENCES|ACL_TRIGGER)
|
||||
|
||||
acl = makeacl(2);
|
||||
acl = makeacl(ownerid ? 2 : 1);
|
||||
aip = ACL_DAT(acl);
|
||||
aip[0].ai_idtype = ACL_IDTYPE_WORLD;
|
||||
aip[0].ai_id = ACL_ID_WORLD;
|
||||
aip[0].ai_mode = (IsSystemRelationName(relname) &&
|
||||
!IsToastRelationName(relname)) ? ACL_SELECT
|
||||
: ACL_WORLD_DEFAULT;
|
||||
aip[1].ai_idtype = ACL_IDTYPE_UID;
|
||||
aip[1].ai_id = ownerid;
|
||||
aip[1].ai_mode = ACL_OWNER_DEFAULT;
|
||||
aip[0].ai_mode = ACL_WORLD_DEFAULT;
|
||||
/* FIXME: The owner's default should vary with the object type. */
|
||||
if (ownerid)
|
||||
{
|
||||
aip[1].ai_idtype = ACL_IDTYPE_UID;
|
||||
aip[1].ai_id = ownerid;
|
||||
aip[1].ai_mode = ACL_OWNER_DEFAULT;
|
||||
}
|
||||
return acl;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.39 2001/10/02 21:39:35 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.40 2002/02/18 23:11:23 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -20,6 +20,7 @@
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/catname.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/pg_language.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "executor/executor.h"
|
||||
#include "utils/fcache.h"
|
||||
@ -54,7 +55,7 @@ SetDefine(char *querystr, char *typename)
|
||||
false, /* don't replace */
|
||||
true, /* returnsSet */
|
||||
typename, /* returnTypeName */
|
||||
"sql", /* languageName */
|
||||
SQLlanguageId, /* language */
|
||||
querystr, /* sourceCode */
|
||||
fileName, /* fileName */
|
||||
true, /* trusted */
|
||||
|
6
src/backend/utils/cache/fcache.c
vendored
6
src/backend/utils/cache/fcache.c
vendored
@ -8,12 +8,14 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.41 2001/10/06 23:21:44 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.42 2002/02/18 23:11:25 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "miscadmin.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/fcache.h"
|
||||
|
||||
|
||||
@ -40,5 +42,7 @@ init_fcache(Oid foid, int nargs, MemoryContext fcacheCxt)
|
||||
/* Initialize additional info */
|
||||
retval->setArgsValid = false;
|
||||
|
||||
retval->permission_ok = pg_proc_aclcheck(foid, GetUserId()) == ACLCHECK_OK;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.19 2001/09/08 15:24:00 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.20 2002/02/18 23:11:26 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -30,16 +30,23 @@
|
||||
*/
|
||||
bool
|
||||
superuser(void)
|
||||
{
|
||||
return superuser_arg(GetUserId());
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
superuser_arg(Oid userid)
|
||||
{
|
||||
bool result = false;
|
||||
HeapTuple utup;
|
||||
|
||||
/* Special escape path in case you deleted all your users. */
|
||||
if (!IsUnderPostmaster && GetUserId() == BOOTSTRAP_USESYSID)
|
||||
if (!IsUnderPostmaster && userid == BOOTSTRAP_USESYSID)
|
||||
return true;
|
||||
|
||||
utup = SearchSysCache(SHADOWSYSID,
|
||||
ObjectIdGetDatum(GetUserId()),
|
||||
ObjectIdGetDatum(userid),
|
||||
0, 0, 0);
|
||||
if (HeapTupleIsValid(utup))
|
||||
{
|
||||
@ -49,6 +56,7 @@ superuser(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The Postgres user running this command is the owner of the specified
|
||||
* database.
|
||||
|
@ -27,7 +27,7 @@
|
||||
# Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
# Portions Copyright (c) 1994, Regents of the University of California
|
||||
#
|
||||
# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.142 2001/11/25 22:19:30 petere Exp $
|
||||
# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.143 2002/02/18 23:11:28 petere Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@ -833,6 +833,24 @@ EOF
|
||||
| "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
|
||||
echo "ok"
|
||||
|
||||
# Set most system catalogs and built-in functions as world-accessible.
|
||||
# Some objects may require different permissions by default, so we
|
||||
# make sure we don't overwrite privilege sets that have already been
|
||||
# set (NOT NULL).
|
||||
$ECHO_N "setting privileges on built-in objects... "$ECHO_C
|
||||
(
|
||||
cat <<EOF
|
||||
UPDATE pg_class SET relacl = '{"=r"}' \
|
||||
WHERE relkind IN ('r', 'v', 'S') AND relacl IS NULL;
|
||||
UPDATE pg_proc SET proacl = '{"=r"}' \
|
||||
WHERE proacl IS NULL;
|
||||
UPDATE pg_language SET lanacl = '{"=r"}' \
|
||||
WHERE lanpltrusted;
|
||||
EOF
|
||||
) \
|
||||
| "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
|
||||
echo "ok"
|
||||
|
||||
$ECHO_N "vacuuming database template1... "$ECHO_C
|
||||
|
||||
"$PGPATH"/postgres $PGSQL_OPT template1 >/dev/null <<EOF
|
||||
|
@ -7,7 +7,7 @@
|
||||
# Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
# Portions Copyright (c) 1994, Regents of the University of California
|
||||
#
|
||||
# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/createlang.sh,v 1.33 2002/02/18 05:48:44 momjian Exp $
|
||||
# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/createlang.sh,v 1.34 2002/02/18 23:11:30 petere Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@ -289,4 +289,15 @@ if [ "$?" -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -n "$trusted"; then
|
||||
sqlcmd="GRANT USAGE ON LANGUAGE \"$langname\" TO PUBLIC;"
|
||||
if [ "$showsql" = yes ]; then
|
||||
echo "$sqlcmd"
|
||||
fi
|
||||
$PSQL "$sqlcmd"
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo "$CMDNAME: language installation failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
exit 0
|
||||
|
@ -37,7 +37,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: catversion.h,v 1.103 2002/01/12 18:09:04 tgl Exp $
|
||||
* $Id: catversion.h,v 1.104 2002/02/18 23:11:32 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -53,6 +53,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 200201121
|
||||
#define CATALOG_VERSION_NO 200202181
|
||||
|
||||
#endif
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: pg_attribute.h,v 1.79 2001/11/05 17:46:32 momjian Exp $
|
||||
* $Id: pg_attribute.h,v 1.80 2002/02/18 23:11:33 petere Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -310,7 +310,8 @@ DATA(insert ( 1262 tableoid 26 0 4 -7 0 -1 -1 t p f i f f));
|
||||
{ 1255, {"propercall_cpu"}, 23, 0, 4, 14, 0, -1, -1, true, 'p', false, 'i', false, false }, \
|
||||
{ 1255, {"prooutin_ratio"}, 23, 0, 4, 15, 0, -1, -1, true, 'p', false, 'i', false, false }, \
|
||||
{ 1255, {"prosrc"}, 25, 0, -1, 16, 0, -1, -1, false, 'x', false, 'i', false, false }, \
|
||||
{ 1255, {"probin"}, 17, 0, -1, 17, 0, -1, -1, false, 'x', false, 'i', false, false }
|
||||
{ 1255, {"probin"}, 17, 0, -1, 17, 0, -1, -1, false, 'x', false, 'i', false, false }, \
|
||||
{ 1255, {"proacl"}, 1034, 0, -1, 18, 0, -1, -1, false, 'x', false, 'i', false, false }
|
||||
|
||||
DATA(insert ( 1255 proname 19 DEFAULT_ATTSTATTARGET NAMEDATALEN 1 0 -1 -1 f p f i f f));
|
||||
DATA(insert ( 1255 proowner 23 0 4 2 0 -1 -1 t p f i f f));
|
||||
@ -329,6 +330,7 @@ DATA(insert ( 1255 propercall_cpu 23 0 4 14 0 -1 -1 t p f i f f));
|
||||
DATA(insert ( 1255 prooutin_ratio 23 0 4 15 0 -1 -1 t p f i f f));
|
||||
DATA(insert ( 1255 prosrc 25 0 -1 16 0 -1 -1 f x f i f f));
|
||||
DATA(insert ( 1255 probin 17 0 -1 17 0 -1 -1 f x f i f f));
|
||||
DATA(insert ( 1255 proacl 1034 0 -1 18 0 -1 -1 f x f i f f));
|
||||
DATA(insert ( 1255 ctid 27 0 6 -1 0 -1 -1 f p f i f f));
|
||||
DATA(insert ( 1255 oid 26 0 4 -2 0 -1 -1 t p f i f f));
|
||||
DATA(insert ( 1255 xmin 28 0 4 -3 0 -1 -1 t p f i f f));
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: pg_class.h,v 1.57 2001/11/05 17:46:32 momjian Exp $
|
||||
* $Id: pg_class.h,v 1.58 2002/02/18 23:11:34 petere Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -136,7 +136,7 @@ DATA(insert OID = 1247 ( pg_type 71 PGUID 0 1247 0 0 0 0 f f r 17 0 0 0 0 0 t
|
||||
DESCR("");
|
||||
DATA(insert OID = 1249 ( pg_attribute 75 PGUID 0 1249 0 0 0 0 f f r 15 0 0 0 0 0 f f f f _null_ ));
|
||||
DESCR("");
|
||||
DATA(insert OID = 1255 ( pg_proc 81 PGUID 0 1255 0 0 0 0 f f r 17 0 0 0 0 0 t f f f _null_ ));
|
||||
DATA(insert OID = 1255 ( pg_proc 81 PGUID 0 1255 0 0 0 0 f f r 18 0 0 0 0 0 t f f f _null_ ));
|
||||
DESCR("");
|
||||
DATA(insert OID = 1259 ( pg_class 83 PGUID 0 1259 0 0 0 0 f f r 23 0 0 0 0 0 t f f f _null_ ));
|
||||
DESCR("");
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: pg_language.h,v 1.15 2001/11/05 17:46:32 momjian Exp $
|
||||
* $Id: pg_language.h,v 1.16 2002/02/18 23:11:35 petere Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -38,6 +38,7 @@ CATALOG(pg_language)
|
||||
bool lanpltrusted; /* PL is trusted */
|
||||
Oid lanplcallfoid; /* Call handler for PL */
|
||||
text lancompiler; /* VARIABLE LENGTH FIELD */
|
||||
aclitem lanacl[1]; /* Access privileges */
|
||||
} FormData_pg_language;
|
||||
|
||||
/* ----------------
|
||||
@ -51,25 +52,26 @@ typedef FormData_pg_language *Form_pg_language;
|
||||
* compiler constants for pg_language
|
||||
* ----------------
|
||||
*/
|
||||
#define Natts_pg_language 5
|
||||
#define Natts_pg_language 6
|
||||
#define Anum_pg_language_lanname 1
|
||||
#define Anum_pg_language_lanispl 2
|
||||
#define Anum_pg_language_lanpltrusted 3
|
||||
#define Anum_pg_language_lanplcallfoid 4
|
||||
#define Anum_pg_language_lancompiler 5
|
||||
#define Anum_pg_language_lanacl 6
|
||||
|
||||
/* ----------------
|
||||
* initial contents of pg_language
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
DATA(insert OID = 12 ( internal f f 0 "n/a" ));
|
||||
DATA(insert OID = 12 ( "internal" f f 0 "n/a" _null_ ));
|
||||
DESCR("Built-in functions");
|
||||
#define INTERNALlanguageId 12
|
||||
DATA(insert OID = 13 ( "C" f f 0 "/bin/cc" ));
|
||||
DATA(insert OID = 13 ( "c" f f 0 "/bin/cc" _null_ ));
|
||||
DESCR("Dynamically-loaded C functions");
|
||||
#define ClanguageId 13
|
||||
DATA(insert OID = 14 ( "sql" f f 0 "postgres"));
|
||||
DATA(insert OID = 14 ( "sql" f t 0 "postgres" _null_ ));
|
||||
DESCR("SQL-language functions");
|
||||
#define SQLlanguageId 14
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: miscadmin.h,v 1.98 2002/01/01 23:16:22 tgl Exp $
|
||||
* $Id: miscadmin.h,v 1.99 2002/02/18 23:11:31 petere Exp $
|
||||
*
|
||||
* NOTES
|
||||
* some of the information in this file should be moved to
|
||||
@ -227,6 +227,7 @@ extern char *convertstr(unsigned char *buff, int len, int dest);
|
||||
|
||||
/* in utils/misc/superuser.c */
|
||||
extern bool superuser(void); /* current user is superuser */
|
||||
extern bool superuser_arg(Oid userid); /* given user is superuser */
|
||||
extern bool is_dbadmin(Oid dbid); /* current user is owner of
|
||||
* database */
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: nodes.h,v 1.96 2001/11/05 17:46:34 momjian Exp $
|
||||
* $Id: nodes.h,v 1.97 2002/02/18 23:11:41 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -222,6 +222,8 @@ typedef enum NodeTag
|
||||
T_CaseWhen,
|
||||
T_FkConstraint,
|
||||
T_PrivGrantee,
|
||||
T_FuncWithArgs,
|
||||
T_PrivTarget,
|
||||
|
||||
/*
|
||||
* TAGS FOR FUNCTION-CALL CONTEXT AND RESULTINFO NODES (see fmgr.h)
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: parsenodes.h,v 1.151 2001/11/05 17:46:34 momjian Exp $
|
||||
* $Id: parsenodes.h,v 1.152 2002/02/18 23:11:41 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -145,8 +145,9 @@ typedef struct GrantStmt
|
||||
{
|
||||
NodeTag type;
|
||||
bool is_grant; /* not revoke */
|
||||
List *relnames;
|
||||
char *privileges;
|
||||
int objtype;
|
||||
List *objects;
|
||||
List *privileges;
|
||||
List *grantees;
|
||||
} GrantStmt;
|
||||
|
||||
@ -159,6 +160,23 @@ typedef struct PrivGrantee
|
||||
} PrivGrantee;
|
||||
|
||||
|
||||
typedef struct FuncWithArgs
|
||||
{
|
||||
NodeTag type;
|
||||
char *funcname;
|
||||
List *funcargs;
|
||||
} FuncWithArgs;
|
||||
|
||||
|
||||
/* This is only used internally in gram.y. */
|
||||
typedef struct PrivTarget
|
||||
{
|
||||
NodeTag type;
|
||||
int objtype;
|
||||
List *objs;
|
||||
} PrivTarget;
|
||||
|
||||
|
||||
/* ----------------------
|
||||
* Close Portal Statement
|
||||
* ----------------------
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: keywords.h,v 1.12 2001/11/05 17:46:34 momjian Exp $
|
||||
* $Id: keywords.h,v 1.13 2002/02/18 23:11:45 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -21,5 +21,6 @@ typedef struct ScanKeyword
|
||||
} ScanKeyword;
|
||||
|
||||
extern ScanKeyword *ScanKeywordLookup(char *text);
|
||||
extern const char *TokenString(int token);
|
||||
|
||||
#endif /* KEYWORDS_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: acl.h,v 1.39 2001/11/05 17:46:36 momjian Exp $
|
||||
* $Id: acl.h,v 1.40 2002/02/18 23:11:45 petere Exp $
|
||||
*
|
||||
* NOTES
|
||||
* For backward-compatibility purposes we have to allow there
|
||||
@ -171,7 +171,7 @@ extern char *aclcheck_error_strings[];
|
||||
/*
|
||||
* routines used internally
|
||||
*/
|
||||
extern Acl *acldefault(const char *relname, AclId ownerid);
|
||||
extern Acl *acldefault(AclId ownerid);
|
||||
extern Acl *aclinsert3(const Acl *old_acl, const AclItem *mod_aip, unsigned modechg);
|
||||
|
||||
/*
|
||||
@ -208,4 +208,7 @@ extern bool pg_func_ownercheck(Oid userid, char *funcname,
|
||||
extern bool pg_aggr_ownercheck(Oid userid, char *aggname,
|
||||
Oid basetypeID);
|
||||
|
||||
extern int32 pg_proc_aclcheck(Oid proc_oid, Oid userid);
|
||||
extern int32 pg_language_aclcheck(Oid lang_oid, Oid userid);
|
||||
|
||||
#endif /* ACL_H */
|
||||
|
@ -11,7 +11,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: fcache.h,v 1.20 2001/11/05 17:46:36 momjian Exp $
|
||||
* $Id: fcache.h,v 1.21 2002/02/18 23:11:46 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -41,6 +41,8 @@ typedef struct FunctionCache
|
||||
*/
|
||||
FmgrInfo func;
|
||||
|
||||
bool permission_ok;
|
||||
|
||||
/*
|
||||
* setArgsValid is true when we are evaluating a set-valued function
|
||||
* and we are in the middle of a call series; we want to pass the same
|
||||
|
@ -188,6 +188,49 @@ SELECT * FROM atestv3; -- ok
|
||||
-----+-----+-------
|
||||
(0 rows)
|
||||
|
||||
-- privileges on functions, languages
|
||||
-- switch to superuser
|
||||
\c -
|
||||
REVOKE ALL PRIVILEGES ON LANGUAGE sql FROM PUBLIC;
|
||||
GRANT USAGE ON LANGUAGE sql TO regressuser1; -- ok
|
||||
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
|
||||
CREATE FUNCTION testfunc1(int) RETURNS int AS 'select 2 * $1;' LANGUAGE sql;
|
||||
CREATE FUNCTION testfunc2(int) RETURNS int AS 'select 3 * $1;' LANGUAGE sql;
|
||||
GRANT EXECUTE ON FUNCTION testfunc1(int), testfunc2(int) TO regressuser2;
|
||||
GRANT USAGE ON FUNCTION testfunc1(int) TO regressuser3; -- semantic error
|
||||
ERROR: invalid privilege type USAGE for function object
|
||||
GRANT ALL PRIVILEGES ON FUNCTION testfunc1(int) TO regressuser4;
|
||||
GRANT ALL PRIVILEGES ON FUNCTION testfunc_nosuch(int) TO regressuser4;
|
||||
ERROR: Function 'testfunc_nosuch(int4)' does not exist
|
||||
SET SESSION AUTHORIZATION regressuser2;
|
||||
SELECT testfunc1(5), testfunc2(5); -- ok
|
||||
testfunc1 | testfunc2
|
||||
-----------+-----------
|
||||
10 | 15
|
||||
(1 row)
|
||||
|
||||
CREATE FUNCTION testfunc3(int) RETURNS int AS 'select 2 * $1;' LANGUAGE sql; -- fail
|
||||
ERROR: permission denied
|
||||
SET SESSION AUTHORIZATION regressuser3;
|
||||
SELECT testfunc1(5); -- fail
|
||||
ERROR: permission denied
|
||||
SET SESSION AUTHORIZATION regressuser4;
|
||||
SELECT testfunc1(5); -- ok
|
||||
testfunc1
|
||||
-----------
|
||||
10
|
||||
(1 row)
|
||||
|
||||
DROP FUNCTION testfunc1(int); -- fail
|
||||
ERROR: RemoveFunction: function 'testfunc1': permission denied
|
||||
\c -
|
||||
DROP FUNCTION testfunc1(int); -- ok
|
||||
-- restore to sanity
|
||||
GRANT ALL PRIVILEGES ON LANGUAGE sql TO PUBLIC;
|
||||
-- has_table_privilege function
|
||||
-- bad-input checks
|
||||
select has_table_privilege(NULL,'pg_shadow','select');
|
||||
@ -207,7 +250,7 @@ ERROR: pg_aclcheck: invalid user id 4293967297
|
||||
select has_table_privilege(1,'rule');
|
||||
ERROR: has_table_privilege: invalid relation oid 1
|
||||
-- superuser
|
||||
\c regression
|
||||
\c -
|
||||
select has_table_privilege(current_user,'pg_shadow','select');
|
||||
has_table_privilege
|
||||
---------------------
|
||||
|
@ -126,6 +126,42 @@ SELECT * FROM atestv1; -- ok
|
||||
SELECT * FROM atestv3; -- ok
|
||||
|
||||
|
||||
-- privileges on functions, languages
|
||||
|
||||
-- switch to superuser
|
||||
\c -
|
||||
REVOKE ALL PRIVILEGES ON LANGUAGE sql FROM PUBLIC;
|
||||
GRANT USAGE ON LANGUAGE sql TO regressuser1; -- ok
|
||||
GRANT USAGE ON LANGUAGE c TO PUBLIC; -- fail
|
||||
|
||||
SET SESSION AUTHORIZATION regressuser1;
|
||||
GRANT USAGE ON LANGUAGE sql TO regressuser2; -- fail
|
||||
CREATE FUNCTION testfunc1(int) RETURNS int AS 'select 2 * $1;' LANGUAGE sql;
|
||||
CREATE FUNCTION testfunc2(int) RETURNS int AS 'select 3 * $1;' LANGUAGE sql;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION testfunc1(int), testfunc2(int) TO regressuser2;
|
||||
GRANT USAGE ON FUNCTION testfunc1(int) TO regressuser3; -- semantic error
|
||||
GRANT ALL PRIVILEGES ON FUNCTION testfunc1(int) TO regressuser4;
|
||||
GRANT ALL PRIVILEGES ON FUNCTION testfunc_nosuch(int) TO regressuser4;
|
||||
|
||||
SET SESSION AUTHORIZATION regressuser2;
|
||||
SELECT testfunc1(5), testfunc2(5); -- ok
|
||||
CREATE FUNCTION testfunc3(int) RETURNS int AS 'select 2 * $1;' LANGUAGE sql; -- fail
|
||||
|
||||
SET SESSION AUTHORIZATION regressuser3;
|
||||
SELECT testfunc1(5); -- fail
|
||||
|
||||
SET SESSION AUTHORIZATION regressuser4;
|
||||
SELECT testfunc1(5); -- ok
|
||||
|
||||
DROP FUNCTION testfunc1(int); -- fail
|
||||
|
||||
\c -
|
||||
DROP FUNCTION testfunc1(int); -- ok
|
||||
-- restore to sanity
|
||||
GRANT ALL PRIVILEGES ON LANGUAGE sql TO PUBLIC;
|
||||
|
||||
|
||||
-- has_table_privilege function
|
||||
|
||||
-- bad-input checks
|
||||
@ -137,7 +173,7 @@ select has_table_privilege(-999999,'pg_shadow','update');
|
||||
select has_table_privilege(1,'rule');
|
||||
|
||||
-- superuser
|
||||
\c regression
|
||||
\c -
|
||||
select has_table_privilege(current_user,'pg_shadow','select');
|
||||
select has_table_privilege(current_user,'pg_shadow','insert');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user