1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
/*
* objectaccess.h
*
* Object access hooks.
*
* Portions Copyright (c) 1996-2020, 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 */
|