1
0
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:
Robert Haas
2013-04-05 08:51:31 -04:00
parent 52f436b807
commit e965e6344c
13 changed files with 258 additions and 15 deletions

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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)

View File

@ -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 */