Line data Source code
1 : /*--------------------------------------------------------------------------
2 : *
3 : * test_rls_hooks.c
4 : * Code for testing RLS hooks.
5 : *
6 : * Copyright (c) 2015-2024, 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 "nodes/makefuncs.h"
19 : #include "parser/parse_clause.h"
20 : #include "parser/parse_collate.h"
21 : #include "parser/parse_node.h"
22 : #include "parser/parse_relation.h"
23 : #include "rewrite/rowsecurity.h"
24 : #include "test_rls_hooks.h"
25 : #include "utils/acl.h"
26 : #include "utils/rel.h"
27 : #include "utils/relcache.h"
28 :
29 2 : PG_MODULE_MAGIC;
30 :
31 : /* Install hooks */
32 : void
33 2 : _PG_init(void)
34 : {
35 : /* Set our hooks */
36 2 : row_security_policy_hook_permissive = test_rls_hooks_permissive;
37 2 : row_security_policy_hook_restrictive = test_rls_hooks_restrictive;
38 2 : }
39 :
40 : /*
41 : * Return permissive policies to be added
42 : */
43 : List *
44 60 : test_rls_hooks_permissive(CmdType cmdtype, Relation relation)
45 : {
46 60 : List *policies = NIL;
47 60 : RowSecurityPolicy *policy = palloc0(sizeof(RowSecurityPolicy));
48 : Datum role;
49 : FuncCall *n;
50 : Node *e;
51 : ColumnRef *c;
52 : ParseState *qual_pstate;
53 : ParseNamespaceItem *nsitem;
54 :
55 60 : if (strcmp(RelationGetRelationName(relation), "rls_test_permissive") != 0 &&
56 42 : strcmp(RelationGetRelationName(relation), "rls_test_both") != 0)
57 20 : return NIL;
58 :
59 40 : qual_pstate = make_parsestate(NULL);
60 :
61 40 : nsitem = addRangeTableEntryForRelation(qual_pstate,
62 : relation, AccessShareLock,
63 : NULL, false, false);
64 40 : addNSItemToQuery(qual_pstate, nsitem, false, true, true);
65 :
66 40 : role = ObjectIdGetDatum(ACL_ID_PUBLIC);
67 :
68 40 : policy->policy_name = pstrdup("extension policy");
69 40 : policy->polcmd = '*';
70 40 : policy->roles = construct_array_builtin(&role, 1, OIDOID);
71 :
72 : /*
73 : * policy->qual = (Expr *) makeConst(BOOLOID, -1, InvalidOid,
74 : * sizeof(bool), BoolGetDatum(true), false, true);
75 : */
76 :
77 40 : n = makeFuncCall(list_make2(makeString("pg_catalog"),
78 : makeString("current_user")),
79 : NIL,
80 : COERCE_EXPLICIT_CALL,
81 : -1);
82 :
83 40 : c = makeNode(ColumnRef);
84 40 : c->fields = list_make1(makeString("username"));
85 40 : c->location = 0;
86 :
87 40 : e = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", (Node *) n, (Node *) c, 0);
88 :
89 40 : policy->qual = (Expr *) transformWhereClause(qual_pstate, copyObject(e),
90 : EXPR_KIND_POLICY,
91 : "POLICY");
92 : /* Fix up collation information */
93 40 : assign_expr_collations(qual_pstate, (Node *) policy->qual);
94 :
95 40 : policy->with_check_qual = copyObject(policy->qual);
96 40 : policy->hassublinks = false;
97 :
98 40 : policies = list_make1(policy);
99 :
100 40 : return policies;
101 : }
102 :
103 : /*
104 : * Return restrictive policies to be added
105 : *
106 : * Note that a permissive policy must exist or the default-deny policy
107 : * will be included and nothing will be visible. If no filtering should
108 : * be done except for the restrictive policy, then a single "USING (true)"
109 : * permissive policy can be used; see the regression tests.
110 : */
111 : List *
112 60 : test_rls_hooks_restrictive(CmdType cmdtype, Relation relation)
113 : {
114 60 : List *policies = NIL;
115 60 : RowSecurityPolicy *policy = palloc0(sizeof(RowSecurityPolicy));
116 : Datum role;
117 : FuncCall *n;
118 : Node *e;
119 : ColumnRef *c;
120 : ParseState *qual_pstate;
121 : ParseNamespaceItem *nsitem;
122 :
123 60 : if (strcmp(RelationGetRelationName(relation), "rls_test_restrictive") != 0 &&
124 40 : strcmp(RelationGetRelationName(relation), "rls_test_both") != 0)
125 18 : return NIL;
126 :
127 42 : qual_pstate = make_parsestate(NULL);
128 :
129 42 : nsitem = addRangeTableEntryForRelation(qual_pstate,
130 : relation, AccessShareLock,
131 : NULL, false, false);
132 42 : addNSItemToQuery(qual_pstate, nsitem, false, true, true);
133 :
134 42 : role = ObjectIdGetDatum(ACL_ID_PUBLIC);
135 :
136 42 : policy->policy_name = pstrdup("extension policy");
137 42 : policy->polcmd = '*';
138 42 : policy->roles = construct_array_builtin(&role, 1, OIDOID);
139 :
140 42 : n = makeFuncCall(list_make2(makeString("pg_catalog"),
141 : makeString("current_user")),
142 : NIL,
143 : COERCE_EXPLICIT_CALL,
144 : -1);
145 :
146 42 : c = makeNode(ColumnRef);
147 42 : c->fields = list_make1(makeString("supervisor"));
148 42 : c->location = 0;
149 :
150 42 : e = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", (Node *) n, (Node *) c, 0);
151 :
152 42 : policy->qual = (Expr *) transformWhereClause(qual_pstate, copyObject(e),
153 : EXPR_KIND_POLICY,
154 : "POLICY");
155 : /* Fix up collation information */
156 42 : assign_expr_collations(qual_pstate, (Node *) policy->qual);
157 :
158 42 : policy->with_check_qual = copyObject(policy->qual);
159 42 : policy->hassublinks = false;
160 :
161 42 : policies = list_make1(policy);
162 :
163 42 : return policies;
164 : }
|