mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
sepgsql: Enforce db_schema:search permission.
KaiGai Kohei, with comment and doc wordsmithing by me
This commit is contained in:
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
Reference in New Issue
Block a user