objectaccess.h 9.0 KB

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