PostgreSQL Source Code  git master
test_rls_hooks.c
Go to the documentation of this file.
1 /*--------------------------------------------------------------------------
2  *
3  * test_rls_hooks.c
4  * Code for testing RLS hooks.
5  *
6  * Copyright (c) 2015-2021, PostgreSQL Global Development Group
7  *
8  * IDENTIFICATION
9  * src/test/modules/test_rls_hooks/test_rls_hooks.c
10  *
11  * -------------------------------------------------------------------------
12  */
13 
14 #include "postgres.h"
15 
16 #include "catalog/pg_type.h"
17 #include "fmgr.h"
18 #include "miscadmin.h"
19 #include "nodes/makefuncs.h"
20 #include "parser/parse_clause.h"
21 #include "parser/parse_collate.h"
22 #include "parser/parse_node.h"
23 #include "parser/parse_relation.h"
24 #include "rewrite/rowsecurity.h"
25 #include "test_rls_hooks.h"
26 #include "utils/acl.h"
27 #include "utils/rel.h"
28 #include "utils/relcache.h"
29 
31 
32 /* Saved hook values in case of unload */
35 
36 void _PG_init(void);
37 void _PG_fini(void);
38 
39 /* Install hooks */
40 void
41 _PG_init(void)
42 {
43  /* Save values for unload */
46 
47  /* Set our hooks */
50 }
51 
52 /* Uninstall hooks */
53 void
54 _PG_fini(void)
55 {
58 }
59 
60 /*
61  * Return permissive policies to be added
62  */
63 List *
65 {
66  List *policies = NIL;
67  RowSecurityPolicy *policy = palloc0(sizeof(RowSecurityPolicy));
68  Datum role;
69  FuncCall *n;
70  Node *e;
71  ColumnRef *c;
72  ParseState *qual_pstate;
73  ParseNamespaceItem *nsitem;
74 
75  if (strcmp(RelationGetRelationName(relation), "rls_test_permissive") != 0 &&
76  strcmp(RelationGetRelationName(relation), "rls_test_both") != 0)
77  return NIL;
78 
79  qual_pstate = make_parsestate(NULL);
80 
81  nsitem = addRangeTableEntryForRelation(qual_pstate,
82  relation, AccessShareLock,
83  NULL, false, false);
84  addNSItemToQuery(qual_pstate, nsitem, false, true, true);
85 
87 
88  policy->policy_name = pstrdup("extension policy");
89  policy->polcmd = '*';
90  policy->roles = construct_array(&role, 1, OIDOID, sizeof(Oid), true, TYPALIGN_INT);
91 
92  /*
93  * policy->qual = (Expr *) makeConst(BOOLOID, -1, InvalidOid,
94  * sizeof(bool), BoolGetDatum(true), false, true);
95  */
96 
97  n = makeFuncCall(list_make2(makeString("pg_catalog"),
98  makeString("current_user")),
99  NIL,
101  -1);
102 
103  c = makeNode(ColumnRef);
104  c->fields = list_make1(makeString("username"));
105  c->location = 0;
106 
107  e = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", (Node *) n, (Node *) c, 0);
108 
109  policy->qual = (Expr *) transformWhereClause(qual_pstate, copyObject(e),
111  "POLICY");
112  /* Fix up collation information */
113  assign_expr_collations(qual_pstate, (Node *) policy->qual);
114 
115  policy->with_check_qual = copyObject(policy->qual);
116  policy->hassublinks = false;
117 
118  policies = list_make1(policy);
119 
120  return policies;
121 }
122 
123 /*
124  * Return restrictive policies to be added
125  *
126  * Note that a permissive policy must exist or the default-deny policy
127  * will be included and nothing will be visible. If no filtering should
128  * be done except for the restrictive policy, then a single "USING (true)"
129  * permissive policy can be used; see the regression tests.
130  */
131 List *
133 {
134  List *policies = NIL;
135  RowSecurityPolicy *policy = palloc0(sizeof(RowSecurityPolicy));
136  Datum role;
137  FuncCall *n;
138  Node *e;
139  ColumnRef *c;
140  ParseState *qual_pstate;
141  ParseNamespaceItem *nsitem;
142 
143  if (strcmp(RelationGetRelationName(relation), "rls_test_restrictive") != 0 &&
144  strcmp(RelationGetRelationName(relation), "rls_test_both") != 0)
145  return NIL;
146 
147  qual_pstate = make_parsestate(NULL);
148 
149  nsitem = addRangeTableEntryForRelation(qual_pstate,
150  relation, AccessShareLock,
151  NULL, false, false);
152  addNSItemToQuery(qual_pstate, nsitem, false, true, true);
153 
155 
156  policy->policy_name = pstrdup("extension policy");
157  policy->polcmd = '*';
158  policy->roles = construct_array(&role, 1, OIDOID, sizeof(Oid), true, TYPALIGN_INT);
159 
160  n = makeFuncCall(list_make2(makeString("pg_catalog"),
161  makeString("current_user")),
162  NIL,
164  -1);
165 
166  c = makeNode(ColumnRef);
167  c->fields = list_make1(makeString("supervisor"));
168  c->location = 0;
169 
170  e = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", (Node *) n, (Node *) c, 0);
171 
172  policy->qual = (Expr *) transformWhereClause(qual_pstate, copyObject(e),
174  "POLICY");
175  /* Fix up collation information */
176  assign_expr_collations(qual_pstate, (Node *) policy->qual);
177 
178  policy->with_check_qual = copyObject(policy->qual);
179  policy->hassublinks = false;
180 
181  policies = list_make1(policy);
182 
183  return policies;
184 }
#define list_make2(x1, x2)
Definition: pg_list.h:208
void _PG_fini(void)
static row_security_policy_hook_type prev_row_security_policy_hook_permissive
#define NIL
Definition: pg_list.h:65
void _PG_init(void)
PG_MODULE_MAGIC
char * pstrdup(const char *in)
Definition: mcxt.c:1299
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3319
#define AccessShareLock
Definition: lockdefs.h:36
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
Definition: nodes.h:536
String * makeString(char *str)
Definition: value.c:51
row_security_policy_hook_type row_security_policy_hook_permissive
Definition: rowsecurity.c:96
List * test_rls_hooks_permissive(CmdType cmdtype, Relation relation)
unsigned int Oid
Definition: postgres_ext.h:31
A_Expr * makeSimpleA_Expr(A_Expr_Kind kind, char *name, Node *lexpr, Node *rexpr, int location)
Definition: makefuncs.c:48
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
int location
Definition: parsenodes.h:248
static row_security_policy_hook_type prev_row_security_policy_hook_restrictive
#define list_make1(x1)
Definition: pg_list.h:206
void assign_expr_collations(ParseState *pstate, Node *expr)
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
List *(* row_security_policy_hook_type)(CmdType cmdtype, Relation relation)
Definition: rowsecurity.h:37
char * c
Expr * with_check_qual
Definition: rowsecurity.h:27
row_security_policy_hook_type row_security_policy_hook_restrictive
Definition: rowsecurity.c:97
#define RelationGetRelationName(relation)
Definition: rel.h:511
ArrayType * roles
Definition: rowsecurity.h:24
FuncCall * makeFuncCall(List *name, List *args, CoercionForm funcformat, int location)
Definition: makefuncs.c:585
void * palloc0(Size size)
Definition: mcxt.c:1093
uintptr_t Datum
Definition: postgres.h:411
#define makeNode(_type_)
Definition: nodes.h:584
List * test_rls_hooks_restrictive(CmdType cmdtype, Relation relation)
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
e
Definition: preproc-init.c:82
#define ACL_ID_PUBLIC
Definition: acl.h:46
#define copyObject(obj)
Definition: nodes.h:652
Definition: pg_list.h:50
CmdType
Definition: nodes.h:680
List * fields
Definition: parsenodes.h:247