|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.58 2002/03/05 05:33:20 momjian Exp $ |
| 11 | + * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.59 2002/05/18 13:47:59 petere Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
|
19 | 19 | #include"catalog/pg_language.h"
|
20 | 20 | #include"catalog/pg_proc.h"
|
21 | 21 | #include"executor/functions.h"
|
| 22 | +#include"miscadmin.h" |
22 | 23 | #include"utils/builtins.h"
|
23 | 24 | #include"utils/fmgrtab.h"
|
24 | 25 | #include"utils/lsyscache.h"
|
@@ -56,10 +57,12 @@ typedef struct
|
56 | 57 | }Oldstyle_fnextra;
|
57 | 58 |
|
58 | 59 |
|
| 60 | +staticvoidfmgr_info_cxt_security(OidfunctionId,FmgrInfo*finfo,MemoryContextmcxt, |
| 61 | +boolignore_security); |
59 | 62 | staticvoidfmgr_info_C_lang(OidfunctionId,FmgrInfo*finfo,HeapTupleprocedureTuple);
|
60 | 63 | staticvoidfmgr_info_other_lang(OidfunctionId,FmgrInfo*finfo,HeapTupleprocedureTuple);
|
61 | 64 | staticDatumfmgr_oldstyle(PG_FUNCTION_ARGS);
|
62 |
| -staticDatumfmgr_untrusted(PG_FUNCTION_ARGS); |
| 65 | +staticDatumfmgr_security_definer(PG_FUNCTION_ARGS); |
63 | 66 |
|
64 | 67 |
|
65 | 68 | /*
|
@@ -135,6 +138,18 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
|
135 | 138 | */
|
136 | 139 | void
|
137 | 140 | fmgr_info_cxt(OidfunctionId,FmgrInfo*finfo,MemoryContextmcxt)
|
| 141 | +{ |
| 142 | +fmgr_info_cxt_security(functionId,finfo,mcxt, false); |
| 143 | +} |
| 144 | + |
| 145 | +/* |
| 146 | + * This one does the actual work. ignore_security is ordinarily false |
| 147 | + * but is set to true by fmgr_security_definer to avoid infinite |
| 148 | + * recursive lookups. |
| 149 | + */ |
| 150 | +staticvoid |
| 151 | +fmgr_info_cxt_security(OidfunctionId,FmgrInfo*finfo,MemoryContextmcxt, |
| 152 | +boolignore_security) |
138 | 153 | {
|
139 | 154 | constFmgrBuiltin*fbp;
|
140 | 155 | HeapTupleprocedureTuple;
|
@@ -177,10 +192,9 @@ fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
|
177 | 192 | finfo->fn_strict=procedureStruct->proisstrict;
|
178 | 193 | finfo->fn_retset=procedureStruct->proretset;
|
179 | 194 |
|
180 |
| -if (!procedureStruct->proistrusted) |
| 195 | +if (procedureStruct->prosecdef&& !ignore_security) |
181 | 196 | {
|
182 |
| -/* This isn't really supported anymore... */ |
183 |
| -finfo->fn_addr=fmgr_untrusted; |
| 197 | +finfo->fn_addr=fmgr_security_definer; |
184 | 198 | finfo->fn_oid=functionId;
|
185 | 199 | ReleaseSysCache(procedureTuple);
|
186 | 200 | return;
|
@@ -620,17 +634,63 @@ fmgr_oldstyle(PG_FUNCTION_ARGS)
|
620 | 634 |
|
621 | 635 |
|
622 | 636 | /*
|
623 |
| - * Handler for all functions marked "untrusted" |
| 637 | + * Support for security definer functions |
| 638 | + */ |
| 639 | + |
| 640 | +structfmgr_security_definer_cache |
| 641 | +{ |
| 642 | +FmgrInfoflinfo; |
| 643 | +Oiduserid; |
| 644 | +}; |
| 645 | + |
| 646 | +/* |
| 647 | + * Function handler for security definer functions. We extract the |
| 648 | + * OID of the actual function and do a fmgr lookup again. Then we |
| 649 | + * look up the owner of the function and cache both the fmgr info and |
| 650 | + * the owner ID. During the call we temporarily replace the flinfo |
| 651 | + * with the cached/looked-up one, while keeping the outer fcinfo |
| 652 | + * (which contains all the actual arguments, etc.) intact. |
624 | 653 | */
|
625 | 654 | staticDatum
|
626 |
| -fmgr_untrusted(PG_FUNCTION_ARGS) |
| 655 | +fmgr_security_definer(PG_FUNCTION_ARGS) |
627 | 656 | {
|
628 |
| -/* |
629 |
| - * Currently these are unsupported. Someday we might do something |
630 |
| - * like forking a subprocess to execute 'em. |
631 |
| - */ |
632 |
| -elog(ERROR,"Untrusted functions not supported"); |
633 |
| -return0;/* keep compiler happy */ |
| 657 | +Datumresult; |
| 658 | +FmgrInfo*save_flinfo; |
| 659 | +structfmgr_security_definer_cache*fcache; |
| 660 | +Oidsave_userid; |
| 661 | +HeapTupletuple; |
| 662 | + |
| 663 | +if (!fcinfo->flinfo->fn_extra) |
| 664 | +{ |
| 665 | +fcache=MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,sizeof(*fcache)); |
| 666 | +memset(fcache,0,sizeof(*fcache)); |
| 667 | + |
| 668 | +fmgr_info_cxt_security(fcinfo->flinfo->fn_oid,&fcache->flinfo, |
| 669 | +fcinfo->flinfo->fn_mcxt, true); |
| 670 | + |
| 671 | +tuple=SearchSysCache(PROCOID,ObjectIdGetDatum(fcinfo->flinfo->fn_oid),0,0,0); |
| 672 | +if (!HeapTupleIsValid(tuple)) |
| 673 | +elog(ERROR,"fmgr_security_definer: function %u: cache lookup failed", |
| 674 | +fcinfo->flinfo->fn_oid); |
| 675 | +fcache->userid= ((Form_pg_proc)GETSTRUCT(tuple))->proowner; |
| 676 | +ReleaseSysCache(tuple); |
| 677 | + |
| 678 | +fcinfo->flinfo->fn_extra=fcache; |
| 679 | +} |
| 680 | +else |
| 681 | +fcache=fcinfo->flinfo->fn_extra; |
| 682 | + |
| 683 | +save_flinfo=fcinfo->flinfo; |
| 684 | +fcinfo->flinfo=&fcache->flinfo; |
| 685 | + |
| 686 | +save_userid=GetUserId(); |
| 687 | +SetUserId(fcache->userid); |
| 688 | +result=FunctionCallInvoke(fcinfo); |
| 689 | +SetUserId(save_userid); |
| 690 | + |
| 691 | +fcinfo->flinfo=save_flinfo; |
| 692 | + |
| 693 | +returnresult; |
634 | 694 | }
|
635 | 695 |
|
636 | 696 |
|
|