Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Defines | Typedefs | Enumerations | Functions

acl.h File Reference

#include "nodes/parsenodes.h"
#include "utils/array.h"
#include "utils/snapshot.h"
Include dependency graph for acl.h:

Go to the source code of this file.

Data Structures

struct  AclItem

Defines

#define ACL_ID_PUBLIC   0
#define ACLITEM_GET_PRIVS(item)   ((item).ai_privs & 0xFFFF)
#define ACLITEM_GET_GOPTIONS(item)   (((item).ai_privs >> 16) & 0xFFFF)
#define ACLITEM_GET_RIGHTS(item)   ((item).ai_privs)
#define ACL_GRANT_OPTION_FOR(privs)   (((AclMode) (privs) & 0xFFFF) << 16)
#define ACL_OPTION_TO_PRIVS(privs)   (((AclMode) (privs) >> 16) & 0xFFFF)
#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) 0xFFFF)
#define ACLITEM_ALL_GOPTION_BITS   ((AclMode) 0xFFFF << 16)
#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'
#define ACL_SELECT_CHR   'r'
#define ACL_UPDATE_CHR   'w'
#define ACL_DELETE_CHR   'd'
#define ACL_TRUNCATE_CHR   'D'
#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_ALL_RIGHTS_STR   "arwdDxtXUCTc"
#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)
#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_NAMESPACE   (ACL_USAGE|ACL_CREATE)
#define ACL_ALL_RIGHTS_TABLESPACE   (ACL_CREATE)
#define ACL_ALL_RIGHTS_TYPE   (ACL_USAGE)

Typedefs

typedef struct AclItem AclItem
typedef ArrayType Acl
typedef enum AclObjectKind AclObjectKind

Enumerations

enum  AclMaskHow { ACLMASK_ALL, ACLMASK_ANY }
enum  AclResult { ACLCHECK_OK = 0, ACLCHECK_NO_PRIV, ACLCHECK_NOT_OWNER }
enum  AclObjectKind {
  ACL_KIND_COLUMN, ACL_KIND_CLASS, ACL_KIND_SEQUENCE, ACL_KIND_DATABASE,
  ACL_KIND_PROC, ACL_KIND_OPER, ACL_KIND_TYPE, ACL_KIND_LANGUAGE,
  ACL_KIND_LARGEOBJECT, ACL_KIND_NAMESPACE, ACL_KIND_OPCLASS, ACL_KIND_OPFAMILY,
  ACL_KIND_COLLATION, ACL_KIND_CONVERSION, ACL_KIND_TABLESPACE, ACL_KIND_TSDICTIONARY,
  ACL_KIND_TSCONFIGURATION, ACL_KIND_FDW, ACL_KIND_FOREIGN_SERVER, ACL_KIND_EVENT_TRIGGER,
  ACL_KIND_EXTENSION, MAX_ACL_KIND
}

Functions

Aclacldefault (GrantObjectType objtype, Oid ownerId)
Aclget_user_default_acl (GrantObjectType objtype, Oid ownerId, Oid nsp_oid)
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 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)
void check_is_member_of_role (Oid member, Oid role)
Oid get_role_oid (const char *rolname, bool missing_ok)
void select_best_grantor (Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
void initialize_acl (void)
Datum aclitemin (PG_FUNCTION_ARGS)
Datum aclitemout (PG_FUNCTION_ARGS)
Datum aclinsert (PG_FUNCTION_ARGS)
Datum aclremove (PG_FUNCTION_ARGS)
Datum aclcontains (PG_FUNCTION_ARGS)
Datum makeaclitem (PG_FUNCTION_ARGS)
Datum aclitem_eq (PG_FUNCTION_ARGS)
Datum hash_aclitem (PG_FUNCTION_ARGS)
Datum acldefault_sql (PG_FUNCTION_ARGS)
Datum aclexplode (PG_FUNCTION_ARGS)
void ExecuteGrantStmt (GrantStmt *stmt)
void ExecAlterDefaultPrivilegesStmt (AlterDefaultPrivilegesStmt *stmt)
void RemoveRoleFromObjectACL (Oid roleid, Oid classid, Oid objid)
void RemoveDefaultACLById (Oid defaclOid)
AclMode pg_attribute_aclmask (Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
AclMode pg_class_aclmask (Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
AclMode pg_database_aclmask (Oid db_oid, Oid roleid, AclMode mask, AclMaskHow how)
AclMode pg_proc_aclmask (Oid proc_oid, Oid roleid, AclMode mask, AclMaskHow how)
AclMode pg_language_aclmask (Oid lang_oid, Oid roleid, AclMode mask, AclMaskHow how)
AclMode pg_largeobject_aclmask_snapshot (Oid lobj_oid, Oid roleid, AclMode mask, AclMaskHow how, Snapshot snapshot)
AclMode pg_namespace_aclmask (Oid nsp_oid, Oid roleid, AclMode mask, AclMaskHow how)
AclMode pg_tablespace_aclmask (Oid spc_oid, Oid roleid, AclMode mask, AclMaskHow how)
AclMode pg_foreign_data_wrapper_aclmask (Oid fdw_oid, Oid roleid, AclMode mask, AclMaskHow how)
AclMode pg_foreign_server_aclmask (Oid srv_oid, Oid roleid, AclMode mask, AclMaskHow how)
AclMode pg_type_aclmask (Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
AclResult pg_attribute_aclcheck (Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
AclResult pg_attribute_aclcheck_all (Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
AclResult pg_class_aclcheck (Oid table_oid, Oid roleid, AclMode mode)
AclResult pg_database_aclcheck (Oid db_oid, Oid roleid, AclMode mode)
AclResult pg_proc_aclcheck (Oid proc_oid, Oid roleid, AclMode mode)
AclResult pg_language_aclcheck (Oid lang_oid, Oid roleid, AclMode mode)
AclResult pg_largeobject_aclcheck_snapshot (Oid lang_oid, Oid roleid, AclMode mode, Snapshot snapshot)
AclResult pg_namespace_aclcheck (Oid nsp_oid, Oid roleid, AclMode mode)
AclResult pg_tablespace_aclcheck (Oid spc_oid, Oid roleid, AclMode mode)
AclResult pg_foreign_data_wrapper_aclcheck (Oid fdw_oid, Oid roleid, AclMode mode)
AclResult pg_foreign_server_aclcheck (Oid srv_oid, Oid roleid, AclMode mode)
AclResult pg_type_aclcheck (Oid type_oid, Oid roleid, AclMode mode)
void aclcheck_error (AclResult aclerr, AclObjectKind objectkind, const char *objectname)
void aclcheck_error_col (AclResult aclerr, AclObjectKind objectkind, const char *objectname, const char *colname)
void aclcheck_error_type (AclResult aclerr, Oid typeOid)
bool pg_class_ownercheck (Oid class_oid, Oid roleid)
bool pg_type_ownercheck (Oid type_oid, Oid roleid)
bool pg_oper_ownercheck (Oid oper_oid, Oid roleid)
bool pg_proc_ownercheck (Oid proc_oid, Oid roleid)
bool pg_language_ownercheck (Oid lan_oid, Oid roleid)
bool pg_largeobject_ownercheck (Oid lobj_oid, Oid roleid)
bool pg_namespace_ownercheck (Oid nsp_oid, Oid roleid)
bool pg_tablespace_ownercheck (Oid spc_oid, Oid roleid)
bool pg_opclass_ownercheck (Oid opc_oid, Oid roleid)
bool pg_opfamily_ownercheck (Oid opf_oid, Oid roleid)
bool pg_database_ownercheck (Oid db_oid, Oid roleid)
bool pg_collation_ownercheck (Oid coll_oid, Oid roleid)
bool pg_conversion_ownercheck (Oid conv_oid, Oid roleid)
bool pg_ts_dict_ownercheck (Oid dict_oid, Oid roleid)
bool pg_ts_config_ownercheck (Oid cfg_oid, Oid roleid)
bool pg_foreign_data_wrapper_ownercheck (Oid srv_oid, Oid roleid)
bool pg_foreign_server_ownercheck (Oid srv_oid, Oid roleid)
bool pg_event_trigger_ownercheck (Oid et_oid, Oid roleid)
bool pg_extension_ownercheck (Oid ext_oid, Oid roleid)
bool has_createrole_privilege (Oid roleid)

Define Documentation

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

Definition at line 147 of file acl.h.

Referenced by ExecGrant_Attribute(), and ExecGrant_Relation().

#define ACL_ALL_RIGHTS_DATABASE   (ACL_CREATE|ACL_CREATE_TEMP|ACL_CONNECT)

Definition at line 150 of file acl.h.

#define ACL_ALL_RIGHTS_FDW   (ACL_USAGE)

Definition at line 151 of file acl.h.

#define ACL_ALL_RIGHTS_FOREIGN_SERVER   (ACL_USAGE)

Definition at line 152 of file acl.h.

#define ACL_ALL_RIGHTS_FUNCTION   (ACL_EXECUTE)

Definition at line 153 of file acl.h.

#define ACL_ALL_RIGHTS_LANGUAGE   (ACL_USAGE)

Definition at line 154 of file acl.h.

#define ACL_ALL_RIGHTS_LARGEOBJECT   (ACL_SELECT|ACL_UPDATE)

Definition at line 155 of file acl.h.

#define ACL_ALL_RIGHTS_NAMESPACE   (ACL_USAGE|ACL_CREATE)

Definition at line 156 of file acl.h.

#define ACL_ALL_RIGHTS_RELATION   (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_TRUNCATE|ACL_REFERENCES|ACL_TRIGGER)

Definition at line 148 of file acl.h.

Referenced by ExecGrant_Relation(), and ExecuteGrantStmt().

#define ACL_ALL_RIGHTS_SEQUENCE   (ACL_USAGE|ACL_SELECT|ACL_UPDATE)

Definition at line 149 of file acl.h.

Referenced by ExecGrant_Relation().

#define ACL_ALL_RIGHTS_STR   "arwdDxtXUCTc"

Definition at line 142 of file acl.h.

Referenced by aclitemout(), and aclparse().

#define ACL_ALL_RIGHTS_TABLESPACE   (ACL_CREATE)

Definition at line 157 of file acl.h.

#define ACL_ALL_RIGHTS_TYPE   (ACL_USAGE)

Definition at line 158 of file acl.h.

#define ACL_CONNECT_CHR   'c'

Definition at line 139 of file acl.h.

Referenced by aclparse().

#define ACL_CREATE_CHR   'C'

Definition at line 137 of file acl.h.

Referenced by aclparse().

#define ACL_CREATE_TEMP_CHR   'T'

Definition at line 138 of file acl.h.

Referenced by aclparse().

#define ACL_DAT (   ACL  )     ((AclItem *) ARR_DATA_PTR(ACL))
#define ACL_DELETE_CHR   'd'

Definition at line 131 of file acl.h.

Referenced by aclparse().

#define ACL_EXECUTE_CHR   'X'

Definition at line 135 of file acl.h.

Referenced by aclparse().

#define ACL_GRANT_OPTION_FOR (   privs  )     (((AclMode) (privs) & 0xFFFF) << 16)
#define ACL_ID_PUBLIC   0
#define ACL_INSERT_CHR   'a'

Definition at line 128 of file acl.h.

Referenced by aclparse().

#define ACL_MODECHG_ADD   1

Definition at line 120 of file acl.h.

Referenced by aclmerge(), aclupdate(), and merge_acl_with_grant().

#define ACL_MODECHG_DEL   2

Definition at line 121 of file acl.h.

Referenced by aclupdate(), check_circularity(), and recursive_revoke().

#define ACL_MODECHG_EQL   3

Definition at line 122 of file acl.h.

Referenced by aclupdate().

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

Definition at line 101 of file acl.h.

Referenced by aclnewowner(), aclupdate(), and allocacl().

#define ACL_NUM (   ACL  )     (ARR_DIMS(ACL)[0])
#define ACL_OPTION_TO_PRIVS (   privs  )     (((AclMode) (privs) >> 16) & 0xFFFF)

Definition at line 62 of file acl.h.

Referenced by check_circularity(), recursive_revoke(), and restrict_and_check_grant().

#define ACL_REFERENCES_CHR   'x'

Definition at line 133 of file acl.h.

Referenced by aclparse().

#define ACL_SELECT_CHR   'r'

Definition at line 129 of file acl.h.

Referenced by aclparse().

#define ACL_SIZE (   ACL  )     ARR_SIZE(ACL)

Definition at line 102 of file acl.h.

Referenced by aclupdate(), and check_circularity().

#define ACL_TRIGGER_CHR   't'

Definition at line 134 of file acl.h.

Referenced by aclparse().

#define ACL_TRUNCATE_CHR   'D'

Definition at line 132 of file acl.h.

Referenced by aclparse().

#define ACL_UPDATE_CHR   'w'

Definition at line 130 of file acl.h.

Referenced by aclparse().

#define ACL_USAGE_CHR   'U'

Definition at line 136 of file acl.h.

Referenced by aclparse().

#define ACLITEM_ALL_GOPTION_BITS   ((AclMode) 0xFFFF << 16)

Definition at line 79 of file acl.h.

Referenced by aclmask(), and aclmask_direct().

#define ACLITEM_ALL_PRIV_BITS   ((AclMode) 0xFFFF)

Definition at line 78 of file acl.h.

#define ACLITEM_GET_GOPTIONS (   item  )     (((item).ai_privs >> 16) & 0xFFFF)

Definition at line 58 of file acl.h.

Referenced by aclexplode(), aclitemout(), aclupdate(), and check_circularity().

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

Definition at line 57 of file acl.h.

Referenced by aclexplode(), aclitemout(), and recursive_revoke().

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

Definition at line 59 of file acl.h.

Referenced by aclcontains(), aclnewowner(), and aclupdate().

#define ACLITEM_SET_GOPTIONS (   item,
  goptions 
)
Value:
((item).ai_privs = ((item).ai_privs & ~(((AclMode) 0xFFFF) << 16)) | \
                     (((AclMode) (goptions) & 0xFFFF) << 16))

Definition at line 67 of file acl.h.

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

Definition at line 64 of file acl.h.

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

Definition at line 73 of file acl.h.

Referenced by acldefault(), aclparse(), aclupdate(), makeaclitem(), merge_acl_with_grant(), and recursive_revoke().

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

Definition at line 70 of file acl.h.

Referenced by aclnewowner(), and aclupdate().

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

Definition at line 107 of file acl.h.

#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))

Definition at line 113 of file acl.h.

Referenced by aclcontains(), and aclexplode().

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

Definition at line 114 of file acl.h.

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

Definition at line 108 of file acl.h.

Referenced by aclcontains(), aclitem_eq(), aclitemout(), and hash_aclitem().

#define PG_RETURN_ACL_P (   x  )     PG_RETURN_POINTER(x)

Definition at line 115 of file acl.h.

Referenced by acldefault_sql().

#define PG_RETURN_ACLITEM_P (   x  )     PG_RETURN_POINTER(x)

Definition at line 109 of file acl.h.

Referenced by aclitemin(), and makeaclitem().


Typedef Documentation

typedef ArrayType Acl

Definition at line 97 of file acl.h.

typedef struct AclItem AclItem

Enumeration Type Documentation

enum AclMaskHow
Enumerator:
ACLMASK_ALL 
ACLMASK_ANY 

Definition at line 161 of file acl.h.

{
    ACLMASK_ALL,                /* normal case: compute all bits */
    ACLMASK_ANY                 /* return when result is known nonzero */
} AclMaskHow;

Enumerator:
ACL_KIND_COLUMN 
ACL_KIND_CLASS 
ACL_KIND_SEQUENCE 
ACL_KIND_DATABASE 
ACL_KIND_PROC 
ACL_KIND_OPER 
ACL_KIND_TYPE 
ACL_KIND_LANGUAGE 
ACL_KIND_LARGEOBJECT 
ACL_KIND_NAMESPACE 
ACL_KIND_OPCLASS 
ACL_KIND_OPFAMILY 
ACL_KIND_COLLATION 
ACL_KIND_CONVERSION 
ACL_KIND_TABLESPACE 
ACL_KIND_TSDICTIONARY 
ACL_KIND_TSCONFIGURATION 
ACL_KIND_FDW 
ACL_KIND_FOREIGN_SERVER 
ACL_KIND_EVENT_TRIGGER 
ACL_KIND_EXTENSION 
MAX_ACL_KIND 

Definition at line 177 of file acl.h.

{
    ACL_KIND_COLUMN,            /* pg_attribute */
    ACL_KIND_CLASS,             /* pg_class */
    ACL_KIND_SEQUENCE,          /* pg_sequence */
    ACL_KIND_DATABASE,          /* pg_database */
    ACL_KIND_PROC,              /* pg_proc */
    ACL_KIND_OPER,              /* pg_operator */
    ACL_KIND_TYPE,              /* pg_type */
    ACL_KIND_LANGUAGE,          /* pg_language */
    ACL_KIND_LARGEOBJECT,       /* pg_largeobject */
    ACL_KIND_NAMESPACE,         /* pg_namespace */
    ACL_KIND_OPCLASS,           /* pg_opclass */
    ACL_KIND_OPFAMILY,          /* pg_opfamily */
    ACL_KIND_COLLATION,         /* pg_collation */
    ACL_KIND_CONVERSION,        /* pg_conversion */
    ACL_KIND_TABLESPACE,        /* pg_tablespace */
    ACL_KIND_TSDICTIONARY,      /* pg_ts_dict */
    ACL_KIND_TSCONFIGURATION,   /* pg_ts_config */
    ACL_KIND_FDW,               /* pg_foreign_data_wrapper */
    ACL_KIND_FOREIGN_SERVER,    /* pg_foreign_server */
    ACL_KIND_EVENT_TRIGGER,     /* pg_event_trigger */
    ACL_KIND_EXTENSION,         /* pg_extension */
    MAX_ACL_KIND                /* MUST BE LAST */
} AclObjectKind;

enum AclResult
Enumerator:
ACLCHECK_OK 
ACLCHECK_NO_PRIV 
ACLCHECK_NOT_OWNER 

Definition at line 168 of file acl.h.

{
    ACLCHECK_OK = 0,
    ACLCHECK_NO_PRIV,
    ACLCHECK_NOT_OWNER
} AclResult;


Function Documentation

void aclcheck_error ( AclResult  aclerr,
AclObjectKind  objectkind,
const char *  objectname 
)

Definition at line 3362 of file aclchk.c.

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

Referenced by aclcheck_error_type(), AlterDatabase(), AlterDatabaseOwner(), AlterDatabaseSet(), AlterEventTrigger(), AlterEventTriggerOwner_internal(), AlterExtensionNamespace(), AlterForeignServer(), AlterForeignServerOwner_internal(), AlterFunction(), AlterObjectNamespace_internal(), AlterObjectOwner_internal(), AlterObjectRename_internal(), AlterOpFamilyAdd(), AlterRoleSet(), AlterSchemaOwner_internal(), AlterSequence(), AlterTableSpaceOptions(), AlterTSConfiguration(), AlterTSDictionary(), AlterTypeOwner(), ATExecChangeOwner(), ATPrepSetStatistics(), ATPrepSetTableSpace(), ATSimplePermissions(), calculate_database_size(), calculate_tablespace_size(), check_object_ownership(), check_temp_tablespaces(), checkFkeyPermissions(), CheckRelationOwnership(), compute_return_type(), create_proc_lang(), CreateConversionCommand(), createdb(), CreateForeignServer(), CreateForeignTable(), CreateFunction(), CreateProceduralLanguage(), CreateSchemaCommand(), CreateTrigger(), currtid_byrelname(), currtid_byreloid(), DefineAggregate(), DefineCollation(), DefineDomain(), DefineEnum(), DefineIndex(), DefineOpClass(), DefineOperator(), DefineOpFamily(), DefineQueryRewrite(), DefineRange(), DefineRelation(), DefineTSConfiguration(), DefineTSDictionary(), DefineType(), dropdb(), DropTableSpace(), EnableDisableRule(), ExecAlterExtensionContentsStmt(), ExecAlterExtensionStmt(), ExecCheckRTPerms(), ExecEvalArrayCoerceExpr(), ExecInitAgg(), ExecInitWindowAgg(), ExecuteDoStmt(), ExecuteTruncate(), findRangeCanonicalFunction(), findRangeSubtypeDiffFunction(), get_connect_string(), get_other_operator(), get_rel_from_relname(), HandleFunctionRequest(), init_fcache(), initialize_peragg(), LockTableRecurse(), lookup_agg_function(), LookupCreationNamespace(), LookupExplicitNamespace(), MergeAttributes(), movedb(), OperatorCreate(), pgrowlocks(), ProcedureCreate(), RangeVarCallbackForAlterRelation(), RangeVarCallbackForDropRelation(), RangeVarCallbackForLockTable(), RangeVarCallbackForReindexIndex(), RangeVarCallbackForRenameRule(), RangeVarCallbackForRenameTrigger(), RangeVarCallbackOwnsTable(), RangeVarGetAndCheckCreationNamespace(), ReindexDatabase(), renameatt_check(), RenameDatabase(), RenameSchema(), RenameTableSpace(), restrict_and_check_grant(), SetDefaultACLsInSchemas(), transformTableLikeClause(), truncate_check_rel(), TypeCreate(), and user_mapping_ddl_aclcheck().

{
    switch (aclerr)
    {
        case ACLCHECK_OK:
            /* no error, so return to caller */
            break;
        case ACLCHECK_NO_PRIV:
            ereport(ERROR,
                    (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                     errmsg(no_priv_msg[objectkind], objectname)));
            break;
        case ACLCHECK_NOT_OWNER:
            ereport(ERROR,
                    (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                     errmsg(not_owner_msg[objectkind], objectname)));
            break;
        default:
            elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
            break;
    }
}

void aclcheck_error_col ( AclResult  aclerr,
AclObjectKind  objectkind,
const char *  objectname,
const char *  colname 
)

Definition at line 3388 of file aclchk.c.

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

Referenced by restrict_and_check_grant().

{
    switch (aclerr)
    {
        case ACLCHECK_OK:
            /* no error, so return to caller */
            break;
        case ACLCHECK_NO_PRIV:
            ereport(ERROR,
                    (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
             errmsg("permission denied for column \"%s\" of relation \"%s\"",
                    colname, objectname)));
            break;
        case ACLCHECK_NOT_OWNER:
            /* relation msg is OK since columns don't have separate owners */
            ereport(ERROR,
                    (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                     errmsg(not_owner_msg[objectkind], objectname)));
            break;
        default:
            elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
            break;
    }
}

void aclcheck_error_type ( AclResult  aclerr,
Oid  typeOid 
)
Acl* aclconcat ( const Acl left_acl,
const Acl right_acl 
)

Definition at line 426 of file acl.c.

References ACL_DAT, ACL_NUM, and allocacl().

Referenced by ExecGrant_Attribute().

{
    Acl        *result_acl;

    result_acl = allocacl(ACL_NUM(left_acl) + ACL_NUM(right_acl));

    memcpy(ACL_DAT(result_acl),
           ACL_DAT(left_acl),
           ACL_NUM(left_acl) * sizeof(AclItem));

    memcpy(ACL_DAT(result_acl) + ACL_NUM(left_acl),
           ACL_DAT(right_acl),
           ACL_NUM(right_acl) * sizeof(AclItem));

    return result_acl;
}

Datum aclcontains ( PG_FUNCTION_ARGS   ) 

Definition at line 1553 of file acl.c.

References ACL_DAT, ACL_NUM, ACLITEM_GET_RIGHTS, AclItem::ai_grantee, AclItem::ai_grantor, check_acl(), i, PG_GETARG_ACL_P, PG_GETARG_ACLITEM_P, and PG_RETURN_BOOL.

{
    Acl        *acl = PG_GETARG_ACL_P(0);
    AclItem    *aip = PG_GETARG_ACLITEM_P(1);
    AclItem    *aidat;
    int         i,
                num;

    check_acl(acl);
    num = ACL_NUM(acl);
    aidat = ACL_DAT(acl);
    for (i = 0; i < num; ++i)
    {
        if (aip->ai_grantee == aidat[i].ai_grantee &&
            aip->ai_grantor == aidat[i].ai_grantor &&
            (ACLITEM_GET_RIGHTS(*aip) & ACLITEM_GET_RIGHTS(aidat[i])) == ACLITEM_GET_RIGHTS(*aip))
            PG_RETURN_BOOL(true);
    }
    PG_RETURN_BOOL(false);
}

Acl* aclcopy ( const Acl orig_acl  ) 

Definition at line 406 of file acl.c.

References ACL_DAT, ACL_NUM, and allocacl().

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

{
    Acl        *result_acl;

    result_acl = allocacl(ACL_NUM(orig_acl));

    memcpy(ACL_DAT(result_acl),
           ACL_DAT(orig_acl),
           ACL_NUM(orig_acl) * sizeof(AclItem));

    return result_acl;
}

Acl* acldefault ( GrantObjectType  objtype,
Oid  ownerId 
)

Definition at line 731 of file acl.c.

References ACL_CREATE_TEMP, ACL_DAT, ACL_NO_RIGHTS, ACL_OBJECT_COLUMN, ACL_OBJECT_DATABASE, ACL_OBJECT_DOMAIN, ACL_OBJECT_FDW, ACL_OBJECT_FOREIGN_SERVER, ACL_OBJECT_FUNCTION, ACL_OBJECT_LANGUAGE, ACL_OBJECT_LARGEOBJECT, ACL_OBJECT_NAMESPACE, ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TABLESPACE, ACL_OBJECT_TYPE, ACLITEM_SET_PRIVS_GOPTIONS, AclItem::ai_grantee, AclItem::ai_grantor, allocacl(), elog, and ERROR.

Referenced by acldefault_sql(), ExecGrant_Attribute(), ExecGrant_Database(), ExecGrant_Fdw(), ExecGrant_ForeignServer(), ExecGrant_Function(), ExecGrant_Language(), ExecGrant_Largeobject(), ExecGrant_Namespace(), ExecGrant_Relation(), ExecGrant_Tablespace(), ExecGrant_Type(), get_user_default_acl(), pg_class_aclmask(), pg_database_aclmask(), pg_foreign_data_wrapper_aclmask(), pg_foreign_server_aclmask(), pg_language_aclmask(), pg_largeobject_aclmask_snapshot(), pg_namespace_aclmask(), pg_proc_aclmask(), pg_tablespace_aclmask(), pg_type_aclmask(), and SetDefaultACL().

{
    AclMode     world_default;
    AclMode     owner_default;
    int         nacl;
    Acl        *acl;
    AclItem    *aip;

    switch (objtype)
    {
        case ACL_OBJECT_COLUMN:
            /* by default, columns have no extra privileges */
            world_default = ACL_NO_RIGHTS;
            owner_default = ACL_NO_RIGHTS;
            break;
        case ACL_OBJECT_RELATION:
            world_default = ACL_NO_RIGHTS;
            owner_default = ACL_ALL_RIGHTS_RELATION;
            break;
        case ACL_OBJECT_SEQUENCE:
            world_default = ACL_NO_RIGHTS;
            owner_default = ACL_ALL_RIGHTS_SEQUENCE;
            break;
        case ACL_OBJECT_DATABASE:
            /* for backwards compatibility, grant some rights by default */
            world_default = ACL_CREATE_TEMP | ACL_CONNECT;
            owner_default = ACL_ALL_RIGHTS_DATABASE;
            break;
        case ACL_OBJECT_FUNCTION:
            /* Grant EXECUTE by default, for now */
            world_default = ACL_EXECUTE;
            owner_default = ACL_ALL_RIGHTS_FUNCTION;
            break;
        case ACL_OBJECT_LANGUAGE:
            /* Grant USAGE by default, for now */
            world_default = ACL_USAGE;
            owner_default = ACL_ALL_RIGHTS_LANGUAGE;
            break;
        case ACL_OBJECT_LARGEOBJECT:
            world_default = ACL_NO_RIGHTS;
            owner_default = ACL_ALL_RIGHTS_LARGEOBJECT;
            break;
        case ACL_OBJECT_NAMESPACE:
            world_default = ACL_NO_RIGHTS;
            owner_default = ACL_ALL_RIGHTS_NAMESPACE;
            break;
        case ACL_OBJECT_TABLESPACE:
            world_default = ACL_NO_RIGHTS;
            owner_default = ACL_ALL_RIGHTS_TABLESPACE;
            break;
        case ACL_OBJECT_FDW:
            world_default = ACL_NO_RIGHTS;
            owner_default = ACL_ALL_RIGHTS_FDW;
            break;
        case ACL_OBJECT_FOREIGN_SERVER:
            world_default = ACL_NO_RIGHTS;
            owner_default = ACL_ALL_RIGHTS_FOREIGN_SERVER;
            break;
        case ACL_OBJECT_DOMAIN:
        case ACL_OBJECT_TYPE:
            world_default = ACL_USAGE;
            owner_default = ACL_ALL_RIGHTS_TYPE;
            break;
        default:
            elog(ERROR, "unrecognized objtype: %d", (int) objtype);
            world_default = ACL_NO_RIGHTS;      /* keep compiler quiet */
            owner_default = ACL_NO_RIGHTS;
            break;
    }

    nacl = 0;
    if (world_default != ACL_NO_RIGHTS)
        nacl++;
    if (owner_default != ACL_NO_RIGHTS)
        nacl++;

    acl = allocacl(nacl);
    aip = ACL_DAT(acl);

    if (world_default != ACL_NO_RIGHTS)
    {
        aip->ai_grantee = ACL_ID_PUBLIC;
        aip->ai_grantor = ownerId;
        ACLITEM_SET_PRIVS_GOPTIONS(*aip, world_default, ACL_NO_RIGHTS);
        aip++;
    }

    /*
     * Note that the owner's entry shows all ordinary privileges but no grant
     * options.  This is because his grant options come "from the system" and
     * not from his own efforts.  (The SQL spec says that the owner's rights
     * come from a "_SYSTEM" authid.)  However, we do consider that the
     * owner's ordinary privileges are self-granted; this lets him revoke
     * them.  We implement the owner's grant options without any explicit
     * "_SYSTEM"-like ACL entry, by internally special-casing the owner
     * wherever we are testing grant options.
     */
    if (owner_default != ACL_NO_RIGHTS)
    {
        aip->ai_grantee = ownerId;
        aip->ai_grantor = ownerId;
        ACLITEM_SET_PRIVS_GOPTIONS(*aip, owner_default, ACL_NO_RIGHTS);
    }

    return acl;
}

Datum acldefault_sql ( PG_FUNCTION_ARGS   ) 

Definition at line 845 of file acl.c.

References acldefault(), elog, ERROR, PG_GETARG_CHAR, PG_GETARG_OID, and PG_RETURN_ACL_P.

{
    char        objtypec = PG_GETARG_CHAR(0);
    Oid         owner = PG_GETARG_OID(1);
    GrantObjectType objtype = 0;

    switch (objtypec)
    {
        case 'c':
            objtype = ACL_OBJECT_COLUMN;
            break;
        case 'r':
            objtype = ACL_OBJECT_RELATION;
            break;
        case 's':
            objtype = ACL_OBJECT_SEQUENCE;
            break;
        case 'd':
            objtype = ACL_OBJECT_DATABASE;
            break;
        case 'f':
            objtype = ACL_OBJECT_FUNCTION;
            break;
        case 'l':
            objtype = ACL_OBJECT_LANGUAGE;
            break;
        case 'L':
            objtype = ACL_OBJECT_LARGEOBJECT;
            break;
        case 'n':
            objtype = ACL_OBJECT_NAMESPACE;
            break;
        case 't':
            objtype = ACL_OBJECT_TABLESPACE;
            break;
        case 'F':
            objtype = ACL_OBJECT_FDW;
            break;
        case 'S':
            objtype = ACL_OBJECT_FOREIGN_SERVER;
            break;
        case 'T':
            objtype = ACL_OBJECT_TYPE;
            break;
        default:
            elog(ERROR, "unrecognized objtype abbreviation: %c", objtypec);
    }

    PG_RETURN_ACL_P(acldefault(objtype, owner));
}

bool aclequal ( const Acl left_acl,
const Acl right_acl 
)

Definition at line 508 of file acl.c.

References ACL_DAT, ACL_NUM, memcmp(), and NULL.

Referenced by get_user_default_acl(), and SetDefaultACL().

{
    /* Check for cases where one or both are empty/null */
    if (left_acl == NULL || ACL_NUM(left_acl) == 0)
    {
        if (right_acl == NULL || ACL_NUM(right_acl) == 0)
            return true;
        else
            return false;
    }
    else
    {
        if (right_acl == NULL || ACL_NUM(right_acl) == 0)
            return false;
    }

    if (ACL_NUM(left_acl) != ACL_NUM(right_acl))
        return false;

    if (memcmp(ACL_DAT(left_acl),
               ACL_DAT(right_acl),
               ACL_NUM(left_acl) * sizeof(AclItem)) == 0)
        return true;

    return false;
}

Datum aclexplode ( PG_FUNCTION_ARGS   ) 

Definition at line 1746 of file acl.c.

References ACL_DAT, ACL_NUM, ACLITEM_GET_GOPTIONS, ACLITEM_GET_PRIVS, AclItem::ai_grantee, AclItem::ai_grantor, BlessTupleDesc(), BoolGetDatum, BOOLOID, check_acl(), convert_aclright_to_string(), CreateTemplateTupleDesc(), CStringGetTextDatum, heap_form_tuple(), HeapTupleGetDatum, MemoryContextSwitchTo(), MemSet, FuncCallContext::multi_call_memory_ctx, N_ACL_RIGHTS, ObjectIdGetDatum, OIDOID, palloc(), PG_GETARG_ACL_P, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, TEXTOID, FuncCallContext::tuple_desc, TupleDescInitEntry(), FuncCallContext::user_fctx, and values.

{
    Acl        *acl = PG_GETARG_ACL_P(0);
    FuncCallContext *funcctx;
    int        *idx;
    AclItem    *aidat;

    if (SRF_IS_FIRSTCALL())
    {
        TupleDesc   tupdesc;
        MemoryContext oldcontext;

        check_acl(acl);

        funcctx = SRF_FIRSTCALL_INIT();
        oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

        /*
         * build tupdesc for result tuples (matches out parameters in pg_proc
         * entry)
         */
        tupdesc = CreateTemplateTupleDesc(4, false);
        TupleDescInitEntry(tupdesc, (AttrNumber) 1, "grantor",
                           OIDOID, -1, 0);
        TupleDescInitEntry(tupdesc, (AttrNumber) 2, "grantee",
                           OIDOID, -1, 0);
        TupleDescInitEntry(tupdesc, (AttrNumber) 3, "privilege_type",
                           TEXTOID, -1, 0);
        TupleDescInitEntry(tupdesc, (AttrNumber) 4, "is_grantable",
                           BOOLOID, -1, 0);

        funcctx->tuple_desc = BlessTupleDesc(tupdesc);

        /* allocate memory for user context */
        idx = (int *) palloc(sizeof(int[2]));
        idx[0] = 0;             /* ACL array item index */
        idx[1] = -1;            /* privilege type counter */
        funcctx->user_fctx = (void *) idx;

        MemoryContextSwitchTo(oldcontext);
    }

    funcctx = SRF_PERCALL_SETUP();
    idx = (int *) funcctx->user_fctx;
    aidat = ACL_DAT(acl);

    /* need test here in case acl has no items */
    while (idx[0] < ACL_NUM(acl))
    {
        AclItem    *aidata;
        AclMode     priv_bit;

        idx[1]++;
        if (idx[1] == N_ACL_RIGHTS)
        {
            idx[1] = 0;
            idx[0]++;
            if (idx[0] >= ACL_NUM(acl)) /* done */
                break;
        }
        aidata = &aidat[idx[0]];
        priv_bit = 1 << idx[1];

        if (ACLITEM_GET_PRIVS(*aidata) & priv_bit)
        {
            Datum       result;
            Datum       values[4];
            bool        nulls[4];
            HeapTuple   tuple;

            values[0] = ObjectIdGetDatum(aidata->ai_grantor);
            values[1] = ObjectIdGetDatum(aidata->ai_grantee);
            values[2] = CStringGetTextDatum(convert_aclright_to_string(priv_bit));
            values[3] = BoolGetDatum((ACLITEM_GET_GOPTIONS(*aidata) & priv_bit) != 0);

            MemSet(nulls, 0, sizeof(nulls));

            tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
            result = HeapTupleGetDatum(tuple);

            SRF_RETURN_NEXT(funcctx, result);
        }
    }

    SRF_RETURN_DONE(funcctx);
}

Datum aclinsert ( PG_FUNCTION_ARGS   ) 

Definition at line 1533 of file acl.c.

References ereport, errcode(), errmsg(), ERROR, and PG_RETURN_NULL.

{
    ereport(ERROR,
            (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
             errmsg("aclinsert is no longer supported")));

    PG_RETURN_NULL();           /* keep compiler quiet */
}

Datum aclitem_eq ( PG_FUNCTION_ARGS   ) 

Definition at line 692 of file acl.c.

References a1, a2, AclItem::ai_grantee, AclItem::ai_grantor, AclItem::ai_privs, PG_GETARG_ACLITEM_P, and PG_RETURN_BOOL.

{
    AclItem    *a1 = PG_GETARG_ACLITEM_P(0);
    AclItem    *a2 = PG_GETARG_ACLITEM_P(1);
    bool        result;

    result = a1->ai_privs == a2->ai_privs &&
        a1->ai_grantee == a2->ai_grantee &&
        a1->ai_grantor == a2->ai_grantor;
    PG_RETURN_BOOL(result);
}

Datum aclitemin ( PG_FUNCTION_ARGS   ) 

Definition at line 564 of file acl.c.

References aclparse(), ereport, errcode(), errmsg(), ERROR, palloc(), PG_GETARG_CSTRING, and PG_RETURN_ACLITEM_P.

{
    const char *s = PG_GETARG_CSTRING(0);
    AclItem    *aip;

    aip = (AclItem *) palloc(sizeof(AclItem));
    s = aclparse(s, aip);
    while (isspace((unsigned char) *s))
        ++s;
    if (*s)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
               errmsg("extra garbage at the end of the ACL specification")));

    PG_RETURN_ACLITEM_P(aip);
}

Datum aclitemout ( PG_FUNCTION_ARGS   ) 

Definition at line 590 of file acl.c.

References ACL_ALL_RIGHTS_STR, ACL_ID_PUBLIC, ACLITEM_GET_GOPTIONS, ACLITEM_GET_PRIVS, AclItem::ai_grantee, AclItem::ai_grantor, AUTHOID, GETSTRUCT, HeapTupleIsValid, i, N_ACL_RIGHTS, NAMEDATALEN, NameStr, ObjectIdGetDatum, palloc(), PG_GETARG_ACLITEM_P, PG_RETURN_CSTRING, putid(), ReleaseSysCache(), and SearchSysCache1.

{
    AclItem    *aip = PG_GETARG_ACLITEM_P(0);
    char       *p;
    char       *out;
    HeapTuple   htup;
    unsigned    i;

    out = palloc(strlen("=/") +
                 2 * N_ACL_RIGHTS +
                 2 * (2 * NAMEDATALEN + 2) +
                 1);

    p = out;
    *p = '\0';

    if (aip->ai_grantee != ACL_ID_PUBLIC)
    {
        htup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(aip->ai_grantee));
        if (HeapTupleIsValid(htup))
        {
            putid(p, NameStr(((Form_pg_authid) GETSTRUCT(htup))->rolname));
            ReleaseSysCache(htup);
        }
        else
        {
            /* Generate numeric OID if we don't find an entry */
            sprintf(p, "%u", aip->ai_grantee);
        }
    }
    while (*p)
        ++p;

    *p++ = '=';

    for (i = 0; i < N_ACL_RIGHTS; ++i)
    {
        if (ACLITEM_GET_PRIVS(*aip) & (1 << i))
            *p++ = ACL_ALL_RIGHTS_STR[i];
        if (ACLITEM_GET_GOPTIONS(*aip) & (1 << i))
            *p++ = '*';
    }

    *p++ = '/';
    *p = '\0';

    htup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(aip->ai_grantor));
    if (HeapTupleIsValid(htup))
    {
        putid(p, NameStr(((Form_pg_authid) GETSTRUCT(htup))->rolname));
        ReleaseSysCache(htup);
    }
    else
    {
        /* Generate numeric OID if we don't find an entry */
        sprintf(p, "%u", aip->ai_grantor);
    }

    PG_RETURN_CSTRING(out);
}

void aclitemsort ( Acl acl  ) 

Definition at line 494 of file acl.c.

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

Referenced by get_user_default_acl(), and SetDefaultACL().

{
    if (acl != NULL && ACL_NUM(acl) > 1)
        qsort(ACL_DAT(acl), ACL_NUM(acl), sizeof(AclItem), aclitemComparator);
}

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

Definition at line 1304 of file acl.c.

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, NULL, and remaining.

Referenced by check_circularity(), pg_attribute_aclmask(), pg_class_aclmask(), pg_database_aclmask(), pg_foreign_data_wrapper_aclmask(), pg_foreign_server_aclmask(), pg_language_aclmask(), pg_largeobject_aclmask_snapshot(), pg_namespace_aclmask(), pg_proc_aclmask(), pg_tablespace_aclmask(), pg_type_aclmask(), and recursive_revoke().

{
    AclMode     result;
    AclMode     remaining;
    AclItem    *aidat;
    int         i,
                num;

    /*
     * Null ACL should not happen, since caller should have inserted
     * appropriate default
     */
    if (acl == NULL)
        elog(ERROR, "null ACL");

    check_acl(acl);

    /* Quick exit for mask == 0 */
    if (mask == 0)
        return 0;

    result = 0;

    /* Owner always implicitly has all grant options */
    if ((mask & ACLITEM_ALL_GOPTION_BITS) &&
        has_privs_of_role(roleid, ownerId))
    {
        result = mask & ACLITEM_ALL_GOPTION_BITS;
        if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
            return result;
    }

    num = ACL_NUM(acl);
    aidat = ACL_DAT(acl);

    /*
     * Check privileges granted directly to roleid or to public
     */
    for (i = 0; i < num; i++)
    {
        AclItem    *aidata = &aidat[i];

        if (aidata->ai_grantee == ACL_ID_PUBLIC ||
            aidata->ai_grantee == roleid)
        {
            result |= aidata->ai_privs & mask;
            if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
                return result;
        }
    }

    /*
     * Check privileges granted indirectly via role memberships. We do this in
     * a separate pass to minimize expensive indirect membership tests.  In
     * particular, it's worth testing whether a given ACL entry grants any
     * privileges still of interest before we perform the has_privs_of_role
     * test.
     */
    remaining = mask & ~result;
    for (i = 0; i < num; i++)
    {
        AclItem    *aidata = &aidat[i];

        if (aidata->ai_grantee == ACL_ID_PUBLIC ||
            aidata->ai_grantee == roleid)
            continue;           /* already checked it */

        if ((aidata->ai_privs & remaining) &&
            has_privs_of_role(roleid, aidata->ai_grantee))
        {
            result |= aidata->ai_privs & mask;
            if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
                return result;
            remaining = mask & ~result;
        }
    }

    return result;
}

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

Definition at line 1456 of file acl.c.

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

Referenced by ExecGrant_Attribute(), ExecGrant_Database(), ExecGrant_Fdw(), ExecGrant_ForeignServer(), ExecGrant_Function(), ExecGrant_Language(), ExecGrant_Largeobject(), ExecGrant_Namespace(), ExecGrant_Relation(), ExecGrant_Tablespace(), ExecGrant_Type(), heap_create_with_catalog(), ProcedureCreate(), and SetDefaultACL().

{
    Oid        *list;
    const AclItem *acldat;
    int         i,
                j,
                k;

    if (acl == NULL || ACL_NUM(acl) == 0)
    {
        *roleids = NULL;
        return 0;
    }

    check_acl(acl);

    /* Allocate the worst-case space requirement */
    list = palloc(ACL_NUM(acl) * 2 * sizeof(Oid));
    acldat = ACL_DAT(acl);

    /*
     * Walk the ACL collecting mentioned RoleIds.
     */
    j = 0;
    for (i = 0; i < ACL_NUM(acl); i++)
    {
        const AclItem *ai = &acldat[i];

        if (ai->ai_grantee != ACL_ID_PUBLIC)
            list[j++] = ai->ai_grantee;
        /* grantor is currently never PUBLIC, but let's check anyway */
        if (ai->ai_grantor != ACL_ID_PUBLIC)
            list[j++] = ai->ai_grantor;
    }

    /* Sort the array */
    qsort(list, j, sizeof(Oid), oidComparator);

    /* Remove duplicates from the array */
    k = 0;
    for (i = 1; i < j; i++)
    {
        if (list[k] != list[i])
            list[++k] = list[i];
    }

    /*
     * We could repalloc the array down to minimum size, but it's hardly worth
     * it since it's only transient memory.
     */
    *roleids = list;

    return k + 1;
}

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

Definition at line 450 of file acl.c.

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

Referenced by get_user_default_acl().

{
    Acl        *result_acl;
    AclItem    *aip;
    int         i,
                num;

    /* Check for cases where one or both are empty/null */
    if (left_acl == NULL || ACL_NUM(left_acl) == 0)
    {
        if (right_acl == NULL || ACL_NUM(right_acl) == 0)
            return NULL;
        else
            return aclcopy(right_acl);
    }
    else
    {
        if (right_acl == NULL || ACL_NUM(right_acl) == 0)
            return aclcopy(left_acl);
    }

    /* Merge them the hard way, one item at a time */
    result_acl = aclcopy(left_acl);

    aip = ACL_DAT(right_acl);
    num = ACL_NUM(right_acl);

    for (i = 0; i < num; i++, aip++)
    {
        Acl        *tmp_acl;

        tmp_acl = aclupdate(result_acl, aip, ACL_MODECHG_ADD,
                            ownerId, DROP_RESTRICT);
        pfree(result_acl);
        result_acl = tmp_acl;
    }

    return result_acl;
}

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

Definition at line 1035 of file acl.c.

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(), AlterObjectOwner_internal(), AlterSchemaOwner_internal(), ATExecChangeOwner(), and change_owner_fix_column_acls().

{
    Acl        *new_acl;
    AclItem    *new_aip;
    AclItem    *old_aip;
    AclItem    *dst_aip;
    AclItem    *src_aip;
    AclItem    *targ_aip;
    bool        newpresent = false;
    int         dst,
                src,
                targ,
                num;

    check_acl(old_acl);

    /*
     * Make a copy of the given ACL, substituting new owner ID for old
     * wherever it appears as either grantor or grantee.  Also note if the new
     * owner ID is already present.
     */
    num = ACL_NUM(old_acl);
    old_aip = ACL_DAT(old_acl);
    new_acl = allocacl(num);
    new_aip = ACL_DAT(new_acl);
    memcpy(new_aip, old_aip, num * sizeof(AclItem));
    for (dst = 0, dst_aip = new_aip; dst < num; dst++, dst_aip++)
    {
        if (dst_aip->ai_grantor == oldOwnerId)
            dst_aip->ai_grantor = newOwnerId;
        else if (dst_aip->ai_grantor == newOwnerId)
            newpresent = true;
        if (dst_aip->ai_grantee == oldOwnerId)
            dst_aip->ai_grantee = newOwnerId;
        else if (dst_aip->ai_grantee == newOwnerId)
            newpresent = true;
    }

    /*
     * If the old ACL contained any references to the new owner, then we may
     * now have generated an ACL containing duplicate entries.  Find them and
     * merge them so that there are not duplicates.  (This is relatively
     * expensive since we use a stupid O(N^2) algorithm, but it's unlikely to
     * be the normal case.)
     *
     * To simplify deletion of duplicate entries, we temporarily leave them in
     * the array but set their privilege masks to zero; when we reach such an
     * entry it's just skipped.  (Thus, a side effect of this code will be to
     * remove privilege-free entries, should there be any in the input.)  dst
     * is the next output slot, targ is the currently considered input slot
     * (always >= dst), and src scans entries to the right of targ looking for
     * duplicates.  Once an entry has been emitted to dst it is known
     * duplicate-free and need not be considered anymore.
     */
    if (newpresent)
    {
        dst = 0;
        for (targ = 0, targ_aip = new_aip; targ < num; targ++, targ_aip++)
        {
            /* ignore if deleted in an earlier pass */
            if (ACLITEM_GET_RIGHTS(*targ_aip) == ACL_NO_RIGHTS)
                continue;
            /* find and merge any duplicates */
            for (src = targ + 1, src_aip = targ_aip + 1; src < num;
                 src++, src_aip++)
            {
                if (ACLITEM_GET_RIGHTS(*src_aip) == ACL_NO_RIGHTS)
                    continue;
                if (aclitem_match(targ_aip, src_aip))
                {
                    ACLITEM_SET_RIGHTS(*targ_aip,
                                       ACLITEM_GET_RIGHTS(*targ_aip) |
                                       ACLITEM_GET_RIGHTS(*src_aip));
                    /* mark the duplicate deleted */
                    ACLITEM_SET_RIGHTS(*src_aip, ACL_NO_RIGHTS);
                }
            }
            /* and emit to output */
            new_aip[dst] = *targ_aip;
            dst++;
        }
        /* Adjust array size to be 'dst' items */
        ARR_DIMS(new_acl)[0] = dst;
        SET_VARSIZE(new_acl, ACL_N_SIZE(dst));
    }

    return new_acl;
}

Datum aclremove ( PG_FUNCTION_ARGS   ) 

Definition at line 1543 of file acl.c.

References ereport, errcode(), errmsg(), ERROR, and PG_RETURN_NULL.

{
    ereport(ERROR,
            (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
             errmsg("aclremove is no longer supported")));

    PG_RETURN_NULL();           /* keep compiler quiet */
}

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

Definition at line 914 of file acl.c.

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(), memmove, recursive_revoke(), and SET_VARSIZE.

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

{
    Acl        *new_acl = NULL;
    AclItem    *old_aip,
               *new_aip = NULL;
    AclMode     old_rights,
                old_goptions,
                new_rights,
                new_goptions;
    int         dst,
                num;

    /* Caller probably already checked old_acl, but be safe */
    check_acl(old_acl);

    /* If granting grant options, check for circularity */
    if (modechg != ACL_MODECHG_DEL &&
        ACLITEM_GET_GOPTIONS(*mod_aip) != ACL_NO_RIGHTS)
        check_circularity(old_acl, mod_aip, ownerId);

    num = ACL_NUM(old_acl);
    old_aip = ACL_DAT(old_acl);

    /*
     * Search the ACL for an existing entry for this grantee and grantor. If
     * one exists, just modify the entry in-place (well, in the same position,
     * since we actually return a copy); otherwise, insert the new entry at
     * the end.
     */

    for (dst = 0; dst < num; ++dst)
    {
        if (aclitem_match(mod_aip, old_aip + dst))
        {
            /* found a match, so modify existing item */
            new_acl = allocacl(num);
            new_aip = ACL_DAT(new_acl);
            memcpy(new_acl, old_acl, ACL_SIZE(old_acl));
            break;
        }
    }

    if (dst == num)
    {
        /* need to append a new item */
        new_acl = allocacl(num + 1);
        new_aip = ACL_DAT(new_acl);
        memcpy(new_aip, old_aip, num * sizeof(AclItem));

        /* initialize the new entry with no permissions */
        new_aip[dst].ai_grantee = mod_aip->ai_grantee;
        new_aip[dst].ai_grantor = mod_aip->ai_grantor;
        ACLITEM_SET_PRIVS_GOPTIONS(new_aip[dst],
                                   ACL_NO_RIGHTS, ACL_NO_RIGHTS);
        num++;                  /* set num to the size of new_acl */
    }

    old_rights = ACLITEM_GET_RIGHTS(new_aip[dst]);
    old_goptions = ACLITEM_GET_GOPTIONS(new_aip[dst]);

    /* apply the specified permissions change */
    switch (modechg)
    {
        case ACL_MODECHG_ADD:
            ACLITEM_SET_RIGHTS(new_aip[dst],
                               old_rights | ACLITEM_GET_RIGHTS(*mod_aip));
            break;
        case ACL_MODECHG_DEL:
            ACLITEM_SET_RIGHTS(new_aip[dst],
                               old_rights & ~ACLITEM_GET_RIGHTS(*mod_aip));
            break;
        case ACL_MODECHG_EQL:
            ACLITEM_SET_RIGHTS(new_aip[dst],
                               ACLITEM_GET_RIGHTS(*mod_aip));
            break;
    }

    new_rights = ACLITEM_GET_RIGHTS(new_aip[dst]);
    new_goptions = ACLITEM_GET_GOPTIONS(new_aip[dst]);

    /*
     * If the adjusted entry has no permissions, delete it from the list.
     */
    if (new_rights == ACL_NO_RIGHTS)
    {
        memmove(new_aip + dst,
                new_aip + dst + 1,
                (num - dst - 1) * sizeof(AclItem));
        /* Adjust array size to be 'num - 1' items */
        ARR_DIMS(new_acl)[0] = num - 1;
        SET_VARSIZE(new_acl, ACL_N_SIZE(num - 1));
    }

    /*
     * Remove abandoned privileges (cascading revoke).  Currently we can only
     * handle this when the grantee is not PUBLIC.
     */
    if ((old_goptions & ~new_goptions) != 0)
    {
        Assert(mod_aip->ai_grantee != ACL_ID_PUBLIC);
        new_acl = recursive_revoke(new_acl, mod_aip->ai_grantee,
                                   (old_goptions & ~new_goptions),
                                   ownerId, behavior);
    }

    return new_acl;
}

void check_is_member_of_role ( Oid  member,
Oid  role 
)
void ExecAlterDefaultPrivilegesStmt ( AlterDefaultPrivilegesStmt stmt  ) 

Definition at line 854 of file aclchk.c.

References ACL_ID_PUBLIC, ACL_OBJECT_FUNCTION, ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TYPE, AlterDefaultPrivilegesStmt::action, InternalDefaultACL::all_privs, DefElem::arg, GrantStmt::behavior, InternalDefaultACL::behavior, check_is_member_of_role(), AccessPriv::cols, DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, get_role_oid(), gettext_noop, GetUserId(), GrantStmt::grant_option, InternalDefaultACL::grant_option, GrantStmt::grantees, InternalDefaultACL::grantees, GrantStmt::is_grant, InternalDefaultACL::is_grant, lappend_oid(), lfirst, NIL, NULL, GrantStmt::objtype, InternalDefaultACL::objtype, AlterDefaultPrivilegesStmt::options, AccessPriv::priv_name, privilege_to_string(), InternalDefaultACL::privileges, GrantStmt::privileges, InternalDefaultACL::roleid, PrivGrantee::rolname, SetDefaultACLsInSchemas(), string_to_privilege(), and strVal.

Referenced by ProcessUtilitySlow().

{
    GrantStmt  *action = stmt->action;
    InternalDefaultACL iacls;
    ListCell   *cell;
    List       *rolenames = NIL;
    List       *nspnames = NIL;
    DefElem    *drolenames = NULL;
    DefElem    *dnspnames = NULL;
    AclMode     all_privileges;
    const char *errormsg;

    /* Deconstruct the "options" part of the statement */
    foreach(cell, stmt->options)
    {
        DefElem    *defel = (DefElem *) lfirst(cell);

        if (strcmp(defel->defname, "schemas") == 0)
        {
            if (dnspnames)
                ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
                         errmsg("conflicting or redundant options")));
            dnspnames = defel;
        }
        else if (strcmp(defel->defname, "roles") == 0)
        {
            if (drolenames)
                ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
                         errmsg("conflicting or redundant options")));
            drolenames = defel;
        }
        else
            elog(ERROR, "option \"%s\" not recognized", defel->defname);
    }

    if (dnspnames)
        nspnames = (List *) dnspnames->arg;
    if (drolenames)
        rolenames = (List *) drolenames->arg;

    /* Prepare the InternalDefaultACL representation of the statement */
    /* roleid to be filled below */
    /* nspid to be filled in SetDefaultACLsInSchemas */
    iacls.is_grant = action->is_grant;
    iacls.objtype = action->objtype;
    /* all_privs to be filled below */
    /* privileges to be filled below */
    iacls.grantees = NIL;       /* filled below */
    iacls.grant_option = action->grant_option;
    iacls.behavior = action->behavior;

    /*
     * Convert the PrivGrantee list into an Oid list.  Note that at this point
     * we insert an ACL_ID_PUBLIC into the list if an empty role name is
     * detected (which is what the grammar uses if PUBLIC is found), so
     * downstream there shouldn't be any additional work needed to support
     * this case.
     */
    foreach(cell, action->grantees)
    {
        PrivGrantee *grantee = (PrivGrantee *) lfirst(cell);

        if (grantee->rolname == NULL)
            iacls.grantees = lappend_oid(iacls.grantees, ACL_ID_PUBLIC);
        else
            iacls.grantees =
                lappend_oid(iacls.grantees,
                            get_role_oid(grantee->rolname, false));
    }

    /*
     * Convert action->privileges, a list of privilege strings, into an
     * AclMode bitmask.
     */
    switch (action->objtype)
    {
        case ACL_OBJECT_RELATION:
            all_privileges = ACL_ALL_RIGHTS_RELATION;
            errormsg = gettext_noop("invalid privilege type %s for relation");
            break;
        case ACL_OBJECT_SEQUENCE:
            all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
            errormsg = gettext_noop("invalid privilege type %s for sequence");
            break;
        case ACL_OBJECT_FUNCTION:
            all_privileges = ACL_ALL_RIGHTS_FUNCTION;
            errormsg = gettext_noop("invalid privilege type %s for function");
            break;
        case ACL_OBJECT_TYPE:
            all_privileges = ACL_ALL_RIGHTS_TYPE;
            errormsg = gettext_noop("invalid privilege type %s for type");
            break;
        default:
            elog(ERROR, "unrecognized GrantStmt.objtype: %d",
                 (int) action->objtype);
            /* keep compiler quiet */
            all_privileges = ACL_NO_RIGHTS;
            errormsg = NULL;
    }

    if (action->privileges == NIL)
    {
        iacls.all_privs = true;

        /*
         * will be turned into ACL_ALL_RIGHTS_* by the internal routines
         * depending on the object type
         */
        iacls.privileges = ACL_NO_RIGHTS;
    }
    else
    {
        iacls.all_privs = false;
        iacls.privileges = ACL_NO_RIGHTS;

        foreach(cell, action->privileges)
        {
            AccessPriv *privnode = (AccessPriv *) lfirst(cell);
            AclMode     priv;

            if (privnode->cols)
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_GRANT_OPERATION),
                    errmsg("default privileges cannot be set for columns")));

            if (privnode->priv_name == NULL)    /* parser mistake? */
                elog(ERROR, "AccessPriv node must specify privilege");
            priv = string_to_privilege(privnode->priv_name);

            if (priv & ~((AclMode) all_privileges))
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_GRANT_OPERATION),
                         errmsg(errormsg, privilege_to_string(priv))));

            iacls.privileges |= priv;
        }
    }

    if (rolenames == NIL)
    {
        /* Set permissions for myself */
        iacls.roleid = GetUserId();

        SetDefaultACLsInSchemas(&iacls, nspnames);
    }
    else
    {
        /* Look up the role OIDs and do permissions checks */
        ListCell   *rolecell;

        foreach(rolecell, rolenames)
        {
            char       *rolename = strVal(lfirst(rolecell));

            iacls.roleid = get_role_oid(rolename, false);

            /*
             * We insist that calling user be a member of each target role. If
             * he has that, he could become that role anyway via SET ROLE, so
             * FOR ROLE is just a syntactic convenience and doesn't give any
             * special privileges.
             */
            check_is_member_of_role(GetUserId(), iacls.roleid);

            SetDefaultACLsInSchemas(&iacls, nspnames);
        }
    }
}

void ExecuteGrantStmt ( GrantStmt stmt  ) 

Definition at line 388 of file aclchk.c.

References ACL_ALL_RIGHTS_RELATION, ACL_ID_PUBLIC, ACL_OBJECT_DATABASE, ACL_OBJECT_DOMAIN, ACL_OBJECT_FDW, ACL_OBJECT_FOREIGN_SERVER, ACL_OBJECT_FUNCTION, ACL_OBJECT_LANGUAGE, ACL_OBJECT_LARGEOBJECT, ACL_OBJECT_NAMESPACE, ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TABLESPACE, ACL_OBJECT_TYPE, ACL_TARGET_ALL_IN_SCHEMA, ACL_TARGET_OBJECT, InternalGrant::all_privs, GrantStmt::behavior, InternalGrant::behavior, InternalGrant::col_privs, AccessPriv::cols, elog, ereport, errcode(), errmsg(), ERROR, ExecGrantStmt_oids(), get_role_oid(), gettext_noop, GrantStmt::grant_option, InternalGrant::grant_option, GrantStmt::grantees, InternalGrant::grantees, GrantStmt::is_grant, InternalGrant::is_grant, lappend(), lappend_oid(), lfirst, NIL, NULL, objectNamesToOids(), GrantStmt::objects, InternalGrant::objects, objectsInSchemaToOids(), GrantStmt::objtype, InternalGrant::objtype, AccessPriv::priv_name, privilege_to_string(), InternalGrant::privileges, GrantStmt::privileges, PrivGrantee::rolname, string_to_privilege(), and GrantStmt::targtype.

Referenced by standard_ProcessUtility().

{
    InternalGrant istmt;
    ListCell   *cell;
    const char *errormsg;
    AclMode     all_privileges;

    /*
     * Turn the regular GrantStmt into the InternalGrant form.
     */
    istmt.is_grant = stmt->is_grant;
    istmt.objtype = stmt->objtype;

    /* Collect the OIDs of the target objects */
    switch (stmt->targtype)
    {
        case ACL_TARGET_OBJECT:
            istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects);
            break;
        case ACL_TARGET_ALL_IN_SCHEMA:
            istmt.objects = objectsInSchemaToOids(stmt->objtype, stmt->objects);
            break;
            /* ACL_TARGET_DEFAULTS should not be seen here */
        default:
            elog(ERROR, "unrecognized GrantStmt.targtype: %d",
                 (int) stmt->targtype);
    }

    /* all_privs to be filled below */
    /* privileges to be filled below */
    istmt.col_privs = NIL;      /* may get filled below */
    istmt.grantees = NIL;       /* filled below */
    istmt.grant_option = stmt->grant_option;
    istmt.behavior = stmt->behavior;

    /*
     * Convert the PrivGrantee list into an Oid list.  Note that at this point
     * we insert an ACL_ID_PUBLIC into the list if an empty role name is
     * detected (which is what the grammar uses if PUBLIC is found), so
     * downstream there shouldn't be any additional work needed to support
     * this case.
     */
    foreach(cell, stmt->grantees)
    {
        PrivGrantee *grantee = (PrivGrantee *) lfirst(cell);

        if (grantee->rolname == NULL)
            istmt.grantees = lappend_oid(istmt.grantees, ACL_ID_PUBLIC);
        else
            istmt.grantees =
                lappend_oid(istmt.grantees,
                            get_role_oid(grantee->rolname, false));
    }

    /*
     * Convert stmt->privileges, a list of AccessPriv nodes, into an AclMode
     * bitmask.  Note: objtype can't be ACL_OBJECT_COLUMN.
     */
    switch (stmt->objtype)
    {
            /*
             * Because this might be a sequence, we test both relation and
             * sequence bits, and later do a more limited test when we know
             * the object type.
             */
        case ACL_OBJECT_RELATION:
            all_privileges = ACL_ALL_RIGHTS_RELATION | ACL_ALL_RIGHTS_SEQUENCE;
            errormsg = gettext_noop("invalid privilege type %s for relation");
            break;
        case ACL_OBJECT_SEQUENCE:
            all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
            errormsg = gettext_noop("invalid privilege type %s for sequence");
            break;
        case ACL_OBJECT_DATABASE:
            all_privileges = ACL_ALL_RIGHTS_DATABASE;
            errormsg = gettext_noop("invalid privilege type %s for database");
            break;
        case ACL_OBJECT_DOMAIN:
            all_privileges = ACL_ALL_RIGHTS_TYPE;
            errormsg = gettext_noop("invalid privilege type %s for domain");
            break;
        case ACL_OBJECT_FUNCTION:
            all_privileges = ACL_ALL_RIGHTS_FUNCTION;
            errormsg = gettext_noop("invalid privilege type %s for function");
            break;
        case ACL_OBJECT_LANGUAGE:
            all_privileges = ACL_ALL_RIGHTS_LANGUAGE;
            errormsg = gettext_noop("invalid privilege type %s for language");
            break;
        case ACL_OBJECT_LARGEOBJECT:
            all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
            errormsg = gettext_noop("invalid privilege type %s for large object");
            break;
        case ACL_OBJECT_NAMESPACE:
            all_privileges = ACL_ALL_RIGHTS_NAMESPACE;
            errormsg = gettext_noop("invalid privilege type %s for schema");
            break;
        case ACL_OBJECT_TABLESPACE:
            all_privileges = ACL_ALL_RIGHTS_TABLESPACE;
            errormsg = gettext_noop("invalid privilege type %s for tablespace");
            break;
        case ACL_OBJECT_TYPE:
            all_privileges = ACL_ALL_RIGHTS_TYPE;
            errormsg = gettext_noop("invalid privilege type %s for type");
            break;
        case ACL_OBJECT_FDW:
            all_privileges = ACL_ALL_RIGHTS_FDW;
            errormsg = gettext_noop("invalid privilege type %s for foreign-data wrapper");
            break;
        case ACL_OBJECT_FOREIGN_SERVER:
            all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
            errormsg = gettext_noop("invalid privilege type %s for foreign server");
            break;
        default:
            elog(ERROR, "unrecognized GrantStmt.objtype: %d",
                 (int) stmt->objtype);
            /* keep compiler quiet */
            all_privileges = ACL_NO_RIGHTS;
            errormsg = NULL;
    }

    if (stmt->privileges == NIL)
    {
        istmt.all_privs = true;

        /*
         * will be turned into ACL_ALL_RIGHTS_* by the internal routines
         * depending on the object type
         */
        istmt.privileges = ACL_NO_RIGHTS;
    }
    else
    {
        istmt.all_privs = false;
        istmt.privileges = ACL_NO_RIGHTS;

        foreach(cell, stmt->privileges)
        {
            AccessPriv *privnode = (AccessPriv *) lfirst(cell);
            AclMode     priv;

            /*
             * If it's a column-level specification, we just set it aside in
             * col_privs for the moment; but insist it's for a relation.
             */
            if (privnode->cols)
            {
                if (stmt->objtype != ACL_OBJECT_RELATION)
                    ereport(ERROR,
                            (errcode(ERRCODE_INVALID_GRANT_OPERATION),
                             errmsg("column privileges are only valid for relations")));
                istmt.col_privs = lappend(istmt.col_privs, privnode);
                continue;
            }

            if (privnode->priv_name == NULL)    /* parser mistake? */
                elog(ERROR, "AccessPriv node must specify privilege or columns");
            priv = string_to_privilege(privnode->priv_name);

            if (priv & ~((AclMode) all_privileges))
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_GRANT_OPERATION),
                         errmsg(errormsg, privilege_to_string(priv))));

            istmt.privileges |= priv;
        }
    }

    ExecGrantStmt_oids(&istmt);
}

Oid get_role_oid ( const char *  rolname,
bool  missing_ok 
)
Acl* get_user_default_acl ( GrantObjectType  objtype,
Oid  ownerId,
Oid  nsp_oid 
)

Definition at line 5120 of file aclchk.c.

References ACL_OBJECT_FUNCTION, ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TYPE, acldefault(), aclequal(), aclitemsort(), aclmerge(), get_default_acl_internal(), InvalidOid, IsBootstrapProcessingMode, and NULL.

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

{
    Acl        *result;
    Acl        *glob_acl;
    Acl        *schema_acl;
    Acl        *def_acl;
    char        defaclobjtype;

    /*
     * Use NULL during bootstrap, since pg_default_acl probably isn't there
     * yet.
     */
    if (IsBootstrapProcessingMode())
        return NULL;

    /* Check if object type is supported in pg_default_acl */
    switch (objtype)
    {
        case ACL_OBJECT_RELATION:
            defaclobjtype = DEFACLOBJ_RELATION;
            break;

        case ACL_OBJECT_SEQUENCE:
            defaclobjtype = DEFACLOBJ_SEQUENCE;
            break;

        case ACL_OBJECT_FUNCTION:
            defaclobjtype = DEFACLOBJ_FUNCTION;
            break;

        case ACL_OBJECT_TYPE:
            defaclobjtype = DEFACLOBJ_TYPE;
            break;

        default:
            return NULL;
    }

    /* Look up the relevant pg_default_acl entries */
    glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
    schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);

    /* Quick out if neither entry exists */
    if (glob_acl == NULL && schema_acl == NULL)
        return NULL;

    /* We need to know the hard-wired default value, too */
    def_acl = acldefault(objtype, ownerId);

    /* If there's no global entry, substitute the hard-wired default */
    if (glob_acl == NULL)
        glob_acl = def_acl;

    /* Merge in any per-schema privileges */
    result = aclmerge(glob_acl, schema_acl, ownerId);

    /*
     * For efficiency, we want to return NULL if the result equals default.
     * This requires sorting both arrays to get an accurate comparison.
     */
    aclitemsort(result);
    aclitemsort(def_acl);
    if (aclequal(result, def_acl))
        result = NULL;

    return result;
}

bool has_createrole_privilege ( Oid  roleid  ) 

Definition at line 5064 of file aclchk.c.

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

Referenced by check_object_ownership(), and have_createrole_privilege().

{
    bool        result = false;
    HeapTuple   utup;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
    if (HeapTupleIsValid(utup))
    {
        result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
        ReleaseSysCache(utup);
    }
    return result;
}

bool has_privs_of_role ( Oid  member,
Oid  role 
)
Datum hash_aclitem ( PG_FUNCTION_ARGS   ) 

Definition at line 712 of file acl.c.

References AclItem::ai_grantee, AclItem::ai_grantor, AclItem::ai_privs, PG_GETARG_ACLITEM_P, and PG_RETURN_UINT32.

{
    AclItem    *a = PG_GETARG_ACLITEM_P(0);

    /* not very bright, but avoids any issue of padding in struct */
    PG_RETURN_UINT32((uint32) (a->ai_privs + a->ai_grantee + a->ai_grantor));
}

void initialize_acl ( void   ) 

Definition at line 4606 of file acl.c.

References AUTHMEMROLEMEM, CacheRegisterSyscacheCallback(), IsBootstrapProcessingMode, and RoleMembershipCacheCallback().

Referenced by InitPostgres().

{
    if (!IsBootstrapProcessingMode())
    {
        /*
         * In normal mode, set a callback on any syscache invalidation of
         * pg_auth_members rows
         */
        CacheRegisterSyscacheCallback(AUTHMEMROLEMEM,
                                      RoleMembershipCacheCallback,
                                      (Datum) 0);
    }
}

bool is_admin_of_role ( Oid  member,
Oid  role 
)

Definition at line 4909 of file acl.c.

References AUTHMEMMEMROLE, GETSTRUCT, i, lfirst_oid, list_append_unique_oid(), list_free(), list_make1_oid, catclist::members, catclist::n_members, ObjectIdGetDatum, ReleaseSysCacheList, SearchSysCacheList1, superuser_arg(), and catctup::tuple.

Referenced by AddRoleMems(), DelRoleMems(), and pg_role_aclcheck().

{
    bool        result = false;
    List       *roles_list;
    ListCell   *l;

    /* Fast path for simple case */
    if (member == role)
        return true;

    /* Superusers have every privilege, so are part of every role */
    if (superuser_arg(member))
        return true;

    /*
     * Find all the roles that member is a member of, including multi-level
     * recursion.  We build a list in the same way that is_member_of_role does
     * to track visited and unvisited roles.
     */
    roles_list = list_make1_oid(member);

    foreach(l, roles_list)
    {
        Oid         memberid = lfirst_oid(l);
        CatCList   *memlist;
        int         i;

        /* Find roles that memberid is directly a member of */
        memlist = SearchSysCacheList1(AUTHMEMMEMROLE,
                                      ObjectIdGetDatum(memberid));
        for (i = 0; i < memlist->n_members; i++)
        {
            HeapTuple   tup = &memlist->members[i]->tuple;
            Oid         otherid = ((Form_pg_auth_members) GETSTRUCT(tup))->roleid;

            if (otherid == role &&
                ((Form_pg_auth_members) GETSTRUCT(tup))->admin_option)
            {
                /* Found what we came for, so can stop searching */
                result = true;
                break;
            }

            roles_list = list_append_unique_oid(roles_list, otherid);
        }
        ReleaseSysCacheList(memlist);
        if (result)
            break;
    }

    list_free(roles_list);

    return result;
}

bool is_member_of_role ( Oid  member,
Oid  role 
)

Definition at line 4849 of file acl.c.

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

Referenced by check_is_member_of_role(), check_role(), and pg_role_aclcheck().

{
    /* Fast path for simple case */
    if (member == role)
        return true;

    /* Superusers have every privilege, so are part of every role */
    if (superuser_arg(member))
        return true;

    /*
     * Find all the roles that member is a member of, including multi-level
     * recursion, then see if target role is any one of them.
     */
    return list_member_oid(roles_is_member_of(member), role);
}

bool is_member_of_role_nosuper ( Oid  member,
Oid  role 
)

Definition at line 4887 of file acl.c.

References list_member_oid(), and roles_is_member_of().

Referenced by AddRoleMems(), and is_member().

{
    /* Fast path for simple case */
    if (member == role)
        return true;

    /*
     * Find all the roles that member is a member of, including multi-level
     * recursion, then see if target role is any one of them.
     */
    return list_member_oid(roles_is_member_of(member), role);
}

Acl* make_empty_acl ( void   ) 

Definition at line 397 of file acl.c.

References allocacl().

Referenced by SetDefaultACL().

{
    return allocacl(0);
}

Datum makeaclitem ( PG_FUNCTION_ARGS   ) 

Definition at line 1575 of file acl.c.

References ACL_NO_RIGHTS, ACLITEM_SET_PRIVS_GOPTIONS, AclItem::ai_grantee, AclItem::ai_grantor, convert_priv_string(), palloc(), PG_GETARG_BOOL, PG_GETARG_OID, PG_GETARG_TEXT_P, and PG_RETURN_ACLITEM_P.

{
    Oid         grantee = PG_GETARG_OID(0);
    Oid         grantor = PG_GETARG_OID(1);
    text       *privtext = PG_GETARG_TEXT_P(2);
    bool        goption = PG_GETARG_BOOL(3);
    AclItem    *result;
    AclMode     priv;

    priv = convert_priv_string(privtext);

    result = (AclItem *) palloc(sizeof(AclItem));

    result->ai_grantee = grantee;
    result->ai_grantor = grantor;

    ACLITEM_SET_PRIVS_GOPTIONS(*result, priv,
                               (goption ? priv : ACL_NO_RIGHTS));

    PG_RETURN_ACLITEM_P(result);
}

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

Definition at line 4280 of file aclchk.c.

References ACLMASK_ANY, and pg_attribute_aclmask().

Referenced by checkFkeyPermissions(), column_privilege_check(), and ExecCheckRTEPerms().

{
    if (pg_attribute_aclmask(table_oid, attnum, roleid, mode, ACLMASK_ANY) != 0)
        return ACLCHECK_OK;
    else
        return ACLCHECK_NO_PRIV;
}

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

Definition at line 4309 of file aclchk.c.

References ACLMASK_ALL, ACLMASK_ANY, Anum_pg_attribute_attacl, ATTNUM, GETSTRUCT, heap_attisnull(), HeapTupleIsValid, Int16GetDatum, ObjectIdGetDatum, pg_attribute_aclmask(), ReleaseSysCache(), RELOID, SearchSysCache1, and SearchSysCache2.

Referenced by ExecCheckRTEPerms(), has_any_column_privilege_id(), has_any_column_privilege_id_id(), has_any_column_privilege_id_name(), has_any_column_privilege_name(), has_any_column_privilege_name_id(), and has_any_column_privilege_name_name().

{
    AclResult   result;
    HeapTuple   classTuple;
    Form_pg_class classForm;
    AttrNumber  nattrs;
    AttrNumber  curr_att;

    /*
     * Must fetch pg_class row to check number of attributes.  As in
     * pg_attribute_aclmask, we prefer to return "no privileges" instead of
     * throwing an error if we get any unexpected lookup errors.
     */
    classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
    if (!HeapTupleIsValid(classTuple))
        return ACLCHECK_NO_PRIV;
    classForm = (Form_pg_class) GETSTRUCT(classTuple);

    nattrs = classForm->relnatts;

    ReleaseSysCache(classTuple);

    /*
     * Initialize result in case there are no non-dropped columns.  We want to
     * report failure in such cases for either value of 'how'.
     */
    result = ACLCHECK_NO_PRIV;

    for (curr_att = 1; curr_att <= nattrs; curr_att++)
    {
        HeapTuple   attTuple;
        AclMode     attmask;

        attTuple = SearchSysCache2(ATTNUM,
                                   ObjectIdGetDatum(table_oid),
                                   Int16GetDatum(curr_att));
        if (!HeapTupleIsValid(attTuple))
            continue;

        /* ignore dropped columns */
        if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
        {
            ReleaseSysCache(attTuple);
            continue;
        }

        /*
         * Here we hard-wire knowledge that the default ACL for a column
         * grants no privileges, so that we can fall out quickly in the very
         * common case where attacl is null.
         */
        if (heap_attisnull(attTuple, Anum_pg_attribute_attacl))
            attmask = 0;
        else
            attmask = pg_attribute_aclmask(table_oid, curr_att, roleid,
                                           mode, ACLMASK_ANY);

        ReleaseSysCache(attTuple);

        if (attmask != 0)
        {
            result = ACLCHECK_OK;
            if (how == ACLMASK_ANY)
                break;          /* succeed on any success */
        }
        else
        {
            result = ACLCHECK_NO_PRIV;
            if (how == ACLMASK_ALL)
                break;          /* fail on any failure */
        }
    }

    return result;
}

AclMode pg_attribute_aclmask ( Oid  table_oid,
AttrNumber  attnum,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 3516 of file aclchk.c.

References aclmask(), Anum_pg_attribute_attacl, ATTNUM, DatumGetAclP, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, Int16GetDatum, ObjectIdGetDatum, pfree(), ReleaseSysCache(), RELOID, SearchSysCache1, SearchSysCache2, and SysCacheGetAttr().

Referenced by pg_aclmask(), pg_attribute_aclcheck(), and pg_attribute_aclcheck_all().

{
    AclMode     result;
    HeapTuple   classTuple;
    HeapTuple   attTuple;
    Form_pg_class classForm;
    Form_pg_attribute attributeForm;
    Datum       aclDatum;
    bool        isNull;
    Acl        *acl;
    Oid         ownerId;

    /*
     * First, get the column's ACL from its pg_attribute entry
     */
    attTuple = SearchSysCache2(ATTNUM,
                               ObjectIdGetDatum(table_oid),
                               Int16GetDatum(attnum));
    if (!HeapTupleIsValid(attTuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_COLUMN),
                 errmsg("attribute %d of relation with OID %u does not exist",
                        attnum, table_oid)));
    attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);

    /* Throw error on dropped columns, too */
    if (attributeForm->attisdropped)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_COLUMN),
                 errmsg("attribute %d of relation with OID %u does not exist",
                        attnum, table_oid)));

    aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
                               &isNull);

    /*
     * Here we hard-wire knowledge that the default ACL for a column grants no
     * privileges, so that we can fall out quickly in the very common case
     * where attacl is null.
     */
    if (isNull)
    {
        ReleaseSysCache(attTuple);
        return 0;
    }

    /*
     * Must get the relation's ownerId from pg_class.  Since we already found
     * a pg_attribute entry, the only likely reason for this to fail is that a
     * concurrent DROP of the relation committed since then (which could only
     * happen if we don't have lock on the relation).  We prefer to report "no
     * privileges" rather than failing in such a case, so as to avoid unwanted
     * failures in has_column_privilege() tests.
     */
    classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
    if (!HeapTupleIsValid(classTuple))
    {
        ReleaseSysCache(attTuple);
        return 0;
    }
    classForm = (Form_pg_class) GETSTRUCT(classTuple);

    ownerId = classForm->relowner;

    ReleaseSysCache(classTuple);

    /* detoast column's ACL if necessary */
    acl = DatumGetAclP(aclDatum);

    result = aclmask(acl, roleid, ownerId, mask, how);

    /* if we have a detoasted copy, free it */
    if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
        pfree(acl);

    ReleaseSysCache(attTuple);

    return result;
}

AclResult pg_class_aclcheck ( Oid  table_oid,
Oid  roleid,
AclMode  mode 
)
AclMode pg_class_aclmask ( Oid  table_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 3601 of file aclchk.c.

References ACL_DELETE, ACL_INSERT, ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, ACL_TRUNCATE, ACL_UPDATE, ACL_USAGE, acldefault(), aclmask(), allowSystemTableMods, Anum_pg_class_relacl, DatumGetAclP, DatumGetPointer, DEBUG2, elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_rolcatupdate(), HeapTupleIsValid, IsSystemClass(), ObjectIdGetDatum, pfree(), ReleaseSysCache(), RELKIND_SEQUENCE, RELKIND_VIEW, RELOID, SearchSysCache1, superuser_arg(), and SysCacheGetAttr().

Referenced by ExecCheckRTEPerms(), pg_aclmask(), and pg_class_aclcheck().

{
    AclMode     result;
    HeapTuple   tuple;
    Form_pg_class classForm;
    Datum       aclDatum;
    bool        isNull;
    Acl        *acl;
    Oid         ownerId;

    /*
     * Must get the relation's tuple from pg_class
     */
    tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_TABLE),
                 errmsg("relation with OID %u does not exist",
                        table_oid)));
    classForm = (Form_pg_class) GETSTRUCT(tuple);

    /*
     * Deny anyone permission to update a system catalog unless
     * pg_authid.rolcatupdate is set.   (This is to let superusers protect
     * themselves from themselves.)  Also allow it if allowSystemTableMods.
     *
     * As of 7.4 we have some updatable system views; those shouldn't be
     * protected in this way.  Assume the view rules can take care of
     * themselves.  ACL_USAGE is if we ever have system sequences.
     */
    if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE)) &&
        IsSystemClass(classForm) &&
        classForm->relkind != RELKIND_VIEW &&
        !has_rolcatupdate(roleid) &&
        !allowSystemTableMods)
    {
#ifdef ACLDEBUG
        elog(DEBUG2, "permission denied for system catalog update");
#endif
        mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE);
    }

    /*
     * Otherwise, superusers bypass all permission-checking.
     */
    if (superuser_arg(roleid))
    {
#ifdef ACLDEBUG
        elog(DEBUG2, "OID %u is superuser, home free", roleid);
#endif
        ReleaseSysCache(tuple);
        return mask;
    }

    /*
     * Normal case: get the relation's ACL from pg_class
     */
    ownerId = classForm->relowner;

    aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
                               &isNull);
    if (isNull)
    {
        /* No ACL, so build default ACL */
        switch (classForm->relkind)
        {
            case RELKIND_SEQUENCE:
                acl = acldefault(ACL_OBJECT_SEQUENCE, ownerId);
                break;
            default:
                acl = acldefault(ACL_OBJECT_RELATION, ownerId);
                break;
        }
        aclDatum = (Datum) 0;
    }
    else
    {
        /* detoast rel's ACL if necessary */
        acl = DatumGetAclP(aclDatum);
    }

    result = aclmask(acl, roleid, ownerId, mask, how);

    /* if we have a detoasted copy, free it */
    if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
        pfree(acl);

    ReleaseSysCache(tuple);

    return result;
}

bool pg_class_ownercheck ( Oid  class_oid,
Oid  roleid 
)
bool pg_collation_ownercheck ( Oid  coll_oid,
Oid  roleid 
)

Definition at line 4962 of file aclchk.c.

References COLLOID, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().

Referenced by check_object_ownership().

{
    HeapTuple   tuple;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    tuple = SearchSysCache1(COLLOID, ObjectIdGetDatum(coll_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("collation with OID %u does not exist", coll_oid)));

    ownerId = ((Form_pg_collation) GETSTRUCT(tuple))->collowner;

    ReleaseSysCache(tuple);

    return has_privs_of_role(roleid, ownerId);
}

bool pg_conversion_ownercheck ( Oid  conv_oid,
Oid  roleid 
)

Definition at line 4988 of file aclchk.c.

References CONVOID, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().

Referenced by check_object_ownership().

{
    HeapTuple   tuple;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    tuple = SearchSysCache1(CONVOID, ObjectIdGetDatum(conv_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("conversion with OID %u does not exist", conv_oid)));

    ownerId = ((Form_pg_conversion) GETSTRUCT(tuple))->conowner;

    ReleaseSysCache(tuple);

    return has_privs_of_role(roleid, ownerId);
}

AclResult pg_database_aclcheck ( Oid  db_oid,
Oid  roleid,
AclMode  mode 
)
AclMode pg_database_aclmask ( Oid  db_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 3698 of file aclchk.c.

References ACL_OBJECT_DATABASE, acldefault(), aclmask(), Anum_pg_database_datacl, DATABASEOID, DatumGetAclP, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, pfree(), ReleaseSysCache(), SearchSysCache1, superuser_arg(), and SysCacheGetAttr().

Referenced by pg_aclmask(), and pg_database_aclcheck().

{
    AclMode     result;
    HeapTuple   tuple;
    Datum       aclDatum;
    bool        isNull;
    Acl        *acl;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return mask;

    /*
     * Get the database's ACL from pg_database
     */
    tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_DATABASE),
                 errmsg("database with OID %u does not exist", db_oid)));

    ownerId = ((Form_pg_database) GETSTRUCT(tuple))->datdba;

    aclDatum = SysCacheGetAttr(DATABASEOID, tuple, Anum_pg_database_datacl,
                               &isNull);
    if (isNull)
    {
        /* No ACL, so build default ACL */
        acl = acldefault(ACL_OBJECT_DATABASE, ownerId);
        aclDatum = (Datum) 0;
    }
    else
    {
        /* detoast ACL if necessary */
        acl = DatumGetAclP(aclDatum);
    }

    result = aclmask(acl, roleid, ownerId, mask, how);

    /* if we have a detoasted copy, free it */
    if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
        pfree(acl);

    ReleaseSysCache(tuple);

    return result;
}

bool pg_database_ownercheck ( Oid  db_oid,
Oid  roleid 
)

Definition at line 4936 of file aclchk.c.

References DATABASEOID, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().

Referenced by AlterDatabase(), AlterDatabaseOwner(), AlterDatabaseSet(), AlterRoleSet(), analyze_rel(), check_object_ownership(), createdb(), CreateProceduralLanguage(), dropdb(), movedb(), ReindexDatabase(), RenameDatabase(), and vacuum_rel().

{
    HeapTuple   tuple;
    Oid         dba;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_DATABASE),
                 errmsg("database with OID %u does not exist", db_oid)));

    dba = ((Form_pg_database) GETSTRUCT(tuple))->datdba;

    ReleaseSysCache(tuple);

    return has_privs_of_role(roleid, dba);
}

bool pg_event_trigger_ownercheck ( Oid  et_oid,
Oid  roleid 
)

Definition at line 4909 of file aclchk.c.

References ereport, errcode(), errmsg(), ERROR, EVENTTRIGGEROID, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().

Referenced by AlterEventTrigger(), AlterEventTriggerOwner_internal(), and check_object_ownership().

{
    HeapTuple   tuple;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    tuple = SearchSysCache1(EVENTTRIGGEROID, ObjectIdGetDatum(et_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("event trigger with OID %u does not exist",
                        et_oid)));

    ownerId = ((Form_pg_event_trigger) GETSTRUCT(tuple))->evtowner;

    ReleaseSysCache(tuple);

    return has_privs_of_role(roleid, ownerId);
}

bool pg_extension_ownercheck ( Oid  ext_oid,
Oid  roleid 
)

Definition at line 5014 of file aclchk.c.

References AccessShareLock, BTEqualStrategyNumber, ereport, errcode(), errmsg(), ERROR, ExtensionOidIndexId, ExtensionRelationId, GETSTRUCT, has_privs_of_role(), heap_close, heap_open(), HeapTupleIsValid, ObjectIdAttributeNumber, ObjectIdGetDatum, ScanKeyInit(), SnapshotNow, superuser_arg(), systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by AlterExtensionNamespace(), check_object_ownership(), ExecAlterExtensionContentsStmt(), and ExecAlterExtensionStmt().

{
    Relation    pg_extension;
    ScanKeyData entry[1];
    SysScanDesc scan;
    HeapTuple   tuple;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    /* There's no syscache for pg_extension, so do it the hard way */
    pg_extension = heap_open(ExtensionRelationId, AccessShareLock);

    ScanKeyInit(&entry[0],
                ObjectIdAttributeNumber,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(ext_oid));

    scan = systable_beginscan(pg_extension,
                              ExtensionOidIndexId, true,
                              SnapshotNow, 1, entry);

    tuple = systable_getnext(scan);
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("extension with OID %u does not exist", ext_oid)));

    ownerId = ((Form_pg_extension) GETSTRUCT(tuple))->extowner;

    systable_endscan(scan);
    heap_close(pg_extension, AccessShareLock);

    return has_privs_of_role(roleid, ownerId);
}

AclResult pg_foreign_data_wrapper_aclcheck ( Oid  fdw_oid,
Oid  roleid,
AclMode  mode 
)
AclMode pg_foreign_data_wrapper_aclmask ( Oid  fdw_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 4078 of file aclchk.c.

References ACL_OBJECT_FDW, acldefault(), aclmask(), Anum_pg_foreign_data_wrapper_fdwacl, DatumGetAclP, DatumGetPointer, ereport, errmsg(), ERROR, FOREIGNDATAWRAPPEROID, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, pfree(), ReleaseSysCache(), SearchSysCache1, superuser_arg(), and SysCacheGetAttr().

Referenced by pg_aclmask(), and pg_foreign_data_wrapper_aclcheck().

{
    AclMode     result;
    HeapTuple   tuple;
    Datum       aclDatum;
    bool        isNull;
    Acl        *acl;
    Oid         ownerId;

    Form_pg_foreign_data_wrapper fdwForm;

    /* Bypass permission checks for superusers */
    if (superuser_arg(roleid))
        return mask;

    /*
     * Must get the FDW's tuple from pg_foreign_data_wrapper
     */
    tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(fdw_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errmsg("foreign-data wrapper with OID %u does not exist",
                        fdw_oid)));
    fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);

    /*
     * Normal case: get the FDW's ACL from pg_foreign_data_wrapper
     */
    ownerId = fdwForm->fdwowner;

    aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
                               Anum_pg_foreign_data_wrapper_fdwacl, &isNull);
    if (isNull)
    {
        /* No ACL, so build default ACL */
        acl = acldefault(ACL_OBJECT_FDW, ownerId);
        aclDatum = (Datum) 0;
    }
    else
    {
        /* detoast rel's ACL if necessary */
        acl = DatumGetAclP(aclDatum);
    }

    result = aclmask(acl, roleid, ownerId, mask, how);

    /* if we have a detoasted copy, free it */
    if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
        pfree(acl);

    ReleaseSysCache(tuple);

    return result;
}

bool pg_foreign_data_wrapper_ownercheck ( Oid  srv_oid,
Oid  roleid 
)

Definition at line 4855 of file aclchk.c.

References ereport, errcode(), errmsg(), ERROR, FOREIGNDATAWRAPPEROID, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().

Referenced by check_object_ownership().

{
    HeapTuple   tuple;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(srv_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("foreign-data wrapper with OID %u does not exist",
                        srv_oid)));

    ownerId = ((Form_pg_foreign_data_wrapper) GETSTRUCT(tuple))->fdwowner;

    ReleaseSysCache(tuple);

    return has_privs_of_role(roleid, ownerId);
}

AclResult pg_foreign_server_aclcheck ( Oid  srv_oid,
Oid  roleid,
AclMode  mode 
)
AclMode pg_foreign_server_aclmask ( Oid  srv_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 4139 of file aclchk.c.

References ACL_OBJECT_FOREIGN_SERVER, acldefault(), aclmask(), Anum_pg_foreign_server_srvacl, DatumGetAclP, DatumGetPointer, ereport, errmsg(), ERROR, FOREIGNSERVEROID, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, pfree(), ReleaseSysCache(), SearchSysCache1, superuser_arg(), and SysCacheGetAttr().

Referenced by pg_aclmask(), and pg_foreign_server_aclcheck().

{
    AclMode     result;
    HeapTuple   tuple;
    Datum       aclDatum;
    bool        isNull;
    Acl        *acl;
    Oid         ownerId;

    Form_pg_foreign_server srvForm;

    /* Bypass permission checks for superusers */
    if (superuser_arg(roleid))
        return mask;

    /*
     * Must get the FDW's tuple from pg_foreign_data_wrapper
     */
    tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srv_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errmsg("foreign server with OID %u does not exist",
                        srv_oid)));
    srvForm = (Form_pg_foreign_server) GETSTRUCT(tuple);

    /*
     * Normal case: get the foreign server's ACL from pg_foreign_server
     */
    ownerId = srvForm->srvowner;

    aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
                               Anum_pg_foreign_server_srvacl, &isNull);
    if (isNull)
    {
        /* No ACL, so build default ACL */
        acl = acldefault(ACL_OBJECT_FOREIGN_SERVER, ownerId);
        aclDatum = (Datum) 0;
    }
    else
    {
        /* detoast rel's ACL if necessary */
        acl = DatumGetAclP(aclDatum);
    }

    result = aclmask(acl, roleid, ownerId, mask, how);

    /* if we have a detoasted copy, free it */
    if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
        pfree(acl);

    ReleaseSysCache(tuple);

    return result;
}

bool pg_foreign_server_ownercheck ( Oid  srv_oid,
Oid  roleid 
)

Definition at line 4882 of file aclchk.c.

References ereport, errcode(), errmsg(), ERROR, FOREIGNSERVEROID, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().

Referenced by AlterForeignServer(), AlterForeignServerOwner_internal(), check_object_ownership(), and user_mapping_ddl_aclcheck().

{
    HeapTuple   tuple;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srv_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("foreign server with OID %u does not exist",
                        srv_oid)));

    ownerId = ((Form_pg_foreign_server) GETSTRUCT(tuple))->srvowner;

    ReleaseSysCache(tuple);

    return has_privs_of_role(roleid, ownerId);
}

AclResult pg_language_aclcheck ( Oid  lang_oid,
Oid  roleid,
AclMode  mode 
)
AclMode pg_language_aclmask ( Oid  lang_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 3806 of file aclchk.c.

References ACL_OBJECT_LANGUAGE, acldefault(), aclmask(), Anum_pg_language_lanacl, DatumGetAclP, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, LANGOID, ObjectIdGetDatum, pfree(), ReleaseSysCache(), SearchSysCache1, superuser_arg(), and SysCacheGetAttr().

Referenced by pg_aclmask(), and pg_language_aclcheck().

{
    AclMode     result;
    HeapTuple   tuple;
    Datum       aclDatum;
    bool        isNull;
    Acl        *acl;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return mask;

    /*
     * Get the language's ACL from pg_language
     */
    tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(lang_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("language with OID %u does not exist", lang_oid)));

    ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner;

    aclDatum = SysCacheGetAttr(LANGOID, tuple, Anum_pg_language_lanacl,
                               &isNull);
    if (isNull)
    {
        /* No ACL, so build default ACL */
        acl = acldefault(ACL_OBJECT_LANGUAGE, ownerId);
        aclDatum = (Datum) 0;
    }
    else
    {
        /* detoast ACL if necessary */
        acl = DatumGetAclP(aclDatum);
    }

    result = aclmask(acl, roleid, ownerId, mask, how);

    /* if we have a detoasted copy, free it */
    if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
        pfree(acl);

    ReleaseSysCache(tuple);

    return result;
}

bool pg_language_ownercheck ( Oid  lan_oid,
Oid  roleid 
)

Definition at line 4622 of file aclchk.c.

References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, LANGOID, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().

Referenced by check_object_ownership(), and create_proc_lang().

{
    HeapTuple   tuple;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(lan_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_FUNCTION),
                 errmsg("language with OID %u does not exist", lan_oid)));

    ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner;

    ReleaseSysCache(tuple);

    return has_privs_of_role(roleid, ownerId);
}

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

Definition at line 4442 of file aclchk.c.

References ACLMASK_ANY, and pg_largeobject_aclmask_snapshot().

Referenced by lo_read(), lo_truncate_internal(), and lo_write().

{
    if (pg_largeobject_aclmask_snapshot(lobj_oid, roleid, mode,
                                        ACLMASK_ANY, snapshot) != 0)
        return ACLCHECK_OK;
    else
        return ACLCHECK_NO_PRIV;
}

AclMode pg_largeobject_aclmask_snapshot ( Oid  lobj_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how,
Snapshot  snapshot 
)

Definition at line 3866 of file aclchk.c.

References AccessShareLock, ACL_OBJECT_LARGEOBJECT, acldefault(), aclmask(), Anum_pg_largeobject_metadata_lomacl, BTEqualStrategyNumber, DatumGetAclP, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, heap_close, heap_getattr, heap_open(), HeapTupleIsValid, LargeObjectMetadataOidIndexId, LargeObjectMetadataRelationId, ObjectIdAttributeNumber, ObjectIdGetDatum, pfree(), RelationGetDescr, ScanKeyInit(), superuser_arg(), systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by pg_aclmask(), and pg_largeobject_aclcheck_snapshot().

{
    AclMode     result;
    Relation    pg_lo_meta;
    ScanKeyData entry[1];
    SysScanDesc scan;
    HeapTuple   tuple;
    Datum       aclDatum;
    bool        isNull;
    Acl        *acl;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return mask;

    /*
     * Get the largeobject's ACL from pg_language_metadata
     */
    pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
                           AccessShareLock);

    ScanKeyInit(&entry[0],
                ObjectIdAttributeNumber,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(lobj_oid));

    scan = systable_beginscan(pg_lo_meta,
                              LargeObjectMetadataOidIndexId, true,
                              snapshot, 1, entry);

    tuple = systable_getnext(scan);
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("large object %u does not exist", lobj_oid)));

    ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;

    aclDatum = heap_getattr(tuple, Anum_pg_largeobject_metadata_lomacl,
                            RelationGetDescr(pg_lo_meta), &isNull);

    if (isNull)
    {
        /* No ACL, so build default ACL */
        acl = acldefault(ACL_OBJECT_LARGEOBJECT, ownerId);
        aclDatum = (Datum) 0;
    }
    else
    {
        /* detoast ACL if necessary */
        acl = DatumGetAclP(aclDatum);
    }

    result = aclmask(acl, roleid, ownerId, mask, how);

    /* if we have a detoasted copy, free it */
    if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
        pfree(acl);

    systable_endscan(scan);

    heap_close(pg_lo_meta, AccessShareLock);

    return result;
}

bool pg_largeobject_ownercheck ( Oid  lobj_oid,
Oid  roleid 
)

Definition at line 4651 of file aclchk.c.

References AccessShareLock, BTEqualStrategyNumber, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), heap_close, heap_open(), HeapTupleIsValid, LargeObjectMetadataOidIndexId, LargeObjectMetadataRelationId, ObjectIdAttributeNumber, ObjectIdGetDatum, ScanKeyInit(), SnapshotNow, superuser_arg(), systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by check_object_ownership(), and lo_unlink().

{
    Relation    pg_lo_meta;
    ScanKeyData entry[1];
    SysScanDesc scan;
    HeapTuple   tuple;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    /* There's no syscache for pg_largeobject_metadata */
    pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
                           AccessShareLock);

    ScanKeyInit(&entry[0],
                ObjectIdAttributeNumber,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(lobj_oid));

    scan = systable_beginscan(pg_lo_meta,
                              LargeObjectMetadataOidIndexId, true,
                              SnapshotNow, 1, entry);

    tuple = systable_getnext(scan);
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("large object %u does not exist", lobj_oid)));

    ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;

    systable_endscan(scan);
    heap_close(pg_lo_meta, AccessShareLock);

    return has_privs_of_role(roleid, ownerId);
}

AclResult pg_namespace_aclcheck ( Oid  nsp_oid,
Oid  roleid,
AclMode  mode 
)
AclMode pg_namespace_aclmask ( Oid  nsp_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 3939 of file aclchk.c.

References ACL_CREATE_TEMP, ACL_OBJECT_NAMESPACE, ACLCHECK_OK, acldefault(), aclmask(), Anum_pg_namespace_nspacl, DatumGetAclP, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, isTempNamespace(), MyDatabaseId, NAMESPACEOID, ObjectIdGetDatum, pfree(), pg_database_aclcheck(), ReleaseSysCache(), SearchSysCache1, superuser_arg(), and SysCacheGetAttr().

Referenced by pg_aclmask(), and pg_namespace_aclcheck().

{
    AclMode     result;
    HeapTuple   tuple;
    Datum       aclDatum;
    bool        isNull;
    Acl        *acl;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return mask;

    /*
     * If we have been assigned this namespace as a temp namespace, check to
     * make sure we have CREATE TEMP permission on the database, and if so act
     * as though we have all standard (but not GRANT OPTION) permissions on
     * the namespace.  If we don't have CREATE TEMP, act as though we have
     * only USAGE (and not CREATE) rights.
     *
     * This may seem redundant given the check in InitTempTableNamespace, but
     * it really isn't since current user ID may have changed since then. The
     * upshot of this behavior is that a SECURITY DEFINER function can create
     * temp tables that can then be accessed (if permission is granted) by
     * code in the same session that doesn't have permissions to create temp
     * tables.
     *
     * XXX Would it be safe to ereport a special error message as
     * InitTempTableNamespace does?  Returning zero here means we'll get a
     * generic "permission denied for schema pg_temp_N" message, which is not
     * remarkably user-friendly.
     */
    if (isTempNamespace(nsp_oid))
    {
        if (pg_database_aclcheck(MyDatabaseId, roleid,
                                 ACL_CREATE_TEMP) == ACLCHECK_OK)
            return mask & ACL_ALL_RIGHTS_NAMESPACE;
        else
            return mask & ACL_USAGE;
    }

    /*
     * Get the schema's ACL from pg_namespace
     */
    tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_SCHEMA),
                 errmsg("schema with OID %u does not exist", nsp_oid)));

    ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;

    aclDatum = SysCacheGetAttr(NAMESPACEOID, tuple, Anum_pg_namespace_nspacl,
                               &isNull);
    if (isNull)
    {
        /* No ACL, so build default ACL */
        acl = acldefault(ACL_OBJECT_NAMESPACE, ownerId);
        aclDatum = (Datum) 0;
    }
    else
    {
        /* detoast ACL if necessary */
        acl = DatumGetAclP(aclDatum);
    }

    result = aclmask(acl, roleid, ownerId, mask, how);

    /* if we have a detoasted copy, free it */
    if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
        pfree(acl);

    ReleaseSysCache(tuple);

    return result;
}

bool pg_namespace_ownercheck ( Oid  nsp_oid,
Oid  roleid 
)

Definition at line 4694 of file aclchk.c.

References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, NAMESPACEOID, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().

Referenced by AlterSchemaOwner_internal(), check_object_ownership(), RangeVarCallbackForDropRelation(), RemoveObjects(), and RenameSchema().

{
    HeapTuple   tuple;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_SCHEMA),
                 errmsg("schema with OID %u does not exist", nsp_oid)));

    ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;

    ReleaseSysCache(tuple);

    return has_privs_of_role(roleid, ownerId);
}

bool pg_opclass_ownercheck ( Oid  opc_oid,
Oid  roleid 
)

Definition at line 4747 of file aclchk.c.

References CLAOID, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().

Referenced by check_object_ownership().

{
    HeapTuple   tuple;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opc_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("operator class with OID %u does not exist",
                        opc_oid)));

    ownerId = ((Form_pg_opclass) GETSTRUCT(tuple))->opcowner;

    ReleaseSysCache(tuple);

    return has_privs_of_role(roleid, ownerId);
}

bool pg_oper_ownercheck ( Oid  oper_oid,
Oid  roleid 
)

Definition at line 4570 of file aclchk.c.

References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, OPEROID, ReleaseSysCache(), SearchSysCache1, and superuser_arg().

Referenced by AlterOpFamilyAdd(), check_object_ownership(), DefineOpClass(), and OperatorCreate().

{
    HeapTuple   tuple;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(oper_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_FUNCTION),
                 errmsg("operator with OID %u does not exist", oper_oid)));

    ownerId = ((Form_pg_operator) GETSTRUCT(tuple))->oprowner;

    ReleaseSysCache(tuple);

    return has_privs_of_role(roleid, ownerId);
}

bool pg_opfamily_ownercheck ( Oid  opf_oid,
Oid  roleid 
)

Definition at line 4774 of file aclchk.c.

References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, OPFAMILYOID, ReleaseSysCache(), SearchSysCache1, and superuser_arg().

Referenced by check_object_ownership().

{
    HeapTuple   tuple;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    tuple = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opf_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("operator family with OID %u does not exist",
                        opf_oid)));

    ownerId = ((Form_pg_opfamily) GETSTRUCT(tuple))->opfowner;

    ReleaseSysCache(tuple);

    return has_privs_of_role(roleid, ownerId);
}

AclResult pg_proc_aclcheck ( Oid  proc_oid,
Oid  roleid,
AclMode  mode 
)
AclMode pg_proc_aclmask ( Oid  proc_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 3752 of file aclchk.c.

References ACL_OBJECT_FUNCTION, acldefault(), aclmask(), Anum_pg_proc_proacl, DatumGetAclP, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, pfree(), PROCOID, ReleaseSysCache(), SearchSysCache1, superuser_arg(), and SysCacheGetAttr().

Referenced by pg_aclmask(), and pg_proc_aclcheck().

{
    AclMode     result;
    HeapTuple   tuple;
    Datum       aclDatum;
    bool        isNull;
    Acl        *acl;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return mask;

    /*
     * Get the function's ACL from pg_proc
     */
    tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(proc_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_FUNCTION),
                 errmsg("function with OID %u does not exist", proc_oid)));

    ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;

    aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
                               &isNull);
    if (isNull)
    {
        /* No ACL, so build default ACL */
        acl = acldefault(ACL_OBJECT_FUNCTION, ownerId);
        aclDatum = (Datum) 0;
    }
    else
    {
        /* detoast ACL if necessary */
        acl = DatumGetAclP(aclDatum);
    }

    result = aclmask(acl, roleid, ownerId, mask, how);

    /* if we have a detoasted copy, free it */
    if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
        pfree(acl);

    ReleaseSysCache(tuple);

    return result;
}

bool pg_proc_ownercheck ( Oid  proc_oid,
Oid  roleid 
)

Definition at line 4596 of file aclchk.c.

References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, PROCOID, ReleaseSysCache(), SearchSysCache1, and superuser_arg().

Referenced by AlterFunction(), AlterOpFamilyAdd(), check_object_ownership(), DefineOpClass(), DefineType(), and ProcedureCreate().

{
    HeapTuple   tuple;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(proc_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_FUNCTION),
                 errmsg("function with OID %u does not exist", proc_oid)));

    ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;

    ReleaseSysCache(tuple);

    return has_privs_of_role(roleid, ownerId);
}

AclResult pg_tablespace_aclcheck ( Oid  spc_oid,
Oid  roleid,
AclMode  mode 
)
AclMode pg_tablespace_aclmask ( Oid  spc_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 4021 of file aclchk.c.

References ACL_OBJECT_TABLESPACE, acldefault(), aclmask(), Anum_pg_tablespace_spcacl, DatumGetAclP, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, pfree(), ReleaseSysCache(), SearchSysCache1, superuser_arg(), SysCacheGetAttr(), and TABLESPACEOID.

Referenced by pg_aclmask(), and pg_tablespace_aclcheck().

{
    AclMode     result;
    HeapTuple   tuple;
    Datum       aclDatum;
    bool        isNull;
    Acl        *acl;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return mask;

    /*
     * Get the tablespace's ACL from pg_tablespace
     */
    tuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(spc_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("tablespace with OID %u does not exist", spc_oid)));

    ownerId = ((Form_pg_tablespace) GETSTRUCT(tuple))->spcowner;

    aclDatum = SysCacheGetAttr(TABLESPACEOID, tuple,
                               Anum_pg_tablespace_spcacl,
                               &isNull);

    if (isNull)
    {
        /* No ACL, so build default ACL */
        acl = acldefault(ACL_OBJECT_TABLESPACE, ownerId);
        aclDatum = (Datum) 0;
    }
    else
    {
        /* detoast ACL if necessary */
        acl = DatumGetAclP(aclDatum);
    }

    result = aclmask(acl, roleid, ownerId, mask, how);

    /* if we have a detoasted copy, free it */
    if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
        pfree(acl);

    ReleaseSysCache(tuple);

    return result;
}

bool pg_tablespace_ownercheck ( Oid  spc_oid,
Oid  roleid 
)

Definition at line 4720 of file aclchk.c.

References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, superuser_arg(), and TABLESPACEOID.

Referenced by AlterTableSpaceOptions(), check_object_ownership(), DropTableSpace(), and RenameTableSpace().

{
    HeapTuple   spctuple;
    Oid         spcowner;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    /* Search syscache for pg_tablespace */
    spctuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(spc_oid));
    if (!HeapTupleIsValid(spctuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("tablespace with OID %u does not exist", spc_oid)));

    spcowner = ((Form_pg_tablespace) GETSTRUCT(spctuple))->spcowner;

    ReleaseSysCache(spctuple);

    return has_privs_of_role(roleid, spcowner);
}

bool pg_ts_config_ownercheck ( Oid  cfg_oid,
Oid  roleid 
)

Definition at line 4828 of file aclchk.c.

References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, superuser_arg(), and TSCONFIGOID.

Referenced by AlterTSConfiguration(), and check_object_ownership().

{
    HeapTuple   tuple;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    tuple = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfg_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
               errmsg("text search configuration with OID %u does not exist",
                      cfg_oid)));

    ownerId = ((Form_pg_ts_config) GETSTRUCT(tuple))->cfgowner;

    ReleaseSysCache(tuple);

    return has_privs_of_role(roleid, ownerId);
}

bool pg_ts_dict_ownercheck ( Oid  dict_oid,
Oid  roleid 
)

Definition at line 4801 of file aclchk.c.

References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, superuser_arg(), and TSDICTOID.

Referenced by AlterTSDictionary(), and check_object_ownership().

{
    HeapTuple   tuple;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    tuple = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dict_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("text search dictionary with OID %u does not exist",
                        dict_oid)));

    ownerId = ((Form_pg_ts_dict) GETSTRUCT(tuple))->dictowner;

    ReleaseSysCache(tuple);

    return has_privs_of_role(roleid, ownerId);
}

AclResult pg_type_aclcheck ( Oid  type_oid,
Oid  roleid,
AclMode  mode 
)
AclMode pg_type_aclmask ( Oid  type_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 4199 of file aclchk.c.

References ACL_OBJECT_TYPE, acldefault(), aclmask(), Anum_pg_type_typacl, DatumGetAclP, DatumGetPointer, ereport, errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, pfree(), ReleaseSysCache(), SearchSysCache1, superuser_arg(), SysCacheGetAttr(), and TYPEOID.

Referenced by pg_aclmask(), and pg_type_aclcheck().

{
    AclMode     result;
    HeapTuple   tuple;
    Datum       aclDatum;
    bool        isNull;
    Acl        *acl;
    Oid         ownerId;

    Form_pg_type typeForm;

    /* Bypass permission checks for superusers */
    if (superuser_arg(roleid))
        return mask;

    /*
     * Must get the type's tuple from pg_type
     */
    tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errmsg("type with OID %u does not exist",
                        type_oid)));
    typeForm = (Form_pg_type) GETSTRUCT(tuple);

    /* "True" array types don't manage permissions of their own */
    if (typeForm->typelem != 0 && typeForm->typlen == -1)
    {
        Oid         elttype_oid = typeForm->typelem;

        ReleaseSysCache(tuple);

        tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(elttype_oid));
        if (!HeapTupleIsValid(tuple))
            ereport(ERROR,
                    (errmsg("type with OID %u does not exist",
                            type_oid)));
        typeForm = (Form_pg_type) GETSTRUCT(tuple);
    }

    /*
     * Normal case: get the type's ACL from pg_type
     */
    ownerId = typeForm->typowner;

    aclDatum = SysCacheGetAttr(TYPEOID, tuple,
                               Anum_pg_type_typacl, &isNull);
    if (isNull)
    {
        /* No ACL, so build default ACL */
        acl = acldefault(ACL_OBJECT_TYPE, ownerId);
        aclDatum = (Datum) 0;
    }
    else
    {
        /* detoast rel's ACL if necessary */
        acl = DatumGetAclP(aclDatum);
    }

    result = aclmask(acl, roleid, ownerId, mask, how);

    /* if we have a detoasted copy, free it */
    if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
        pfree(acl);

    ReleaseSysCache(tuple);

    return result;
}

bool pg_type_ownercheck ( Oid  type_oid,
Oid  roleid 
)

Definition at line 4544 of file aclchk.c.

References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, superuser_arg(), and TYPEOID.

Referenced by AlterTypeNamespace_oid(), AlterTypeOwner(), check_object_ownership(), checkDomainOwner(), checkEnumOwner(), CreateCast(), DefineOpClass(), and RenameType().

{
    HeapTuple   tuple;
    Oid         ownerId;

    /* Superusers bypass all permission checking. */
    if (superuser_arg(roleid))
        return true;

    tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
    if (!HeapTupleIsValid(tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("type with OID %u does not exist", type_oid)));

    ownerId = ((Form_pg_type) GETSTRUCT(tuple))->typowner;

    ReleaseSysCache(tuple);

    return has_privs_of_role(roleid, ownerId);
}

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

Definition at line 1316 of file aclchk.c.

References AccessShareLock, InternalGrant::all_privs, InternalDefaultACL::all_privs, InternalGrant::behavior, InternalDefaultACL::behavior, BTEqualStrategyNumber, InternalGrant::col_privs, DatabaseRelationId, DEFACLOBJ_FUNCTION, DEFACLOBJ_RELATION, DEFACLOBJ_SEQUENCE, DEFACLOBJ_TYPE, DefaultAclOidIndexId, DefaultAclRelationId, elog, ERROR, ExecGrantStmt_oids(), ForeignDataWrapperRelationId, ForeignServerRelationId, GETSTRUCT, InternalGrant::grant_option, InternalDefaultACL::grant_option, InternalGrant::grantees, InternalDefaultACL::grantees, heap_close, heap_open(), HeapTupleIsValid, InternalGrant::is_grant, InternalDefaultACL::is_grant, LanguageRelationId, LargeObjectRelationId, list_make1_oid, NamespaceRelationId, InternalDefaultACL::nspid, ObjectIdAttributeNumber, ObjectIdGetDatum, InternalGrant::objects, InternalGrant::objtype, InternalDefaultACL::objtype, InternalGrant::privileges, InternalDefaultACL::privileges, ProcedureRelationId, RelationRelationId, InternalDefaultACL::roleid, ScanKeyInit(), SetDefaultACL(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), TableSpaceRelationId, and TypeRelationId.

Referenced by shdepDropOwned().

{
    if (classid == DefaultAclRelationId)
    {
        InternalDefaultACL iacls;
        Form_pg_default_acl pg_default_acl_tuple;
        Relation    rel;
        ScanKeyData skey[1];
        SysScanDesc scan;
        HeapTuple   tuple;

        /* first fetch info needed by SetDefaultACL */
        rel = heap_open(DefaultAclRelationId, AccessShareLock);

        ScanKeyInit(&skey[0],
                    ObjectIdAttributeNumber,
                    BTEqualStrategyNumber, F_OIDEQ,
                    ObjectIdGetDatum(objid));

        scan = systable_beginscan(rel, DefaultAclOidIndexId, true,
                                  SnapshotNow, 1, skey);

        tuple = systable_getnext(scan);

        if (!HeapTupleIsValid(tuple))
            elog(ERROR, "could not find tuple for default ACL %u", objid);

        pg_default_acl_tuple = (Form_pg_default_acl) GETSTRUCT(tuple);

        iacls.roleid = pg_default_acl_tuple->defaclrole;
        iacls.nspid = pg_default_acl_tuple->defaclnamespace;

        switch (pg_default_acl_tuple->defaclobjtype)
        {
            case DEFACLOBJ_RELATION:
                iacls.objtype = ACL_OBJECT_RELATION;
                break;
            case DEFACLOBJ_SEQUENCE:
                iacls.objtype = ACL_OBJECT_SEQUENCE;
                break;
            case DEFACLOBJ_FUNCTION:
                iacls.objtype = ACL_OBJECT_FUNCTION;
                break;
            case DEFACLOBJ_TYPE:
                iacls.objtype = ACL_OBJECT_TYPE;
                break;
            default:
                /* Shouldn't get here */
                elog(ERROR, "unexpected default ACL type: %d",
                     (int) pg_default_acl_tuple->defaclobjtype);
                break;
        }

        systable_endscan(scan);
        heap_close(rel, AccessShareLock);

        iacls.is_grant = false;
        iacls.all_privs = true;
        iacls.privileges = ACL_NO_RIGHTS;
        iacls.grantees = list_make1_oid(roleid);
        iacls.grant_option = false;
        iacls.behavior = DROP_CASCADE;

        /* Do it */
        SetDefaultACL(&iacls);
    }
    else
    {
        InternalGrant istmt;

        switch (classid)
        {
            case RelationRelationId:
                /* it's OK to use RELATION for a sequence */
                istmt.objtype = ACL_OBJECT_RELATION;
                break;
            case DatabaseRelationId:
                istmt.objtype = ACL_OBJECT_DATABASE;
                break;
            case TypeRelationId:
                istmt.objtype = ACL_OBJECT_TYPE;
                break;
            case ProcedureRelationId:
                istmt.objtype = ACL_OBJECT_FUNCTION;
                break;
            case LanguageRelationId:
                istmt.objtype = ACL_OBJECT_LANGUAGE;
                break;
            case LargeObjectRelationId:
                istmt.objtype = ACL_OBJECT_LARGEOBJECT;
                break;
            case NamespaceRelationId:
                istmt.objtype = ACL_OBJECT_NAMESPACE;
                break;
            case TableSpaceRelationId:
                istmt.objtype = ACL_OBJECT_TABLESPACE;
                break;
            case ForeignServerRelationId:
                istmt.objtype = ACL_OBJECT_FOREIGN_SERVER;
                break;
            case ForeignDataWrapperRelationId:
                istmt.objtype = ACL_OBJECT_FDW;
                break;
            default:
                elog(ERROR, "unexpected object class %u", classid);
                break;
        }
        istmt.is_grant = false;
        istmt.objects = list_make1_oid(objid);
        istmt.all_privs = true;
        istmt.privileges = ACL_NO_RIGHTS;
        istmt.col_privs = NIL;
        istmt.grantees = list_make1_oid(roleid);
        istmt.grant_option = false;
        istmt.behavior = DROP_CASCADE;

        ExecGrantStmt_oids(&istmt);
    }
}

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

Definition at line 5007 of file acl.c.

References ACL_GRANT_OPTION_FOR, ACL_NO_RIGHTS, ACLMASK_ALL, aclmask_direct(), count_one_bits(), lfirst_oid, roles_has_privs_of(), and superuser_arg().

Referenced by ExecGrant_Attribute(), ExecGrant_Database(), ExecGrant_Fdw(), ExecGrant_ForeignServer(), ExecGrant_Function(), ExecGrant_Language(), ExecGrant_Largeobject(), ExecGrant_Namespace(), ExecGrant_Relation(), ExecGrant_Tablespace(), and ExecGrant_Type().

{
    AclMode     needed_goptions = ACL_GRANT_OPTION_FOR(privileges);
    List       *roles_list;
    int         nrights;
    ListCell   *l;

    /*
     * The object owner is always treated as having all grant options, so if
     * roleId is the owner it's easy.  Also, if roleId is a superuser it's
     * easy: superusers are implicitly members of every role, so they act as
     * the object owner.
     */
    if (roleId == ownerId || superuser_arg(roleId))
    {
        *grantorId = ownerId;
        *grantOptions = needed_goptions;
        return;
    }

    /*
     * Otherwise we have to do a careful search to see if roleId has the
     * privileges of any suitable role.  Note: we can hang onto the result of
     * roles_has_privs_of() throughout this loop, because aclmask_direct()
     * doesn't query any role memberships.
     */
    roles_list = roles_has_privs_of(roleId);

    /* initialize candidate result as default */
    *grantorId = roleId;
    *grantOptions = ACL_NO_RIGHTS;
    nrights = 0;

    foreach(l, roles_list)
    {
        Oid         otherrole = lfirst_oid(l);
        AclMode     otherprivs;

        otherprivs = aclmask_direct(acl, otherrole, ownerId,
                                    needed_goptions, ACLMASK_ALL);
        if (otherprivs == needed_goptions)
        {
            /* Found a suitable grantor */
            *grantorId = otherrole;
            *grantOptions = otherprivs;
            return;
        }

        /*
         * If it has just some of the needed privileges, remember best
         * candidate.
         */
        if (otherprivs != ACL_NO_RIGHTS)
        {
            int         nnewrights = count_one_bits(otherprivs);

            if (nnewrights > nrights)
            {
                *grantorId = otherrole;
                *grantOptions = otherprivs;
                nrights = nnewrights;
            }
        }
    }
}