1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-30 21:42:05 +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

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