mirror of
https://github.com/postgres/postgres.git
synced 2025-11-13 16:22:44 +03:00
Allow functions to be executed with the privileges of the function owner.
I took the opportunity to remove the pg_proc.proistrusted field.
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.43 2002/04/11 20:00:05 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.44 2002/05/18 13:47:59 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -61,7 +61,7 @@ SetDefine(char *querystr, Oid elemType)
|
||||
querystr, /* prosrc */
|
||||
fileName, /* probin */
|
||||
false, /* not aggregate */
|
||||
true, /* trusted */
|
||||
false, /* security invoker */
|
||||
false, /* not implicit coercion */
|
||||
false, /* isStrict (irrelevant, no args) */
|
||||
PROVOLATILE_VOLATILE, /* assume unsafe */
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.58 2002/03/05 05:33:20 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.59 2002/05/18 13:47:59 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "catalog/pg_language.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "executor/functions.h"
|
||||
#include "miscadmin.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgrtab.h"
|
||||
#include "utils/lsyscache.h"
|
||||
@@ -56,10 +57,12 @@ typedef struct
|
||||
} Oldstyle_fnextra;
|
||||
|
||||
|
||||
static void fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt,
|
||||
bool ignore_security);
|
||||
static void fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple);
|
||||
static void fmgr_info_other_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple);
|
||||
static Datum fmgr_oldstyle(PG_FUNCTION_ARGS);
|
||||
static Datum fmgr_untrusted(PG_FUNCTION_ARGS);
|
||||
static Datum fmgr_security_definer(PG_FUNCTION_ARGS);
|
||||
|
||||
|
||||
/*
|
||||
@@ -135,6 +138,18 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
|
||||
*/
|
||||
void
|
||||
fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
|
||||
{
|
||||
fmgr_info_cxt_security(functionId, finfo, mcxt, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* This one does the actual work. ignore_security is ordinarily false
|
||||
* but is set to true by fmgr_security_definer to avoid infinite
|
||||
* recursive lookups.
|
||||
*/
|
||||
static void
|
||||
fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt,
|
||||
bool ignore_security)
|
||||
{
|
||||
const FmgrBuiltin *fbp;
|
||||
HeapTuple procedureTuple;
|
||||
@@ -177,10 +192,9 @@ fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
|
||||
finfo->fn_strict = procedureStruct->proisstrict;
|
||||
finfo->fn_retset = procedureStruct->proretset;
|
||||
|
||||
if (!procedureStruct->proistrusted)
|
||||
if (procedureStruct->prosecdef && !ignore_security)
|
||||
{
|
||||
/* This isn't really supported anymore... */
|
||||
finfo->fn_addr = fmgr_untrusted;
|
||||
finfo->fn_addr = fmgr_security_definer;
|
||||
finfo->fn_oid = functionId;
|
||||
ReleaseSysCache(procedureTuple);
|
||||
return;
|
||||
@@ -620,17 +634,63 @@ fmgr_oldstyle(PG_FUNCTION_ARGS)
|
||||
|
||||
|
||||
/*
|
||||
* Handler for all functions marked "untrusted"
|
||||
* Support for security definer functions
|
||||
*/
|
||||
|
||||
struct fmgr_security_definer_cache
|
||||
{
|
||||
FmgrInfo flinfo;
|
||||
Oid userid;
|
||||
};
|
||||
|
||||
/*
|
||||
* Function handler for security definer functions. We extract the
|
||||
* OID of the actual function and do a fmgr lookup again. Then we
|
||||
* look up the owner of the function and cache both the fmgr info and
|
||||
* the owner ID. During the call we temporarily replace the flinfo
|
||||
* with the cached/looked-up one, while keeping the outer fcinfo
|
||||
* (which contains all the actual arguments, etc.) intact.
|
||||
*/
|
||||
static Datum
|
||||
fmgr_untrusted(PG_FUNCTION_ARGS)
|
||||
fmgr_security_definer(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/*
|
||||
* Currently these are unsupported. Someday we might do something
|
||||
* like forking a subprocess to execute 'em.
|
||||
*/
|
||||
elog(ERROR, "Untrusted functions not supported");
|
||||
return 0; /* keep compiler happy */
|
||||
Datum result;
|
||||
FmgrInfo *save_flinfo;
|
||||
struct fmgr_security_definer_cache *fcache;
|
||||
Oid save_userid;
|
||||
HeapTuple tuple;
|
||||
|
||||
if (!fcinfo->flinfo->fn_extra)
|
||||
{
|
||||
fcache = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(*fcache));
|
||||
memset(fcache, 0, sizeof(*fcache));
|
||||
|
||||
fmgr_info_cxt_security(fcinfo->flinfo->fn_oid, &fcache->flinfo,
|
||||
fcinfo->flinfo->fn_mcxt, true);
|
||||
|
||||
tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(fcinfo->flinfo->fn_oid), 0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "fmgr_security_definer: function %u: cache lookup failed",
|
||||
fcinfo->flinfo->fn_oid);
|
||||
fcache->userid = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
fcinfo->flinfo->fn_extra = fcache;
|
||||
}
|
||||
else
|
||||
fcache = fcinfo->flinfo->fn_extra;
|
||||
|
||||
save_flinfo = fcinfo->flinfo;
|
||||
fcinfo->flinfo = &fcache->flinfo;
|
||||
|
||||
save_userid = GetUserId();
|
||||
SetUserId(fcache->userid);
|
||||
result = FunctionCallInvoke(fcinfo);
|
||||
SetUserId(save_userid);
|
||||
|
||||
fcinfo->flinfo = save_flinfo;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user