1/*
2 * objectaccess.h
3 *
4 * Object access hooks.
5 *
6 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 */
9
10#ifndef OBJECTACCESS_H
11#define OBJECTACCESS_H
12
13/*
14 * Object access hooks are intended to be called just before or just after
15 * performing certain actions on a SQL object. This is intended as
16 * infrastructure for security or logging plugins.
17 *
18 * OAT_POST_CREATE should be invoked just after the object is created.
19 * Typically, this is done after inserting the primary catalog records and
20 * associated dependencies.
21 *
22 * OAT_DROP should be invoked just before deletion of objects; typically
23 * deleteOneObject(). Its arguments are packed within ObjectAccessDrop.
24 *
25 * OAT_POST_ALTER should be invoked just after the object is altered,
26 * but before the command counter is incremented. An extension using the
27 * hook can use a current MVCC snapshot to get the old version of the tuple,
28 * and can use SnapshotSelf to get the new version of the tuple.
29 *
30 * OAT_NAMESPACE_SEARCH should be invoked prior to object name lookup under
31 * a particular namespace. This event is equivalent to usage permission
32 * on a schema under the default access control mechanism.
33 *
34 * OAT_FUNCTION_EXECUTE should be invoked prior to function execution.
35 * This event is almost equivalent to execute permission on functions,
36 * except for the case when execute permission is checked during object
37 * creation or altering, because OAT_POST_CREATE or OAT_POST_ALTER are
38 * sufficient for extensions to track these kind of checks.
39 *
40 * Other types may be added in the future.
41 */
42typedef enum ObjectAccessType
43{
44 OAT_POST_CREATE,
45 OAT_DROP,
46 OAT_POST_ALTER,
47 OAT_NAMESPACE_SEARCH,
48 OAT_FUNCTION_EXECUTE
49} ObjectAccessType;
50
51/*
52 * Arguments of OAT_POST_CREATE event
53 */
54typedef struct
55{
56 /*
57 * This flag informs extensions whether the context of this creation is
58 * invoked by user's operations, or not. E.g, it shall be dealt as
59 * internal stuff on toast tables or indexes due to type changes.
60 */
61 bool is_internal;
62} ObjectAccessPostCreate;
63
64/*
65 * Arguments of OAT_DROP event
66 */
67typedef struct
68{
69 /*
70 * Flags to inform extensions the context of this deletion. Also see
71 * PERFORM_DELETION_* in dependency.h
72 */
73 int dropflags;
74} ObjectAccessDrop;
75
76/*
77 * Arguments of OAT_POST_ALTER event
78 */
79typedef struct
80{
81 /*
82 * This identifier is used when system catalog takes two IDs to identify a
83 * particular tuple of the catalog. It is only used when the caller want
84 * to identify an entry of pg_inherits, pg_db_role_setting or
85 * pg_user_mapping. Elsewhere, InvalidOid should be set.
86 */
87 Oid auxiliary_id;
88
89 /*
90 * If this flag is set, the user hasn't requested that the object be
91 * altered, but we're doing it anyway for some internal reason.
92 * Permissions-checking hooks may want to skip checks if, say, we're alter
93 * the constraints of a temporary heap during CLUSTER.
94 */
95 bool is_internal;
96} ObjectAccessPostAlter;
97
98/*
99 * Arguments of OAT_NAMESPACE_SEARCH
100 */
101typedef struct
102{
103 /*
104 * If true, hook should report an error when permission to search this
105 * schema is denied.
106 */
107 bool ereport_on_violation;
108
109 /*
110 * This is, in essence, an out parameter. Core code should initialize
111 * this to true, and any extension that wants to deny access should reset
112 * it to false. But an extension should be careful never to store a true
113 * value here, so that in case there are multiple extensions access is
114 * only allowed if all extensions agree.
115 */
116 bool result;
117} ObjectAccessNamespaceSearch;
118
119/* Plugin provides a hook function matching this signature. */
120typedef void (*object_access_hook_type) (ObjectAccessType access,
121 Oid classId,
122 Oid objectId,
123 int subId,
124 void *arg);
125
126/* Plugin sets this variable to a suitable hook function. */
127extern PGDLLIMPORT object_access_hook_type object_access_hook;
128
129/* Core code uses these functions to call the hook (see macros below). */
130extern void RunObjectPostCreateHook(Oid classId, Oid objectId, int subId,
131 bool is_internal);
132extern void RunObjectDropHook(Oid classId, Oid objectId, int subId,
133 int dropflags);
134extern void RunObjectPostAlterHook(Oid classId, Oid objectId, int subId,
135 Oid auxiliaryId, bool is_internal);
136extern bool RunNamespaceSearchHook(Oid objectId, bool ereport_on_violation);
137extern void RunFunctionExecuteHook(Oid objectId);
138
139/*
140 * The following macros are wrappers around the functions above; these should
141 * normally be used to invoke the hook in lieu of calling the above functions
142 * directly.
143 */
144
145#define InvokeObjectPostCreateHook(classId,objectId,subId) \
146 InvokeObjectPostCreateHookArg((classId),(objectId),(subId),false)
147#define InvokeObjectPostCreateHookArg(classId,objectId,subId,is_internal) \
148 do { \
149 if (object_access_hook) \
150 RunObjectPostCreateHook((classId),(objectId),(subId), \
151 (is_internal)); \
152 } while(0)
153
154#define InvokeObjectDropHook(classId,objectId,subId) \
155 InvokeObjectDropHookArg((classId),(objectId),(subId),0)
156#define InvokeObjectDropHookArg(classId,objectId,subId,dropflags) \
157 do { \
158 if (object_access_hook) \
159 RunObjectDropHook((classId),(objectId),(subId), \
160 (dropflags)); \
161 } while(0)
162
163#define InvokeObjectPostAlterHook(classId,objectId,subId) \
164 InvokeObjectPostAlterHookArg((classId),(objectId),(subId), \
165 InvalidOid,false)
166#define InvokeObjectPostAlterHookArg(classId,objectId,subId, \
167 auxiliaryId,is_internal) \
168 do { \
169 if (object_access_hook) \
170 RunObjectPostAlterHook((classId),(objectId),(subId), \
171 (auxiliaryId),(is_internal)); \
172 } while(0)
173
174#define InvokeNamespaceSearchHook(objectId, ereport_on_violation) \
175 (!object_access_hook \
176 ? true \
177 : RunNamespaceSearchHook((objectId), (ereport_on_violation)))
178
179#define InvokeFunctionExecuteHook(objectId) \
180 do { \
181 if (object_access_hook) \
182 RunFunctionExecuteHook(objectId); \
183 } while(0)
184
185#endif /* OBJECTACCESS_H */
186