* ExecCheckRTEPerms * Check access permissions for a single RTE. */
| 1477 | * Check access permissions for a single RTE. |
| 1478 | */ |
| 1479 | bool |
| 1480 | ExecCheckRTEPerms(RangeTblEntry *rte) |
| 1481 | { |
| 1482 | AclMode requiredPerms; |
| 1483 | AclMode relPerms; |
| 1484 | AclMode remainingPerms; |
| 1485 | Oid relOid; |
| 1486 | Oid userid; |
| 1487 | |
| 1488 | /* |
| 1489 | * Only plain-relation RTEs need to be checked here. Function RTEs are |
| 1490 | * checked when the function is prepared for execution. Join, subquery, |
| 1491 | * and special RTEs need no checks. |
| 1492 | */ |
| 1493 | if (rte->rtekind != RTE_RELATION) |
| 1494 | return true; |
| 1495 | |
| 1496 | /* |
| 1497 | * No work if requiredPerms is empty. |
| 1498 | */ |
| 1499 | requiredPerms = rte->requiredPerms; |
| 1500 | if (requiredPerms == 0) |
| 1501 | return true; |
| 1502 | |
| 1503 | relOid = rte->relid; |
| 1504 | |
| 1505 | /* |
| 1506 | * userid to check as: current user unless we have a setuid indication. |
| 1507 | * |
| 1508 | * Note: GetUserId() is presently fast enough that there's no harm in |
| 1509 | * calling it separately for each RTE. If that stops being true, we could |
| 1510 | * call it once in ExecCheckRTPerms and pass the userid down from there. |
| 1511 | * But for now, no need for the extra clutter. |
| 1512 | */ |
| 1513 | userid = rte->checkAsUser ? rte->checkAsUser : GetUserId(); |
| 1514 | |
| 1515 | /* |
| 1516 | * We must have *all* the requiredPerms bits, but some of the bits can be |
| 1517 | * satisfied from column-level rather than relation-level permissions. |
| 1518 | * First, remove any bits that are satisfied by relation permissions. |
| 1519 | */ |
| 1520 | relPerms = pg_class_aclmask(relOid, userid, requiredPerms, ACLMASK_ALL); |
| 1521 | remainingPerms = requiredPerms & ~relPerms; |
| 1522 | if (remainingPerms != 0) |
| 1523 | { |
| 1524 | int col = -1; |
| 1525 | |
| 1526 | /* |
| 1527 | * If we lack any permissions that exist only as relation permissions, |
| 1528 | * we can fail straight away. |
| 1529 | */ |
| 1530 | if (remainingPerms & ~(ACL_SELECT | ACL_INSERT | ACL_UPDATE)) |
| 1531 | return false; |
| 1532 | |
| 1533 | /* |
| 1534 | * Check to see if we have the needed privileges at column level. |
| 1535 | * |
| 1536 | * Note: failures just report a table-level error; it would be nicer |
no test coverage detected