diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/catalog/namespace.c | 15 | ||||
-rw-r--r-- | src/backend/catalog/objectaccess.c | 25 | ||||
-rw-r--r-- | src/backend/tcop/fastpath.c | 2 | ||||
-rw-r--r-- | src/include/catalog/objectaccess.h | 33 |
4 files changed, 72 insertions, 3 deletions
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 07a8761709e..f48c0bcb31f 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -22,6 +22,7 @@ #include "access/htup_details.h" #include "access/xact.h" #include "catalog/dependency.h" +#include "catalog/objectaccess.h" #include "catalog/pg_authid.h" #include "catalog/pg_collation.h" #include "catalog/pg_conversion.h" @@ -2655,7 +2656,10 @@ LookupNamespaceNoError(const char *nspname) if (strcmp(nspname, "pg_temp") == 0) { if (OidIsValid(myTempNamespace)) + { + InvokeNamespaceSearchHook(myTempNamespace, true); return myTempNamespace; + } /* * Since this is used only for looking up existing objects, there is @@ -2702,6 +2706,8 @@ LookupExplicitNamespace(const char *nspname, bool missing_ok) if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, ACL_KIND_NAMESPACE, nspname); + /* Schema search hook for this lookup */ + InvokeNamespaceSearchHook(namespaceId, true); return namespaceId; } @@ -3468,7 +3474,8 @@ recomputeNamespacePath(void) if (OidIsValid(namespaceId) && !list_member_oid(oidlist, namespaceId) && pg_namespace_aclcheck(namespaceId, roleid, - ACL_USAGE) == ACLCHECK_OK) + ACL_USAGE) == ACLCHECK_OK && + InvokeNamespaceSearchHook(namespaceId, false)) oidlist = lappend_oid(oidlist, namespaceId); } } @@ -3477,7 +3484,8 @@ recomputeNamespacePath(void) /* pg_temp --- substitute temp namespace, if any */ if (OidIsValid(myTempNamespace)) { - if (!list_member_oid(oidlist, myTempNamespace)) + if (!list_member_oid(oidlist, myTempNamespace) && + InvokeNamespaceSearchHook(myTempNamespace, false)) oidlist = lappend_oid(oidlist, myTempNamespace); } else @@ -3494,7 +3502,8 @@ recomputeNamespacePath(void) if (OidIsValid(namespaceId) && !list_member_oid(oidlist, namespaceId) && pg_namespace_aclcheck(namespaceId, roleid, - ACL_USAGE) == ACLCHECK_OK) + ACL_USAGE) == ACLCHECK_OK && + InvokeNamespaceSearchHook(namespaceId, false)) oidlist = lappend_oid(oidlist, namespaceId); } } diff --git a/src/backend/catalog/objectaccess.c b/src/backend/catalog/objectaccess.c index bc565ebe497..f70797f2643 100644 --- a/src/backend/catalog/objectaccess.c +++ b/src/backend/catalog/objectaccess.c @@ -11,6 +11,7 @@ #include "postgres.h" #include "catalog/objectaccess.h" +#include "catalog/pg_namespace.h" /* * Hook on object accesses. This is intended as infrastructure for security @@ -84,3 +85,27 @@ RunObjectPostAlterHook(Oid classId, Oid objectId, int subId, classId, objectId, subId, (void *) &pa_arg); } + +/* + * RunNamespaceSearchHook + * + * It is entrypoint of OAT_NAMESPACE_SEARCH event + */ +bool +RunNamespaceSearchHook(Oid objectId, bool ereport_on_violation) +{ + ObjectAccessNamespaceSearch ns_arg; + + /* XXX - should be checked at caller side */ + Assert(object_access_hook != NULL); + + memset(&ns_arg, 0, sizeof(ObjectAccessNamespaceSearch)); + ns_arg.ereport_on_violation = ereport_on_violation; + ns_arg.result = true; + + (*object_access_hook)(OAT_NAMESPACE_SEARCH, + NamespaceRelationId, objectId, 0, + (void *) &ns_arg); + + return ns_arg.result; +} diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c index 21c979753e0..016e7d9ec66 100644 --- a/src/backend/tcop/fastpath.c +++ b/src/backend/tcop/fastpath.c @@ -22,6 +22,7 @@ #include "access/htup_details.h" #include "access/xact.h" +#include "catalog/objectaccess.h" #include "catalog/pg_proc.h" #include "libpq/libpq.h" #include "libpq/pqformat.h" @@ -355,6 +356,7 @@ HandleFunctionRequest(StringInfo msgBuf) if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, ACL_KIND_NAMESPACE, get_namespace_name(fip->namespace)); + InvokeNamespaceSearchHook(fip->namespace, true); aclresult = pg_proc_aclcheck(fid, GetUserId(), ACL_EXECUTE); if (aclresult != ACLCHECK_OK) diff --git a/src/include/catalog/objectaccess.h b/src/include/catalog/objectaccess.h index 25f963b0748..12ae55f498c 100644 --- a/src/include/catalog/objectaccess.h +++ b/src/include/catalog/objectaccess.h @@ -27,6 +27,10 @@ * hook can use SnapshotNow and SnapshotSelf to get the old and new * versions of the tuple. * + * OAT_NAMESPACE_SEARCH should be invoked prior to object name lookup under + * a particular namespace. This event is equivalent to usage permission + * permission on a schema under the default access control mechanism. + * * Other types may be added in the future. */ typedef enum ObjectAccessType @@ -34,6 +38,7 @@ typedef enum ObjectAccessType OAT_POST_CREATE, OAT_DROP, OAT_POST_ALTER, + OAT_NAMESPACE_SEARCH, } ObjectAccessType; /* @@ -84,6 +89,28 @@ typedef struct bool is_internal; } ObjectAccessPostAlter; +/* + * Arguments of OAT_NAMESPACE_SEARCH + */ +typedef struct +{ + /* + * If true, hook should report an error when permission to search this + * schema is denied. + */ + bool ereport_on_violation; + + /* + * This is, in essence, an out parameter. Core code should + * initialize this to true, and any extension that wants to deny + * access should reset it to false. But an extension should be + * careful never to store a true value here, so that in case there are + * multiple extensions access is only allowed if all extensions + * agree. + */ + bool result; +} ObjectAccessNamespaceSearch; + /* Plugin provides a hook function matching this signature. */ typedef void (*object_access_hook_type) (ObjectAccessType access, Oid classId, @@ -101,6 +128,7 @@ extern void RunObjectDropHook(Oid classId, Oid objectId, int subId, int dropflags); extern void RunObjectPostAlterHook(Oid classId, Oid objectId, int subId, Oid auxiliaryId, bool is_internal); +extern bool RunNamespaceSearchHook(Oid objectId, bool ereport_on_volation); /* * The following macros are wrappers around the functions above; these should @@ -137,4 +165,9 @@ extern void RunObjectPostAlterHook(Oid classId, Oid objectId, int subId, (auxiliaryId),(is_internal)); \ } while(0) +#define InvokeNamespaceSearchHook(objectId, ereport_on_violation) \ + (!object_access_hook \ + ? true \ + : RunNamespaceSearchHook((objectId), (ereport_on_violation))) + #endif /* OBJECTACCESS_H */ |