|
24 | 24 | #include"miscadmin.h"
|
25 | 25 | #include"nodes/nodeFuncs.h"
|
26 | 26 | #include"pgstat.h"
|
| 27 | +#include"utils/acl.h" |
27 | 28 | #include"utils/builtins.h"
|
28 | 29 | #include"utils/fmgrtab.h"
|
29 | 30 | #include"utils/guc.h"
|
@@ -2468,3 +2469,86 @@ get_fn_expr_variadic(FmgrInfo *flinfo)
|
2468 | 2469 | else
|
2469 | 2470 | return false;
|
2470 | 2471 | }
|
| 2472 | + |
| 2473 | +/*------------------------------------------------------------------------- |
| 2474 | + *Support routines for procedural language implementations |
| 2475 | + *------------------------------------------------------------------------- |
| 2476 | + */ |
| 2477 | + |
| 2478 | +/* |
| 2479 | + * Verify that a validator is actually associated with the language of a |
| 2480 | + * particular function and that the user has access to both the language and |
| 2481 | + * the function. All validators should call this before doing anything |
| 2482 | + * substantial. Doing so ensures a user cannot achieve anything with explicit |
| 2483 | + * calls to validators that he could not achieve with CREATE FUNCTION or by |
| 2484 | + * simply calling an existing function. |
| 2485 | + * |
| 2486 | + * When this function returns false, callers should skip all validation work |
| 2487 | + * and call PG_RETURN_VOID(). This never happens at present; it is reserved |
| 2488 | + * for future expansion. |
| 2489 | + * |
| 2490 | + * In particular, checking that the validator corresponds to the function's |
| 2491 | + * language allows untrusted language validators to assume they process only |
| 2492 | + * superuser-chosen source code. (Untrusted language call handlers, by |
| 2493 | + * definition, do assume that.) A user lacking the USAGE language privilege |
| 2494 | + * would be unable to reach the validator through CREATE FUNCTION, so we check |
| 2495 | + * that to block explicit calls as well. Checking the EXECUTE privilege on |
| 2496 | + * the function is often superfluous, because most users can clone the |
| 2497 | + * function to get an executable copy. It is meaningful against users with no |
| 2498 | + * database TEMP right and no permanent schema CREATE right, thereby unable to |
| 2499 | + * create any function. Also, if the function tracks persistent state by |
| 2500 | + * function OID or name, validating the original function might permit more |
| 2501 | + * mischief than creating and validating a clone thereof. |
| 2502 | + */ |
| 2503 | +bool |
| 2504 | +CheckFunctionValidatorAccess(OidvalidatorOid,OidfunctionOid) |
| 2505 | +{ |
| 2506 | +HeapTupleprocTup; |
| 2507 | +HeapTuplelangTup; |
| 2508 | +Form_pg_procprocStruct; |
| 2509 | +Form_pg_languagelangStruct; |
| 2510 | +AclResultaclresult; |
| 2511 | + |
| 2512 | +/* Get the function's pg_proc entry */ |
| 2513 | +procTup=SearchSysCache1(PROCOID,ObjectIdGetDatum(functionOid)); |
| 2514 | +if (!HeapTupleIsValid(procTup)) |
| 2515 | +elog(ERROR,"cache lookup failed for function %u",functionOid); |
| 2516 | +procStruct= (Form_pg_proc)GETSTRUCT(procTup); |
| 2517 | + |
| 2518 | +/* |
| 2519 | + * Fetch pg_language entry to know if this is the correct validation |
| 2520 | + * function for that pg_proc entry. |
| 2521 | + */ |
| 2522 | +langTup=SearchSysCache1(LANGOID,ObjectIdGetDatum(procStruct->prolang)); |
| 2523 | +if (!HeapTupleIsValid(langTup)) |
| 2524 | +elog(ERROR,"cache lookup failed for language %u",procStruct->prolang); |
| 2525 | +langStruct= (Form_pg_language)GETSTRUCT(langTup); |
| 2526 | + |
| 2527 | +if (langStruct->lanvalidator!=validatorOid) |
| 2528 | +ereport(ERROR, |
| 2529 | +(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), |
| 2530 | +errmsg("language validation function %u called for language %u instead of %u", |
| 2531 | +validatorOid,procStruct->prolang, |
| 2532 | +langStruct->lanvalidator))); |
| 2533 | + |
| 2534 | +/* first validate that we have permissions to use the language */ |
| 2535 | +aclresult=pg_language_aclcheck(procStruct->prolang,GetUserId(), |
| 2536 | +ACL_USAGE); |
| 2537 | +if (aclresult!=ACLCHECK_OK) |
| 2538 | +aclcheck_error(aclresult,ACL_KIND_LANGUAGE, |
| 2539 | +NameStr(langStruct->lanname)); |
| 2540 | + |
| 2541 | +/* |
| 2542 | + * Check whether we are allowed to execute the function itself. If we can |
| 2543 | + * execute it, there should be no possible side-effect of |
| 2544 | + * compiling/validation that execution can't have. |
| 2545 | + */ |
| 2546 | +aclresult=pg_proc_aclcheck(functionOid,GetUserId(),ACL_EXECUTE); |
| 2547 | +if (aclresult!=ACLCHECK_OK) |
| 2548 | +aclcheck_error(aclresult,ACL_KIND_PROC,NameStr(procStruct->proname)); |
| 2549 | + |
| 2550 | +ReleaseSysCache(procTup); |
| 2551 | +ReleaseSysCache(langTup); |
| 2552 | + |
| 2553 | +return true; |
| 2554 | +} |