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 "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 2 : PG_MODULE_MAGIC;
31 :
32 : /* Install hooks */
33 : void
34 2 : _PG_init(void)
35 : {
36 : /* Set our hooks */
37 2 : row_security_policy_hook_permissive = test_rls_hooks_permissive;
38 2 : row_security_policy_hook_restrictive = test_rls_hooks_restrictive;
39 2 : }
40 :
41 : /*
42 : * Return permissive policies to be added
43 : */
44 : List *
45 60 : test_rls_hooks_permissive(CmdType cmdtype, Relation relation)
46 : {
47 60 : List *policies = NIL;
48 60 : RowSecurityPolicy *policy = palloc0(sizeof(RowSecurityPolicy));
49 : Datum role;
50 : FuncCall *n;
51 : Node *e;
52 : ColumnRef *c;
53 : ParseState *qual_pstate;
54 : ParseNamespaceItem *nsitem;
55 :
56 60 : if (strcmp(RelationGetRelationName(relation), "rls_test_permissive") != 0 &&
57 42 : strcmp(RelationGetRelationName(relation), "rls_test_both") != 0)
58 20 : return NIL;
59 :
60 40 : qual_pstate = make_parsestate(NULL);
61 :
62 40 : nsitem = addRangeTableEntryForRelation(qual_pstate,
63 : relation, AccessShareLock,
64 : NULL, false, false);
65 40 : addNSItemToQuery(qual_pstate, nsitem, false, true, true);
66 :
67 40 : role = ObjectIdGetDatum(ACL_ID_PUBLIC);
68 :
69 40 : policy->policy_name = pstrdup("extension policy");
70 40 : policy->polcmd = '*';
71 40 : 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 : */
77 :
78 40 : n = makeFuncCall(list_make2(makeString("pg_catalog"),
79 : makeString("current_user")),
80 : NIL,
81 : COERCE_EXPLICIT_CALL,
82 : -1);
83 :
84 40 : c = makeNode(ColumnRef);
85 40 : c->fields = list_make1(makeString("username"));
86 40 : c->location = 0;
87 :
88 40 : e = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", (Node *) n, (Node *) c, 0);
89 :
90 40 : policy->qual = (Expr *) transformWhereClause(qual_pstate, copyObject(e),
91 : EXPR_KIND_POLICY,
92 : "POLICY");
93 : /* Fix up collation information */
94 40 : assign_expr_collations(qual_pstate, (Node *) policy->qual);
95 :
96 40 : policy->with_check_qual = copyObject(policy->qual);
97 40 : policy->hassublinks = false;
98 :
99 40 : policies = list_make1(policy);
100 :
101 40 : 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 : */
112 : List *
113 60 : test_rls_hooks_restrictive(CmdType cmdtype, Relation relation)
114 : {
115 60 : List *policies = NIL;
116 60 : RowSecurityPolicy *policy = palloc0(sizeof(RowSecurityPolicy));
117 : Datum role;
118 : FuncCall *n;
119 : Node *e;
120 : ColumnRef *c;
121 : ParseState *qual_pstate;
122 : ParseNamespaceItem *nsitem;
123 :
124 60 : if (strcmp(RelationGetRelationName(relation), "rls_test_restrictive") != 0 &&
125 40 : strcmp(RelationGetRelationName(relation), "rls_test_both") != 0)
126 18 : return NIL;
127 :
128 42 : qual_pstate = make_parsestate(NULL);
129 :
130 42 : nsitem = addRangeTableEntryForRelation(qual_pstate,
131 : relation, AccessShareLock,
132 : NULL, false, false);
133 42 : addNSItemToQuery(qual_pstate, nsitem, false, true, true);
134 :
135 42 : role = ObjectIdGetDatum(ACL_ID_PUBLIC);
136 :
137 42 : policy->policy_name = pstrdup("extension policy");
138 42 : policy->polcmd = '*';
139 42 : policy->roles = construct_array_builtin(&role, 1, OIDOID);
140 :
141 42 : n = makeFuncCall(list_make2(makeString("pg_catalog"),
142 : makeString("current_user")),
143 : NIL,
144 : COERCE_EXPLICIT_CALL,
145 : -1);
146 :
147 42 : c = makeNode(ColumnRef);
148 42 : c->fields = list_make1(makeString("supervisor"));
149 42 : c->location = 0;
150 :
151 42 : e = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", (Node *) n, (Node *) c, 0);
152 :
153 42 : policy->qual = (Expr *) transformWhereClause(qual_pstate, copyObject(e),
154 : EXPR_KIND_POLICY,
155 : "POLICY");
156 : /* Fix up collation information */
157 42 : assign_expr_collations(qual_pstate, (Node *) policy->qual);
158 :
159 42 : policy->with_check_qual = copyObject(policy->qual);
160 42 : policy->hassublinks = false;
161 :
162 42 : policies = list_make1(policy);
163 :
164 42 : return policies;
165 : }
|