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