| /* |
| * objectaccess.h |
| * |
| * Object access hooks. |
| * |
| * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group |
| * Portions Copyright (c) 1994, Regents of the University of California |
| */ |
| |
| #ifndef OBJECTACCESS_H |
| #define OBJECTACCESS_H |
| |
| /* |
| * Object access hooks are intended to be called just before or just after |
| * performing certain actions on a SQL object. This is intended as |
| * infrastructure for security or logging plugins. |
| * |
| * OAT_POST_CREATE should be invoked just after the object is created. |
| * Typically, this is done after inserting the primary catalog records and |
| * associated dependencies. |
| * |
| * OAT_DROP should be invoked just before deletion of objects; typically |
| * deleteOneObject(). Its arguments are packed within ObjectAccessDrop. |
| * |
| * OAT_POST_ALTER should be invoked just after the object is altered, |
| * but before the command counter is incremented. An extension using the |
| * hook can use a current MVCC snapshot to get the old version of the tuple, |
| * and can use SnapshotSelf to get the new version 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 |
| * on a schema under the default access control mechanism. |
| * |
| * OAT_FUNCTION_EXECUTE should be invoked prior to function execution. |
| * This event is almost equivalent to execute permission on functions, |
| * except for the case when execute permission is checked during object |
| * creation or altering, because OAT_POST_CREATE or OAT_POST_ALTER are |
| * sufficient for extensions to track these kind of checks. |
| * |
| * OAT_TRUNCATE should be invoked just before truncation of objects. This |
| * event is equivalent to truncate permission on a relation under the |
| * default access control mechanism. |
| * |
| * Other types may be added in the future. |
| */ |
| typedef enum ObjectAccessType |
| { |
| OAT_POST_CREATE, |
| OAT_DROP, |
| OAT_POST_ALTER, |
| OAT_NAMESPACE_SEARCH, |
| OAT_FUNCTION_EXECUTE, |
| OAT_TRUNCATE |
| } ObjectAccessType; |
| |
| /* |
| * Arguments of OAT_POST_CREATE event |
| */ |
| typedef struct |
| { |
| /* |
| * This flag informs extensions whether the context of this creation is |
| * invoked by user's operations, or not. E.g, it shall be dealt as |
| * internal stuff on toast tables or indexes due to type changes. |
| */ |
| bool is_internal; |
| } ObjectAccessPostCreate; |
| |
| /* |
| * Arguments of OAT_DROP event |
| */ |
| typedef struct |
| { |
| /* |
| * Flags to inform extensions the context of this deletion. Also see |
| * PERFORM_DELETION_* in dependency.h |
| */ |
| int dropflags; |
| } ObjectAccessDrop; |
| |
| /* |
| * Arguments of OAT_POST_ALTER event |
| */ |
| typedef struct |
| { |
| /* |
| * This identifier is used when system catalog takes two IDs to identify a |
| * particular tuple of the catalog. It is only used when the caller want |
| * to identify an entry of pg_inherits, pg_db_role_setting or |
| * pg_user_mapping. Elsewhere, InvalidOid should be set. |
| */ |
| Oid auxiliary_id; |
| |
| /* |
| * If this flag is set, the user hasn't requested that the object be |
| * altered, but we're doing it anyway for some internal reason. |
| * Permissions-checking hooks may want to skip checks if, say, we're alter |
| * the constraints of a temporary heap during CLUSTER. |
| */ |
| 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, |
| Oid objectId, |
| int subId, |
| void *arg); |
| |
| /* Plugin sets this variable to a suitable hook function. */ |
| extern PGDLLIMPORT object_access_hook_type object_access_hook; |
| |
| /* Core code uses these functions to call the hook (see macros below). */ |
| extern void RunObjectPostCreateHook(Oid classId, Oid objectId, int subId, |
| bool is_internal); |
| extern void RunObjectDropHook(Oid classId, Oid objectId, int subId, |
| int dropflags); |
| extern void RunObjectTruncateHook(Oid objectId); |
| extern void RunObjectPostAlterHook(Oid classId, Oid objectId, int subId, |
| Oid auxiliaryId, bool is_internal); |
| extern bool RunNamespaceSearchHook(Oid objectId, bool ereport_on_violation); |
| extern void RunFunctionExecuteHook(Oid objectId); |
| |
| /* |
| * The following macros are wrappers around the functions above; these should |
| * normally be used to invoke the hook in lieu of calling the above functions |
| * directly. |
| */ |
| |
| #define InvokeObjectPostCreateHook(classId,objectId,subId) \ |
| InvokeObjectPostCreateHookArg((classId),(objectId),(subId),false) |
| #define InvokeObjectPostCreateHookArg(classId,objectId,subId,is_internal) \ |
| do { \ |
| if (object_access_hook) \ |
| RunObjectPostCreateHook((classId),(objectId),(subId), \ |
| (is_internal)); \ |
| } while(0) |
| |
| #define InvokeObjectDropHook(classId,objectId,subId) \ |
| InvokeObjectDropHookArg((classId),(objectId),(subId),0) |
| #define InvokeObjectDropHookArg(classId,objectId,subId,dropflags) \ |
| do { \ |
| if (object_access_hook) \ |
| RunObjectDropHook((classId),(objectId),(subId), \ |
| (dropflags)); \ |
| } while(0) |
| |
| #define InvokeObjectTruncateHook(objectId) \ |
| do { \ |
| if (object_access_hook) \ |
| RunObjectTruncateHook(objectId); \ |
| } while(0) |
| |
| #define InvokeObjectPostAlterHook(classId,objectId,subId) \ |
| InvokeObjectPostAlterHookArg((classId),(objectId),(subId), \ |
| InvalidOid,false) |
| #define InvokeObjectPostAlterHookArg(classId,objectId,subId, \ |
| auxiliaryId,is_internal) \ |
| do { \ |
| if (object_access_hook) \ |
| RunObjectPostAlterHook((classId),(objectId),(subId), \ |
| (auxiliaryId),(is_internal)); \ |
| } while(0) |
| |
| #define InvokeNamespaceSearchHook(objectId, ereport_on_violation) \ |
| (!object_access_hook \ |
| ? true \ |
| : RunNamespaceSearchHook((objectId), (ereport_on_violation))) |
| |
| #define InvokeFunctionExecuteHook(objectId) \ |
| do { \ |
| if (object_access_hook) \ |
| RunFunctionExecuteHook(objectId); \ |
| } while(0) |
| |
| #endif /* OBJECTACCESS_H */ |