Age Owner TLA Line data Source code
1 : /*
2 : * rewrite/rowsecurity.c
3 : * Routines to support policies for row-level security (aka RLS).
4 : *
5 : * Policies in PostgreSQL provide a mechanism to limit what records are
6 : * returned to a user and what records a user is permitted to add to a table.
7 : *
8 : * Policies can be defined for specific roles, specific commands, or provided
9 : * by an extension. Row security can also be enabled for a table without any
10 : * policies being explicitly defined, in which case a default-deny policy is
11 : * applied.
12 : *
13 : * Any part of the system which is returning records back to the user, or
14 : * which is accepting records from the user to add to a table, needs to
15 : * consider the policies associated with the table (if any). For normal
16 : * queries, this is handled by calling get_row_security_policies() during
17 : * rewrite, for each RTE in the query. This returns the expressions defined
18 : * by the table's policies as a list that is prepended to the securityQuals
19 : * list for the RTE. For queries which modify the table, any WITH CHECK
20 : * clauses from the table's policies are also returned and prepended to the
21 : * list of WithCheckOptions for the Query to check each row that is being
22 : * added to the table. Other parts of the system (eg: COPY) simply construct
23 : * a normal query and use that, if RLS is to be applied.
24 : *
25 : * The check to see if RLS should be enabled is provided through
26 : * check_enable_rls(), which returns an enum (defined in rowsecurity.h) to
27 : * indicate if RLS should be enabled (RLS_ENABLED), or bypassed (RLS_NONE or
28 : * RLS_NONE_ENV). RLS_NONE_ENV indicates that RLS should be bypassed
29 : * in the current environment, but that may change if the row_security GUC or
30 : * the current role changes.
31 : *
32 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
33 : * Portions Copyright (c) 1994, Regents of the University of California
34 : */
35 : #include "postgres.h"
36 :
37 : #include "access/htup_details.h"
38 : #include "access/sysattr.h"
39 : #include "access/table.h"
40 : #include "catalog/pg_class.h"
41 : #include "catalog/pg_inherits.h"
42 : #include "catalog/pg_policy.h"
43 : #include "catalog/pg_type.h"
44 : #include "miscadmin.h"
45 : #include "nodes/makefuncs.h"
46 : #include "nodes/nodeFuncs.h"
47 : #include "nodes/pg_list.h"
48 : #include "nodes/plannodes.h"
49 : #include "parser/parsetree.h"
50 : #include "parser/parse_relation.h"
51 : #include "rewrite/rewriteDefine.h"
52 : #include "rewrite/rewriteHandler.h"
53 : #include "rewrite/rewriteManip.h"
54 : #include "rewrite/rowsecurity.h"
55 : #include "tcop/utility.h"
56 : #include "utils/acl.h"
57 : #include "utils/lsyscache.h"
58 : #include "utils/rel.h"
59 : #include "utils/rls.h"
60 : #include "utils/syscache.h"
61 :
62 : static void get_policies_for_relation(Relation relation,
63 : CmdType cmd, Oid user_id,
64 : List **permissive_policies,
65 : List **restrictive_policies);
66 :
67 : static void sort_policies_by_name(List *policies);
68 :
69 : static int row_security_policy_cmp(const ListCell *a, const ListCell *b);
70 :
71 : static void add_security_quals(int rt_index,
72 : List *permissive_policies,
73 : List *restrictive_policies,
74 : List **securityQuals,
75 : bool *hasSubLinks);
76 :
77 : static void add_with_check_options(Relation rel,
78 : int rt_index,
79 : WCOKind kind,
80 : List *permissive_policies,
81 : List *restrictive_policies,
82 : List **withCheckOptions,
83 : bool *hasSubLinks,
84 : bool force_using);
85 :
86 : static bool check_role_for_policy(ArrayType *policy_roles, Oid user_id);
87 :
88 : /*
89 : * hooks to allow extensions to add their own security policies
90 : *
91 : * row_security_policy_hook_permissive can be used to add policies which
92 : * are combined with the other permissive policies, using OR.
93 : *
94 : * row_security_policy_hook_restrictive can be used to add policies which
95 : * are enforced, regardless of other policies (they are combined using AND).
96 : */
97 : row_security_policy_hook_type row_security_policy_hook_permissive = NULL;
98 : row_security_policy_hook_type row_security_policy_hook_restrictive = NULL;
99 :
100 : /*
101 : * Get any row security quals and WithCheckOption checks that should be
102 : * applied to the specified RTE.
103 : *
104 : * In addition, hasRowSecurity is set to true if row-level security is enabled
105 : * (even if this RTE doesn't have any row security quals), and hasSubLinks is
106 : * set to true if any of the quals returned contain sublinks.
107 : */
108 : void
2763 sfrost 109 GIC 194254 : get_row_security_policies(Query *root, RangeTblEntry *rte, int rt_index,
2763 sfrost 110 ECB : List **securityQuals, List **withCheckOptions,
111 : bool *hasRowSecurity, bool *hasSubLinks)
112 : {
113 : Oid user_id;
114 : int rls_status;
115 : Relation rel;
116 : CmdType commandType;
117 : List *permissive_policies;
118 : List *restrictive_policies;
119 : RTEPermissionInfo *perminfo;
120 :
121 : /* Defaults for the return values */
2909 sfrost 122 GIC 194254 : *securityQuals = NIL;
123 194254 : *withCheckOptions = NIL;
2909 sfrost 124 CBC 194254 : *hasRowSecurity = false;
125 194254 : *hasSubLinks = false;
3124 sfrost 126 ECB :
124 alvherre 127 GNC 194254 : Assert(rte->rtekind == RTE_RELATION);
128 :
2812 mail 129 ECB : /* If this is not a normal relation, just return immediately */
2314 rhaas 130 GIC 194254 : if (rte->relkind != RELKIND_RELATION &&
2314 rhaas 131 CBC 7601 : rte->relkind != RELKIND_PARTITIONED_TABLE)
2812 mail 132 GIC 193045 : return;
133 :
124 alvherre 134 GNC 194254 : perminfo = getRTEPermissionInfo(root->rteperminfos, rte);
135 :
3124 sfrost 136 ECB : /* Switch to checkAsUser if it's set */
124 alvherre 137 GNC 388508 : user_id = OidIsValid(perminfo->checkAsUser) ?
138 194254 : perminfo->checkAsUser : GetUserId();
3124 sfrost 139 ECB :
140 : /* Determine the state of RLS for this, pass checkAsUser explicitly */
124 alvherre 141 GNC 194254 : rls_status = check_enable_rls(rte->relid, perminfo->checkAsUser, false);
142 :
143 : /* If there is no RLS on this table at all, nothing to do */
3124 sfrost 144 CBC 194230 : if (rls_status == RLS_NONE)
2909 145 192785 : return;
146 :
147 : /*
3124 sfrost 148 ECB : * RLS_NONE_ENV means we are not doing any RLS now, but that may change
149 : * with changes to the environment, so we mark it as hasRowSecurity to
150 : * force a re-plan when the environment changes.
151 : */
3124 sfrost 152 CBC 1445 : if (rls_status == RLS_NONE_ENV)
153 : {
154 : /*
155 : * Indicate that this query may involve RLS and must therefore be
156 : * replanned if the environment changes (GUCs, role), but we are not
157 : * adding anything here.
158 : */
2909 159 260 : *hasRowSecurity = true;
160 :
2909 sfrost 161 GIC 260 : return;
162 : }
163 :
164 : /*
165 : * RLS is enabled for this relation.
2810 mail 166 ECB : *
167 : * Get the security policies that should be applied, based on the command
168 : * type. Note that if this isn't the target relation, we actually want
169 : * the relation's SELECT policies, regardless of the query command type,
170 : * for example in UPDATE t1 ... FROM t2 we need to apply t1's UPDATE
171 : * policies and t2's SELECT policies.
172 : */
1539 andres 173 GIC 1185 : rel = table_open(rte->relid, NoLock);
174 :
2763 sfrost 175 2370 : commandType = rt_index == root->resultRelation ?
2495 rhaas 176 1185 : root->commandType : CMD_SELECT;
177 :
178 : /*
179 : * In some cases, we need to apply USING policies (which control the
2748 sfrost 180 ECB : * visibility of records) associated with multiple command types (see
181 : * specific cases below).
182 : *
2495 rhaas 183 : * When considering the order in which to apply these USING policies, we
184 : * prefer to apply higher privileged policies, those which allow the user
185 : * to lock records (UPDATE and DELETE), first, followed by policies which
186 : * don't (SELECT).
187 : *
188 : * Note that the optimizer is free to push down and reorder quals which
189 : * use leakproof functions.
190 : *
191 : * In all cases, if there are no policy clauses allowing access to rows in
192 : * the table for the specific type of operation, then a single
193 : * always-false clause (a default-deny policy) will be added (see
194 : * add_security_quals).
195 : */
196 :
197 : /*
198 : * For a SELECT, if UPDATE privileges are required (eg: the user has
199 : * specified FOR [KEY] UPDATE/SHARE), then add the UPDATE USING quals
200 : * first.
201 : *
202 : * This way, we filter out any records from the SELECT FOR SHARE/UPDATE
203 : * which the user does not have access to via the UPDATE USING policies,
204 : * similar to how we require normal UPDATE rights for these queries.
205 : */
124 alvherre 206 GNC 1185 : if (commandType == CMD_SELECT && perminfo->requiredPerms & ACL_UPDATE)
207 : {
208 : List *update_permissive_policies;
209 : List *update_restrictive_policies;
210 :
2748 sfrost 211 GIC 12 : get_policies_for_relation(rel, CMD_UPDATE, user_id,
212 : &update_permissive_policies,
2748 sfrost 213 ECB : &update_restrictive_policies);
214 :
2748 sfrost 215 GIC 12 : add_security_quals(rt_index,
216 : update_permissive_policies,
217 : update_restrictive_policies,
2748 sfrost 218 ECB : securityQuals,
219 : hasSubLinks);
220 : }
221 :
222 : /*
223 : * For SELECT, UPDATE and DELETE, add security quals to enforce the USING
224 : * policies. These security quals control access to existing table rows.
225 : * Restrictive policies are combined together using AND, and permissive
226 : * policies are combined together using OR.
227 : */
228 :
2748 sfrost 229 GIC 1185 : get_policies_for_relation(rel, commandType, user_id, &permissive_policies,
230 : &restrictive_policies);
231 :
2763 232 1185 : if (commandType == CMD_SELECT ||
233 222 : commandType == CMD_UPDATE ||
234 : commandType == CMD_DELETE)
235 1005 : add_security_quals(rt_index,
2763 sfrost 236 ECB : permissive_policies,
237 : restrictive_policies,
238 : securityQuals,
239 : hasSubLinks);
3124 240 :
241 : /*
377 alvherre 242 : * Similar to above, during an UPDATE, DELETE, or MERGE, if SELECT rights
243 : * are also required (eg: when a RETURNING clause exists, or the user has
244 : * provided a WHERE clause which involves columns from the relation), we
245 : * collect up CMD_SELECT policies and add them via add_security_quals
246 : * first.
247 : *
248 : * This way, we filter out any records which are not visible through an
249 : * ALL or SELECT USING policy.
250 : */
377 alvherre 251 GIC 1185 : if ((commandType == CMD_UPDATE || commandType == CMD_DELETE ||
252 201 : commandType == CMD_MERGE) &&
124 alvherre 253 GNC 201 : perminfo->requiredPerms & ACL_SELECT)
254 : {
255 : List *select_permissive_policies;
256 : List *select_restrictive_policies;
257 :
2763 sfrost 258 CBC 192 : get_policies_for_relation(rel, CMD_SELECT, user_id,
2748 sfrost 259 ECB : &select_permissive_policies,
260 : &select_restrictive_policies);
261 :
2763 sfrost 262 GIC 192 : add_security_quals(rt_index,
263 : select_permissive_policies,
264 : select_restrictive_policies,
2763 sfrost 265 ECB : securityQuals,
266 : hasSubLinks);
267 : }
268 :
3124 269 : /*
270 : * For INSERT and UPDATE, add withCheckOptions to verify that any new
271 : * records added are consistent with the security policies. This will use
272 : * each policy's WITH CHECK clause, or its USING clause if no explicit
273 : * WITH CHECK clause is defined.
274 : */
2893 andres 275 GIC 1185 : if (commandType == CMD_INSERT || commandType == CMD_UPDATE)
276 : {
277 : /* This should be the target relation */
2763 sfrost 278 261 : Assert(rt_index == root->resultRelation);
279 :
280 261 : add_with_check_options(rel, rt_index,
281 : commandType == CMD_INSERT ?
2763 sfrost 282 ECB : WCO_RLS_INSERT_CHECK : WCO_RLS_UPDATE_CHECK,
283 : permissive_policies,
284 : restrictive_policies,
285 : withCheckOptions,
286 : hasSubLinks,
2164 287 : false);
288 :
289 : /*
290 : * Get and add ALL/SELECT policies, if SELECT rights are required for
291 : * this relation (eg: when RETURNING is used). These are added as WCO
292 : * policies rather than security quals to ensure that an error is
293 : * raised if a policy is violated; otherwise, we might end up silently
294 : * dropping rows to be added.
295 : */
124 alvherre 296 GNC 261 : if (perminfo->requiredPerms & ACL_SELECT)
297 : {
2743 sfrost 298 GIC 174 : List *select_permissive_policies = NIL;
299 174 : List *select_restrictive_policies = NIL;
300 :
301 174 : get_policies_for_relation(rel, CMD_SELECT, user_id,
302 : &select_permissive_policies,
2743 sfrost 303 ECB : &select_restrictive_policies);
2743 sfrost 304 GIC 174 : add_with_check_options(rel, rt_index,
2743 sfrost 305 ECB : commandType == CMD_INSERT ?
2118 tgl 306 : WCO_RLS_INSERT_CHECK : WCO_RLS_UPDATE_CHECK,
307 : select_permissive_policies,
2743 sfrost 308 : select_restrictive_policies,
309 : withCheckOptions,
310 : hasSubLinks,
2164 311 : true);
312 : }
313 :
314 : /*
315 : * For INSERT ... ON CONFLICT DO UPDATE we need additional policy
316 : * checks for the UPDATE which may be applied to the same RTE.
317 : */
2763 sfrost 318 GIC 261 : if (commandType == CMD_INSERT &&
319 141 : root->onConflict && root->onConflict->action == ONCONFLICT_UPDATE)
320 : {
321 : List *conflict_permissive_policies;
322 : List *conflict_restrictive_policies;
1980 dean.a.rasheed 323 48 : List *conflict_select_permissive_policies = NIL;
324 48 : List *conflict_select_restrictive_policies = NIL;
2763 sfrost 325 ECB :
326 : /* Get the policies that apply to the auxiliary UPDATE */
2763 sfrost 327 GIC 48 : get_policies_for_relation(rel, CMD_UPDATE, user_id,
328 : &conflict_permissive_policies,
329 : &conflict_restrictive_policies);
3124 sfrost 330 ECB :
2763 331 : /*
332 : * Enforce the USING clauses of the UPDATE policies using WCOs
333 : * rather than security quals. This ensures that an error is
334 : * raised if the conflicting row cannot be updated due to RLS,
335 : * rather than the change being silently dropped.
336 : */
2763 sfrost 337 GIC 48 : add_with_check_options(rel, rt_index,
338 : WCO_RLS_CONFLICT_CHECK,
339 : conflict_permissive_policies,
340 : conflict_restrictive_policies,
341 : withCheckOptions,
342 : hasSubLinks,
343 : true);
2763 sfrost 344 ECB :
345 : /*
346 : * Get and add ALL/SELECT policies, as WCO_RLS_CONFLICT_CHECK WCOs
347 : * to ensure they are considered when taking the UPDATE path of an
348 : * INSERT .. ON CONFLICT DO UPDATE, if SELECT rights are required
349 : * for this relation, also as WCO policies, again, to avoid
350 : * silently dropping data. See above.
351 : */
124 alvherre 352 GNC 48 : if (perminfo->requiredPerms & ACL_SELECT)
353 : {
2763 sfrost 354 GIC 48 : get_policies_for_relation(rel, CMD_SELECT, user_id,
355 : &conflict_select_permissive_policies,
356 : &conflict_select_restrictive_policies);
357 48 : add_with_check_options(rel, rt_index,
358 : WCO_RLS_CONFLICT_CHECK,
2748 sfrost 359 ECB : conflict_select_permissive_policies,
360 : conflict_select_restrictive_policies,
2763 361 : withCheckOptions,
362 : hasSubLinks,
363 : true);
364 : }
365 :
366 : /* Enforce the WITH CHECK clauses of the UPDATE policies */
2763 sfrost 367 GIC 48 : add_with_check_options(rel, rt_index,
368 : WCO_RLS_UPDATE_CHECK,
369 : conflict_permissive_policies,
370 : conflict_restrictive_policies,
371 : withCheckOptions,
372 : hasSubLinks,
373 : false);
1980 dean.a.rasheed 374 ECB :
375 : /*
376 : * Add ALL/SELECT policies as WCO_RLS_UPDATE_CHECK WCOs, to ensure
377 : * that the final updated row is visible when taking the UPDATE
378 : * path of an INSERT .. ON CONFLICT DO UPDATE, if SELECT rights
379 : * are required for this relation.
380 : */
124 alvherre 381 GNC 48 : if (perminfo->requiredPerms & ACL_SELECT)
1980 dean.a.rasheed 382 GIC 48 : add_with_check_options(rel, rt_index,
383 : WCO_RLS_UPDATE_CHECK,
384 : conflict_select_permissive_policies,
385 : conflict_select_restrictive_policies,
386 : withCheckOptions,
387 : hasSubLinks,
1980 dean.a.rasheed 388 ECB : true);
3124 sfrost 389 : }
390 : }
391 :
392 : /*
393 : * FOR MERGE, we fetch policies for UPDATE, DELETE and INSERT (and ALL)
394 : * and set them up so that we can enforce the appropriate policy depending
395 : * on the final action we take.
396 : *
397 : * We already fetched the SELECT policies above.
398 : *
399 : * We don't push the UPDATE/DELETE USING quals to the RTE because we don't
400 : * really want to apply them while scanning the relation since we don't
401 : * know whether we will be doing an UPDATE or a DELETE at the end. We
402 : * apply the respective policy once we decide the final action on the
403 : * target tuple.
404 : *
405 : * XXX We are setting up USING quals as WITH CHECK. If RLS prohibits
406 : * UPDATE/DELETE on the target row, we shall throw an error instead of
407 : * silently ignoring the row. This is different than how normal
408 : * UPDATE/DELETE works and more in line with INSERT ON CONFLICT DO UPDATE
409 : * handling.
410 : */
377 alvherre 411 GIC 1185 : if (commandType == CMD_MERGE)
412 : {
413 : List *merge_permissive_policies;
414 : List *merge_restrictive_policies;
415 :
416 : /*
417 : * Fetch the UPDATE policies and set them up to execute on the
377 alvherre 418 ECB : * existing target row before doing UPDATE.
419 : */
377 alvherre 420 GIC 39 : get_policies_for_relation(rel, CMD_UPDATE, user_id,
421 : &merge_permissive_policies,
422 : &merge_restrictive_policies);
423 :
424 : /*
425 : * WCO_RLS_MERGE_UPDATE_CHECK is used to check UPDATE USING quals on
426 : * the existing target row.
377 alvherre 427 ECB : */
377 alvherre 428 GIC 39 : add_with_check_options(rel, rt_index,
429 : WCO_RLS_MERGE_UPDATE_CHECK,
430 : merge_permissive_policies,
431 : merge_restrictive_policies,
432 : withCheckOptions,
433 : hasSubLinks,
434 : true);
377 alvherre 435 ECB :
436 : /*
437 : * Same with DELETE policies.
438 : */
377 alvherre 439 GIC 39 : get_policies_for_relation(rel, CMD_DELETE, user_id,
440 : &merge_permissive_policies,
441 : &merge_restrictive_policies);
442 :
443 39 : add_with_check_options(rel, rt_index,
444 : WCO_RLS_MERGE_DELETE_CHECK,
445 : merge_permissive_policies,
377 alvherre 446 ECB : merge_restrictive_policies,
447 : withCheckOptions,
448 : hasSubLinks,
449 : true);
450 :
451 : /*
452 : * No special handling is required for INSERT policies. They will be
453 : * checked and enforced during ExecInsert(). But we must add them to
454 : * withCheckOptions.
455 : */
377 alvherre 456 GIC 39 : get_policies_for_relation(rel, CMD_INSERT, user_id,
457 : &merge_permissive_policies,
458 : &merge_restrictive_policies);
459 :
460 39 : add_with_check_options(rel, rt_index,
461 : WCO_RLS_INSERT_CHECK,
462 : merge_permissive_policies,
377 alvherre 463 ECB : merge_restrictive_policies,
464 : withCheckOptions,
465 : hasSubLinks,
466 : false);
467 :
468 : /* Enforce the WITH CHECK clauses of the UPDATE policies */
377 alvherre 469 GIC 39 : add_with_check_options(rel, rt_index,
470 : WCO_RLS_UPDATE_CHECK,
471 : merge_permissive_policies,
472 : merge_restrictive_policies,
473 : withCheckOptions,
474 : hasSubLinks,
475 : false);
377 alvherre 476 ECB : }
477 :
1539 andres 478 GIC 1185 : table_close(rel, NoLock);
479 :
480 : /*
481 : * Copy checkAsUser to the row security quals and WithCheckOption checks,
482 : * in case they contain any subqueries referring to other relations.
483 : */
124 alvherre 484 GNC 1185 : setRuleCheckAsUser((Node *) *securityQuals, perminfo->checkAsUser);
485 1185 : setRuleCheckAsUser((Node *) *withCheckOptions, perminfo->checkAsUser);
486 :
487 : /*
488 : * Mark this query as having row security, so plancache can invalidate it
489 : * when necessary (eg: role changes)
490 : */
2763 sfrost 491 CBC 1185 : *hasRowSecurity = true;
2763 sfrost 492 ECB : }
493 :
494 : /*
495 : * get_policies_for_relation
496 : *
497 : * Returns lists of permissive and restrictive policies to be applied to the
498 : * specified relation, based on the command type and role.
499 : *
500 : * This includes any policies added by extensions.
501 : */
502 : static void
2763 sfrost 503 GIC 1776 : get_policies_for_relation(Relation relation, CmdType cmd, Oid user_id,
504 : List **permissive_policies,
505 : List **restrictive_policies)
506 : {
507 : ListCell *item;
508 :
509 1776 : *permissive_policies = NIL;
2763 sfrost 510 CBC 1776 : *restrictive_policies = NIL;
511 :
512 : /* First find all internal policies for the relation. */
2763 sfrost 513 GIC 5700 : foreach(item, relation->rd_rsdesc->policies)
514 : {
2495 rhaas 515 3924 : bool cmd_matches = false;
2495 rhaas 516 CBC 3924 : RowSecurityPolicy *policy = (RowSecurityPolicy *) lfirst(item);
2909 sfrost 517 ECB :
518 : /* Always add ALL policies, if they exist. */
2763 sfrost 519 GIC 3924 : if (policy->polcmd == '*')
2763 sfrost 520 CBC 2046 : cmd_matches = true;
521 : else
2763 sfrost 522 ECB : {
523 : /* Check whether the policy applies to the specified command type */
2763 sfrost 524 GIC 1878 : switch (cmd)
525 : {
2763 sfrost 526 CBC 864 : case CMD_SELECT:
527 864 : if (policy->polcmd == ACL_SELECT_CHR)
2763 sfrost 528 GIC 273 : cmd_matches = true;
529 864 : break;
530 285 : case CMD_INSERT:
2763 sfrost 531 CBC 285 : if (policy->polcmd == ACL_INSERT_CHR)
2763 sfrost 532 GIC 84 : cmd_matches = true;
2763 sfrost 533 CBC 285 : break;
534 399 : case CMD_UPDATE:
535 399 : if (policy->polcmd == ACL_UPDATE_CHR)
536 141 : cmd_matches = true;
537 399 : break;
538 186 : case CMD_DELETE:
539 186 : if (policy->polcmd == ACL_DELETE_CHR)
540 48 : cmd_matches = true;
541 186 : break;
377 alvherre 542 144 : case CMD_MERGE:
377 alvherre 543 ECB :
544 : /*
545 : * We do not support a separate policy for MERGE command.
546 : * Instead it derives from the policies defined for other
547 : * commands.
548 : */
377 alvherre 549 CBC 144 : break;
2763 sfrost 550 UIC 0 : default:
551 0 : elog(ERROR, "unrecognized policy command type %d",
552 : (int) cmd);
553 : break;
554 : }
555 : }
2893 andres 556 ECB :
2893 andres 557 EUB : /*
1962 dean.a.rasheed 558 : * Add this policy to the relevant list of policies if it applies to
559 : * the specified role.
560 : */
2763 sfrost 561 GIC 3924 : if (cmd_matches && check_role_for_policy(policy->roles, user_id))
562 : {
2316 563 1908 : if (policy->permissive)
564 1767 : *permissive_policies = lappend(*permissive_policies, policy);
565 : else
566 141 : *restrictive_policies = lappend(*restrictive_policies, policy);
567 : }
2763 sfrost 568 ECB : }
569 :
2316 570 : /*
571 : * We sort restrictive policies by name so that any WCOs they generate are
572 : * checked in a well-defined order.
573 : */
1363 tgl 574 GIC 1776 : sort_policies_by_name(*restrictive_policies);
575 :
576 : /*
577 : * Then add any permissive or restrictive policies defined by extensions.
578 : * These are simply appended to the lists of internal policies, if they
579 : * apply to the specified role.
580 : */
2763 sfrost 581 CBC 1776 : if (row_security_policy_hook_restrictive)
582 : {
583 : List *hook_policies =
2495 rhaas 584 GIC 30 : (*row_security_policy_hook_restrictive) (cmd, relation);
585 :
586 : /*
587 : * As with built-in restrictive policies, we sort any hook-provided
2316 sfrost 588 ECB : * restrictive policies by name also. Note that we also intentionally
589 : * always check all built-in restrictive policies, in name order,
590 : * before checking restrictive policies added by hooks, in name order.
2763 591 : */
1363 tgl 592 GIC 30 : sort_policies_by_name(hook_policies);
593 :
2763 sfrost 594 51 : foreach(item, hook_policies)
595 : {
596 21 : RowSecurityPolicy *policy = (RowSecurityPolicy *) lfirst(item);
597 :
598 21 : if (check_role_for_policy(policy->roles, user_id))
2763 sfrost 599 CBC 21 : *restrictive_policies = lappend(*restrictive_policies, policy);
600 : }
3124 sfrost 601 ECB : }
602 :
2763 sfrost 603 CBC 1776 : if (row_security_policy_hook_permissive)
604 : {
2763 sfrost 605 ECB : List *hook_policies =
2495 rhaas 606 CBC 30 : (*row_security_policy_hook_permissive) (cmd, relation);
607 :
2763 sfrost 608 GIC 50 : foreach(item, hook_policies)
609 : {
2763 sfrost 610 CBC 20 : RowSecurityPolicy *policy = (RowSecurityPolicy *) lfirst(item);
611 :
2763 sfrost 612 GIC 20 : if (check_role_for_policy(policy->roles, user_id))
2763 sfrost 613 CBC 20 : *permissive_policies = lappend(*permissive_policies, policy);
614 : }
2763 sfrost 615 ECB : }
2763 sfrost 616 GIC 1776 : }
2909 sfrost 617 ECB :
618 : /*
2763 619 : * sort_policies_by_name
620 : *
621 : * This is only used for restrictive policies, ensuring that any
622 : * WithCheckOptions they generate are applied in a well-defined order.
2316 623 : * This is not necessary for permissive policies, since they are all combined
624 : * together using OR into a single WithCheckOption check.
625 : */
626 : static void
2763 sfrost 627 GIC 1806 : sort_policies_by_name(List *policies)
628 : {
1363 tgl 629 1806 : list_sort(policies, row_security_policy_cmp);
2763 sfrost 630 1806 : }
631 :
632 : /*
633 : * list_sort comparator to sort RowSecurityPolicy entries by name
2763 sfrost 634 ECB : */
635 : static int
1363 tgl 636 CBC 24 : row_security_policy_cmp(const ListCell *a, const ListCell *b)
2763 sfrost 637 ECB : {
1363 tgl 638 GIC 24 : const RowSecurityPolicy *pa = (const RowSecurityPolicy *) lfirst(a);
639 24 : const RowSecurityPolicy *pb = (const RowSecurityPolicy *) lfirst(b);
640 :
641 : /* Guard against NULL policy names from extensions */
2763 sfrost 642 24 : if (pa->policy_name == NULL)
2763 sfrost 643 LBC 0 : return pb->policy_name == NULL ? 0 : 1;
2763 sfrost 644 GIC 24 : if (pb->policy_name == NULL)
2763 sfrost 645 LBC 0 : return -1;
2763 sfrost 646 ECB :
2763 sfrost 647 GIC 24 : return strcmp(pa->policy_name, pb->policy_name);
648 : }
3124 sfrost 649 ECB :
3124 sfrost 650 EUB : /*
2763 sfrost 651 ECB : * add_security_quals
3124 sfrost 652 EUB : *
653 : * Add security quals to enforce the specified RLS policies, restricting
2763 sfrost 654 ECB : * access to existing data in a table. If there are no policies controlling
655 : * access to the table, then all access is prohibited --- i.e., an implicit
656 : * default-deny policy is used.
657 : *
658 : * New security quals are added to securityQuals, and hasSubLinks is set to
659 : * true if any of the quals added contain sublink subqueries.
660 : */
661 : static void
2763 sfrost 662 GIC 1209 : add_security_quals(int rt_index,
663 : List *permissive_policies,
664 : List *restrictive_policies,
665 : List **securityQuals,
666 : bool *hasSubLinks)
667 : {
668 : ListCell *item;
2763 sfrost 669 CBC 1209 : List *permissive_quals = NIL;
670 : Expr *rowsec_expr;
671 :
672 : /*
673 : * First collect up the permissive quals. If we do not find any
674 : * permissive policies then no rows are visible (this is handled below).
675 : */
676 2470 : foreach(item, permissive_policies)
677 : {
2878 bruce 678 GIC 1261 : RowSecurityPolicy *policy = (RowSecurityPolicy *) lfirst(item);
679 :
2763 sfrost 680 1261 : if (policy->qual != NULL)
681 : {
682 1261 : permissive_quals = lappend(permissive_quals,
2763 sfrost 683 CBC 1261 : copyObject(policy->qual));
2763 sfrost 684 GIC 1261 : *hasSubLinks |= policy->hassublinks;
3124 sfrost 685 ECB : }
686 : }
687 :
688 : /*
2763 689 : * We must have permissive quals, always, or no rows are visible.
690 : *
691 : * If we do not, then we simply return a single 'false' qual which results
692 : * in no rows being visible.
693 : */
2763 sfrost 694 GIC 1209 : if (permissive_quals != NIL)
695 : {
696 : /*
697 : * We now know that permissive policies exist, so we can now add
698 : * security quals based on the USING clauses from the restrictive
699 : * policies. Since these need to be combined together using AND, we
700 : * can just add them one at a time.
2763 sfrost 701 ECB : */
2763 sfrost 702 GIC 1301 : foreach(item, restrictive_policies)
703 : {
704 119 : RowSecurityPolicy *policy = (RowSecurityPolicy *) lfirst(item);
705 : Expr *qual;
706 :
707 119 : if (policy->qual != NULL)
708 : {
2763 sfrost 709 CBC 119 : qual = copyObject(policy->qual);
2763 sfrost 710 GIC 119 : ChangeVarNodes((Node *) qual, 1, rt_index, 0);
3124 sfrost 711 ECB :
2748 sfrost 712 GIC 119 : *securityQuals = list_append_unique(*securityQuals, qual);
2763 713 119 : *hasSubLinks |= policy->hassublinks;
2763 sfrost 714 ECB : }
715 : }
716 :
717 : /*
718 : * Then add a single security qual combining together the USING
2316 719 : * clauses from all the permissive policies using OR.
2763 720 : */
2763 sfrost 721 GIC 1182 : if (list_length(permissive_quals) == 1)
722 1127 : rowsec_expr = (Expr *) linitial(permissive_quals);
723 : else
724 55 : rowsec_expr = makeBoolExpr(OR_EXPR, permissive_quals, -1);
725 :
726 1182 : ChangeVarNodes((Node *) rowsec_expr, 1, rt_index, 0);
2748 727 1182 : *securityQuals = list_append_unique(*securityQuals, rowsec_expr);
2763 sfrost 728 ECB : }
729 : else
730 :
731 : /*
732 : * A permissive policy must exist for rows to be visible at all.
733 : * Therefore, if there were no permissive policies found, return a
734 : * single always-false clause.
735 : */
2763 sfrost 736 GIC 27 : *securityQuals = lappend(*securityQuals,
737 27 : makeConst(BOOLOID, -1, InvalidOid,
738 : sizeof(bool), BoolGetDatum(false),
739 : false, true));
3124 740 1209 : }
741 :
742 : /*
2763 sfrost 743 ECB : * add_with_check_options
3124 744 : *
745 : * Add WithCheckOptions of the specified kind to check that new records
746 : * added by an INSERT or UPDATE are consistent with the specified RLS
2763 747 : * policies. Normally new data must satisfy the WITH CHECK clauses from the
748 : * policies. If a policy has no explicit WITH CHECK clause, its USING clause
749 : * is used instead. In the special case of an UPDATE arising from an
750 : * INSERT ... ON CONFLICT DO UPDATE, existing records are first checked using
751 : * a WCO_RLS_CONFLICT_CHECK WithCheckOption, which always uses the USING
752 : * clauses from RLS policies.
753 : *
754 : * New WCOs are added to withCheckOptions, and hasSubLinks is set to true if
755 : * any of the check clauses added contain sublink subqueries.
756 : */
757 : static void
2763 sfrost 758 GIC 783 : add_with_check_options(Relation rel,
759 : int rt_index,
760 : WCOKind kind,
761 : List *permissive_policies,
762 : List *restrictive_policies,
763 : List **withCheckOptions,
764 : bool *hasSubLinks,
2164 sfrost 765 ECB : bool force_using)
766 : {
767 : ListCell *item;
2763 sfrost 768 GIC 783 : List *permissive_quals = NIL;
769 :
770 : #define QUAL_FOR_WCO(policy) \
771 : ( !force_using && \
772 : (policy)->with_check_qual != NULL ? \
773 : (policy)->with_check_qual : (policy)->qual )
774 :
3124 sfrost 775 ECB : /*
776 : * First collect up the permissive policy clauses, similar to
777 : * add_security_quals.
778 : */
2763 sfrost 779 GIC 1561 : foreach(item, permissive_policies)
780 : {
3124 781 778 : RowSecurityPolicy *policy = (RowSecurityPolicy *) lfirst(item);
2763 782 778 : Expr *qual = QUAL_FOR_WCO(policy);
783 :
784 778 : if (qual != NULL)
785 : {
2763 sfrost 786 CBC 778 : permissive_quals = lappend(permissive_quals, copyObject(qual));
2763 sfrost 787 GIC 778 : *hasSubLinks |= policy->hassublinks;
2763 sfrost 788 ECB : }
789 : }
790 :
791 : /*
792 : * There must be at least one permissive qual found or no rows are allowed
2495 rhaas 793 : * to be added. This is the same as in add_security_quals.
2763 sfrost 794 : *
795 : * If there are no permissive_quals then we fall through and return a
796 : * single 'false' WCO, preventing all new rows.
797 : */
2763 sfrost 798 GIC 783 : if (permissive_quals != NIL)
799 : {
800 : /*
801 : * Add a single WithCheckOption for all the permissive policy clauses,
802 : * combining them together using OR. This check has no policy name,
803 : * since if the check fails it means that no policy granted permission
804 : * to perform the update, rather than any particular policy being
2316 sfrost 805 ECB : * violated.
806 : */
807 : WithCheckOption *wco;
808 :
2298 peter_e 809 GIC 756 : wco = makeNode(WithCheckOption);
2763 sfrost 810 756 : wco->kind = kind;
811 756 : wco->relname = pstrdup(RelationGetRelationName(rel));
812 756 : wco->polname = NULL;
813 756 : wco->cascaded = false;
814 :
815 756 : if (list_length(permissive_quals) == 1)
2763 sfrost 816 CBC 734 : wco->qual = (Node *) linitial(permissive_quals);
2763 sfrost 817 ECB : else
2763 sfrost 818 CBC 22 : wco->qual = (Node *) makeBoolExpr(OR_EXPR, permissive_quals, -1);
3124 sfrost 819 ECB :
2763 sfrost 820 CBC 756 : ChangeVarNodes(wco->qual, 1, rt_index, 0);
821 :
2748 822 756 : *withCheckOptions = list_append_unique(*withCheckOptions, wco);
2909 sfrost 823 ECB :
824 : /*
2763 825 : * Now add WithCheckOptions for each of the restrictive policy clauses
826 : * (which will be combined together using AND). We use a separate
2316 827 : * WithCheckOption for each restrictive policy to allow the policy
828 : * name to be included in error reports if the policy is violated.
2763 829 : */
2763 sfrost 830 GIC 811 : foreach(item, restrictive_policies)
831 : {
832 55 : RowSecurityPolicy *policy = (RowSecurityPolicy *) lfirst(item);
833 55 : Expr *qual = QUAL_FOR_WCO(policy);
834 :
835 55 : if (qual != NULL)
2763 sfrost 836 ECB : {
2763 sfrost 837 GIC 55 : qual = copyObject(qual);
2763 sfrost 838 CBC 55 : ChangeVarNodes((Node *) qual, 1, rt_index, 0);
3124 sfrost 839 ECB :
2298 peter_e 840 GIC 55 : wco = makeNode(WithCheckOption);
2763 sfrost 841 CBC 55 : wco->kind = kind;
2763 sfrost 842 GIC 55 : wco->relname = pstrdup(RelationGetRelationName(rel));
2763 sfrost 843 CBC 55 : wco->polname = pstrdup(policy->policy_name);
844 55 : wco->qual = (Node *) qual;
2763 sfrost 845 GIC 55 : wco->cascaded = false;
3124 sfrost 846 ECB :
2748 sfrost 847 CBC 55 : *withCheckOptions = list_append_unique(*withCheckOptions, wco);
2763 848 55 : *hasSubLinks |= policy->hassublinks;
2763 sfrost 849 ECB : }
850 : }
851 : }
852 : else
853 : {
854 : /*
855 : * If there were no policy clauses to check new data, add a single
856 : * always-false WCO (a default-deny policy).
857 : */
858 : WithCheckOption *wco;
859 :
2298 peter_e 860 GIC 27 : wco = makeNode(WithCheckOption);
2763 sfrost 861 27 : wco->kind = kind;
862 27 : wco->relname = pstrdup(RelationGetRelationName(rel));
863 27 : wco->polname = NULL;
864 27 : wco->qual = (Node *) makeConst(BOOLOID, -1, InvalidOid,
865 : sizeof(bool), BoolGetDatum(false),
2763 sfrost 866 ECB : false, true);
2763 sfrost 867 CBC 27 : wco->cascaded = false;
2763 sfrost 868 ECB :
2763 sfrost 869 CBC 27 : *withCheckOptions = lappend(*withCheckOptions, wco);
2763 sfrost 870 ECB : }
3124 sfrost 871 GIC 783 : }
872 :
3124 sfrost 873 ECB : /*
874 : * check_role_for_policy -
2878 bruce 875 : * determines if the policy should be applied for the current role
876 : */
3119 sfrost 877 : static bool
3119 sfrost 878 GIC 2633 : check_role_for_policy(ArrayType *policy_roles, Oid user_id)
879 : {
880 : int i;
881 2633 : Oid *roles = (Oid *) ARR_DATA_PTR(policy_roles);
882 :
883 : /* Quick fall-thru for policies applied to all roles */
3124 sfrost 884 CBC 2633 : if (roles[0] == ACL_ID_PUBLIC)
3124 sfrost 885 GIC 1718 : return true;
886 :
3119 sfrost 887 CBC 1599 : for (i = 0; i < ARR_DIMS(policy_roles)[0]; i++)
888 : {
3119 sfrost 889 GIC 915 : if (has_privs_of_role(user_id, roles[i]))
3124 sfrost 890 CBC 231 : return true;
3124 sfrost 891 ECB : }
892 :
3124 sfrost 893 CBC 684 : return false;
894 : }
|