1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-27 12:41:57 +03:00

Privileges on functions and procedural languages

This commit is contained in:
Peter Eisentraut
2002-02-18 23:11:58 +00:00
parent 5e03503126
commit 8adf56f77a
35 changed files with 2325 additions and 1534 deletions

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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") */

View File

@ -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);

View File

@ -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

View File

@ -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",

View File

@ -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",

View File

@ -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"; }

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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("");

View File

@ -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

View File

@ -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 */

View File

@ -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)

View File

@ -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
* ----------------------

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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
---------------------

View File

@ -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');