PostgreSQL Source Code  git master
acl.h File Reference
#include "access/htup.h"
#include "nodes/parsenodes.h"
#include "parser/parse_node.h"
#include "utils/snapshot.h"
Include dependency graph for acl.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  AclItem
 

Macros

#define ACL_ID_PUBLIC   0 /* placeholder for id in a PUBLIC acl item */
 
#define ACLITEM_GET_PRIVS(item)   ((item).ai_privs & 0xFFFFFFFF)
 
#define ACLITEM_GET_GOPTIONS(item)   (((item).ai_privs >> 32) & 0xFFFFFFFF)
 
#define ACLITEM_GET_RIGHTS(item)   ((item).ai_privs)
 
#define ACL_GRANT_OPTION_FOR(privs)   (((AclMode) (privs) & 0xFFFFFFFF) << 32)
 
#define ACL_OPTION_TO_PRIVS(privs)   (((AclMode) (privs) >> 32) & 0xFFFFFFFF)
 
#define ACLITEM_SET_PRIVS(item, privs)
 
#define ACLITEM_SET_GOPTIONS(item, goptions)
 
#define ACLITEM_SET_RIGHTS(item, rights)    ((item).ai_privs = (AclMode) (rights))
 
#define ACLITEM_SET_PRIVS_GOPTIONS(item, privs, goptions)
 
#define ACLITEM_ALL_PRIV_BITS   ((AclMode) 0xFFFFFFFF)
 
#define ACLITEM_ALL_GOPTION_BITS   ((AclMode) 0xFFFFFFFF << 32)
 
#define ACL_NUM(ACL)   (ARR_DIMS(ACL)[0])
 
#define ACL_DAT(ACL)   ((AclItem *) ARR_DATA_PTR(ACL))
 
#define ACL_N_SIZE(N)   (ARR_OVERHEAD_NONULLS(1) + ((N) * sizeof(AclItem)))
 
#define ACL_SIZE(ACL)   ARR_SIZE(ACL)
 
#define DatumGetAclItemP(X)   ((AclItem *) DatumGetPointer(X))
 
#define PG_GETARG_ACLITEM_P(n)   DatumGetAclItemP(PG_GETARG_DATUM(n))
 
#define PG_RETURN_ACLITEM_P(x)   PG_RETURN_POINTER(x)
 
#define DatumGetAclP(X)   ((Acl *) PG_DETOAST_DATUM(X))
 
#define DatumGetAclPCopy(X)   ((Acl *) PG_DETOAST_DATUM_COPY(X))
 
#define PG_GETARG_ACL_P(n)   DatumGetAclP(PG_GETARG_DATUM(n))
 
#define PG_GETARG_ACL_P_COPY(n)   DatumGetAclPCopy(PG_GETARG_DATUM(n))
 
#define PG_RETURN_ACL_P(x)   PG_RETURN_POINTER(x)
 
#define ACL_MODECHG_ADD   1
 
#define ACL_MODECHG_DEL   2
 
#define ACL_MODECHG_EQL   3
 
#define ACL_INSERT_CHR   'a' /* formerly known as "append" */
 
#define ACL_SELECT_CHR   'r' /* formerly known as "read" */
 
#define ACL_UPDATE_CHR   'w' /* formerly known as "write" */
 
#define ACL_DELETE_CHR   'd'
 
#define ACL_TRUNCATE_CHR   'D' /* super-delete, as it were */
 
#define ACL_REFERENCES_CHR   'x'
 
#define ACL_TRIGGER_CHR   't'
 
#define ACL_EXECUTE_CHR   'X'
 
#define ACL_USAGE_CHR   'U'
 
#define ACL_CREATE_CHR   'C'
 
#define ACL_CREATE_TEMP_CHR   'T'
 
#define ACL_CONNECT_CHR   'c'
 
#define ACL_SET_CHR   's'
 
#define ACL_ALTER_SYSTEM_CHR   'A'
 
#define ACL_MAINTAIN_CHR   'm'
 
#define ACL_ALL_RIGHTS_STR   "arwdDxtXUCTcsAm"
 
#define ACL_ALL_RIGHTS_COLUMN   (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_REFERENCES)
 
#define ACL_ALL_RIGHTS_RELATION   (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_TRUNCATE|ACL_REFERENCES|ACL_TRIGGER|ACL_MAINTAIN)
 
#define ACL_ALL_RIGHTS_SEQUENCE   (ACL_USAGE|ACL_SELECT|ACL_UPDATE)
 
#define ACL_ALL_RIGHTS_DATABASE   (ACL_CREATE|ACL_CREATE_TEMP|ACL_CONNECT)
 
#define ACL_ALL_RIGHTS_FDW   (ACL_USAGE)
 
#define ACL_ALL_RIGHTS_FOREIGN_SERVER   (ACL_USAGE)
 
#define ACL_ALL_RIGHTS_FUNCTION   (ACL_EXECUTE)
 
#define ACL_ALL_RIGHTS_LANGUAGE   (ACL_USAGE)
 
#define ACL_ALL_RIGHTS_LARGEOBJECT   (ACL_SELECT|ACL_UPDATE)
 
#define ACL_ALL_RIGHTS_PARAMETER_ACL   (ACL_SET|ACL_ALTER_SYSTEM)
 
#define ACL_ALL_RIGHTS_SCHEMA   (ACL_USAGE|ACL_CREATE)
 
#define ACL_ALL_RIGHTS_TABLESPACE   (ACL_CREATE)
 
#define ACL_ALL_RIGHTS_TYPE   (ACL_USAGE)
 

Typedefs

typedef struct AclItem AclItem
 
typedef struct ArrayType Acl
 

Enumerations

enum  AclMaskHow { ACLMASK_ALL , ACLMASK_ANY }
 
enum  AclResult { ACLCHECK_OK = 0 , ACLCHECK_NO_PRIV , ACLCHECK_NOT_OWNER }
 

Functions

Aclacldefault (ObjectType objtype, Oid ownerId)
 
Aclget_user_default_acl (ObjectType objtype, Oid ownerId, Oid nsp_oid)
 
void recordDependencyOnNewAcl (Oid classId, Oid objectId, int32 objsubId, Oid ownerId, Acl *acl)
 
Aclaclupdate (const Acl *old_acl, const AclItem *mod_aip, int modechg, Oid ownerId, DropBehavior behavior)
 
Aclaclnewowner (const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
 
Aclmake_empty_acl (void)
 
Aclaclcopy (const Acl *orig_acl)
 
Aclaclconcat (const Acl *left_acl, const Acl *right_acl)
 
Aclaclmerge (const Acl *left_acl, const Acl *right_acl, Oid ownerId)
 
void aclitemsort (Acl *acl)
 
bool aclequal (const Acl *left_acl, const Acl *right_acl)
 
AclMode aclmask (const Acl *acl, Oid roleid, Oid ownerId, AclMode mask, AclMaskHow how)
 
int aclmembers (const Acl *acl, Oid **roleids)
 
bool has_privs_of_role (Oid member, Oid role)
 
bool member_can_set_role (Oid member, Oid role)
 
void check_can_set_role (Oid member, Oid role)
 
bool is_member_of_role (Oid member, Oid role)
 
bool is_member_of_role_nosuper (Oid member, Oid role)
 
bool is_admin_of_role (Oid member, Oid role)
 
Oid select_best_admin (Oid member, Oid role)
 
Oid get_role_oid (const char *rolname, bool missing_ok)
 
Oid get_role_oid_or_public (const char *rolname)
 
Oid get_rolespec_oid (const RoleSpec *role, bool missing_ok)
 
void check_rolespec_name (const RoleSpec *role, const char *detail_msg)
 
HeapTuple get_rolespec_tuple (const RoleSpec *role)
 
char * get_rolespec_name (const RoleSpec *role)
 
void select_best_grantor (Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
 
void initialize_acl (void)
 
void ExecuteGrantStmt (GrantStmt *stmt)
 
void ExecAlterDefaultPrivilegesStmt (ParseState *pstate, AlterDefaultPrivilegesStmt *stmt)
 
void RemoveRoleFromObjectACL (Oid roleid, Oid classid, Oid objid)
 
AclMode pg_class_aclmask (Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclResult object_aclcheck (Oid classid, Oid objectid, Oid roleid, AclMode mode)
 
AclResult object_aclcheck_ext (Oid classid, Oid objectid, Oid roleid, AclMode mode, bool *is_missing)
 
AclResult pg_attribute_aclcheck (Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
 
AclResult pg_attribute_aclcheck_ext (Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode, bool *is_missing)
 
AclResult pg_attribute_aclcheck_all (Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
 
AclResult pg_attribute_aclcheck_all_ext (Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how, bool *is_missing)
 
AclResult pg_class_aclcheck (Oid table_oid, Oid roleid, AclMode mode)
 
AclResult pg_class_aclcheck_ext (Oid table_oid, Oid roleid, AclMode mode, bool *is_missing)
 
AclResult pg_parameter_aclcheck (const char *name, Oid roleid, AclMode mode)
 
AclResult pg_largeobject_aclcheck_snapshot (Oid lobj_oid, Oid roleid, AclMode mode, Snapshot snapshot)
 
void aclcheck_error (AclResult aclerr, ObjectType objtype, const char *objectname)
 
void aclcheck_error_col (AclResult aclerr, ObjectType objtype, const char *objectname, const char *colname)
 
void aclcheck_error_type (AclResult aclerr, Oid typeOid)
 
void recordExtObjInitPriv (Oid objoid, Oid classoid)
 
void removeExtObjInitPriv (Oid objoid, Oid classoid)
 
void ReplaceRoleInInitPriv (Oid oldroleid, Oid newroleid, Oid classid, Oid objid, int32 objsubid)
 
void RemoveRoleFromInitPriv (Oid roleid, Oid classid, Oid objid, int32 objsubid)
 
bool object_ownercheck (Oid classid, Oid objectid, Oid roleid)
 
bool has_createrole_privilege (Oid roleid)
 
bool has_bypassrls_privilege (Oid roleid)
 

Macro Definition Documentation

◆ ACL_ALL_RIGHTS_COLUMN

#define ACL_ALL_RIGHTS_COLUMN   (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_REFERENCES)

Definition at line 159 of file acl.h.

◆ ACL_ALL_RIGHTS_DATABASE

#define ACL_ALL_RIGHTS_DATABASE   (ACL_CREATE|ACL_CREATE_TEMP|ACL_CONNECT)

Definition at line 162 of file acl.h.

◆ ACL_ALL_RIGHTS_FDW

#define ACL_ALL_RIGHTS_FDW   (ACL_USAGE)

Definition at line 163 of file acl.h.

◆ ACL_ALL_RIGHTS_FOREIGN_SERVER

#define ACL_ALL_RIGHTS_FOREIGN_SERVER   (ACL_USAGE)

Definition at line 164 of file acl.h.

◆ ACL_ALL_RIGHTS_FUNCTION

#define ACL_ALL_RIGHTS_FUNCTION   (ACL_EXECUTE)

Definition at line 165 of file acl.h.

◆ ACL_ALL_RIGHTS_LANGUAGE

#define ACL_ALL_RIGHTS_LANGUAGE   (ACL_USAGE)

Definition at line 166 of file acl.h.

◆ ACL_ALL_RIGHTS_LARGEOBJECT

#define ACL_ALL_RIGHTS_LARGEOBJECT   (ACL_SELECT|ACL_UPDATE)

Definition at line 167 of file acl.h.

◆ ACL_ALL_RIGHTS_PARAMETER_ACL

#define ACL_ALL_RIGHTS_PARAMETER_ACL   (ACL_SET|ACL_ALTER_SYSTEM)

Definition at line 168 of file acl.h.

◆ ACL_ALL_RIGHTS_RELATION

Definition at line 160 of file acl.h.

◆ ACL_ALL_RIGHTS_SCHEMA

#define ACL_ALL_RIGHTS_SCHEMA   (ACL_USAGE|ACL_CREATE)

Definition at line 169 of file acl.h.

◆ ACL_ALL_RIGHTS_SEQUENCE

#define ACL_ALL_RIGHTS_SEQUENCE   (ACL_USAGE|ACL_SELECT|ACL_UPDATE)

Definition at line 161 of file acl.h.

◆ ACL_ALL_RIGHTS_STR

#define ACL_ALL_RIGHTS_STR   "arwdDxtXUCTcsAm"

Definition at line 154 of file acl.h.

◆ ACL_ALL_RIGHTS_TABLESPACE

#define ACL_ALL_RIGHTS_TABLESPACE   (ACL_CREATE)

Definition at line 170 of file acl.h.

◆ ACL_ALL_RIGHTS_TYPE

#define ACL_ALL_RIGHTS_TYPE   (ACL_USAGE)

Definition at line 171 of file acl.h.

◆ ACL_ALTER_SYSTEM_CHR

#define ACL_ALTER_SYSTEM_CHR   'A'

Definition at line 150 of file acl.h.

◆ ACL_CONNECT_CHR

#define ACL_CONNECT_CHR   'c'

Definition at line 148 of file acl.h.

◆ ACL_CREATE_CHR

#define ACL_CREATE_CHR   'C'

Definition at line 146 of file acl.h.

◆ ACL_CREATE_TEMP_CHR

#define ACL_CREATE_TEMP_CHR   'T'

Definition at line 147 of file acl.h.

◆ ACL_DAT

#define ACL_DAT (   ACL)    ((AclItem *) ARR_DATA_PTR(ACL))

Definition at line 109 of file acl.h.

◆ ACL_DELETE_CHR

#define ACL_DELETE_CHR   'd'

Definition at line 140 of file acl.h.

◆ ACL_EXECUTE_CHR

#define ACL_EXECUTE_CHR   'X'

Definition at line 144 of file acl.h.

◆ ACL_GRANT_OPTION_FOR

#define ACL_GRANT_OPTION_FOR (   privs)    (((AclMode) (privs) & 0xFFFFFFFF) << 32)

Definition at line 70 of file acl.h.

◆ ACL_ID_PUBLIC

#define ACL_ID_PUBLIC   0 /* placeholder for id in a PUBLIC acl item */

Definition at line 46 of file acl.h.

◆ ACL_INSERT_CHR

#define ACL_INSERT_CHR   'a' /* formerly known as "append" */

Definition at line 137 of file acl.h.

◆ ACL_MAINTAIN_CHR

#define ACL_MAINTAIN_CHR   'm'

Definition at line 151 of file acl.h.

◆ ACL_MODECHG_ADD

#define ACL_MODECHG_ADD   1

Definition at line 129 of file acl.h.

◆ ACL_MODECHG_DEL

#define ACL_MODECHG_DEL   2

Definition at line 130 of file acl.h.

◆ ACL_MODECHG_EQL

#define ACL_MODECHG_EQL   3

Definition at line 131 of file acl.h.

◆ ACL_N_SIZE

#define ACL_N_SIZE (   N)    (ARR_OVERHEAD_NONULLS(1) + ((N) * sizeof(AclItem)))

Definition at line 110 of file acl.h.

◆ ACL_NUM

#define ACL_NUM (   ACL)    (ARR_DIMS(ACL)[0])

Definition at line 108 of file acl.h.

◆ ACL_OPTION_TO_PRIVS

#define ACL_OPTION_TO_PRIVS (   privs)    (((AclMode) (privs) >> 32) & 0xFFFFFFFF)

Definition at line 71 of file acl.h.

◆ ACL_REFERENCES_CHR

#define ACL_REFERENCES_CHR   'x'

Definition at line 142 of file acl.h.

◆ ACL_SELECT_CHR

#define ACL_SELECT_CHR   'r' /* formerly known as "read" */

Definition at line 138 of file acl.h.

◆ ACL_SET_CHR

#define ACL_SET_CHR   's'

Definition at line 149 of file acl.h.

◆ ACL_SIZE

#define ACL_SIZE (   ACL)    ARR_SIZE(ACL)

Definition at line 111 of file acl.h.

◆ ACL_TRIGGER_CHR

#define ACL_TRIGGER_CHR   't'

Definition at line 143 of file acl.h.

◆ ACL_TRUNCATE_CHR

#define ACL_TRUNCATE_CHR   'D' /* super-delete, as it were */

Definition at line 141 of file acl.h.

◆ ACL_UPDATE_CHR

#define ACL_UPDATE_CHR   'w' /* formerly known as "write" */

Definition at line 139 of file acl.h.

◆ ACL_USAGE_CHR

#define ACL_USAGE_CHR   'U'

Definition at line 145 of file acl.h.

◆ ACLITEM_ALL_GOPTION_BITS

#define ACLITEM_ALL_GOPTION_BITS   ((AclMode) 0xFFFFFFFF << 32)

Definition at line 88 of file acl.h.

◆ ACLITEM_ALL_PRIV_BITS

#define ACLITEM_ALL_PRIV_BITS   ((AclMode) 0xFFFFFFFF)

Definition at line 87 of file acl.h.

◆ ACLITEM_GET_GOPTIONS

#define ACLITEM_GET_GOPTIONS (   item)    (((item).ai_privs >> 32) & 0xFFFFFFFF)

Definition at line 67 of file acl.h.

◆ ACLITEM_GET_PRIVS

#define ACLITEM_GET_PRIVS (   item)    ((item).ai_privs & 0xFFFFFFFF)

Definition at line 66 of file acl.h.

◆ ACLITEM_GET_RIGHTS

#define ACLITEM_GET_RIGHTS (   item)    ((item).ai_privs)

Definition at line 68 of file acl.h.

◆ ACLITEM_SET_GOPTIONS

#define ACLITEM_SET_GOPTIONS (   item,
  goptions 
)
Value:
((item).ai_privs = ((item).ai_privs & ~(((AclMode) 0xFFFFFFFF) << 32)) | \
(((AclMode) (goptions) & 0xFFFFFFFF) << 32))
uint64 AclMode
Definition: parsenodes.h:74

Definition at line 76 of file acl.h.

◆ ACLITEM_SET_PRIVS

#define ACLITEM_SET_PRIVS (   item,
  privs 
)
Value:
((item).ai_privs = ((item).ai_privs & ~((AclMode) 0xFFFFFFFF)) | \
((AclMode) (privs) & 0xFFFFFFFF))

Definition at line 73 of file acl.h.

◆ ACLITEM_SET_PRIVS_GOPTIONS

#define ACLITEM_SET_PRIVS_GOPTIONS (   item,
  privs,
  goptions 
)
Value:
((item).ai_privs = ((AclMode) (privs) & 0xFFFFFFFF) | \
(((AclMode) (goptions) & 0xFFFFFFFF) << 32))

Definition at line 82 of file acl.h.

◆ ACLITEM_SET_RIGHTS

#define ACLITEM_SET_RIGHTS (   item,
  rights 
)     ((item).ai_privs = (AclMode) (rights))

Definition at line 79 of file acl.h.

◆ DatumGetAclItemP

#define DatumGetAclItemP (   X)    ((AclItem *) DatumGetPointer(X))

Definition at line 116 of file acl.h.

◆ DatumGetAclP

#define DatumGetAclP (   X)    ((Acl *) PG_DETOAST_DATUM(X))

Definition at line 120 of file acl.h.

◆ DatumGetAclPCopy

#define DatumGetAclPCopy (   X)    ((Acl *) PG_DETOAST_DATUM_COPY(X))

Definition at line 121 of file acl.h.

◆ PG_GETARG_ACL_P

#define PG_GETARG_ACL_P (   n)    DatumGetAclP(PG_GETARG_DATUM(n))

Definition at line 122 of file acl.h.

◆ PG_GETARG_ACL_P_COPY

#define PG_GETARG_ACL_P_COPY (   n)    DatumGetAclPCopy(PG_GETARG_DATUM(n))

Definition at line 123 of file acl.h.

◆ PG_GETARG_ACLITEM_P

#define PG_GETARG_ACLITEM_P (   n)    DatumGetAclItemP(PG_GETARG_DATUM(n))

Definition at line 117 of file acl.h.

◆ PG_RETURN_ACL_P

#define PG_RETURN_ACL_P (   x)    PG_RETURN_POINTER(x)

Definition at line 124 of file acl.h.

◆ PG_RETURN_ACLITEM_P

#define PG_RETURN_ACLITEM_P (   x)    PG_RETURN_POINTER(x)

Definition at line 118 of file acl.h.

Typedef Documentation

◆ Acl

typedef struct ArrayType Acl

Definition at line 1 of file acl.h.

◆ AclItem

typedef struct AclItem AclItem

Enumeration Type Documentation

◆ AclMaskHow

enum AclMaskHow
Enumerator
ACLMASK_ALL 
ACLMASK_ANY 

Definition at line 174 of file acl.h.

175 {
176  ACLMASK_ALL, /* normal case: compute all bits */
177  ACLMASK_ANY, /* return when result is known nonzero */
178 } AclMaskHow;
AclMaskHow
Definition: acl.h:175
@ ACLMASK_ANY
Definition: acl.h:177
@ ACLMASK_ALL
Definition: acl.h:176

◆ AclResult

enum AclResult
Enumerator
ACLCHECK_OK 
ACLCHECK_NO_PRIV 
ACLCHECK_NOT_OWNER 

Definition at line 181 of file acl.h.

182 {
183  ACLCHECK_OK = 0,
186 } AclResult;
AclResult
Definition: acl.h:182
@ ACLCHECK_NO_PRIV
Definition: acl.h:184
@ ACLCHECK_OK
Definition: acl.h:183
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185

Function Documentation

◆ aclcheck_error()

void aclcheck_error ( AclResult  aclerr,
ObjectType  objtype,
const char *  objectname 
)

Definition at line 2703 of file aclchk.c.

2705 {
2706  switch (aclerr)
2707  {
2708  case ACLCHECK_OK:
2709  /* no error, so return to caller */
2710  break;
2711  case ACLCHECK_NO_PRIV:
2712  {
2713  const char *msg = "???";
2714 
2715  switch (objtype)
2716  {
2717  case OBJECT_AGGREGATE:
2718  msg = gettext_noop("permission denied for aggregate %s");
2719  break;
2720  case OBJECT_COLLATION:
2721  msg = gettext_noop("permission denied for collation %s");
2722  break;
2723  case OBJECT_COLUMN:
2724  msg = gettext_noop("permission denied for column %s");
2725  break;
2726  case OBJECT_CONVERSION:
2727  msg = gettext_noop("permission denied for conversion %s");
2728  break;
2729  case OBJECT_DATABASE:
2730  msg = gettext_noop("permission denied for database %s");
2731  break;
2732  case OBJECT_DOMAIN:
2733  msg = gettext_noop("permission denied for domain %s");
2734  break;
2735  case OBJECT_EVENT_TRIGGER:
2736  msg = gettext_noop("permission denied for event trigger %s");
2737  break;
2738  case OBJECT_EXTENSION:
2739  msg = gettext_noop("permission denied for extension %s");
2740  break;
2741  case OBJECT_FDW:
2742  msg = gettext_noop("permission denied for foreign-data wrapper %s");
2743  break;
2744  case OBJECT_FOREIGN_SERVER:
2745  msg = gettext_noop("permission denied for foreign server %s");
2746  break;
2747  case OBJECT_FOREIGN_TABLE:
2748  msg = gettext_noop("permission denied for foreign table %s");
2749  break;
2750  case OBJECT_FUNCTION:
2751  msg = gettext_noop("permission denied for function %s");
2752  break;
2753  case OBJECT_INDEX:
2754  msg = gettext_noop("permission denied for index %s");
2755  break;
2756  case OBJECT_LANGUAGE:
2757  msg = gettext_noop("permission denied for language %s");
2758  break;
2759  case OBJECT_LARGEOBJECT:
2760  msg = gettext_noop("permission denied for large object %s");
2761  break;
2762  case OBJECT_MATVIEW:
2763  msg = gettext_noop("permission denied for materialized view %s");
2764  break;
2765  case OBJECT_OPCLASS:
2766  msg = gettext_noop("permission denied for operator class %s");
2767  break;
2768  case OBJECT_OPERATOR:
2769  msg = gettext_noop("permission denied for operator %s");
2770  break;
2771  case OBJECT_OPFAMILY:
2772  msg = gettext_noop("permission denied for operator family %s");
2773  break;
2774  case OBJECT_PARAMETER_ACL:
2775  msg = gettext_noop("permission denied for parameter %s");
2776  break;
2777  case OBJECT_POLICY:
2778  msg = gettext_noop("permission denied for policy %s");
2779  break;
2780  case OBJECT_PROCEDURE:
2781  msg = gettext_noop("permission denied for procedure %s");
2782  break;
2783  case OBJECT_PUBLICATION:
2784  msg = gettext_noop("permission denied for publication %s");
2785  break;
2786  case OBJECT_ROUTINE:
2787  msg = gettext_noop("permission denied for routine %s");
2788  break;
2789  case OBJECT_SCHEMA:
2790  msg = gettext_noop("permission denied for schema %s");
2791  break;
2792  case OBJECT_SEQUENCE:
2793  msg = gettext_noop("permission denied for sequence %s");
2794  break;
2795  case OBJECT_STATISTIC_EXT:
2796  msg = gettext_noop("permission denied for statistics object %s");
2797  break;
2798  case OBJECT_SUBSCRIPTION:
2799  msg = gettext_noop("permission denied for subscription %s");
2800  break;
2801  case OBJECT_TABLE:
2802  msg = gettext_noop("permission denied for table %s");
2803  break;
2804  case OBJECT_TABLESPACE:
2805  msg = gettext_noop("permission denied for tablespace %s");
2806  break;
2808  msg = gettext_noop("permission denied for text search configuration %s");
2809  break;
2810  case OBJECT_TSDICTIONARY:
2811  msg = gettext_noop("permission denied for text search dictionary %s");
2812  break;
2813  case OBJECT_TYPE:
2814  msg = gettext_noop("permission denied for type %s");
2815  break;
2816  case OBJECT_VIEW:
2817  msg = gettext_noop("permission denied for view %s");
2818  break;
2819  /* these currently aren't used */
2820  case OBJECT_ACCESS_METHOD:
2821  case OBJECT_AMOP:
2822  case OBJECT_AMPROC:
2823  case OBJECT_ATTRIBUTE:
2824  case OBJECT_CAST:
2825  case OBJECT_DEFAULT:
2826  case OBJECT_DEFACL:
2827  case OBJECT_DOMCONSTRAINT:
2830  case OBJECT_ROLE:
2831  case OBJECT_RULE:
2832  case OBJECT_TABCONSTRAINT:
2833  case OBJECT_TRANSFORM:
2834  case OBJECT_TRIGGER:
2835  case OBJECT_TSPARSER:
2836  case OBJECT_TSTEMPLATE:
2837  case OBJECT_USER_MAPPING:
2838  elog(ERROR, "unsupported object type: %d", objtype);
2839  }
2840 
2841  ereport(ERROR,
2842  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2843  errmsg(msg, objectname)));
2844  break;
2845  }
2846  case ACLCHECK_NOT_OWNER:
2847  {
2848  const char *msg = "???";
2849 
2850  switch (objtype)
2851  {
2852  case OBJECT_AGGREGATE:
2853  msg = gettext_noop("must be owner of aggregate %s");
2854  break;
2855  case OBJECT_COLLATION:
2856  msg = gettext_noop("must be owner of collation %s");
2857  break;
2858  case OBJECT_CONVERSION:
2859  msg = gettext_noop("must be owner of conversion %s");
2860  break;
2861  case OBJECT_DATABASE:
2862  msg = gettext_noop("must be owner of database %s");
2863  break;
2864  case OBJECT_DOMAIN:
2865  msg = gettext_noop("must be owner of domain %s");
2866  break;
2867  case OBJECT_EVENT_TRIGGER:
2868  msg = gettext_noop("must be owner of event trigger %s");
2869  break;
2870  case OBJECT_EXTENSION:
2871  msg = gettext_noop("must be owner of extension %s");
2872  break;
2873  case OBJECT_FDW:
2874  msg = gettext_noop("must be owner of foreign-data wrapper %s");
2875  break;
2876  case OBJECT_FOREIGN_SERVER:
2877  msg = gettext_noop("must be owner of foreign server %s");
2878  break;
2879  case OBJECT_FOREIGN_TABLE:
2880  msg = gettext_noop("must be owner of foreign table %s");
2881  break;
2882  case OBJECT_FUNCTION:
2883  msg = gettext_noop("must be owner of function %s");
2884  break;
2885  case OBJECT_INDEX:
2886  msg = gettext_noop("must be owner of index %s");
2887  break;
2888  case OBJECT_LANGUAGE:
2889  msg = gettext_noop("must be owner of language %s");
2890  break;
2891  case OBJECT_LARGEOBJECT:
2892  msg = gettext_noop("must be owner of large object %s");
2893  break;
2894  case OBJECT_MATVIEW:
2895  msg = gettext_noop("must be owner of materialized view %s");
2896  break;
2897  case OBJECT_OPCLASS:
2898  msg = gettext_noop("must be owner of operator class %s");
2899  break;
2900  case OBJECT_OPERATOR:
2901  msg = gettext_noop("must be owner of operator %s");
2902  break;
2903  case OBJECT_OPFAMILY:
2904  msg = gettext_noop("must be owner of operator family %s");
2905  break;
2906  case OBJECT_PROCEDURE:
2907  msg = gettext_noop("must be owner of procedure %s");
2908  break;
2909  case OBJECT_PUBLICATION:
2910  msg = gettext_noop("must be owner of publication %s");
2911  break;
2912  case OBJECT_ROUTINE:
2913  msg = gettext_noop("must be owner of routine %s");
2914  break;
2915  case OBJECT_SEQUENCE:
2916  msg = gettext_noop("must be owner of sequence %s");
2917  break;
2918  case OBJECT_SUBSCRIPTION:
2919  msg = gettext_noop("must be owner of subscription %s");
2920  break;
2921  case OBJECT_TABLE:
2922  msg = gettext_noop("must be owner of table %s");
2923  break;
2924  case OBJECT_TYPE:
2925  msg = gettext_noop("must be owner of type %s");
2926  break;
2927  case OBJECT_VIEW:
2928  msg = gettext_noop("must be owner of view %s");
2929  break;
2930  case OBJECT_SCHEMA:
2931  msg = gettext_noop("must be owner of schema %s");
2932  break;
2933  case OBJECT_STATISTIC_EXT:
2934  msg = gettext_noop("must be owner of statistics object %s");
2935  break;
2936  case OBJECT_TABLESPACE:
2937  msg = gettext_noop("must be owner of tablespace %s");
2938  break;
2940  msg = gettext_noop("must be owner of text search configuration %s");
2941  break;
2942  case OBJECT_TSDICTIONARY:
2943  msg = gettext_noop("must be owner of text search dictionary %s");
2944  break;
2945 
2946  /*
2947  * Special cases: For these, the error message talks
2948  * about "relation", because that's where the
2949  * ownership is attached. See also
2950  * check_object_ownership().
2951  */
2952  case OBJECT_COLUMN:
2953  case OBJECT_POLICY:
2954  case OBJECT_RULE:
2955  case OBJECT_TABCONSTRAINT:
2956  case OBJECT_TRIGGER:
2957  msg = gettext_noop("must be owner of relation %s");
2958  break;
2959  /* these currently aren't used */
2960  case OBJECT_ACCESS_METHOD:
2961  case OBJECT_AMOP:
2962  case OBJECT_AMPROC:
2963  case OBJECT_ATTRIBUTE:
2964  case OBJECT_CAST:
2965  case OBJECT_DEFAULT:
2966  case OBJECT_DEFACL:
2967  case OBJECT_DOMCONSTRAINT:
2968  case OBJECT_PARAMETER_ACL:
2971  case OBJECT_ROLE:
2972  case OBJECT_TRANSFORM:
2973  case OBJECT_TSPARSER:
2974  case OBJECT_TSTEMPLATE:
2975  case OBJECT_USER_MAPPING:
2976  elog(ERROR, "unsupported object type: %d", objtype);
2977  }
2978 
2979  ereport(ERROR,
2980  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2981  errmsg(msg, objectname)));
2982  break;
2983  }
2984  default:
2985  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
2986  break;
2987  }
2988 }
#define gettext_noop(x)
Definition: c.h:1187
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
@ OBJECT_EVENT_TRIGGER
Definition: parsenodes.h:2272
@ OBJECT_FDW
Definition: parsenodes.h:2274
@ OBJECT_TSPARSER
Definition: parsenodes.h:2305
@ OBJECT_COLLATION
Definition: parsenodes.h:2265
@ OBJECT_USER_MAPPING
Definition: parsenodes.h:2308
@ OBJECT_ACCESS_METHOD
Definition: parsenodes.h:2258
@ OBJECT_OPCLASS
Definition: parsenodes.h:2282
@ OBJECT_DEFACL
Definition: parsenodes.h:2269
@ OBJECT_AGGREGATE
Definition: parsenodes.h:2259
@ OBJECT_MATVIEW
Definition: parsenodes.h:2281
@ OBJECT_SCHEMA
Definition: parsenodes.h:2294
@ OBJECT_POLICY
Definition: parsenodes.h:2286
@ OBJECT_OPERATOR
Definition: parsenodes.h:2283
@ OBJECT_FOREIGN_TABLE
Definition: parsenodes.h:2276
@ OBJECT_TSCONFIGURATION
Definition: parsenodes.h:2303
@ OBJECT_OPFAMILY
Definition: parsenodes.h:2284
@ OBJECT_DOMAIN
Definition: parsenodes.h:2270
@ OBJECT_COLUMN
Definition: parsenodes.h:2264
@ OBJECT_TABLESPACE
Definition: parsenodes.h:2300
@ OBJECT_ROLE
Definition: parsenodes.h:2291
@ OBJECT_ROUTINE
Definition: parsenodes.h:2292
@ OBJECT_LARGEOBJECT
Definition: parsenodes.h:2280
@ OBJECT_PUBLICATION_NAMESPACE
Definition: parsenodes.h:2289
@ OBJECT_PROCEDURE
Definition: parsenodes.h:2287
@ OBJECT_EXTENSION
Definition: parsenodes.h:2273
@ OBJECT_INDEX
Definition: parsenodes.h:2278
@ OBJECT_DEFAULT
Definition: parsenodes.h:2268
@ OBJECT_DATABASE
Definition: parsenodes.h:2267
@ OBJECT_SEQUENCE
Definition: parsenodes.h:2295
@ OBJECT_TSTEMPLATE
Definition: parsenodes.h:2306
@ OBJECT_LANGUAGE
Definition: parsenodes.h:2279
@ OBJECT_AMOP
Definition: parsenodes.h:2260
@ OBJECT_PUBLICATION_REL
Definition: parsenodes.h:2290
@ OBJECT_FOREIGN_SERVER
Definition: parsenodes.h:2275
@ OBJECT_TSDICTIONARY
Definition: parsenodes.h:2304
@ OBJECT_ATTRIBUTE
Definition: parsenodes.h:2262
@ OBJECT_PUBLICATION
Definition: parsenodes.h:2288
@ OBJECT_RULE
Definition: parsenodes.h:2293
@ OBJECT_CONVERSION
Definition: parsenodes.h:2266
@ OBJECT_AMPROC
Definition: parsenodes.h:2261
@ OBJECT_TABLE
Definition: parsenodes.h:2299
@ OBJECT_VIEW
Definition: parsenodes.h:2309
@ OBJECT_PARAMETER_ACL
Definition: parsenodes.h:2285
@ OBJECT_TYPE
Definition: parsenodes.h:2307
@ OBJECT_FUNCTION
Definition: parsenodes.h:2277
@ OBJECT_TABCONSTRAINT
Definition: parsenodes.h:2298
@ OBJECT_DOMCONSTRAINT
Definition: parsenodes.h:2271
@ OBJECT_SUBSCRIPTION
Definition: parsenodes.h:2296
@ OBJECT_STATISTIC_EXT
Definition: parsenodes.h:2297
@ OBJECT_CAST
Definition: parsenodes.h:2263
@ OBJECT_TRIGGER
Definition: parsenodes.h:2302
@ OBJECT_TRANSFORM
Definition: parsenodes.h:2301

References ACLCHECK_NO_PRIV, ACLCHECK_NOT_OWNER, ACLCHECK_OK, elog, ereport, errcode(), errmsg(), ERROR, gettext_noop, OBJECT_ACCESS_METHOD, OBJECT_AGGREGATE, OBJECT_AMOP, OBJECT_AMPROC, OBJECT_ATTRIBUTE, OBJECT_CAST, OBJECT_COLLATION, OBJECT_COLUMN, OBJECT_CONVERSION, OBJECT_DATABASE, OBJECT_DEFACL, OBJECT_DEFAULT, OBJECT_DOMAIN, OBJECT_DOMCONSTRAINT, OBJECT_EVENT_TRIGGER, OBJECT_EXTENSION, OBJECT_FDW, OBJECT_FOREIGN_SERVER, OBJECT_FOREIGN_TABLE, OBJECT_FUNCTION, OBJECT_INDEX, OBJECT_LANGUAGE, OBJECT_LARGEOBJECT, OBJECT_MATVIEW, OBJECT_OPCLASS, OBJECT_OPERATOR, OBJECT_OPFAMILY, OBJECT_PARAMETER_ACL, OBJECT_POLICY, OBJECT_PROCEDURE, OBJECT_PUBLICATION, OBJECT_PUBLICATION_NAMESPACE, OBJECT_PUBLICATION_REL, OBJECT_ROLE, OBJECT_ROUTINE, OBJECT_RULE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_STATISTIC_EXT, OBJECT_SUBSCRIPTION, OBJECT_TABCONSTRAINT, OBJECT_TABLE, OBJECT_TABLESPACE, OBJECT_TRANSFORM, OBJECT_TRIGGER, OBJECT_TSCONFIGURATION, OBJECT_TSDICTIONARY, OBJECT_TSPARSER, OBJECT_TSTEMPLATE, OBJECT_TYPE, OBJECT_USER_MAPPING, and OBJECT_VIEW.

Referenced by aclcheck_error_col(), aclcheck_error_type(), AlterCollation(), AlterDatabase(), AlterDatabaseOwner(), AlterDatabaseRefreshColl(), AlterDatabaseSet(), AlterEventTrigger(), AlterEventTriggerOwner_internal(), AlterExtensionNamespace(), AlterForeignServer(), AlterForeignServerOwner_internal(), AlterFunction(), AlterObjectNamespace_internal(), AlterObjectOwner_internal(), AlterObjectRename_internal(), AlterOperator(), AlterOpFamilyAdd(), AlterPublication(), AlterPublicationOwner_internal(), AlterRoleSet(), AlterSchemaOwner_internal(), AlterStatistics(), AlterSubscription(), AlterSubscriptionOwner_internal(), AlterTableMoveAll(), AlterTableSpaceOptions(), AlterTSConfiguration(), AlterTSDictionary(), AlterTypeOwner(), ATExecChangeOwner(), ATPrepSetTableSpace(), ATSimplePermissions(), brin_desummarize_range(), brin_summarize_range(), calculate_database_size(), calculate_tablespace_size(), call_pltcl_start_proc(), check_object_ownership(), check_temp_tablespaces(), checkFkeyPermissions(), CheckFunctionValidatorAccess(), compute_return_type(), CreateConversionCommand(), createdb(), CreateForeignServer(), CreateForeignTable(), CreateFunction(), CreateProceduralLanguage(), CreatePublication(), CreateSchemaCommand(), CreateStatistics(), CreateSubscription(), CreateTransform(), CreateTriggerFiringOn(), currtid_internal(), DefineAggregate(), DefineCollation(), DefineDomain(), DefineEnum(), DefineIndex(), DefineOpClass(), DefineOperator(), DefineOpFamily(), DefineQueryRewrite(), DefineRange(), DefineRelation(), DefineTSConfiguration(), DefineTSDictionary(), DefineType(), dropdb(), DropSubscription(), DropTableSpace(), EnableDisableRule(), ExecAlterExtensionContentsStmt(), ExecAlterExtensionStmt(), ExecBuildGroupingEqual(), ExecBuildParamSetEqual(), ExecCheckPermissions(), ExecInitAgg(), ExecInitExprRec(), ExecInitFunc(), ExecInitWindowAgg(), ExecReindex(), ExecuteCallStmt(), ExecuteDoStmt(), ExecuteTruncateGuts(), findRangeCanonicalFunction(), findRangeSubtypeDiffFunction(), get_connect_string(), get_other_operator(), get_rel_from_relname(), gin_clean_pending_list(), HandleFunctionRequest(), heap_force_common(), ImportForeignSchema(), init_sexpr(), initialize_peragg(), LockViewRecurse_walker(), LogicalRepSyncTableStart(), lookup_agg_function(), LookupCreationNamespace(), LookupExplicitNamespace(), MergeAttributes(), movedb(), OperatorCreate(), pg_prewarm(), pgrowlocks(), ProcedureCreate(), PublicationAddTables(), RangeVarCallbackForAlterRelation(), RangeVarCallbackForDropRelation(), RangeVarCallbackForLockTable(), RangeVarCallbackForPolicy(), RangeVarCallbackForReindexIndex(), RangeVarCallbackForRenameRule(), RangeVarCallbackForRenameTrigger(), RangeVarCallbackMaintainsTable(), RangeVarCallbackOwnsRelation(), RangeVarGetAndCheckCreationNamespace(), ReindexMultipleInternal(), ReindexMultipleTables(), renameatt_check(), RenameDatabase(), RenameSchema(), RenameTableSpace(), restrict_and_check_grant(), stats_lock_check_privileges(), TargetPrivilegesCheck(), transformTableLikeClause(), truncate_check_perms(), TypeCreate(), user_mapping_ddl_aclcheck(), ValidateJoinEstimator(), ValidateOperatorReference(), and ValidateRestrictionEstimator().

◆ aclcheck_error_col()

void aclcheck_error_col ( AclResult  aclerr,
ObjectType  objtype,
const char *  objectname,
const char *  colname 
)

Definition at line 2992 of file aclchk.c.

2994 {
2995  switch (aclerr)
2996  {
2997  case ACLCHECK_OK:
2998  /* no error, so return to caller */
2999  break;
3000  case ACLCHECK_NO_PRIV:
3001  ereport(ERROR,
3002  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3003  errmsg("permission denied for column \"%s\" of relation \"%s\"",
3004  colname, objectname)));
3005  break;
3006  case ACLCHECK_NOT_OWNER:
3007  /* relation msg is OK since columns don't have separate owners */
3008  aclcheck_error(aclerr, objtype, objectname);
3009  break;
3010  default:
3011  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3012  break;
3013  }
3014 }
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2703

References aclcheck_error(), ACLCHECK_NO_PRIV, ACLCHECK_NOT_OWNER, ACLCHECK_OK, elog, ereport, errcode(), errmsg(), and ERROR.

Referenced by restrict_and_check_grant().

◆ aclcheck_error_type()

void aclcheck_error_type ( AclResult  aclerr,
Oid  typeOid 
)

◆ aclconcat()

Acl* aclconcat ( const Acl left_acl,
const Acl right_acl 
)

Definition at line 461 of file acl.c.

462 {
463  Acl *result_acl;
464 
465  result_acl = allocacl(ACL_NUM(left_acl) + ACL_NUM(right_acl));
466 
467  memcpy(ACL_DAT(result_acl),
468  ACL_DAT(left_acl),
469  ACL_NUM(left_acl) * sizeof(AclItem));
470 
471  memcpy(ACL_DAT(result_acl) + ACL_NUM(left_acl),
472  ACL_DAT(right_acl),
473  ACL_NUM(right_acl) * sizeof(AclItem));
474 
475  return result_acl;
476 }
static Acl * allocacl(int n)
Definition: acl.c:410
#define ACL_DAT(ACL)
Definition: acl.h:109
#define ACL_NUM(ACL)
Definition: acl.h:108
Definition: acl.h:55

References ACL_DAT, ACL_NUM, and allocacl().

Referenced by ExecGrant_Attribute().

◆ aclcopy()

Acl* aclcopy ( const Acl orig_acl)

Definition at line 441 of file acl.c.

442 {
443  Acl *result_acl;
444 
445  result_acl = allocacl(ACL_NUM(orig_acl));
446 
447  memcpy(ACL_DAT(result_acl),
448  ACL_DAT(orig_acl),
449  ACL_NUM(orig_acl) * sizeof(AclItem));
450 
451  return result_acl;
452 }

References ACL_DAT, ACL_NUM, and allocacl().

Referenced by aclmerge(), ExecGrant_Relation(), and SetDefaultACL().

◆ acldefault()

Acl* acldefault ( ObjectType  objtype,
Oid  ownerId 
)

Definition at line 787 of file acl.c.

788 {
789  AclMode world_default;
790  AclMode owner_default;
791  int nacl;
792  Acl *acl;
793  AclItem *aip;
794 
795  switch (objtype)
796  {
797  case OBJECT_COLUMN:
798  /* by default, columns have no extra privileges */
799  world_default = ACL_NO_RIGHTS;
800  owner_default = ACL_NO_RIGHTS;
801  break;
802  case OBJECT_TABLE:
803  world_default = ACL_NO_RIGHTS;
804  owner_default = ACL_ALL_RIGHTS_RELATION;
805  break;
806  case OBJECT_SEQUENCE:
807  world_default = ACL_NO_RIGHTS;
808  owner_default = ACL_ALL_RIGHTS_SEQUENCE;
809  break;
810  case OBJECT_DATABASE:
811  /* for backwards compatibility, grant some rights by default */
812  world_default = ACL_CREATE_TEMP | ACL_CONNECT;
813  owner_default = ACL_ALL_RIGHTS_DATABASE;
814  break;
815  case OBJECT_FUNCTION:
816  /* Grant EXECUTE by default, for now */
817  world_default = ACL_EXECUTE;
818  owner_default = ACL_ALL_RIGHTS_FUNCTION;
819  break;
820  case OBJECT_LANGUAGE:
821  /* Grant USAGE by default, for now */
822  world_default = ACL_USAGE;
823  owner_default = ACL_ALL_RIGHTS_LANGUAGE;
824  break;
825  case OBJECT_LARGEOBJECT:
826  world_default = ACL_NO_RIGHTS;
827  owner_default = ACL_ALL_RIGHTS_LARGEOBJECT;
828  break;
829  case OBJECT_SCHEMA:
830  world_default = ACL_NO_RIGHTS;
831  owner_default = ACL_ALL_RIGHTS_SCHEMA;
832  break;
833  case OBJECT_TABLESPACE:
834  world_default = ACL_NO_RIGHTS;
835  owner_default = ACL_ALL_RIGHTS_TABLESPACE;
836  break;
837  case OBJECT_FDW:
838  world_default = ACL_NO_RIGHTS;
839  owner_default = ACL_ALL_RIGHTS_FDW;
840  break;
842  world_default = ACL_NO_RIGHTS;
843  owner_default = ACL_ALL_RIGHTS_FOREIGN_SERVER;
844  break;
845  case OBJECT_DOMAIN:
846  case OBJECT_TYPE:
847  world_default = ACL_USAGE;
848  owner_default = ACL_ALL_RIGHTS_TYPE;
849  break;
851  world_default = ACL_NO_RIGHTS;
852  owner_default = ACL_ALL_RIGHTS_PARAMETER_ACL;
853  break;
854  default:
855  elog(ERROR, "unrecognized object type: %d", (int) objtype);
856  world_default = ACL_NO_RIGHTS; /* keep compiler quiet */
857  owner_default = ACL_NO_RIGHTS;
858  break;
859  }
860 
861  nacl = 0;
862  if (world_default != ACL_NO_RIGHTS)
863  nacl++;
864  if (owner_default != ACL_NO_RIGHTS)
865  nacl++;
866 
867  acl = allocacl(nacl);
868  aip = ACL_DAT(acl);
869 
870  if (world_default != ACL_NO_RIGHTS)
871  {
872  aip->ai_grantee = ACL_ID_PUBLIC;
873  aip->ai_grantor = ownerId;
874  ACLITEM_SET_PRIVS_GOPTIONS(*aip, world_default, ACL_NO_RIGHTS);
875  aip++;
876  }
877 
878  /*
879  * Note that the owner's entry shows all ordinary privileges but no grant
880  * options. This is because his grant options come "from the system" and
881  * not from his own efforts. (The SQL spec says that the owner's rights
882  * come from a "_SYSTEM" authid.) However, we do consider that the
883  * owner's ordinary privileges are self-granted; this lets him revoke
884  * them. We implement the owner's grant options without any explicit
885  * "_SYSTEM"-like ACL entry, by internally special-casing the owner
886  * wherever we are testing grant options.
887  */
888  if (owner_default != ACL_NO_RIGHTS)
889  {
890  aip->ai_grantee = ownerId;
891  aip->ai_grantor = ownerId;
892  ACLITEM_SET_PRIVS_GOPTIONS(*aip, owner_default, ACL_NO_RIGHTS);
893  }
894 
895  return acl;
896 }
#define ACL_ALL_RIGHTS_FOREIGN_SERVER
Definition: acl.h:164
#define ACL_ALL_RIGHTS_TABLESPACE
Definition: acl.h:170
#define ACL_ALL_RIGHTS_PARAMETER_ACL
Definition: acl.h:168
#define ACL_ALL_RIGHTS_SCHEMA
Definition: acl.h:169
#define ACL_ALL_RIGHTS_SEQUENCE
Definition: acl.h:161
#define ACL_ALL_RIGHTS_DATABASE
Definition: acl.h:162
#define ACL_ALL_RIGHTS_FUNCTION
Definition: acl.h:165
#define ACL_ALL_RIGHTS_LANGUAGE
Definition: acl.h:166
#define ACL_ALL_RIGHTS_TYPE
Definition: acl.h:171
#define ACL_ALL_RIGHTS_FDW
Definition: acl.h:163
#define ACLITEM_SET_PRIVS_GOPTIONS(item, privs, goptions)
Definition: acl.h:82
#define ACL_ALL_RIGHTS_RELATION
Definition: acl.h:160
#define ACL_ID_PUBLIC
Definition: acl.h:46
#define ACL_ALL_RIGHTS_LARGEOBJECT
Definition: acl.h:167
#define ACL_CREATE_TEMP
Definition: parsenodes.h:86
#define ACL_USAGE
Definition: parsenodes.h:84
#define ACL_NO_RIGHTS
Definition: parsenodes.h:92
#define ACL_CONNECT
Definition: parsenodes.h:87
#define ACL_EXECUTE
Definition: parsenodes.h:83
Oid ai_grantee
Definition: acl.h:56
Oid ai_grantor
Definition: acl.h:57

References ACL_ALL_RIGHTS_DATABASE, ACL_ALL_RIGHTS_FDW, ACL_ALL_RIGHTS_FOREIGN_SERVER, ACL_ALL_RIGHTS_FUNCTION, ACL_ALL_RIGHTS_LANGUAGE, ACL_ALL_RIGHTS_LARGEOBJECT, ACL_ALL_RIGHTS_PARAMETER_ACL, ACL_ALL_RIGHTS_RELATION, ACL_ALL_RIGHTS_SCHEMA, ACL_ALL_RIGHTS_SEQUENCE, ACL_ALL_RIGHTS_TABLESPACE, ACL_ALL_RIGHTS_TYPE, ACL_CONNECT, ACL_CREATE_TEMP, ACL_DAT, ACL_EXECUTE, ACL_ID_PUBLIC, ACL_NO_RIGHTS, ACL_USAGE, ACLITEM_SET_PRIVS_GOPTIONS, AclItem::ai_grantee, AclItem::ai_grantor, allocacl(), elog, ERROR, OBJECT_COLUMN, OBJECT_DATABASE, OBJECT_DOMAIN, OBJECT_FDW, OBJECT_FOREIGN_SERVER, OBJECT_FUNCTION, OBJECT_LANGUAGE, OBJECT_LARGEOBJECT, OBJECT_PARAMETER_ACL, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_TABLESPACE, and OBJECT_TYPE.

Referenced by acldefault_sql(), buildDefaultACLCommands(), dumpACL(), dumpRoleGUCPrivs(), dumpTable(), dumpTablespaces(), ExecGrant_Attribute(), ExecGrant_common(), ExecGrant_Largeobject(), ExecGrant_Parameter(), ExecGrant_Relation(), get_user_default_acl(), object_aclmask_ext(), pg_class_aclmask_ext(), pg_largeobject_aclmask_snapshot(), pg_namespace_aclmask_ext(), pg_parameter_acl_aclmask(), pg_parameter_aclmask(), pg_type_aclmask_ext(), and SetDefaultACL().

◆ aclequal()

bool aclequal ( const Acl left_acl,
const Acl right_acl 
)

Definition at line 543 of file acl.c.

544 {
545  /* Check for cases where one or both are empty/null */
546  if (left_acl == NULL || ACL_NUM(left_acl) == 0)
547  {
548  if (right_acl == NULL || ACL_NUM(right_acl) == 0)
549  return true;
550  else
551  return false;
552  }
553  else
554  {
555  if (right_acl == NULL || ACL_NUM(right_acl) == 0)
556  return false;
557  }
558 
559  if (ACL_NUM(left_acl) != ACL_NUM(right_acl))
560  return false;
561 
562  if (memcmp(ACL_DAT(left_acl),
563  ACL_DAT(right_acl),
564  ACL_NUM(left_acl) * sizeof(AclItem)) == 0)
565  return true;
566 
567  return false;
568 }

References ACL_DAT, and ACL_NUM.

Referenced by ExecGrant_Parameter(), get_user_default_acl(), and SetDefaultACL().

◆ aclitemsort()

void aclitemsort ( Acl acl)

Definition at line 529 of file acl.c.

530 {
531  if (acl != NULL && ACL_NUM(acl) > 1)
532  qsort(ACL_DAT(acl), ACL_NUM(acl), sizeof(AclItem), aclitemComparator);
533 }
static int aclitemComparator(const void *arg1, const void *arg2)
Definition: acl.c:708
#define qsort(a, b, c, d)
Definition: port.h:447

References ACL_DAT, ACL_NUM, aclitemComparator(), and qsort.

Referenced by get_user_default_acl(), and SetDefaultACL().

◆ aclmask()

AclMode aclmask ( const Acl acl,
Oid  roleid,
Oid  ownerId,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 1372 of file acl.c.

1374 {
1375  AclMode result;
1377  AclItem *aidat;
1378  int i,
1379  num;
1380 
1381  /*
1382  * Null ACL should not happen, since caller should have inserted
1383  * appropriate default
1384  */
1385  if (acl == NULL)
1386  elog(ERROR, "null ACL");
1387 
1388  check_acl(acl);
1389 
1390  /* Quick exit for mask == 0 */
1391  if (mask == 0)
1392  return 0;
1393 
1394  result = 0;
1395 
1396  /* Owner always implicitly has all grant options */
1397  if ((mask & ACLITEM_ALL_GOPTION_BITS) &&
1398  has_privs_of_role(roleid, ownerId))
1399  {
1400  result = mask & ACLITEM_ALL_GOPTION_BITS;
1401  if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1402  return result;
1403  }
1404 
1405  num = ACL_NUM(acl);
1406  aidat = ACL_DAT(acl);
1407 
1408  /*
1409  * Check privileges granted directly to roleid or to public
1410  */
1411  for (i = 0; i < num; i++)
1412  {
1413  AclItem *aidata = &aidat[i];
1414 
1415  if (aidata->ai_grantee == ACL_ID_PUBLIC ||
1416  aidata->ai_grantee == roleid)
1417  {
1418  result |= aidata->ai_privs & mask;
1419  if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1420  return result;
1421  }
1422  }
1423 
1424  /*
1425  * Check privileges granted indirectly via role memberships. We do this in
1426  * a separate pass to minimize expensive indirect membership tests. In
1427  * particular, it's worth testing whether a given ACL entry grants any
1428  * privileges still of interest before we perform the has_privs_of_role
1429  * test.
1430  */
1431  remaining = mask & ~result;
1432  for (i = 0; i < num; i++)
1433  {
1434  AclItem *aidata = &aidat[i];
1435 
1436  if (aidata->ai_grantee == ACL_ID_PUBLIC ||
1437  aidata->ai_grantee == roleid)
1438  continue; /* already checked it */
1439 
1440  if ((aidata->ai_privs & remaining) &&
1441  has_privs_of_role(roleid, aidata->ai_grantee))
1442  {
1443  result |= aidata->ai_privs & mask;
1444  if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1445  return result;
1446  remaining = mask & ~result;
1447  }
1448  }
1449 
1450  return result;
1451 }
static void check_acl(const Acl *acl)
Definition: acl.c:574
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:5268
#define ACLITEM_ALL_GOPTION_BITS
Definition: acl.h:88
int remaining
Definition: informix.c:692
int i
Definition: isn.c:73
AclMode ai_privs
Definition: acl.h:58

References ACL_DAT, ACL_ID_PUBLIC, ACL_NUM, ACLITEM_ALL_GOPTION_BITS, ACLMASK_ALL, AclItem::ai_grantee, AclItem::ai_privs, check_acl(), elog, ERROR, has_privs_of_role(), i, and remaining.

Referenced by check_circularity(), LockTableAclCheck(), object_aclmask_ext(), pg_attribute_aclcheck_all_ext(), pg_attribute_aclmask_ext(), pg_class_aclmask_ext(), pg_largeobject_aclmask_snapshot(), pg_namespace_aclmask_ext(), pg_parameter_acl_aclmask(), pg_parameter_aclmask(), pg_type_aclmask_ext(), and recursive_revoke().

◆ aclmembers()

int aclmembers ( const Acl acl,
Oid **  roleids 
)

Definition at line 1524 of file acl.c.

1525 {
1526  Oid *list;
1527  const AclItem *acldat;
1528  int i,
1529  j;
1530 
1531  if (acl == NULL || ACL_NUM(acl) == 0)
1532  {
1533  *roleids = NULL;
1534  return 0;
1535  }
1536 
1537  check_acl(acl);
1538 
1539  /* Allocate the worst-case space requirement */
1540  list = palloc(ACL_NUM(acl) * 2 * sizeof(Oid));
1541  acldat = ACL_DAT(acl);
1542 
1543  /*
1544  * Walk the ACL collecting mentioned RoleIds.
1545  */
1546  j = 0;
1547  for (i = 0; i < ACL_NUM(acl); i++)
1548  {
1549  const AclItem *ai = &acldat[i];
1550 
1551  if (ai->ai_grantee != ACL_ID_PUBLIC)
1552  list[j++] = ai->ai_grantee;
1553  /* grantor is currently never PUBLIC, but let's check anyway */
1554  if (ai->ai_grantor != ACL_ID_PUBLIC)
1555  list[j++] = ai->ai_grantor;
1556  }
1557 
1558  /* Sort the array */
1559  qsort(list, j, sizeof(Oid), oid_cmp);
1560 
1561  /*
1562  * We could repalloc the array down to minimum size, but it's hardly worth
1563  * it since it's only transient memory.
1564  */
1565  *roleids = list;
1566 
1567  /* Remove duplicates from the array */
1568  return qunique(list, j, sizeof(Oid), oid_cmp);
1569 }
int j
Definition: isn.c:74
void * palloc(Size size)
Definition: mcxt.c:1317
int oid_cmp(const void *p1, const void *p2)
Definition: oid.c:258
static size_t qunique(void *array, size_t elements, size_t width, int(*compare)(const void *, const void *))
Definition: qunique.h:21

References ACL_DAT, ACL_ID_PUBLIC, ACL_NUM, AclItem::ai_grantee, AclItem::ai_grantor, check_acl(), i, j, sort-test::list, oid_cmp(), palloc(), qsort, and qunique().

Referenced by ExecGrant_Attribute(), ExecGrant_common(), ExecGrant_Largeobject(), ExecGrant_Parameter(), ExecGrant_Relation(), recordDependencyOnNewAcl(), recordExtensionInitPrivWorker(), RemoveRoleFromInitPriv(), ReplaceRoleInInitPriv(), and SetDefaultACL().

◆ aclmerge()

Acl* aclmerge ( const Acl left_acl,
const Acl right_acl,
Oid  ownerId 
)

Definition at line 485 of file acl.c.

486 {
487  Acl *result_acl;
488  AclItem *aip;
489  int i,
490  num;
491 
492  /* Check for cases where one or both are empty/null */
493  if (left_acl == NULL || ACL_NUM(left_acl) == 0)
494  {
495  if (right_acl == NULL || ACL_NUM(right_acl) == 0)
496  return NULL;
497  else
498  return aclcopy(right_acl);
499  }
500  else
501  {
502  if (right_acl == NULL || ACL_NUM(right_acl) == 0)
503  return aclcopy(left_acl);
504  }
505 
506  /* Merge them the hard way, one item at a time */
507  result_acl = aclcopy(left_acl);
508 
509  aip = ACL_DAT(right_acl);
510  num = ACL_NUM(right_acl);
511 
512  for (i = 0; i < num; i++, aip++)
513  {
514  Acl *tmp_acl;
515 
516  tmp_acl = aclupdate(result_acl, aip, ACL_MODECHG_ADD,
517  ownerId, DROP_RESTRICT);
518  pfree(result_acl);
519  result_acl = tmp_acl;
520  }
521 
522  return result_acl;
523 }
Acl * aclupdate(const Acl *old_acl, const AclItem *mod_aip, int modechg, Oid ownerId, DropBehavior behavior)
Definition: acl.c:976
Acl * aclcopy(const Acl *orig_acl)
Definition: acl.c:441
#define ACL_MODECHG_ADD
Definition: acl.h:129
void pfree(void *pointer)
Definition: mcxt.c:1521
@ DROP_RESTRICT
Definition: parsenodes.h:2331

References ACL_DAT, ACL_MODECHG_ADD, ACL_NUM, aclcopy(), aclupdate(), DROP_RESTRICT, i, and pfree().

Referenced by get_user_default_acl().

◆ aclnewowner()

Acl* aclnewowner ( const Acl old_acl,
Oid  oldOwnerId,
Oid  newOwnerId 
)

Definition at line 1103 of file acl.c.

1104 {
1105  Acl *new_acl;
1106  AclItem *new_aip;
1107  AclItem *old_aip;
1108  AclItem *dst_aip;
1109  AclItem *src_aip;
1110  AclItem *targ_aip;
1111  bool newpresent = false;
1112  int dst,
1113  src,
1114  targ,
1115  num;
1116 
1117  check_acl(old_acl);
1118 
1119  /*
1120  * Make a copy of the given ACL, substituting new owner ID for old
1121  * wherever it appears as either grantor or grantee. Also note if the new
1122  * owner ID is already present.
1123  */
1124  num = ACL_NUM(old_acl);
1125  old_aip = ACL_DAT(old_acl);
1126  new_acl = allocacl(num);
1127  new_aip = ACL_DAT(new_acl);
1128  memcpy(new_aip, old_aip, num * sizeof(AclItem));
1129  for (dst = 0, dst_aip = new_aip; dst < num; dst++, dst_aip++)
1130  {
1131  if (dst_aip->ai_grantor == oldOwnerId)
1132  dst_aip->ai_grantor = newOwnerId;
1133  else if (dst_aip->ai_grantor == newOwnerId)
1134  newpresent = true;
1135  if (dst_aip->ai_grantee == oldOwnerId)
1136  dst_aip->ai_grantee = newOwnerId;
1137  else if (dst_aip->ai_grantee == newOwnerId)
1138  newpresent = true;
1139  }
1140 
1141  /*
1142  * If the old ACL contained any references to the new owner, then we may
1143  * now have generated an ACL containing duplicate entries. Find them and
1144  * merge them so that there are not duplicates. (This is relatively
1145  * expensive since we use a stupid O(N^2) algorithm, but it's unlikely to
1146  * be the normal case.)
1147  *
1148  * To simplify deletion of duplicate entries, we temporarily leave them in
1149  * the array but set their privilege masks to zero; when we reach such an
1150  * entry it's just skipped. (Thus, a side effect of this code will be to
1151  * remove privilege-free entries, should there be any in the input.) dst
1152  * is the next output slot, targ is the currently considered input slot
1153  * (always >= dst), and src scans entries to the right of targ looking for
1154  * duplicates. Once an entry has been emitted to dst it is known
1155  * duplicate-free and need not be considered anymore.
1156  */
1157  if (newpresent)
1158  {
1159  dst = 0;
1160  for (targ = 0, targ_aip = new_aip; targ < num; targ++, targ_aip++)
1161  {
1162  /* ignore if deleted in an earlier pass */
1163  if (ACLITEM_GET_RIGHTS(*targ_aip) == ACL_NO_RIGHTS)
1164  continue;
1165  /* find and merge any duplicates */
1166  for (src = targ + 1, src_aip = targ_aip + 1; src < num;
1167  src++, src_aip++)
1168  {
1169  if (ACLITEM_GET_RIGHTS(*src_aip) == ACL_NO_RIGHTS)
1170  continue;
1171  if (aclitem_match(targ_aip, src_aip))
1172  {
1173  ACLITEM_SET_RIGHTS(*targ_aip,
1174  ACLITEM_GET_RIGHTS(*targ_aip) |
1175  ACLITEM_GET_RIGHTS(*src_aip));
1176  /* mark the duplicate deleted */
1177  ACLITEM_SET_RIGHTS(*src_aip, ACL_NO_RIGHTS);
1178  }
1179  }
1180  /* and emit to output */
1181  new_aip[dst] = *targ_aip;
1182  dst++;
1183  }
1184  /* Adjust array size to be 'dst' items */
1185  ARR_DIMS(new_acl)[0] = dst;
1186  SET_VARSIZE(new_acl, ACL_N_SIZE(dst));
1187  }
1188 
1189  return new_acl;
1190 }
static bool aclitem_match(const AclItem *a1, const AclItem *a2)
Definition: acl.c:697
#define ACL_N_SIZE(N)
Definition: acl.h:110
#define ACLITEM_GET_RIGHTS(item)
Definition: acl.h:68
#define ACLITEM_SET_RIGHTS(item, rights)
Definition: acl.h:79
#define ARR_DIMS(a)
Definition: array.h:294
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305

References ACL_DAT, ACL_N_SIZE, ACL_NO_RIGHTS, ACL_NUM, ACLITEM_GET_RIGHTS, aclitem_match(), ACLITEM_SET_RIGHTS, AclItem::ai_grantee, AclItem::ai_grantor, allocacl(), ARR_DIMS, check_acl(), and SET_VARSIZE.

Referenced by AlterDatabaseOwner(), AlterForeignDataWrapperOwner_internal(), AlterForeignServerOwner_internal(), AlterObjectOwner_internal(), AlterSchemaOwner_internal(), AlterTypeOwnerInternal(), ATExecChangeOwner(), change_owner_fix_column_acls(), and ReplaceRoleInInitPriv().

◆ aclupdate()

Acl* aclupdate ( const Acl old_acl,
const AclItem mod_aip,
int  modechg,
Oid  ownerId,
DropBehavior  behavior 
)

Definition at line 976 of file acl.c.

978 {
979  Acl *new_acl = NULL;
980  AclItem *old_aip,
981  *new_aip = NULL;
982  AclMode old_rights,
983  old_goptions,
984  new_rights,
985  new_goptions;
986  int dst,
987  num;
988 
989  /* Caller probably already checked old_acl, but be safe */
990  check_acl(old_acl);
991 
992  /* If granting grant options, check for circularity */
993  if (modechg != ACL_MODECHG_DEL &&
994  ACLITEM_GET_GOPTIONS(*mod_aip) != ACL_NO_RIGHTS)
995  check_circularity(old_acl, mod_aip, ownerId);
996 
997  num = ACL_NUM(old_acl);
998  old_aip = ACL_DAT(old_acl);
999 
1000  /*
1001  * Search the ACL for an existing entry for this grantee and grantor. If
1002  * one exists, just modify the entry in-place (well, in the same position,
1003  * since we actually return a copy); otherwise, insert the new entry at
1004  * the end.
1005  */
1006 
1007  for (dst = 0; dst < num; ++dst)
1008  {
1009  if (aclitem_match(mod_aip, old_aip + dst))
1010  {
1011  /* found a match, so modify existing item */
1012  new_acl = allocacl(num);
1013  new_aip = ACL_DAT(new_acl);
1014  memcpy(new_acl, old_acl, ACL_SIZE(old_acl));
1015  break;
1016  }
1017  }
1018 
1019  if (dst == num)
1020  {
1021  /* need to append a new item */
1022  new_acl = allocacl(num + 1);
1023  new_aip = ACL_DAT(new_acl);
1024  memcpy(new_aip, old_aip, num * sizeof(AclItem));
1025 
1026  /* initialize the new entry with no permissions */
1027  new_aip[dst].ai_grantee = mod_aip->ai_grantee;
1028  new_aip[dst].ai_grantor = mod_aip->ai_grantor;
1029  ACLITEM_SET_PRIVS_GOPTIONS(new_aip[dst],
1031  num++; /* set num to the size of new_acl */
1032  }
1033 
1034  old_rights = ACLITEM_GET_RIGHTS(new_aip[dst]);
1035  old_goptions = ACLITEM_GET_GOPTIONS(new_aip[dst]);
1036 
1037  /* apply the specified permissions change */
1038  switch (modechg)
1039  {
1040  case ACL_MODECHG_ADD:
1041  ACLITEM_SET_RIGHTS(new_aip[dst],
1042  old_rights | ACLITEM_GET_RIGHTS(*mod_aip));
1043  break;
1044  case ACL_MODECHG_DEL:
1045  ACLITEM_SET_RIGHTS(new_aip[dst],
1046  old_rights & ~ACLITEM_GET_RIGHTS(*mod_aip));
1047  break;
1048  case ACL_MODECHG_EQL:
1049  ACLITEM_SET_RIGHTS(new_aip[dst],
1050  ACLITEM_GET_RIGHTS(*mod_aip));
1051  break;
1052  }
1053 
1054  new_rights = ACLITEM_GET_RIGHTS(new_aip[dst]);
1055  new_goptions = ACLITEM_GET_GOPTIONS(new_aip[dst]);
1056 
1057  /*
1058  * If the adjusted entry has no permissions, delete it from the list.
1059  */
1060  if (new_rights == ACL_NO_RIGHTS)
1061  {
1062  memmove(new_aip + dst,
1063  new_aip + dst + 1,
1064  (num - dst - 1) * sizeof(AclItem));
1065  /* Adjust array size to be 'num - 1' items */
1066  ARR_DIMS(new_acl)[0] = num - 1;
1067  SET_VARSIZE(new_acl, ACL_N_SIZE(num - 1));
1068  }
1069 
1070  /*
1071  * Remove abandoned privileges (cascading revoke). Currently we can only
1072  * handle this when the grantee is not PUBLIC.
1073  */
1074  if ((old_goptions & ~new_goptions) != 0)
1075  {
1076  Assert(mod_aip->ai_grantee != ACL_ID_PUBLIC);
1077  new_acl = recursive_revoke(new_acl, mod_aip->ai_grantee,
1078  (old_goptions & ~new_goptions),
1079  ownerId, behavior);
1080  }
1081 
1082  return new_acl;
1083 }
static Acl * recursive_revoke(Acl *acl, Oid grantee, AclMode revoke_privs, Oid ownerId, DropBehavior behavior)
Definition: acl.c:1286
static void check_circularity(const Acl *old_acl, const AclItem *mod_aip, Oid ownerId)
Definition: acl.c:1206
#define ACL_SIZE(ACL)
Definition: acl.h:111
#define ACL_MODECHG_DEL
Definition: acl.h:130
#define ACLITEM_GET_GOPTIONS(item)
Definition: acl.h:67
#define ACL_MODECHG_EQL
Definition: acl.h:131
#define Assert(condition)
Definition: c.h:849

References ACL_DAT, ACL_ID_PUBLIC, ACL_MODECHG_ADD, ACL_MODECHG_DEL, ACL_MODECHG_EQL, ACL_N_SIZE, ACL_NO_RIGHTS, ACL_NUM, ACL_SIZE, ACLITEM_GET_GOPTIONS, ACLITEM_GET_RIGHTS, aclitem_match(), ACLITEM_SET_PRIVS_GOPTIONS, ACLITEM_SET_RIGHTS, AclItem::ai_grantee, AclItem::ai_grantor, allocacl(), ARR_DIMS, Assert, check_acl(), check_circularity(), recursive_revoke(), and SET_VARSIZE.

Referenced by aclmerge(), check_circularity(), merge_acl_with_grant(), and recursive_revoke().

◆ check_can_set_role()

void check_can_set_role ( Oid  member,
Oid  role 
)

Definition at line 5325 of file acl.c.

5326 {
5327  if (!member_can_set_role(member, role))
5328  ereport(ERROR,
5329  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
5330  errmsg("must be able to SET ROLE \"%s\"",
5331  GetUserNameFromId(role, false))));
5332 }
bool member_can_set_role(Oid member, Oid role)
Definition: acl.c:5302
char * GetUserNameFromId(Oid roleid, bool noerr)
Definition: miscinit.c:980

References ereport, errcode(), errmsg(), ERROR, GetUserNameFromId(), and member_can_set_role().

Referenced by AlterDatabaseOwner(), AlterForeignServerOwner_internal(), AlterObjectOwner_internal(), AlterPublicationOwner_internal(), AlterSchemaOwner_internal(), AlterSubscriptionOwner_internal(), AlterTypeOwner(), ATExecChangeOwner(), createdb(), and CreateSchemaCommand().

◆ check_rolespec_name()

void check_rolespec_name ( const RoleSpec role,
const char *  detail_msg 
)

Definition at line 5695 of file acl.c.

5696 {
5697  if (!role)
5698  return;
5699 
5700  if (role->roletype != ROLESPEC_CSTRING)
5701  return;
5702 
5703  if (IsReservedName(role->rolename))
5704  {
5705  if (detail_msg)
5706  ereport(ERROR,
5707  (errcode(ERRCODE_RESERVED_NAME),
5708  errmsg("role name \"%s\" is reserved",
5709  role->rolename),
5710  errdetail_internal("%s", detail_msg)));
5711  else
5712  ereport(ERROR,
5713  (errcode(ERRCODE_RESERVED_NAME),
5714  errmsg("role name \"%s\" is reserved",
5715  role->rolename)));
5716  }
5717 }
bool IsReservedName(const char *name)
Definition: catalog.c:247
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1230
@ ROLESPEC_CSTRING
Definition: parsenodes.h:396
RoleSpecType roletype
Definition: parsenodes.h:406
char * rolename
Definition: parsenodes.h:407

References ereport, errcode(), errdetail_internal(), errmsg(), ERROR, IsReservedName(), RoleSpec::rolename, ROLESPEC_CSTRING, and RoleSpec::roletype.

Referenced by AlterRole(), and AlterRoleSet().

◆ ExecAlterDefaultPrivilegesStmt()

void ExecAlterDefaultPrivilegesStmt ( ParseState pstate,
AlterDefaultPrivilegesStmt stmt 
)

Definition at line 976 of file aclchk.c.

977 {
978  GrantStmt *action = stmt->action;
979  InternalDefaultACL iacls;
980  ListCell *cell;
981  List *rolespecs = NIL;
982  List *nspnames = NIL;
983  DefElem *drolespecs = NULL;
984  DefElem *dnspnames = NULL;
985  AclMode all_privileges;
986  const char *errormsg;
987 
988  /* Deconstruct the "options" part of the statement */
989  foreach(cell, stmt->options)
990  {
991  DefElem *defel = (DefElem *) lfirst(cell);
992 
993  if (strcmp(defel->defname, "schemas") == 0)
994  {
995  if (dnspnames)
996  errorConflictingDefElem(defel, pstate);
997  dnspnames = defel;
998  }
999  else if (strcmp(defel->defname, "roles") == 0)
1000  {
1001  if (drolespecs)
1002  errorConflictingDefElem(defel, pstate);
1003  drolespecs = defel;
1004  }
1005  else
1006  elog(ERROR, "option \"%s\" not recognized", defel->defname);
1007  }
1008 
1009  if (dnspnames)
1010  nspnames = (List *) dnspnames->arg;
1011  if (drolespecs)
1012  rolespecs = (List *) drolespecs->arg;
1013 
1014  /* Prepare the InternalDefaultACL representation of the statement */
1015  /* roleid to be filled below */
1016  /* nspid to be filled in SetDefaultACLsInSchemas */
1017  iacls.is_grant = action->is_grant;
1018  iacls.objtype = action->objtype;
1019  /* all_privs to be filled below */
1020  /* privileges to be filled below */
1021  iacls.grantees = NIL; /* filled below */
1022  iacls.grant_option = action->grant_option;
1023  iacls.behavior = action->behavior;
1024 
1025  /*
1026  * Convert the RoleSpec list into an Oid list. Note that at this point we
1027  * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
1028  * there shouldn't be any additional work needed to support this case.
1029  */
1030  foreach(cell, action->grantees)
1031  {
1032  RoleSpec *grantee = (RoleSpec *) lfirst(cell);
1033  Oid grantee_uid;
1034 
1035  switch (grantee->roletype)
1036  {
1037  case ROLESPEC_PUBLIC:
1038  grantee_uid = ACL_ID_PUBLIC;
1039  break;
1040  default:
1041  grantee_uid = get_rolespec_oid(grantee, false);
1042  break;
1043  }
1044  iacls.grantees = lappend_oid(iacls.grantees, grantee_uid);
1045  }
1046 
1047  /*
1048  * Convert action->privileges, a list of privilege strings, into an
1049  * AclMode bitmask.
1050  */
1051  switch (action->objtype)
1052  {
1053  case OBJECT_TABLE:
1054  all_privileges = ACL_ALL_RIGHTS_RELATION;
1055  errormsg = gettext_noop("invalid privilege type %s for relation");
1056  break;
1057  case OBJECT_SEQUENCE:
1058  all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
1059  errormsg = gettext_noop("invalid privilege type %s for sequence");
1060  break;
1061  case OBJECT_FUNCTION:
1062  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
1063  errormsg = gettext_noop("invalid privilege type %s for function");
1064  break;
1065  case OBJECT_PROCEDURE:
1066  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
1067  errormsg = gettext_noop("invalid privilege type %s for procedure");
1068  break;
1069  case OBJECT_ROUTINE:
1070  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
1071  errormsg = gettext_noop("invalid privilege type %s for routine");
1072  break;
1073  case OBJECT_TYPE:
1074  all_privileges = ACL_ALL_RIGHTS_TYPE;
1075  errormsg = gettext_noop("invalid privilege type %s for type");
1076  break;
1077  case OBJECT_SCHEMA:
1078  all_privileges = ACL_ALL_RIGHTS_SCHEMA;
1079  errormsg = gettext_noop("invalid privilege type %s for schema");
1080  break;
1081  default:
1082  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
1083  (int) action->objtype);
1084  /* keep compiler quiet */
1085  all_privileges = ACL_NO_RIGHTS;
1086  errormsg = NULL;
1087  }
1088 
1089  if (action->privileges == NIL)
1090  {
1091  iacls.all_privs = true;
1092 
1093  /*
1094  * will be turned into ACL_ALL_RIGHTS_* by the internal routines
1095  * depending on the object type
1096  */
1097  iacls.privileges = ACL_NO_RIGHTS;
1098  }
1099  else
1100  {
1101  iacls.all_privs = false;
1102  iacls.privileges = ACL_NO_RIGHTS;
1103 
1104  foreach(cell, action->privileges)
1105  {
1106  AccessPriv *privnode = (AccessPriv *) lfirst(cell);
1107  AclMode priv;
1108 
1109  if (privnode->cols)
1110  ereport(ERROR,
1111  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1112  errmsg("default privileges cannot be set for columns")));
1113 
1114  if (privnode->priv_name == NULL) /* parser mistake? */
1115  elog(ERROR, "AccessPriv node must specify privilege");
1116  priv = string_to_privilege(privnode->priv_name);
1117 
1118  if (priv & ~((AclMode) all_privileges))
1119  ereport(ERROR,
1120  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1121  errmsg(errormsg, privilege_to_string(priv))));
1122 
1123  iacls.privileges |= priv;
1124  }
1125  }
1126 
1127  if (rolespecs == NIL)
1128  {
1129  /* Set permissions for myself */
1130  iacls.roleid = GetUserId();
1131 
1132  SetDefaultACLsInSchemas(&iacls, nspnames);
1133  }
1134  else
1135  {
1136  /* Look up the role OIDs and do permissions checks */
1137  ListCell *rolecell;
1138 
1139  foreach(rolecell, rolespecs)
1140  {
1141  RoleSpec *rolespec = lfirst(rolecell);
1142 
1143  iacls.roleid = get_rolespec_oid(rolespec, false);
1144 
1145  if (!has_privs_of_role(GetUserId(), iacls.roleid))
1146  ereport(ERROR,
1147  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1148  errmsg("permission denied to change default privileges")));
1149 
1150  SetDefaultACLsInSchemas(&iacls, nspnames);
1151  }
1152  }
1153 }
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5588
static AclMode string_to_privilege(const char *privname)
Definition: aclchk.c:2615
static void SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames)
Definition: aclchk.c:1161
static const char * privilege_to_string(AclMode privilege)
Definition: aclchk.c:2656
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:384
#define stmt
Definition: indent_codes.h:59
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
Oid GetUserId(void)
Definition: miscinit.c:514
@ ROLESPEC_PUBLIC
Definition: parsenodes.h:400
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
char * priv_name
Definition: parsenodes.h:2543
List * cols
Definition: parsenodes.h:2544
char * defname
Definition: parsenodes.h:817
Node * arg
Definition: parsenodes.h:818
AclMode privileges
Definition: aclchk.c:99
List * grantees
Definition: aclchk.c:100
DropBehavior behavior
Definition: aclchk.c:102
ObjectType objtype
Definition: aclchk.c:97
Definition: pg_list.h:54

References ACL_ALL_RIGHTS_FUNCTION, ACL_ALL_RIGHTS_RELATION, ACL_ALL_RIGHTS_SCHEMA, ACL_ALL_RIGHTS_SEQUENCE, ACL_ALL_RIGHTS_TYPE, ACL_ID_PUBLIC, ACL_NO_RIGHTS, generate_unaccent_rules::action, InternalDefaultACL::all_privs, DefElem::arg, InternalDefaultACL::behavior, AccessPriv::cols, DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, errorConflictingDefElem(), get_rolespec_oid(), gettext_noop, GetUserId(), InternalDefaultACL::grant_option, InternalDefaultACL::grantees, has_privs_of_role(), if(), InternalDefaultACL::is_grant, lappend_oid(), lfirst, NIL, OBJECT_FUNCTION, OBJECT_PROCEDURE, OBJECT_ROUTINE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_TYPE, InternalDefaultACL::objtype, AccessPriv::priv_name, privilege_to_string(), InternalDefaultACL::privileges, InternalDefaultACL::roleid, ROLESPEC_PUBLIC, RoleSpec::roletype, SetDefaultACLsInSchemas(), stmt, and string_to_privilege().

Referenced by ProcessUtilitySlow().

◆ ExecuteGrantStmt()

void ExecuteGrantStmt ( GrantStmt stmt)

Definition at line 392 of file aclchk.c.

393 {
394  InternalGrant istmt;
395  ListCell *cell;
396  const char *errormsg;
397  AclMode all_privileges;
398 
399  if (stmt->grantor)
400  {
401  Oid grantor;
402 
403  grantor = get_rolespec_oid(stmt->grantor, false);
404 
405  /*
406  * Currently, this clause is only for SQL compatibility, not very
407  * interesting otherwise.
408  */
409  if (grantor != GetUserId())
410  ereport(ERROR,
411  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
412  errmsg("grantor must be current user")));
413  }
414 
415  /*
416  * Turn the regular GrantStmt into the InternalGrant form.
417  */
418  istmt.is_grant = stmt->is_grant;
419  istmt.objtype = stmt->objtype;
420 
421  /* Collect the OIDs of the target objects */
422  switch (stmt->targtype)
423  {
424  case ACL_TARGET_OBJECT:
425  istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects,
426  stmt->is_grant);
427  break;
429  istmt.objects = objectsInSchemaToOids(stmt->objtype, stmt->objects);
430  break;
431  /* ACL_TARGET_DEFAULTS should not be seen here */
432  default:
433  elog(ERROR, "unrecognized GrantStmt.targtype: %d",
434  (int) stmt->targtype);
435  }
436 
437  /* all_privs to be filled below */
438  /* privileges to be filled below */
439  istmt.col_privs = NIL; /* may get filled below */
440  istmt.grantees = NIL; /* filled below */
441  istmt.grant_option = stmt->grant_option;
442  istmt.behavior = stmt->behavior;
443 
444  /*
445  * Convert the RoleSpec list into an Oid list. Note that at this point we
446  * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
447  * there shouldn't be any additional work needed to support this case.
448  */
449  foreach(cell, stmt->grantees)
450  {
451  RoleSpec *grantee = (RoleSpec *) lfirst(cell);
452  Oid grantee_uid;
453 
454  switch (grantee->roletype)
455  {
456  case ROLESPEC_PUBLIC:
457  grantee_uid = ACL_ID_PUBLIC;
458  break;
459  default:
460  grantee_uid = get_rolespec_oid(grantee, false);
461  break;
462  }
463  istmt.grantees = lappend_oid(istmt.grantees, grantee_uid);
464  }
465 
466  /*
467  * Convert stmt->privileges, a list of AccessPriv nodes, into an AclMode
468  * bitmask. Note: objtype can't be OBJECT_COLUMN.
469  */
470  switch (stmt->objtype)
471  {
472  case OBJECT_TABLE:
473 
474  /*
475  * Because this might be a sequence, we test both relation and
476  * sequence bits, and later do a more limited test when we know
477  * the object type.
478  */
480  errormsg = gettext_noop("invalid privilege type %s for relation");
481  break;
482  case OBJECT_SEQUENCE:
483  all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
484  errormsg = gettext_noop("invalid privilege type %s for sequence");
485  break;
486  case OBJECT_DATABASE:
487  all_privileges = ACL_ALL_RIGHTS_DATABASE;
488  errormsg = gettext_noop("invalid privilege type %s for database");
489  break;
490  case OBJECT_DOMAIN:
491  all_privileges = ACL_ALL_RIGHTS_TYPE;
492  errormsg = gettext_noop("invalid privilege type %s for domain");
493  break;
494  case OBJECT_FUNCTION:
495  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
496  errormsg = gettext_noop("invalid privilege type %s for function");
497  break;
498  case OBJECT_LANGUAGE:
499  all_privileges = ACL_ALL_RIGHTS_LANGUAGE;
500  errormsg = gettext_noop("invalid privilege type %s for language");
501  break;
502  case OBJECT_LARGEOBJECT:
503  all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
504  errormsg = gettext_noop("invalid privilege type %s for large object");
505  break;
506  case OBJECT_SCHEMA:
507  all_privileges = ACL_ALL_RIGHTS_SCHEMA;
508  errormsg = gettext_noop("invalid privilege type %s for schema");
509  break;
510  case OBJECT_PROCEDURE:
511  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
512  errormsg = gettext_noop("invalid privilege type %s for procedure");
513  break;
514  case OBJECT_ROUTINE:
515  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
516  errormsg = gettext_noop("invalid privilege type %s for routine");
517  break;
518  case OBJECT_TABLESPACE:
519  all_privileges = ACL_ALL_RIGHTS_TABLESPACE;
520  errormsg = gettext_noop("invalid privilege type %s for tablespace");
521  break;
522  case OBJECT_TYPE:
523  all_privileges = ACL_ALL_RIGHTS_TYPE;
524  errormsg = gettext_noop("invalid privilege type %s for type");
525  break;
526  case OBJECT_FDW:
527  all_privileges = ACL_ALL_RIGHTS_FDW;
528  errormsg = gettext_noop("invalid privilege type %s for foreign-data wrapper");
529  break;
531  all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
532  errormsg = gettext_noop("invalid privilege type %s for foreign server");
533  break;
535  all_privileges = ACL_ALL_RIGHTS_PARAMETER_ACL;
536  errormsg = gettext_noop("invalid privilege type %s for parameter");
537  break;
538  default:
539  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
540  (int) stmt->objtype);
541  /* keep compiler quiet */
542  all_privileges = ACL_NO_RIGHTS;
543  errormsg = NULL;
544  }
545 
546  if (stmt->privileges == NIL)
547  {
548  istmt.all_privs = true;
549 
550  /*
551  * will be turned into ACL_ALL_RIGHTS_* by the internal routines
552  * depending on the object type
553  */
554  istmt.privileges = ACL_NO_RIGHTS;
555  }
556  else
557  {
558  istmt.all_privs = false;
559  istmt.privileges = ACL_NO_RIGHTS;
560 
561  foreach(cell, stmt->privileges)
562  {
563  AccessPriv *privnode = (AccessPriv *) lfirst(cell);
564  AclMode priv;
565 
566  /*
567  * If it's a column-level specification, we just set it aside in
568  * col_privs for the moment; but insist it's for a relation.
569  */
570  if (privnode->cols)
571  {
572  if (stmt->objtype != OBJECT_TABLE)
573  ereport(ERROR,
574  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
575  errmsg("column privileges are only valid for relations")));
576  istmt.col_privs = lappend(istmt.col_privs, privnode);
577  continue;
578  }
579 
580  if (privnode->priv_name == NULL) /* parser mistake? */
581  elog(ERROR, "AccessPriv node must specify privilege or columns");
582  priv = string_to_privilege(privnode->priv_name);
583 
584  if (priv & ~((AclMode) all_privileges))
585  ereport(ERROR,
586  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
587  errmsg(errormsg, privilege_to_string(priv))));
588 
589  istmt.privileges |= priv;
590  }
591  }
592 
593  ExecGrantStmt_oids(&istmt);
594 }
static void ExecGrantStmt_oids(InternalGrant *istmt)
Definition: aclchk.c:602
static List * objectNamesToOids(ObjectType objtype, List *objnames, bool is_grant)
Definition: aclchk.c:669
static List * objectsInSchemaToOids(ObjectType objtype, List *nspnames)
Definition: aclchk.c:849
List * lappend(List *list, void *datum)
Definition: list.c:339
@ ACL_TARGET_OBJECT
Definition: parsenodes.h:2486
@ ACL_TARGET_ALL_IN_SCHEMA
Definition: parsenodes.h:2487
DropBehavior behavior
AclMode privileges
ObjectType objtype

References ACL_ALL_RIGHTS_DATABASE, ACL_ALL_RIGHTS_FDW, ACL_ALL_RIGHTS_FOREIGN_SERVER, ACL_ALL_RIGHTS_FUNCTION, ACL_ALL_RIGHTS_LANGUAGE, ACL_ALL_RIGHTS_LARGEOBJECT, ACL_ALL_RIGHTS_PARAMETER_ACL, ACL_ALL_RIGHTS_RELATION, ACL_ALL_RIGHTS_SCHEMA, ACL_ALL_RIGHTS_SEQUENCE, ACL_ALL_RIGHTS_TABLESPACE, ACL_ALL_RIGHTS_TYPE, ACL_ID_PUBLIC, ACL_NO_RIGHTS, ACL_TARGET_ALL_IN_SCHEMA, ACL_TARGET_OBJECT, InternalGrant::all_privs, InternalGrant::behavior, InternalGrant::col_privs, AccessPriv::cols, elog, ereport, errcode(), errmsg(), ERROR, ExecGrantStmt_oids(), get_rolespec_oid(), gettext_noop, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, InternalGrant::is_grant, lappend(), lappend_oid(), lfirst, NIL, OBJECT_DATABASE, OBJECT_DOMAIN, OBJECT_FDW, OBJECT_FOREIGN_SERVER, OBJECT_FUNCTION, OBJECT_LANGUAGE, OBJECT_LARGEOBJECT, OBJECT_PARAMETER_ACL, OBJECT_PROCEDURE, OBJECT_ROUTINE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_TABLESPACE, OBJECT_TYPE, objectNamesToOids(), InternalGrant::objects, objectsInSchemaToOids(), InternalGrant::objtype, AccessPriv::priv_name, privilege_to_string(), InternalGrant::privileges, ROLESPEC_PUBLIC, RoleSpec::roletype, stmt, and string_to_privilege().

Referenced by ProcessUtilitySlow(), and standard_ProcessUtility().

◆ get_role_oid()

Oid get_role_oid ( const char *  rolname,
bool  missing_ok 
)

Definition at line 5554 of file acl.c.

5555 {
5556  Oid oid;
5557 
5558  oid = GetSysCacheOid1(AUTHNAME, Anum_pg_authid_oid,
5560  if (!OidIsValid(oid) && !missing_ok)
5561  ereport(ERROR,
5562  (errcode(ERRCODE_UNDEFINED_OBJECT),
5563  errmsg("role \"%s\" does not exist", rolname)));
5564  return oid;
5565 }
#define OidIsValid(objectId)
Definition: c.h:766
NameData rolname
Definition: pg_authid.h:34
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition: syscache.h:109

References CStringGetDatum(), ereport, errcode(), errmsg(), ERROR, GetSysCacheOid1, OidIsValid, and rolname.

Referenced by aclparse(), check_hba(), check_ident_usermap(), createdb(), CreateRole(), get_object_address_unqualified(), get_role_oid_or_public(), get_rolespec_oid(), GrantRole(), is_member(), pg_has_role_id_name(), pg_has_role_name(), pg_has_role_name_id(), pg_has_role_name_name(), regrolein(), shell_check_detail(), and worker_spi_launch().

◆ get_role_oid_or_public()

◆ get_rolespec_name()

char* get_rolespec_name ( const RoleSpec role)

Definition at line 5673 of file acl.c.

5674 {
5675  HeapTuple tp;
5676  Form_pg_authid authForm;
5677  char *rolename;
5678 
5679  tp = get_rolespec_tuple(role);
5680  authForm = (Form_pg_authid) GETSTRUCT(tp);
5681  rolename = pstrdup(NameStr(authForm->rolname));
5682  ReleaseSysCache(tp);
5683 
5684  return rolename;
5685 }
HeapTuple get_rolespec_tuple(const RoleSpec *role)
Definition: acl.c:5627
#define NameStr(name)
Definition: c.h:737
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
char * pstrdup(const char *in)
Definition: mcxt.c:1696
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269

References get_rolespec_tuple(), GETSTRUCT, NameStr, pstrdup(), and ReleaseSysCache().

Referenced by AddRoleMems(), and DelRoleMems().

◆ get_rolespec_oid()

Oid get_rolespec_oid ( const RoleSpec role,
bool  missing_ok 
)

Definition at line 5588 of file acl.c.

5589 {
5590  Oid oid;
5591 
5592  switch (role->roletype)
5593  {
5594  case ROLESPEC_CSTRING:
5595  Assert(role->rolename);
5596  oid = get_role_oid(role->rolename, missing_ok);
5597  break;
5598 
5599  case ROLESPEC_CURRENT_ROLE:
5600  case ROLESPEC_CURRENT_USER:
5601  oid = GetUserId();
5602  break;
5603 
5604  case ROLESPEC_SESSION_USER:
5605  oid = GetSessionUserId();
5606  break;
5607 
5608  case ROLESPEC_PUBLIC:
5609  ereport(ERROR,
5610  (errcode(ERRCODE_UNDEFINED_OBJECT),
5611  errmsg("role \"%s\" does not exist", "public")));
5612  oid = InvalidOid; /* make compiler happy */
5613  break;
5614 
5615  default:
5616  elog(ERROR, "unexpected role type %d", role->roletype);
5617  }
5618 
5619  return oid;
5620 }
Oid GetSessionUserId(void)
Definition: miscinit.c:548
@ ROLESPEC_CURRENT_USER
Definition: parsenodes.h:398
@ ROLESPEC_SESSION_USER
Definition: parsenodes.h:399
@ ROLESPEC_CURRENT_ROLE
Definition: parsenodes.h:397
#define InvalidOid
Definition: postgres_ext.h:36

References Assert, elog, ereport, errcode(), errmsg(), ERROR, get_role_oid(), GetSessionUserId(), GetUserId(), InvalidOid, RoleSpec::rolename, ROLESPEC_CSTRING, ROLESPEC_CURRENT_ROLE, ROLESPEC_CURRENT_USER, ROLESPEC_PUBLIC, ROLESPEC_SESSION_USER, and RoleSpec::roletype.

Referenced by AlterUserMapping(), ATExecCmd(), CreateSchemaCommand(), CreateTableSpace(), CreateUserMapping(), ExecAlterDefaultPrivilegesStmt(), ExecAlterOwnerStmt(), ExecuteGrantStmt(), GrantRole(), policy_role_list_to_array(), ReassignOwnedObjects(), RemoveUserMapping(), and roleSpecsToIds().

◆ get_rolespec_tuple()

HeapTuple get_rolespec_tuple ( const RoleSpec role)

Definition at line 5627 of file acl.c.

5628 {
5629  HeapTuple tuple;
5630 
5631  switch (role->roletype)
5632  {
5633  case ROLESPEC_CSTRING:
5634  Assert(role->rolename);
5635  tuple = SearchSysCache1(AUTHNAME, CStringGetDatum(role->rolename));
5636  if (!HeapTupleIsValid(tuple))
5637  ereport(ERROR,
5638  (errcode(ERRCODE_UNDEFINED_OBJECT),
5639  errmsg("role \"%s\" does not exist", role->rolename)));
5640  break;
5641 
5642  case ROLESPEC_CURRENT_ROLE:
5643  case ROLESPEC_CURRENT_USER:
5644  tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(GetUserId()));
5645  if (!HeapTupleIsValid(tuple))
5646  elog(ERROR, "cache lookup failed for role %u", GetUserId());
5647  break;
5648 
5649  case ROLESPEC_SESSION_USER:
5650  tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(GetSessionUserId()));
5651  if (!HeapTupleIsValid(tuple))
5652  elog(ERROR, "cache lookup failed for role %u", GetSessionUserId());
5653  break;
5654 
5655  case ROLESPEC_PUBLIC:
5656  ereport(ERROR,
5657  (errcode(ERRCODE_UNDEFINED_OBJECT),
5658  errmsg("role \"%s\" does not exist", "public")));
5659  tuple = NULL; /* make compiler happy */
5660  break;
5661 
5662  default:
5663  elog(ERROR, "unexpected role type %d", role->roletype);
5664  }
5665 
5666  return tuple;
5667 }
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221

References Assert, CStringGetDatum(), elog, ereport, errcode(), errmsg(), ERROR, GetSessionUserId(), GetUserId(), HeapTupleIsValid, ObjectIdGetDatum(), RoleSpec::rolename, ROLESPEC_CSTRING, ROLESPEC_CURRENT_ROLE, ROLESPEC_CURRENT_USER, ROLESPEC_PUBLIC, ROLESPEC_SESSION_USER, RoleSpec::roletype, and SearchSysCache1().

Referenced by AlterRole(), AlterRoleSet(), CreateRole(), and get_rolespec_name().

◆ get_user_default_acl()

Acl* get_user_default_acl ( ObjectType  objtype,
Oid  ownerId,
Oid  nsp_oid 
)

Definition at line 4304 of file aclchk.c.

4305 {
4306  Acl *result;
4307  Acl *glob_acl;
4308  Acl *schema_acl;
4309  Acl *def_acl;
4310  char defaclobjtype;
4311 
4312  /*
4313  * Use NULL during bootstrap, since pg_default_acl probably isn't there
4314  * yet.
4315  */
4317  return NULL;
4318 
4319  /* Check if object type is supported in pg_default_acl */
4320  switch (objtype)
4321  {
4322  case OBJECT_TABLE:
4323  defaclobjtype = DEFACLOBJ_RELATION;
4324  break;
4325 
4326  case OBJECT_SEQUENCE:
4327  defaclobjtype = DEFACLOBJ_SEQUENCE;
4328  break;
4329 
4330  case OBJECT_FUNCTION:
4331  defaclobjtype = DEFACLOBJ_FUNCTION;
4332  break;
4333 
4334  case OBJECT_TYPE:
4335  defaclobjtype = DEFACLOBJ_TYPE;
4336  break;
4337 
4338  case OBJECT_SCHEMA:
4339  defaclobjtype = DEFACLOBJ_NAMESPACE;
4340  break;
4341 
4342  default:
4343  return NULL;
4344  }
4345 
4346  /* Look up the relevant pg_default_acl entries */
4347  glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
4348  schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);
4349 
4350  /* Quick out if neither entry exists */
4351  if (glob_acl == NULL && schema_acl == NULL)
4352  return NULL;
4353 
4354  /* We need to know the hard-wired default value, too */
4355  def_acl = acldefault(objtype, ownerId);
4356 
4357  /* If there's no global entry, substitute the hard-wired default */
4358  if (glob_acl == NULL)
4359  glob_acl = def_acl;
4360 
4361  /* Merge in any per-schema privileges */
4362  result = aclmerge(glob_acl, schema_acl, ownerId);
4363 
4364  /*
4365  * For efficiency, we want to return NULL if the result equals default.
4366  * This requires sorting both arrays to get an accurate comparison.
4367  */
4368  aclitemsort(result);
4369  aclitemsort(def_acl);
4370  if (aclequal(result, def_acl))
4371  result = NULL;
4372 
4373  return result;
4374 }
bool aclequal(const Acl *left_acl, const Acl *right_acl)
Definition: acl.c:543
void aclitemsort(Acl *acl)
Definition: acl.c:529
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:787
Acl * aclmerge(const Acl *left_acl, const Acl *right_acl, Oid ownerId)
Definition: acl.c:485
static Acl * get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
Definition: aclchk.c:4269
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:451

References acldefault(), aclequal(), aclitemsort(), aclmerge(), get_default_acl_internal(), InvalidOid, IsBootstrapProcessingMode, OBJECT_FUNCTION, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, and OBJECT_TYPE.

Referenced by heap_create_with_catalog(), NamespaceCreate(), ProcedureCreate(), and TypeCreate().

◆ has_bypassrls_privilege()

bool has_bypassrls_privilege ( Oid  roleid)

Definition at line 4245 of file aclchk.c.

4246 {
4247  bool result = false;
4248  HeapTuple utup;
4249 
4250  /* Superusers bypass all permission checking. */
4251  if (superuser_arg(roleid))
4252  return true;
4253 
4254  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
4255  if (HeapTupleIsValid(utup))
4256  {
4257  result = ((Form_pg_authid) GETSTRUCT(utup))->rolbypassrls;
4258  ReleaseSysCache(utup);
4259  }
4260  return result;
4261 }
bool rolbypassrls
Definition: pg_authid.h:41
bool superuser_arg(Oid roleid)
Definition: superuser.c:56

References GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum(), ReleaseSysCache(), rolbypassrls, SearchSysCache1(), and superuser_arg().

Referenced by AlterRole(), check_enable_rls(), CreateRole(), and RI_Initial_Check().

◆ has_createrole_privilege()

bool has_createrole_privilege ( Oid  roleid)

Definition at line 4226 of file aclchk.c.

4227 {
4228  bool result = false;
4229  HeapTuple utup;
4230 
4231  /* Superusers bypass all permission checking. */
4232  if (superuser_arg(roleid))
4233  return true;
4234 
4235  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
4236  if (HeapTupleIsValid(utup))
4237  {
4238  result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
4239  ReleaseSysCache(utup);
4240  }
4241  return result;
4242 }
bool rolcreaterole
Definition: pg_authid.h:37

References GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum(), ReleaseSysCache(), rolcreaterole, SearchSysCache1(), and superuser_arg().

Referenced by check_object_ownership(), CreateRole(), and have_createrole_privilege().

◆ has_privs_of_role()

bool has_privs_of_role ( Oid  member,
Oid  role 
)

Definition at line 5268 of file acl.c.

5269 {
5270  /* Fast path for simple case */
5271  if (member == role)
5272  return true;
5273 
5274  /* Superusers have every privilege, so are part of every role */
5275  if (superuser_arg(member))
5276  return true;
5277 
5278  /*
5279  * Find all the roles that member has the privileges of, including
5280  * multi-level recursion, then see if target role is any one of them.
5281  */
5283  InvalidOid, NULL),
5284  role);
5285 }
@ ROLERECURSE_PRIVS
Definition: acl.c:78
static List * roles_is_member_of(Oid roleid, enum RoleRecurseType type, Oid admin_of, Oid *admin_role)
Definition: acl.c:5136
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:722

References InvalidOid, list_member_oid(), ROLERECURSE_PRIVS, roles_is_member_of(), and superuser_arg().

Referenced by aclmask(), AlterObjectNamespace_internal(), AlterObjectOwner_internal(), AlterObjectRename_internal(), bbsink_server_new(), calculate_database_size(), calculate_tablespace_size(), check_role_for_policy(), check_role_grantor(), ConfigOptionIsVisible(), convert_and_check_filename(), CreateSubscription(), DoCopy(), DropOwnedObjects(), ExecAlterDefaultPrivilegesStmt(), file_fdw_validator(), GetConfigOptionValues(), InitPostgres(), object_ownercheck(), pg_class_aclmask_ext(), pg_namespace_aclmask_ext(), pg_role_aclcheck(), pg_signal_backend(), pg_stat_get_wal_receiver(), pg_stat_get_wal_senders(), pg_stat_statements_internal(), pgrowlocks(), ReassignOwnedObjects(), ReindexMultipleTables(), shell_check_detail(), standard_ProcessUtility(), and TerminateOtherDBBackends().

◆ initialize_acl()

void initialize_acl ( void  )

Definition at line 5024 of file acl.c.

5025 {
5027  {
5028  cached_db_hash =
5029  GetSysCacheHashValue1(DATABASEOID,
5031 
5032  /*
5033  * In normal mode, set a callback on any syscache invalidation of rows
5034  * of pg_auth_members (for roles_is_member_of()) pg_database (for
5035  * roles_is_member_of())
5036  */
5037  CacheRegisterSyscacheCallback(AUTHMEMROLEMEM,
5039  (Datum) 0);
5042  (Datum) 0);
5043  CacheRegisterSyscacheCallback(DATABASEOID,
5045  (Datum) 0);
5046  }
5047 }
static uint32 cached_db_hash
Definition: acl.c:83
static void RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: acl.c:5054
Oid MyDatabaseId
Definition: globals.c:93
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1516
uintptr_t Datum
Definition: postgres.h:64
#define GetSysCacheHashValue1(cacheId, key1)
Definition: syscache.h:118

References cached_db_hash, CacheRegisterSyscacheCallback(), GetSysCacheHashValue1, IsBootstrapProcessingMode, MyDatabaseId, ObjectIdGetDatum(), and RoleMembershipCacheCallback().

Referenced by InitPostgres().

◆ is_admin_of_role()

bool is_admin_of_role ( Oid  member,
Oid  role 
)

Definition at line 5398 of file acl.c.

5399 {
5400  Oid admin_role;
5401 
5402  if (superuser_arg(member))
5403  return true;
5404 
5405  /* By policy, a role cannot have WITH ADMIN OPTION on itself. */
5406  if (member == role)
5407  return false;
5408 
5409  (void) roles_is_member_of(member, ROLERECURSE_MEMBERS, role, &admin_role);
5410  return OidIsValid(admin_role);
5411 }
@ ROLERECURSE_MEMBERS
Definition: acl.c:77

References OidIsValid, ROLERECURSE_MEMBERS, roles_is_member_of(), and superuser_arg().

Referenced by AlterRole(), AlterRoleSet(), check_object_ownership(), check_role_membership_authorization(), DropRole(), pg_role_aclcheck(), and RenameRole().

◆ is_member_of_role()

bool is_member_of_role ( Oid  member,
Oid  role 
)

Definition at line 5348 of file acl.c.

5349 {
5350  /* Fast path for simple case */
5351  if (member == role)
5352  return true;
5353 
5354  /* Superusers have every privilege, so are part of every role */
5355  if (superuser_arg(member))
5356  return true;
5357 
5358  /*
5359  * Find all the roles that member is a member of, including multi-level
5360  * recursion, then see if target role is any one of them.
5361  */
5363  InvalidOid, NULL),
5364  role);
5365 }

References InvalidOid, list_member_oid(), ROLERECURSE_MEMBERS, roles_is_member_of(), and superuser_arg().

Referenced by pg_role_aclcheck().

◆ is_member_of_role_nosuper()

bool is_member_of_role_nosuper ( Oid  member,
Oid  role 
)

Definition at line 5376 of file acl.c.

5377 {
5378  /* Fast path for simple case */
5379  if (member == role)
5380  return true;
5381 
5382  /*
5383  * Find all the roles that member is a member of, including multi-level
5384  * recursion, then see if target role is any one of them.
5385  */
5387  InvalidOid, NULL),
5388  role);
5389 }

References InvalidOid, list_member_oid(), ROLERECURSE_MEMBERS, and roles_is_member_of().

Referenced by AddRoleMems(), and is_member().

◆ make_empty_acl()

Acl* make_empty_acl ( void  )

Definition at line 432 of file acl.c.

433 {
434  return allocacl(0);
435 }

References allocacl().

Referenced by SetDefaultACL().

◆ member_can_set_role()

bool member_can_set_role ( Oid  member,
Oid  role 
)

Definition at line 5302 of file acl.c.

5303 {
5304  /* Fast path for simple case */
5305  if (member == role)
5306  return true;
5307 
5308  /* Superusers have every privilege, so can always SET ROLE */
5309  if (superuser_arg(member))
5310  return true;
5311 
5312  /*
5313  * Find all the roles that member can access via SET ROLE, including
5314  * multi-level recursion, then see if target role is any one of them.
5315  */
5317  InvalidOid, NULL),
5318  role);
5319 }
@ ROLERECURSE_SETROLE
Definition: acl.c:79

References InvalidOid, list_member_oid(), ROLERECURSE_SETROLE, roles_is_member_of(), and superuser_arg().

Referenced by check_can_set_role(), check_role(), pg_role_aclcheck(), and SwitchToUntrustedUser().

◆ object_aclcheck()

AclResult object_aclcheck ( Oid  classid,
Oid  objectid,
Oid  roleid,
AclMode  mode 
)

Definition at line 3891 of file aclchk.c.

3892 {
3893  return object_aclcheck_ext(classid, objectid, roleid, mode, NULL);
3894 }
AclResult object_aclcheck_ext(Oid classid, Oid objectid, Oid roleid, AclMode mode, bool *is_missing)
Definition: aclchk.c:3901
static PgChecksumMode mode
Definition: pg_checksums.c:56

References mode, and object_aclcheck_ext().

Referenced by AggregateCreate(), AlterExtensionNamespace(), AlterForeignServerOwner_internal(), AlterObjectNamespace_internal(), AlterObjectOwner_internal(), AlterObjectRename_internal(), AlterPublicationOwner_internal(), AlterSchemaOwner_internal(), AlterSubscriptionOwner_internal(), AlterTableMoveAll(), AlterTypeOwner(), ATExecChangeOwner(), ATPrepAlterColumnType(), ATPrepSetTableSpace(), BuildDescForRelation(), calculate_database_size(), calculate_tablespace_size(), call_pltcl_start_proc(), check_temp_tablespaces(), CheckFunctionValidatorAccess(), CheckMyDatabase(), compute_return_type(), CreateCast(), CreateConversionCommand(), createdb(), CreateForeignServer(), CreateForeignTable(), CreateFunction(), CreatePublication(), CreateSchemaCommand(), CreateSubscription(), CreateTransform(), CreateTriggerFiringOn(), DefineAggregate(), DefineCollation(), DefineDomain(), DefineEnum(), DefineIndex(), DefineOpClass(), DefineOperator(), DefineOpFamily(), DefineRange(), DefineRelation(), DefineTSConfiguration(), DefineTSDictionary(), DefineType(), ExecBuildGroupingEqual(), ExecBuildParamSetEqual(), ExecInitAgg(), ExecInitExprRec(), ExecInitFunc(), ExecInitWindowAgg(), ExecReindex(), ExecuteCallStmt(), ExecuteDoStmt(), extension_is_trusted(), findRangeCanonicalFunction(), findRangeSubtypeDiffFunction(), get_connect_string(), get_other_operator(), HandleFunctionRequest(), has_database_privilege_id_name(), has_database_privilege_name(), has_database_privilege_name_name(), has_foreign_data_wrapper_privilege_id_name(), has_foreign_data_wrapper_privilege_name(), has_foreign_data_wrapper_privilege_name_name(), has_function_privilege_id_name(), has_function_privilege_name(), has_function_privilege_name_name(), has_language_privilege_id_name(), has_language_privilege_name(), has_language_privilege_name_name(), has_schema_privilege_id_name(), has_schema_privilege_name(), has_schema_privilege_name_name(), has_server_privilege_id_name(), has_server_privilege_name(), has_server_privilege_name_name(), has_tablespace_privilege_id_name(), has_tablespace_privilege_name(), has_tablespace_privilege_name_name(), has_type_privilege_id_name(), has_type_privilege_name(), has_type_privilege_name_name(), ImportForeignSchema(), init_sexpr(), initialize_peragg(), InitTempTableNamespace(), inline_function(), inline_set_returning_function(), interpret_function_parameter_list(), lookup_agg_function(), LookupCreationNamespace(), LookupExplicitNamespace(), movedb(), PrepareTempTablespaces(), preprocessNamespacePath(), RangeVarCallbackForAlterRelation(), RangeVarGetAndCheckCreationNamespace(), ReindexMultipleInternal(), RenameSchema(), transformTableLikeClause(), user_mapping_ddl_aclcheck(), ValidateJoinEstimator(), and ValidateRestrictionEstimator().

◆ object_aclcheck_ext()

◆ object_ownercheck()

bool object_ownercheck ( Oid  classid,
Oid  objectid,
Oid  roleid 
)

Definition at line 4145 of file aclchk.c.

4146 {
4147  int cacheid;
4148  Oid ownerId;
4149 
4150  /* Superusers bypass all permission checking. */
4151  if (superuser_arg(roleid))
4152  return true;
4153 
4154  /* For large objects, the catalog to consult is pg_largeobject_metadata */
4155  if (classid == LargeObjectRelationId)
4156  classid = LargeObjectMetadataRelationId;
4157 
4158  cacheid = get_object_catcache_oid(classid);
4159  if (cacheid != -1)
4160  {
4161  /* we can get the object's tuple from the syscache */
4162  HeapTuple tuple;
4163 
4164  tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid));
4165  if (!HeapTupleIsValid(tuple))
4166  ereport(ERROR,
4167  (errcode(ERRCODE_UNDEFINED_OBJECT),
4168  errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid)));
4169 
4170  ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
4171  tuple,
4172  get_object_attnum_owner(classid)));
4173  ReleaseSysCache(tuple);
4174  }
4175  else
4176  {
4177  /* for catalogs without an appropriate syscache */
4178  Relation rel;
4179  ScanKeyData entry[1];
4180  SysScanDesc scan;
4181  HeapTuple tuple;
4182  bool isnull;
4183 
4184  rel = table_open(classid, AccessShareLock);
4185 
4186  ScanKeyInit(&entry[0],
4187  get_object_attnum_oid(classid),
4188  BTEqualStrategyNumber, F_OIDEQ,
4189  ObjectIdGetDatum(objectid));
4190 
4191  scan = systable_beginscan(rel,
4192  get_object_oid_index(classid), true,
4193  NULL, 1, entry);
4194 
4195  tuple = systable_getnext(scan);
4196  if (!HeapTupleIsValid(tuple))
4197  ereport(ERROR,
4198  (errcode(ERRCODE_UNDEFINED_OBJECT),
4199  errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid)));
4200 
4201  ownerId = DatumGetObjectId(heap_getattr(tuple,
4202  get_object_attnum_owner(classid),
4203  RelationGetDescr(rel),
4204  &isnull));
4205  Assert(!isnull);
4206 
4207  systable_endscan(scan);
4209  }
4210 
4211  return has_privs_of_role(roleid, ownerId);
4212 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:604
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:511
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
#define AccessShareLock
Definition: lockdefs.h:36
AttrNumber get_object_attnum_owner(Oid class_id)
AttrNumber get_object_attnum_oid(Oid class_id)
int get_object_catcache_oid(Oid class_id)
Oid get_object_oid_index(Oid class_id)
const char * get_object_class_descr(Oid class_id)
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:242
#define RelationGetDescr(relation)
Definition: rel.h:531
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:627
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

References AccessShareLock, Assert, BTEqualStrategyNumber, DatumGetObjectId(), ereport, errcode(), errmsg(), ERROR, get_object_attnum_oid(), get_object_attnum_owner(), get_object_catcache_oid(), get_object_class_descr(), get_object_oid_index(), has_privs_of_role(), heap_getattr(), HeapTupleIsValid, ObjectIdGetDatum(), RelationGetDescr, ReleaseSysCache(), ScanKeyInit(), SearchSysCache1(), superuser_arg(), SysCacheGetAttrNotNull(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by AlterCollation(), AlterDatabase(), AlterDatabaseOwner(), AlterDatabaseRefreshColl(), AlterDatabaseSet(), AlterEventTrigger(), AlterEventTriggerOwner_internal(), AlterExtensionNamespace(), AlterForeignServer(), AlterForeignServerOwner_internal(), AlterFunction(), AlterOperator(), AlterOpFamilyAdd(), AlterPublication(), AlterPublicationOwner_internal(), AlterRoleSet(), AlterSchemaOwner_internal(), AlterStatistics(), AlterSubscription(), AlterSubscriptionOwner_internal(), AlterTableMoveAll(), AlterTableSpaceOptions(), AlterTSConfiguration(), AlterTSDictionary(), AlterType(), AlterTypeNamespace_oid(), AlterTypeOwner(), ATExecChangeOwner(), ATSimplePermissions(), be_lo_unlink(), brin_desummarize_range(), brin_summarize_range(), check_enable_rls(), check_object_ownership(), checkDomainOwner(), checkEnumOwner(), CreateCast(), createdb(), CreateProceduralLanguage(), CreateStatistics(), CreateTransform(), DefineOpClass(), DefineQueryRewrite(), DefineType(), dropdb(), DropSubscription(), DropTableSpace(), EnableDisableRule(), ExecAlterExtensionContentsStmt(), ExecAlterExtensionStmt(), ExecuteTruncateGuts(), gin_clean_pending_list(), heap_force_common(), MergeAttributes(), movedb(), OperatorCreate(), ProcedureCreate(), PublicationAddTables(), RangeVarCallbackForAlterRelation(), RangeVarCallbackForDropRelation(), RangeVarCallbackForPolicy(), RangeVarCallbackForRenameRule(), RangeVarCallbackForRenameTrigger(), RangeVarCallbackOwnsRelation(), RangeVarGetAndCheckCreationNamespace(), ReindexMultipleTables(), RemoveObjects(), renameatt_check(), RenameDatabase(), RenameSchema(), RenameTableSpace(), RenameType(), RI_Initial_Check(), stats_lock_check_privileges(), user_mapping_ddl_aclcheck(), vacuum_is_permitted_for_relation(), and ValidateOperatorReference().

◆ pg_attribute_aclcheck()

AclResult pg_attribute_aclcheck ( Oid  table_oid,
AttrNumber  attnum,
Oid  roleid,
AclMode  mode 
)

Definition at line 3923 of file aclchk.c.

3925 {
3926  return pg_attribute_aclcheck_ext(table_oid, attnum, roleid, mode, NULL);
3927 }
AclResult pg_attribute_aclcheck_ext(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode, bool *is_missing)
Definition: aclchk.c:3935
int16 attnum
Definition: pg_attribute.h:74

References attnum, mode, and pg_attribute_aclcheck_ext().

Referenced by BuildIndexValueDescription(), checkFkeyPermissions(), examine_simple_variable(), ExecBuildSlotPartitionKeyDescription(), ExecBuildSlotValueDescription(), ExecCheckOneRelPerms(), ExecCheckPermissionsModified(), ri_ReportViolation(), and statext_is_compatible_clause().

◆ pg_attribute_aclcheck_all()

AclResult pg_attribute_aclcheck_all ( Oid  table_oid,
Oid  roleid,
AclMode  mode,
AclMaskHow  how 
)

Definition at line 3965 of file aclchk.c.

3967 {
3968  return pg_attribute_aclcheck_all_ext(table_oid, roleid, mode, how, NULL);
3969 }
AclResult pg_attribute_aclcheck_all_ext(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how, bool *is_missing)
Definition: aclchk.c:3976

References mode, and pg_attribute_aclcheck_all_ext().

Referenced by ExecCheckOneRelPerms(), ExecCheckPermissionsModified(), has_any_column_privilege_id_name(), has_any_column_privilege_name(), has_any_column_privilege_name_name(), and statext_is_compatible_clause().

◆ pg_attribute_aclcheck_all_ext()

AclResult pg_attribute_aclcheck_all_ext ( Oid  table_oid,
Oid  roleid,
AclMode  mode,
AclMaskHow  how,
bool is_missing 
)

Definition at line 3976 of file aclchk.c.

3979 {
3980  AclResult result;
3981  HeapTuple classTuple;
3982  Form_pg_class classForm;
3983  Oid ownerId;
3984  AttrNumber nattrs;
3985  AttrNumber curr_att;
3986 
3987  /*
3988  * Must fetch pg_class row to get owner ID and number of attributes.
3989  */
3990  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3991  if (!HeapTupleIsValid(classTuple))
3992  {
3993  if (is_missing != NULL)
3994  {
3995  /* return "no privileges" instead of throwing an error */
3996  *is_missing = true;
3997  return ACLCHECK_NO_PRIV;
3998  }
3999  else
4000  ereport(ERROR,
4002  errmsg("relation with OID %u does not exist",
4003  table_oid)));
4004  }
4005  classForm = (Form_pg_class) GETSTRUCT(classTuple);
4006 
4007  ownerId = classForm->relowner;
4008  nattrs = classForm->relnatts;
4009 
4010  ReleaseSysCache(classTuple);
4011 
4012  /*
4013  * Initialize result in case there are no non-dropped columns. We want to
4014  * report failure in such cases for either value of 'how'.
4015  */
4016  result = ACLCHECK_NO_PRIV;
4017 
4018  for (curr_att = 1; curr_att <= nattrs; curr_att++)
4019  {
4020  HeapTuple attTuple;
4021  Datum aclDatum;
4022  bool isNull;
4023  Acl *acl;
4024  AclMode attmask;
4025 
4026  attTuple = SearchSysCache2(ATTNUM,
4027  ObjectIdGetDatum(table_oid),
4028  Int16GetDatum(curr_att));
4029 
4030  /*
4031  * Lookup failure probably indicates that the table was just dropped,
4032  * but we'll treat it the same as a dropped column rather than
4033  * throwing error.
4034  */
4035  if (!HeapTupleIsValid(attTuple))
4036  continue;
4037 
4038  /* ignore dropped columns */
4039  if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
4040  {
4041  ReleaseSysCache(attTuple);
4042  continue;
4043  }
4044 
4045  aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
4046  &isNull);
4047 
4048  /*
4049  * Here we hard-wire knowledge that the default ACL for a column
4050  * grants no privileges, so that we can fall out quickly in the very
4051  * common case where attacl is null.
4052  */
4053  if (isNull)
4054  attmask = 0;
4055  else
4056  {
4057  /* detoast column's ACL if necessary */
4058  acl = DatumGetAclP(aclDatum);
4059 
4060  attmask = aclmask(acl, roleid, ownerId, mode, ACLMASK_ANY);
4061 
4062  /* if we have a detoasted copy, free it */
4063  if ((Pointer) acl != DatumGetPointer(aclDatum))
4064  pfree(acl);
4065  }
4066 
4067  ReleaseSysCache(attTuple);
4068 
4069  if (attmask != 0)
4070  {
4071  result = ACLCHECK_OK;
4072  if (how == ACLMASK_ANY)
4073  break; /* succeed on any success */
4074  }
4075  else
4076  {
4077  result = ACLCHECK_NO_PRIV;
4078  if (how == ACLMASK_ALL)
4079  break; /* fail on any failure */
4080  }
4081  }
4082 
4083  return result;
4084 }
AclMode aclmask(const Acl *acl, Oid roleid, Oid ownerId, AclMode mask, AclMaskHow how)
Definition: acl.c:1372
#define DatumGetAclP(X)
Definition: acl.h:120
int16 AttrNumber
Definition: attnum.h:21
char * Pointer
Definition: c.h:486
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:78
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:172
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:596
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:232

References ACLCHECK_NO_PRIV, ACLCHECK_OK, aclmask(), ACLMASK_ALL, ACLMASK_ANY, DatumGetAclP, DatumGetPointer(), ereport, errcode(), ERRCODE_UNDEFINED_TABLE, errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, Int16GetDatum(), mode, ObjectIdGetDatum(), pfree(), ReleaseSysCache(), SearchSysCache1(), SearchSysCache2(), and SysCacheGetAttr().

Referenced by has_any_column_privilege_id(), has_any_column_privilege_id_id(), has_any_column_privilege_name_id(), and pg_attribute_aclcheck_all().

◆ pg_attribute_aclcheck_ext()

AclResult pg_attribute_aclcheck_ext ( Oid  table_oid,
AttrNumber  attnum,
Oid  roleid,
AclMode  mode,
bool is_missing 
)

Definition at line 3935 of file aclchk.c.

3937 {
3938  if (pg_attribute_aclmask_ext(table_oid, attnum, roleid, mode,
3939  ACLMASK_ANY, is_missing) != 0)
3940  return ACLCHECK_OK;
3941  else
3942  return ACLCHECK_NO_PRIV;
3943 }
static AclMode pg_attribute_aclmask_ext(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
Definition: aclchk.c:3213

References ACLCHECK_NO_PRIV, ACLCHECK_OK, ACLMASK_ANY, attnum, mode, and pg_attribute_aclmask_ext().

Referenced by column_privilege_check(), and pg_attribute_aclcheck().

◆ pg_class_aclcheck()

◆ pg_class_aclcheck_ext()

AclResult pg_class_aclcheck_ext ( Oid  table_oid,
Oid  roleid,
AclMode  mode,
bool is_missing 
)

Definition at line 4104 of file aclchk.c.

4106 {
4107  if (pg_class_aclmask_ext(table_oid, roleid, mode,
4108  ACLMASK_ANY, is_missing) != 0)
4109  return ACLCHECK_OK;
4110  else
4111  return ACLCHECK_NO_PRIV;
4112 }
static AclMode pg_class_aclmask_ext(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
Definition: aclchk.c:3337

References ACLCHECK_NO_PRIV, ACLCHECK_OK, ACLMASK_ANY, mode, and pg_class_aclmask_ext().

Referenced by column_privilege_check(), has_any_column_privilege_id(), has_any_column_privilege_id_id(), has_any_column_privilege_name_id(), has_sequence_privilege_id(), has_sequence_privilege_id_id(), has_sequence_privilege_name_id(), has_table_privilege_id(), has_table_privilege_id_id(), has_table_privilege_name_id(), and pg_class_aclcheck().

◆ pg_class_aclmask()

AclMode pg_class_aclmask ( Oid  table_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 3327 of file aclchk.c.

3329 {
3330  return pg_class_aclmask_ext(table_oid, roleid, mask, how, NULL);
3331 }

References pg_class_aclmask_ext().

Referenced by ExecCheckOneRelPerms(), and pg_aclmask().

◆ pg_largeobject_aclcheck_snapshot()

AclResult pg_largeobject_aclcheck_snapshot ( Oid  lobj_oid,
Oid  roleid,
AclMode  mode,
Snapshot  snapshot 
)

Definition at line 4131 of file aclchk.c.

4133 {
4134  if (pg_largeobject_aclmask_snapshot(lobj_oid, roleid, mode,
4135  ACLMASK_ANY, snapshot) != 0)
4136  return ACLCHECK_OK;
4137  else
4138  return ACLCHECK_NO_PRIV;
4139 }
static AclMode pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid, AclMode mask, AclMaskHow how, Snapshot snapshot)
Definition: aclchk.c:3590

References ACLCHECK_NO_PRIV, ACLCHECK_OK, ACLMASK_ANY, mode, and pg_largeobject_aclmask_snapshot().

Referenced by has_lo_priv_byid(), and inv_open().

◆ pg_parameter_aclcheck()

AclResult pg_parameter_aclcheck ( const char *  name,
Oid  roleid,
AclMode  mode 
)

Definition at line 4119 of file aclchk.c.

4120 {
4121  if (pg_parameter_aclmask(name, roleid, mode, ACLMASK_ANY) != 0)
4122  return ACLCHECK_OK;
4123  else
4124  return ACLCHECK_NO_PRIV;
4125 }
static AclMode pg_parameter_aclmask(const char *name, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3467
const char * name

References ACLCHECK_NO_PRIV, ACLCHECK_OK, ACLMASK_ANY, mode, name, and pg_parameter_aclmask().

Referenced by AlterSystemSetConfigFile(), has_param_priv_byname(), set_config_with_handle(), and validate_option_array_item().

◆ recordDependencyOnNewAcl()

void recordDependencyOnNewAcl ( Oid  classId,
Oid  objectId,
int32  objsubId,
Oid  ownerId,
Acl acl 
)

Definition at line 4380 of file aclchk.c.

4382 {
4383  int nmembers;
4384  Oid *members;
4385 
4386  /* Nothing to do if ACL is defaulted */
4387  if (acl == NULL)
4388  return;
4389 
4390  /* Extract roles mentioned in ACL */
4391  nmembers = aclmembers(acl, &members);
4392 
4393  /* Update the shared dependency ACL info */
4394  updateAclDependencies(classId, objectId, objsubId,
4395  ownerId,
4396  0, NULL,
4397  nmembers, members);
4398 }
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1524
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:491

References aclmembers(), and updateAclDependencies().

Referenced by GenerateTypeDependencies(), heap_create_with_catalog(), NamespaceCreate(), and ProcedureCreate().

◆ recordExtObjInitPriv()

void recordExtObjInitPriv ( Oid  objoid,
Oid  classoid 
)

Definition at line 4407 of file aclchk.c.

4408 {
4409  /*
4410  * pg_class / pg_attribute
4411  *
4412  * If this is a relation then we need to see if there are any sub-objects
4413  * (eg: columns) for it and, if so, be sure to call
4414  * recordExtensionInitPrivWorker() for each one.
4415  */
4416  if (classoid == RelationRelationId)
4417  {
4418  Form_pg_class pg_class_tuple;
4419  Datum aclDatum;
4420  bool isNull;
4421  HeapTuple tuple;
4422 
4423  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
4424  if (!HeapTupleIsValid(tuple))
4425  elog(ERROR, "cache lookup failed for relation %u", objoid);
4426  pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
4427 
4428  /*
4429  * Indexes don't have permissions, neither do the pg_class rows for
4430  * composite types. (These cases are unreachable given the
4431  * restrictions in ALTER EXTENSION ADD, but let's check anyway.)
4432  */
4433  if (pg_class_tuple->relkind == RELKIND_INDEX ||
4434  pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
4435  pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
4436  {
4437  ReleaseSysCache(tuple);
4438  return;
4439  }
4440 
4441  /*
4442  * If this isn't a sequence then it's possibly going to have
4443  * column-level ACLs associated with it.
4444  */
4445  if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
4446  {
4447  AttrNumber curr_att;
4448  AttrNumber nattrs = pg_class_tuple->relnatts;
4449 
4450  for (curr_att = 1; curr_att <= nattrs; curr_att++)
4451  {
4452  HeapTuple attTuple;
4453  Datum attaclDatum;
4454 
4455  attTuple = SearchSysCache2(ATTNUM,
4456  ObjectIdGetDatum(objoid),
4457  Int16GetDatum(curr_att));
4458 
4459  if (!HeapTupleIsValid(attTuple))
4460  continue;
4461 
4462  /* ignore dropped columns */
4463  if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
4464  {
4465  ReleaseSysCache(attTuple);
4466  continue;
4467  }
4468 
4469  attaclDatum = SysCacheGetAttr(ATTNUM, attTuple,
4470  Anum_pg_attribute_attacl,
4471  &isNull);
4472 
4473  /* no need to do anything for a NULL ACL */
4474  if (isNull)
4475  {
4476  ReleaseSysCache(attTuple);
4477  continue;
4478  }
4479 
4480  recordExtensionInitPrivWorker(objoid, classoid, curr_att,
4481  DatumGetAclP(attaclDatum));
4482 
4483  ReleaseSysCache(attTuple);
4484  }
4485  }
4486 
4487  aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
4488  &isNull);
4489 
4490  /* Add the record, if any, for the top-level object */
4491  if (!isNull)
4492  recordExtensionInitPrivWorker(objoid, classoid, 0,
4493  DatumGetAclP(aclDatum));
4494 
4495  ReleaseSysCache(tuple);
4496  }
4497  else if (classoid == LargeObjectRelationId)
4498  {
4499  /* For large objects, we must consult pg_largeobject_metadata */
4500  Datum aclDatum;
4501  bool isNull;
4502  HeapTuple tuple;
4503  ScanKeyData entry[1];
4504  SysScanDesc scan;
4505  Relation relation;
4506 
4507  /*
4508  * Note: this is dead code, given that we don't allow large objects to
4509  * be made extension members. But it seems worth carrying in case
4510  * some future caller of this function has need for it.
4511  */
4512  relation = table_open(LargeObjectMetadataRelationId, RowExclusiveLock);
4513 
4514  /* There's no syscache for pg_largeobject_metadata */
4515  ScanKeyInit(&entry[0],
4516  Anum_pg_largeobject_metadata_oid,
4517  BTEqualStrategyNumber, F_OIDEQ,
4518  ObjectIdGetDatum(objoid));
4519 
4520  scan = systable_beginscan(relation,
4521  LargeObjectMetadataOidIndexId, true,
4522  NULL, 1, entry);
4523 
4524  tuple = systable_getnext(scan);
4525  if (!HeapTupleIsValid(tuple))
4526  elog(ERROR, "could not find tuple for large object %u", objoid);
4527 
4528  aclDatum = heap_getattr(tuple,
4529  Anum_pg_largeobject_metadata_lomacl,
4530  RelationGetDescr(relation), &isNull);
4531 
4532  /* Add the record, if any, for the top-level object */
4533  if (!isNull)
4534  recordExtensionInitPrivWorker(objoid, classoid, 0,
4535  DatumGetAclP(aclDatum));
4536 
4537  systable_endscan(scan);
4538  }
4539  /* This will error on unsupported classoid. */
4540  else if (get_object_attnum_acl(classoid) != InvalidAttrNumber)
4541  {
4542  int cacheid;
4543  Datum aclDatum;
4544  bool isNull;
4545  HeapTuple tuple;
4546 
4547  cacheid = get_object_catcache_oid(classoid);
4548  tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objoid));
4549  if (!HeapTupleIsValid(tuple))
4550  elog(ERROR, "cache lookup failed for %s %u",
4551  get_object_class_descr(classoid), objoid);
4552 
4553  aclDatum = SysCacheGetAttr(cacheid, tuple,
4554  get_object_attnum_acl(classoid),
4555  &isNull);
4556 
4557  /* Add the record, if any, for the top-level object */
4558  if (!isNull)
4559  recordExtensionInitPrivWorker(objoid, classoid, 0,
4560  DatumGetAclP(aclDatum));
4561 
4562  ReleaseSysCache(tuple);
4563  }
4564 }
static void recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:4683
#define InvalidAttrNumber
Definition: attnum.h:23
#define RowExclusiveLock
Definition: lockdefs.h:38
AttrNumber get_object_attnum_acl(Oid class_id)

References BTEqualStrategyNumber, DatumGetAclP, elog, ERROR, get_object_attnum_acl(), get_object_catcache_oid(), get_object_class_descr(), GETSTRUCT, heap_getattr(), HeapTupleIsValid, Int16GetDatum(), InvalidAttrNumber, ObjectIdGetDatum(), recordExtensionInitPrivWorker(), RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, ScanKeyInit(), SearchSysCache1(), SearchSysCache2(), SysCacheGetAttr(), systable_beginscan(), systable_endscan(), systable_getnext(), and table_open().

Referenced by ExecAlterExtensionContentsRecurse().

◆ removeExtObjInitPriv()

void removeExtObjInitPriv ( Oid  objoid,
Oid  classoid 
)

Definition at line 4571 of file aclchk.c.

4572 {
4573  /*
4574  * If this is a relation then we need to see if there are any sub-objects
4575  * (eg: columns) for it and, if so, be sure to call
4576  * recordExtensionInitPrivWorker() for each one.
4577  */
4578  if (classoid == RelationRelationId)
4579  {
4580  Form_pg_class pg_class_tuple;
4581  HeapTuple tuple;
4582 
4583  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
4584  if (!HeapTupleIsValid(tuple))
4585  elog(ERROR, "cache lookup failed for relation %u", objoid);
4586  pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
4587 
4588  /*
4589  * Indexes don't have permissions, neither do the pg_class rows for
4590  * composite types. (These cases are unreachable given the
4591  * restrictions in ALTER EXTENSION DROP, but let's check anyway.)
4592  */
4593  if (pg_class_tuple->relkind == RELKIND_INDEX ||
4594  pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
4595  pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
4596  {
4597  ReleaseSysCache(tuple);
4598  return;
4599  }
4600 
4601  /*
4602  * If this isn't a sequence then it's possibly going to have
4603  * column-level ACLs associated with it.
4604  */
4605  if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
4606  {
4607  AttrNumber curr_att;
4608  AttrNumber nattrs = pg_class_tuple->relnatts;
4609 
4610  for (curr_att = 1; curr_att <= nattrs; curr_att++)
4611  {
4612  HeapTuple attTuple;
4613 
4614  attTuple = SearchSysCache2(ATTNUM,
4615  ObjectIdGetDatum(objoid),
4616  Int16GetDatum(curr_att));
4617 
4618  if (!HeapTupleIsValid(attTuple))
4619  continue;
4620 
4621  /* when removing, remove all entries, even dropped columns */
4622 
4623  recordExtensionInitPrivWorker(objoid, classoid, curr_att, NULL);
4624 
4625  ReleaseSysCache(attTuple);
4626  }
4627  }
4628 
4629  ReleaseSysCache(tuple);
4630  }
4631 
4632  /* Remove the record, if any, for the top-level object */
4633  recordExtensionInitPrivWorker(objoid, classoid, 0, NULL);
4634 }

References elog, ERROR, GETSTRUCT, HeapTupleIsValid, Int16GetDatum(), ObjectIdGetDatum(), recordExtensionInitPrivWorker(), ReleaseSysCache(), SearchSysCache1(), and SearchSysCache2().

Referenced by ExecAlterExtensionContentsRecurse().

◆ RemoveRoleFromInitPriv()

void RemoveRoleFromInitPriv ( Oid  roleid,
Oid  classid,
Oid  objid,
int32  objsubid 
)

Definition at line 4920 of file aclchk.c.

4921 {
4922  Relation rel;
4923  ScanKeyData key[3];
4924  SysScanDesc scan;
4925  HeapTuple oldtuple;
4926  int cacheid;
4927  HeapTuple objtuple;
4928  Oid ownerId;
4929  Datum oldAclDatum;
4930  bool isNull;
4931  Acl *old_acl;
4932  Acl *new_acl;
4933  HeapTuple newtuple;
4934  int noldmembers;
4935  int nnewmembers;
4936  Oid *oldmembers;
4937  Oid *newmembers;
4938 
4939  /* Search for existing pg_init_privs entry for the target object. */
4940  rel = table_open(InitPrivsRelationId, RowExclusiveLock);
4941 
4942  ScanKeyInit(&key[0],
4943  Anum_pg_init_privs_objoid,
4944  BTEqualStrategyNumber, F_OIDEQ,
4945  ObjectIdGetDatum(objid));
4946  ScanKeyInit(&key[1],
4947  Anum_pg_init_privs_classoid,
4948  BTEqualStrategyNumber, F_OIDEQ,
4949  ObjectIdGetDatum(classid));
4950  ScanKeyInit(&key[2],
4951  Anum_pg_init_privs_objsubid,
4952  BTEqualStrategyNumber, F_INT4EQ,
4953  Int32GetDatum(objsubid));
4954 
4955  scan = systable_beginscan(rel, InitPrivsObjIndexId, true,
4956  NULL, 3, key);
4957 
4958  /* There should exist only one entry or none. */
4959  oldtuple = systable_getnext(scan);
4960 
4961  if (!HeapTupleIsValid(oldtuple))
4962  {
4963  /*
4964  * Hmm, why are we here if there's no entry? But pack up and go away
4965  * quietly.
4966  */
4967  systable_endscan(scan);
4969  return;
4970  }
4971 
4972  /* Get a writable copy of the existing ACL. */
4973  oldAclDatum = heap_getattr(oldtuple, Anum_pg_init_privs_initprivs,
4974  RelationGetDescr(rel), &isNull);
4975  Assert(!isNull);
4976  old_acl = DatumGetAclPCopy(oldAclDatum);
4977 
4978  /*
4979  * We need the members of both old and new ACLs so we can correct the
4980  * shared dependency information. Collect data before
4981  * merge_acl_with_grant throws away old_acl.
4982  */
4983  noldmembers = aclmembers(old_acl, &oldmembers);
4984 
4985  /* Must find out the owner's OID the hard way. */
4986  cacheid = get_object_catcache_oid(classid);
4987  objtuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objid));
4988  if (!HeapTupleIsValid(objtuple))
4989  elog(ERROR, "cache lookup failed for %s %u",
4990  get_object_class_descr(classid), objid);
4991 
4992  ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
4993  objtuple,
4994  get_object_attnum_owner(classid)));
4995  ReleaseSysCache(objtuple);
4996 
4997  /*
4998  * Generate new ACL. Grantor of rights is always the same as the owner.
4999  */
5000  if (old_acl != NULL)
5001  new_acl = merge_acl_with_grant(old_acl,
5002  false, /* is_grant */
5003  false, /* grant_option */
5004  DROP_RESTRICT,
5005  list_make1_oid(roleid),
5007  ownerId,
5008  ownerId);
5009  else
5010  new_acl = NULL; /* this case shouldn't happen, probably */
5011 
5012  /* If we end with an empty ACL, delete the pg_init_privs entry. */
5013  if (new_acl == NULL || ACL_NUM(new_acl) == 0)
5014  {
5015  CatalogTupleDelete(rel, &oldtuple->t_self);
5016  }
5017  else
5018  {
5019  Datum values[Natts_pg_init_privs] = {0};
5020  bool nulls[Natts_pg_init_privs] = {0};
5021  bool replaces[Natts_pg_init_privs] = {0};
5022 
5023  /* Update existing entry. */
5024  values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
5025  replaces[Anum_pg_init_privs_initprivs - 1] = true;
5026 
5027  newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(rel),
5028  values, nulls, replaces);
5029  CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
5030  }
5031 
5032  /*
5033  * Update the shared dependency ACL info.
5034  */
5035  nnewmembers = aclmembers(new_acl, &newmembers);
5036 
5037  updateInitAclDependencies(classid, objid, objsubid,
5038  noldmembers, oldmembers,
5039  nnewmembers, newmembers);
5040 
5041  systable_endscan(scan);
5042 
5043  /* prevent error when processing objects multiple times */
5045 
5047 }
#define ACLITEM_ALL_PRIV_BITS
Definition: acl.h:87
#define DatumGetAclPCopy(X)
Definition: acl.h:121
static Acl * merge_acl_with_grant(Acl *old_acl, bool is_grant, bool grant_option, DropBehavior behavior, List *grantees, AclMode privileges, Oid grantorId, Oid ownerId)
Definition: aclchk.c:182
static Datum values[MAXATTR]
Definition: bootstrap.c:150
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition: heaptuple.c:1209
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
#define list_make1_oid(x1)
Definition: pg_list.h:242
void updateInitAclDependencies(Oid classId, Oid objectId, int32 objsubId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:512
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
ItemPointerData t_self
Definition: htup.h:65
void CommandCounterIncrement(void)
Definition: xact.c:1099

References ACL_NUM, ACLITEM_ALL_PRIV_BITS, aclmembers(), Assert, BTEqualStrategyNumber, CatalogTupleDelete(), CatalogTupleUpdate(), CommandCounterIncrement(), DatumGetAclPCopy, DatumGetObjectId(), DROP_RESTRICT, elog, ERROR, get_object_attnum_owner(), get_object_catcache_oid(), get_object_class_descr(), heap_getattr(), heap_modify_tuple(), HeapTupleIsValid, Int32GetDatum(), sort-test::key, list_make1_oid, merge_acl_with_grant(), ObjectIdGetDatum(), PointerGetDatum(), RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, ScanKeyInit(), SearchSysCache1(), SysCacheGetAttrNotNull(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), updateInitAclDependencies(), and values.

Referenced by shdepDropOwned().

◆ RemoveRoleFromObjectACL()

void RemoveRoleFromObjectACL ( Oid  roleid,
Oid  classid,
Oid  objid 
)

Definition at line 1466 of file aclchk.c.

1467 {
1468  if (classid == DefaultAclRelationId)
1469  {
1470  InternalDefaultACL iacls;
1471  Form_pg_default_acl pg_default_acl_tuple;
1472  Relation rel;
1473  ScanKeyData skey[1];
1474  SysScanDesc scan;
1475  HeapTuple tuple;
1476 
1477  /* first fetch info needed by SetDefaultACL */
1478  rel = table_open(DefaultAclRelationId, AccessShareLock);
1479 
1480  ScanKeyInit(&skey[0],
1481  Anum_pg_default_acl_oid,
1482  BTEqualStrategyNumber, F_OIDEQ,
1483  ObjectIdGetDatum(objid));
1484 
1485  scan = systable_beginscan(rel, DefaultAclOidIndexId, true,
1486  NULL, 1, skey);
1487 
1488  tuple = systable_getnext(scan);
1489 
1490  if (!HeapTupleIsValid(tuple))
1491  elog(ERROR, "could not find tuple for default ACL %u", objid);
1492 
1493  pg_default_acl_tuple = (Form_pg_default_acl) GETSTRUCT(tuple);
1494 
1495  iacls.roleid = pg_default_acl_tuple->defaclrole;
1496  iacls.nspid = pg_default_acl_tuple->defaclnamespace;
1497 
1498  switch (pg_default_acl_tuple->defaclobjtype)
1499  {
1500  case DEFACLOBJ_RELATION:
1501  iacls.objtype = OBJECT_TABLE;
1502  break;
1503  case DEFACLOBJ_SEQUENCE:
1504  iacls.objtype = OBJECT_SEQUENCE;
1505  break;
1506  case DEFACLOBJ_FUNCTION:
1507  iacls.objtype = OBJECT_FUNCTION;
1508  break;
1509  case DEFACLOBJ_TYPE:
1510  iacls.objtype = OBJECT_TYPE;
1511  break;
1512  case DEFACLOBJ_NAMESPACE:
1513  iacls.objtype = OBJECT_SCHEMA;
1514  break;
1515  default:
1516  /* Shouldn't get here */
1517  elog(ERROR, "unexpected default ACL type: %d",
1518  (int) pg_default_acl_tuple->defaclobjtype);
1519  break;
1520  }
1521 
1522  systable_endscan(scan);
1524 
1525  iacls.is_grant = false;
1526  iacls.all_privs = true;
1527  iacls.privileges = ACL_NO_RIGHTS;
1528  iacls.grantees = list_make1_oid(roleid);
1529  iacls.grant_option = false;
1530  iacls.behavior = DROP_CASCADE;
1531 
1532  /* Do it */
1533  SetDefaultACL(&iacls);
1534  }
1535  else
1536  {
1537  InternalGrant istmt;
1538 
1539  switch (classid)
1540  {
1541  case RelationRelationId:
1542  /* it's OK to use TABLE for a sequence */
1543  istmt.objtype = OBJECT_TABLE;
1544  break;
1545  case DatabaseRelationId:
1546  istmt.objtype = OBJECT_DATABASE;
1547  break;
1548  case TypeRelationId:
1549  istmt.objtype = OBJECT_TYPE;
1550  break;
1551  case ProcedureRelationId:
1552  istmt.objtype = OBJECT_ROUTINE;
1553  break;
1554  case LanguageRelationId:
1555  istmt.objtype = OBJECT_LANGUAGE;
1556  break;
1557  case LargeObjectRelationId:
1558  istmt.objtype = OBJECT_LARGEOBJECT;
1559  break;
1560  case NamespaceRelationId:
1561  istmt.objtype = OBJECT_SCHEMA;
1562  break;
1563  case TableSpaceRelationId:
1564  istmt.objtype = OBJECT_TABLESPACE;
1565  break;
1566  case ForeignServerRelationId:
1568  break;
1569  case ForeignDataWrapperRelationId:
1570  istmt.objtype = OBJECT_FDW;
1571  break;
1572  case ParameterAclRelationId:
1573  istmt.objtype = OBJECT_PARAMETER_ACL;
1574  break;
1575  default:
1576  elog(ERROR, "unexpected object class %u", classid);
1577  break;
1578  }
1579  istmt.is_grant = false;
1580  istmt.objects = list_make1_oid(objid);
1581  istmt.all_privs = true;
1582  istmt.privileges = ACL_NO_RIGHTS;
1583  istmt.col_privs = NIL;
1584  istmt.grantees = list_make1_oid(roleid);
1585  istmt.grant_option = false;
1586  istmt.behavior = DROP_CASCADE;
1587 
1588  ExecGrantStmt_oids(&istmt);
1589  }
1590 }
static void SetDefaultACL(InternalDefaultACL *iacls)
Definition: aclchk.c:1203
@ DROP_CASCADE
Definition: parsenodes.h:2332
FormData_pg_default_acl * Form_pg_default_acl

References AccessShareLock, ACL_NO_RIGHTS, InternalDefaultACL::all_privs, InternalGrant::all_privs, InternalDefaultACL::behavior, InternalGrant::behavior, BTEqualStrategyNumber, InternalGrant::col_privs, DROP_CASCADE, elog, ERROR, ExecGrantStmt_oids(), GETSTRUCT, InternalDefaultACL::grant_option, InternalGrant::grant_option, InternalDefaultACL::grantees, InternalGrant::grantees, HeapTupleIsValid, InternalDefaultACL::is_grant, InternalGrant::is_grant, list_make1_oid, NIL, InternalDefaultACL::nspid, OBJECT_DATABASE, OBJECT_FDW, OBJECT_FOREIGN_SERVER, OBJECT_FUNCTION, OBJECT_LANGUAGE, OBJECT_LARGEOBJECT, OBJECT_PARAMETER_ACL, OBJECT_ROUTINE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_TABLESPACE, OBJECT_TYPE, ObjectIdGetDatum(), InternalGrant::objects, InternalDefaultACL::objtype, InternalGrant::objtype, InternalDefaultACL::privileges, InternalGrant::privileges, InternalDefaultACL::roleid, ScanKeyInit(), SetDefaultACL(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by shdepDropOwned().

◆ ReplaceRoleInInitPriv()

void ReplaceRoleInInitPriv ( Oid  oldroleid,
Oid  newroleid,
Oid  classid,
Oid  objid,
int32  objsubid 
)

Definition at line 4811 of file aclchk.c.

4813 {
4814  Relation rel;
4815  ScanKeyData key[3];
4816  SysScanDesc scan;
4817  HeapTuple oldtuple;
4818  Datum oldAclDatum;
4819  bool isNull;
4820  Acl *old_acl;
4821  Acl *new_acl;
4822  HeapTuple newtuple;
4823  int noldmembers;
4824  int nnewmembers;
4825  Oid *oldmembers;
4826  Oid *newmembers;
4827 
4828  /* Search for existing pg_init_privs entry for the target object. */
4829  rel = table_open(InitPrivsRelationId, RowExclusiveLock);
4830 
4831  ScanKeyInit(&key[0],
4832  Anum_pg_init_privs_objoid,
4833  BTEqualStrategyNumber, F_OIDEQ,
4834  ObjectIdGetDatum(objid));
4835  ScanKeyInit(&key[1],
4836  Anum_pg_init_privs_classoid,
4837  BTEqualStrategyNumber, F_OIDEQ,
4838  ObjectIdGetDatum(classid));
4839  ScanKeyInit(&key[2],
4840  Anum_pg_init_privs_objsubid,
4841  BTEqualStrategyNumber, F_INT4EQ,
4842  Int32GetDatum(objsubid));
4843 
4844  scan = systable_beginscan(rel, InitPrivsObjIndexId, true,
4845  NULL, 3, key);
4846 
4847  /* There should exist only one entry or none. */
4848  oldtuple = systable_getnext(scan);
4849 
4850  if (!HeapTupleIsValid(oldtuple))
4851  {
4852  /*
4853  * Hmm, why are we here if there's no entry? But pack up and go away
4854  * quietly.
4855  */
4856  systable_endscan(scan);
4858  return;
4859  }
4860 
4861  /* Get a writable copy of the existing ACL. */
4862  oldAclDatum = heap_getattr(oldtuple, Anum_pg_init_privs_initprivs,
4863  RelationGetDescr(rel), &isNull);
4864  Assert(!isNull);
4865  old_acl = DatumGetAclPCopy(oldAclDatum);
4866 
4867  /*
4868  * Generate new ACL. This usage of aclnewowner is a bit off-label when
4869  * oldroleid isn't the owner; but it does the job fine.
4870  */
4871  new_acl = aclnewowner(old_acl, oldroleid, newroleid);
4872 
4873  /*
4874  * If we end with an empty ACL, delete the pg_init_privs entry. (That
4875  * probably can't happen here, but we may as well cover the case.)
4876  */
4877  if (new_acl == NULL || ACL_NUM(new_acl) == 0)
4878  {
4879  CatalogTupleDelete(rel, &oldtuple->t_self);
4880  }
4881  else
4882  {
4883  Datum values[Natts_pg_init_privs] = {0};
4884  bool nulls[Natts_pg_init_privs] = {0};
4885  bool replaces[Natts_pg_init_privs] = {0};
4886 
4887  /* Update existing entry. */
4888  values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
4889  replaces[Anum_pg_init_privs_initprivs - 1] = true;
4890 
4891  newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(rel),
4892  values, nulls, replaces);
4893  CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
4894  }
4895 
4896  /*
4897  * Update the shared dependency ACL info.
4898  */
4899  noldmembers = aclmembers(old_acl, &oldmembers);
4900  nnewmembers = aclmembers(new_acl, &newmembers);
4901 
4902  updateInitAclDependencies(classid, objid, objsubid,
4903  noldmembers, oldmembers,
4904  nnewmembers, newmembers);
4905 
4906  systable_endscan(scan);
4907 
4908  /* prevent error when processing objects multiple times */
4910 
4912 }
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
Definition: acl.c:1103

References ACL_NUM, aclmembers(), aclnewowner(), Assert, BTEqualStrategyNumber, CatalogTupleDelete(), CatalogTupleUpdate(), CommandCounterIncrement(), DatumGetAclPCopy, heap_getattr(), heap_modify_tuple(), HeapTupleIsValid, Int32GetDatum(), sort-test::key, ObjectIdGetDatum(), PointerGetDatum(), RelationGetDescr, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), updateInitAclDependencies(), and values.

Referenced by shdepReassignOwned_InitAcl().

◆ select_best_admin()

Oid select_best_admin ( Oid  member,
Oid  role 
)

Definition at line 5423 of file acl.c.

5424 {
5425  Oid admin_role;
5426 
5427  /* By policy, a role cannot have WITH ADMIN OPTION on itself. */
5428  if (member == role)
5429  return InvalidOid;
5430 
5431  (void) roles_is_member_of(member, ROLERECURSE_PRIVS, role, &admin_role);
5432  return admin_role;
5433 }

References InvalidOid, ROLERECURSE_PRIVS, and roles_is_member_of().

Referenced by check_role_grantor().

◆ select_best_grantor()

void select_best_grantor ( Oid  roleId,
AclMode  privileges,
const Acl acl,
Oid  ownerId,
Oid grantorId,
AclMode grantOptions 
)

Definition at line 5478 of file acl.c.

5481 {
5482  AclMode needed_goptions = ACL_GRANT_OPTION_FOR(privileges);
5483  List *roles_list;
5484  int nrights;
5485  ListCell *l;
5486 
5487  /*
5488  * The object owner is always treated as having all grant options, so if
5489  * roleId is the owner it's easy. Also, if roleId is a superuser it's
5490  * easy: superusers are implicitly members of every role, so they act as
5491  * the object owner.
5492  */
5493  if (roleId == ownerId || superuser_arg(roleId))
5494  {
5495  *grantorId = ownerId;
5496  *grantOptions = needed_goptions;
5497  return;
5498  }
5499 
5500  /*
5501  * Otherwise we have to do a careful search to see if roleId has the
5502  * privileges of any suitable role. Note: we can hang onto the result of
5503  * roles_is_member_of() throughout this loop, because aclmask_direct()
5504  * doesn't query any role memberships.
5505  */
5506  roles_list = roles_is_member_of(roleId, ROLERECURSE_PRIVS,
5507  InvalidOid, NULL);
5508 
5509  /* initialize candidate result as default */
5510  *grantorId = roleId;
5511  *grantOptions = ACL_NO_RIGHTS;
5512  nrights = 0;
5513 
5514  foreach(l, roles_list)
5515  {
5516  Oid otherrole = lfirst_oid(l);
5517  AclMode otherprivs;
5518 
5519  otherprivs = aclmask_direct(acl, otherrole, ownerId,
5520  needed_goptions, ACLMASK_ALL);
5521  if (otherprivs == needed_goptions)
5522  {
5523  /* Found a suitable grantor */
5524  *grantorId = otherrole;
5525  *grantOptions = otherprivs;
5526  return;
5527  }
5528 
5529  /*
5530  * If it has just some of the needed privileges, remember best
5531  * candidate.
5532  */
5533  if (otherprivs != ACL_NO_RIGHTS)
5534  {
5535  int nnewrights = count_one_bits(otherprivs);
5536 
5537  if (nnewrights > nrights)
5538  {
5539  *grantorId = otherrole;
5540  *grantOptions = otherprivs;
5541  nrights = nnewrights;
5542  }
5543  }
5544  }
5545 }
static int count_one_bits(AclMode mask)
Definition: acl.c:5438
static AclMode aclmask_direct(const Acl *acl, Oid roleid, Oid ownerId, AclMode mask, AclMaskHow how)
Definition: acl.c:1461
#define ACL_GRANT_OPTION_FOR(privs)
Definition: acl.h:70
#define lfirst_oid(lc)
Definition: pg_list.h:174

References ACL_GRANT_OPTION_FOR, ACL_NO_RIGHTS, ACLMASK_ALL, aclmask_direct(), count_one_bits(), InvalidOid, lfirst_oid, ROLERECURSE_PRIVS, roles_is_member_of(), and superuser_arg().

Referenced by ExecGrant_Attribute(), ExecGrant_common(), ExecGrant_Largeobject(), ExecGrant_Parameter(), and ExecGrant_Relation().