while (isspace((unsignedchar) *s))
s++; for (;
*s != '\0' &&
(in_quotes || *s == '"' || is_safe_acl_char(*s, true));
s++)
{ if (*s == '"')
{ if (!in_quotes)
{
in_quotes = true; continue;
} /* safe to look at next char (could be '\0' though) */ if (*(s + 1) != '"')
{
in_quotes = false; continue;
} /* it's an escaped double quote; skip the escaping char */
s++;
}
/* Add the character to the string */ if (len >= NAMEDATALEN - 1)
ereturn(escontext, NULL,
(errcode(ERRCODE_NAME_TOO_LONG),
errmsg("identifier too long"),
errdetail("Identifier must be less than %d characters.",
NAMEDATALEN)));
/* Detect whether we need to use double quotes */ for (src = s; *src; src++)
{ if (!is_safe_acl_char(*src, false))
{
safe = false; break;
}
} if (!safe)
*p++ = '"'; for (src = s; *src; src++)
{ /* A double quote character in a username is encoded as "" */ if (*src == '"')
*p++ = '"';
*p++ = *src;
} if (!safe)
*p++ = '"';
*p = '\0';
}
s = getid(s, name, escontext); if (s == NULL) return NULL; if (*s != '=')
{ /* we just read a keyword, not a name */ if (strcmp(name, "group") != 0 && strcmp(name, "user") != 0)
ereturn(escontext, NULL,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("unrecognized key word: \"%s\"", name),
errhint("ACL key word must be \"group\" or \"user\"."))); /* move s to the name beyond the keyword */
s = getid(s, name, escontext); if (s == NULL) return NULL; if (name[0] == '\0')
ereturn(escontext, NULL,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("missing name"),
errhint("A name must follow the \"group\" or \"user\" key word.")));
}
if (*s != '=')
ereturn(escontext, NULL,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("missing \"=\" sign")));
privs = goption = ACL_NO_RIGHTS;
for (++s, read = 0; isalpha((unsignedchar) *s) || *s == '*'; s++)
{ switch (*s)
{ case'*':
goption |= read; break; case ACL_INSERT_CHR:
read = ACL_INSERT; break; case ACL_SELECT_CHR:
read = ACL_SELECT; break; case ACL_UPDATE_CHR:
read = ACL_UPDATE; break; case ACL_DELETE_CHR:
read = ACL_DELETE; break; case ACL_TRUNCATE_CHR:
read = ACL_TRUNCATE; break; case ACL_REFERENCES_CHR:
read = ACL_REFERENCES; break; case ACL_TRIGGER_CHR:
read = ACL_TRIGGER; break; case ACL_EXECUTE_CHR:
read = ACL_EXECUTE; break; case ACL_USAGE_CHR:
read = ACL_USAGE; break; case ACL_CREATE_CHR:
read = ACL_CREATE; break; case ACL_CREATE_TEMP_CHR:
read = ACL_CREATE_TEMP; break; case ACL_CONNECT_CHR:
read = ACL_CONNECT; break; case ACL_SET_CHR:
read = ACL_SET; break; case ACL_ALTER_SYSTEM_CHR:
read = ACL_ALTER_SYSTEM; break; case ACL_MAINTAIN_CHR:
read = ACL_MAINTAIN; break; default:
ereturn(escontext, NULL,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid mode character: must be one of \"%s\"",
ACL_ALL_RIGHTS_STR)));
}
privs |= read;
}
if (name[0] == '\0')
aip->ai_grantee = ACL_ID_PUBLIC; else
{
aip->ai_grantee = get_role_oid(name, true); if (!OidIsValid(aip->ai_grantee))
ereturn(escontext, NULL,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("role \"%s\" does not exist", name)));
}
/* *XXXAllowadegreeofbackwardcompatibilitybydefaultingthegrantor *tothesuperuser.
*/ if (*s == '/')
{
s = getid(s + 1, name2, escontext); if (s == NULL) return NULL; if (name2[0] == '\0')
ereturn(escontext, NULL,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("a name must follow the \"/\" sign")));
aip->ai_grantor = get_role_oid(name2, true); if (!OidIsValid(aip->ai_grantor))
ereturn(escontext, NULL,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("role \"%s\" does not exist", name2)));
} else
{
aip->ai_grantor = BOOTSTRAP_SUPERUSERID;
ereport(WARNING,
(errcode(ERRCODE_INVALID_GRANTOR),
errmsg("defaulting grantor to user ID %u",
BOOTSTRAP_SUPERUSERID)));
}
s = aclparse(s, aip, escontext); if (s == NULL)
PG_RETURN_NULL();
while (isspace((unsignedchar) *s))
++s; if (*s)
ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("extra garbage at the end of the ACL specification")));
/* 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);
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 */
}
/* The owner always has grant options, no need to check */ if (mod_aip->ai_grantor == ownerId) return;
/* Make a working copy */
acl = allocacl(ACL_NUM(old_acl));
memcpy(acl, old_acl, ACL_SIZE(old_acl));
/* Zap all grant options of target grantee, plus what depends on 'em */
cc_restart:
num = ACL_NUM(acl);
aip = ACL_DAT(acl); for (i = 0; i < num; i++)
{ if (aip[i].ai_grantee == mod_aip->ai_grantee &&
ACLITEM_GET_GOPTIONS(aip[i]) != ACL_NO_RIGHTS)
{
Acl *new_acl;
/* We'll actually zap ordinary privs too, but no matter */
new_acl = aclupdate(acl, &aip[i], ACL_MODECHG_DEL,
ownerId, DROP_CASCADE);
pfree(acl);
acl = new_acl;
goto cc_restart;
}
}
/* Now we can compute grantor's independently-derived privileges */
own_privs = aclmask(acl,
mod_aip->ai_grantor,
ownerId,
ACL_GRANT_OPTION_FOR(ACLITEM_GET_GOPTIONS(*mod_aip)),
ACLMASK_ALL);
own_privs = ACL_OPTION_TO_PRIVS(own_privs);
if ((ACLITEM_GET_GOPTIONS(*mod_aip) & ~own_privs) != 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
errmsg("grant options cannot be granted back to your own grantor")));
pfree(acl);
}
/* *Ensurethatnoprivilegeis"abandoned".Aprivilegeisabandoned *iftheuserthatgrantedtheprivilegelosesthegrantoption.(So *thechainthroughwhichitwasgrantedisbroken.)Eitherthe *abandonedprivilegesarerevokedaswell,oranerrormessageis *printed,dependingonthedropbehavioroption. * *acl:theinputACLlist *grantee:theuserfromwhomsomegrantoptionshavebeenrevoked *revoke_privs:thegrantoptionsbeingrevoked *ownerId:Oidofobjectowner *behavior:RESTRICTorCASCADEbehaviorforrecursiveremoval * *TheinputAclobjectispfree'difreplaced.
*/ static Acl *
recursive_revoke(Acl *acl,
Oid grantee,
AclMode revoke_privs,
Oid ownerId,
DropBehavior behavior)
{
AclMode still_has;
AclItem *aip; int i,
num;
check_acl(acl);
/* The owner can never truly lose grant options, so short-circuit */ if (grantee == ownerId) return acl;
/* The grantee might still have some grant options via another grantor */
still_has = aclmask(acl, grantee, ownerId,
ACL_GRANT_OPTION_FOR(revoke_privs),
ACLMASK_ALL);
revoke_privs &= ~ACL_OPTION_TO_PRIVS(still_has); if (revoke_privs == ACL_NO_RIGHTS) return acl;
restart:
num = ACL_NUM(acl);
aip = ACL_DAT(acl); for (i = 0; i < num; i++)
{ if (aip[i].ai_grantor == grantee
&& (ACLITEM_GET_PRIVS(aip[i]) & revoke_privs) != 0)
{
AclItem mod_acl;
Acl *new_acl;
if (behavior == DROP_RESTRICT)
ereport(ERROR,
(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
errmsg("dependent privileges exist"),
errhint("Use CASCADE to revoke them too.")));
/* Quick exit for mask == 0 */ if (mask == 0) return0;
result = 0;
/* Owner always implicitly has all grant options */ if ((mask & ACLITEM_ALL_GOPTION_BITS) &&
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);
/* *Checkprivilegesgranteddirectlytoroleid(andnottopublic)
*/ for (i = 0; i < num; i++)
{
AclItem *aidata = &aidat[i];
if (aidata->ai_grantee == roleid)
{
result |= aidata->ai_privs & mask; if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0)) return result;
}
}
return result;
}
/* *aclmembers *FindoutalltheroleidsmentionedinanAcl. *Notethatwedonotdistinguishgrantorsfromgrantees. * **roleidsissettopointtoapalloc'darraycontainingdistinctOIDs *insortedorder.Thelengthofthearrayisthefunctionresult.
*/ int
aclmembers(const Acl *acl, Oid **roleids)
{
Oid *list; const AclItem *acldat; int i,
j;
/* Allocate the worst-case space requirement */
list = palloc(ACL_NUM(acl) * 2 * sizeof(Oid));
acldat = ACL_DAT(acl);
/* *WalktheACLcollectingmentionedRoleIds.
*/
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), oid_cmp);
/* Remove duplicates from the array */ return qunique(list, j, sizeof(Oid), oid_cmp);
}
/* *aclinsert(exportedfunction)
*/
Datum
aclinsert(PG_FUNCTION_ARGS)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("aclinsert is no longer supported")));
PG_RETURN_NULL(); /* keep compiler quiet */
}
Datum
aclremove(PG_FUNCTION_ARGS)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("aclremove is no longer supported")));
PG_RETURN_NULL(); /* keep compiler quiet */
}
Datum
aclcontains(PG_FUNCTION_ARGS)
{
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);
}
/* We rely on priv_type being a private, modifiable string */ for (chunk = priv_type; chunk; chunk = next_chunk)
{ int chunk_len; const priv_map *this_priv;
/* Split string at commas */
next_chunk = strchr(chunk, ','); if (next_chunk)
*next_chunk++ = '\0';
/* Drop leading/trailing whitespace in this chunk */ while (*chunk && isspace((unsignedchar) *chunk))
chunk++;
chunk_len = strlen(chunk); while (chunk_len > 0 && isspace((unsignedchar) chunk[chunk_len - 1]))
chunk_len--;
chunk[chunk_len] = '\0';
/* Match to the privileges list */ for (this_priv = privileges; this_priv->name; this_priv++)
{ if (pg_strcasecmp(this_priv->name, chunk) == 0)
{
result |= this_priv->value; break;
}
} if (!this_priv->name)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("unrecognized privilege type: \"%s\"", chunk)));
}
pfree(priv_type); return result;
}
staticconstchar *
convert_aclright_to_string(int aclright)
{ switch (aclright)
{ case ACL_INSERT: return"INSERT"; case ACL_SELECT: return"SELECT"; case ACL_UPDATE: return"UPDATE"; case ACL_DELETE: return"DELETE"; case ACL_TRUNCATE: return"TRUNCATE"; case ACL_REFERENCES: return"REFERENCES"; case ACL_TRIGGER: return"TRIGGER"; case ACL_EXECUTE: return"EXECUTE"; case ACL_USAGE: return"USAGE"; case ACL_CREATE: return"CREATE"; case ACL_CREATE_TEMP: return"TEMPORARY"; case ACL_CONNECT: return"CONNECT"; case ACL_SET: return"SET"; case ACL_ALTER_SYSTEM: return"ALTER SYSTEM"; case ACL_MAINTAIN: return"MAINTAIN"; default:
elog(ERROR, "unrecognized aclright: %d", aclright); return NULL;
}
}
/* *has_table_privilege_name_name *Checkuserprivilegesonatablegiven *nameusername,texttablename,andtextprivname.
*/
Datum
has_table_privilege_name_name(PG_FUNCTION_ARGS)
{
Name rolename = PG_GETARG_NAME(0);
text *tablename = PG_GETARG_TEXT_PP(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid roleid;
Oid tableoid;
AclMode mode;
AclResult aclresult;
/* *has_table_privilege_name *Checkuserprivilegesonatablegiven *texttablenameandtextprivname. *current_userisassumed
*/
Datum
has_table_privilege_name(PG_FUNCTION_ARGS)
{
text *tablename = PG_GETARG_TEXT_PP(0);
text *priv_type_text = PG_GETARG_TEXT_PP(1);
Oid roleid;
Oid tableoid;
AclMode mode;
AclResult aclresult;
/* We might not even have permissions on this relation; don't lock it. */ return RangeVarGetRelid(relrv, NoLock, false);
}
/* *convert_table_priv_string *ConverttextstringtoAclModevalue.
*/ static AclMode
convert_table_priv_string(text *priv_type_text)
{ staticconst priv_map table_priv_map[] = {
{"SELECT", ACL_SELECT},
{"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)},
{"INSERT", ACL_INSERT},
{"INSERT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_INSERT)},
{"UPDATE", ACL_UPDATE},
{"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)},
{"DELETE", ACL_DELETE},
{"DELETE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_DELETE)},
{"TRUNCATE", ACL_TRUNCATE},
{"TRUNCATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRUNCATE)},
{"REFERENCES", ACL_REFERENCES},
{"REFERENCES WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_REFERENCES)},
{"TRIGGER", ACL_TRIGGER},
{"TRIGGER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRIGGER)},
{"MAINTAIN", ACL_MAINTAIN},
{"MAINTAIN WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_MAINTAIN)},
{NULL, 0}
};
/* *has_sequence_privilege_name_name *Checkuserprivilegesonasequencegiven *nameusername,textsequencename,andtextprivname.
*/
Datum
has_sequence_privilege_name_name(PG_FUNCTION_ARGS)
{
Name rolename = PG_GETARG_NAME(0);
text *sequencename = PG_GETARG_TEXT_PP(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid roleid;
Oid sequenceoid;
AclMode mode;
AclResult aclresult;
roleid = get_role_oid_or_public(NameStr(*rolename));
mode = convert_sequence_priv_string(priv_type_text);
sequenceoid = convert_table_name(sequencename); if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a sequence",
text_to_cstring(sequencename))));
/* *has_sequence_privilege_name *Checkuserprivilegesonasequencegiven *textsequencenameandtextprivname. *current_userisassumed
*/
Datum
has_sequence_privilege_name(PG_FUNCTION_ARGS)
{
text *sequencename = PG_GETARG_TEXT_PP(0);
text *priv_type_text = PG_GETARG_TEXT_PP(1);
Oid roleid;
Oid sequenceoid;
AclMode mode;
AclResult aclresult;
roleid = GetUserId();
mode = convert_sequence_priv_string(priv_type_text);
sequenceoid = convert_table_name(sequencename); if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a sequence",
text_to_cstring(sequencename))));
/* *has_sequence_privilege_id_name *Checkuserprivilegesonasequencegiven *roleid,textsequencename,andtextprivname.
*/
Datum
has_sequence_privilege_id_name(PG_FUNCTION_ARGS)
{
Oid roleid = PG_GETARG_OID(0);
text *sequencename = PG_GETARG_TEXT_PP(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid sequenceoid;
AclMode mode;
AclResult aclresult;
mode = convert_sequence_priv_string(priv_type_text);
sequenceoid = convert_table_name(sequencename); if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a sequence",
text_to_cstring(sequencename))));
/* *has_any_column_privilege_name_name *Checkuserprivilegesonanycolumnofatablegiven *nameusername,texttablename,andtextprivname.
*/
Datum
has_any_column_privilege_name_name(PG_FUNCTION_ARGS)
{
Name rolename = PG_GETARG_NAME(0);
text *tablename = PG_GETARG_TEXT_PP(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid roleid;
Oid tableoid;
AclMode mode;
AclResult aclresult;
/* First check at table level, then examine each column if needed */
aclresult = pg_class_aclcheck(tableoid, roleid, mode); if (aclresult != ACLCHECK_OK)
aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
ACLMASK_ANY);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/* *has_any_column_privilege_name *Checkuserprivilegesonanycolumnofatablegiven *texttablenameandtextprivname. *current_userisassumed
*/
Datum
has_any_column_privilege_name(PG_FUNCTION_ARGS)
{
text *tablename = PG_GETARG_TEXT_PP(0);
text *priv_type_text = PG_GETARG_TEXT_PP(1);
Oid roleid;
Oid tableoid;
AclMode mode;
AclResult aclresult;
/* First check at table level, then examine each column if needed */
aclresult = pg_class_aclcheck(tableoid, roleid, mode); if (aclresult != ACLCHECK_OK)
aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
ACLMASK_ANY);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/* *has_any_column_privilege_name_id *Checkuserprivilegesonanycolumnofatablegiven *nameusename,tableoid,andtextprivname.
*/
Datum
has_any_column_privilege_name_id(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
Oid tableoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid roleid;
AclMode mode;
AclResult aclresult; bool is_missing = false;
/* First check at table level, then examine each column if needed */
aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing); if (aclresult != ACLCHECK_OK)
{ if (is_missing)
PG_RETURN_NULL();
aclresult = pg_attribute_aclcheck_all_ext(tableoid, roleid, mode,
ACLMASK_ANY, &is_missing); if (is_missing)
PG_RETURN_NULL();
}
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/* *has_any_column_privilege_id *Checkuserprivilegesonanycolumnofatablegiven *tableoid,andtextprivname. *current_userisassumed
*/
Datum
has_any_column_privilege_id(PG_FUNCTION_ARGS)
{
Oid tableoid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_PP(1);
Oid roleid;
AclMode mode;
AclResult aclresult; bool is_missing = false;
/* First check at table level, then examine each column if needed */
aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing); if (aclresult != ACLCHECK_OK)
{ if (is_missing)
PG_RETURN_NULL();
aclresult = pg_attribute_aclcheck_all_ext(tableoid, roleid, mode,
ACLMASK_ANY, &is_missing); if (is_missing)
PG_RETURN_NULL();
}
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/* *has_any_column_privilege_id_name *Checkuserprivilegesonanycolumnofatablegiven *roleid,texttablename,andtextprivname.
*/
Datum
has_any_column_privilege_id_name(PG_FUNCTION_ARGS)
{
Oid roleid = PG_GETARG_OID(0);
text *tablename = PG_GETARG_TEXT_PP(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid tableoid;
AclMode mode;
AclResult aclresult;
/* First check at table level, then examine each column if needed */
aclresult = pg_class_aclcheck(tableoid, roleid, mode); if (aclresult != ACLCHECK_OK)
aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
ACLMASK_ANY);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/* *has_any_column_privilege_id_id *Checkuserprivilegesonanycolumnofatablegiven *roleid,tableoid,andtextprivname.
*/
Datum
has_any_column_privilege_id_id(PG_FUNCTION_ARGS)
{
Oid roleid = PG_GETARG_OID(0);
Oid tableoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
AclMode mode;
AclResult aclresult; bool is_missing = false;
/* First check at table level, then examine each column if needed */
aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing); if (aclresult != ACLCHECK_OK)
{ if (is_missing)
PG_RETURN_NULL();
aclresult = pg_attribute_aclcheck_all_ext(tableoid, roleid, mode,
ACLMASK_ANY, &is_missing); if (is_missing)
PG_RETURN_NULL();
}
/* Next check if we have the privilege at the table level */
aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing); if (aclresult == ACLCHECK_OK) return1; elseif (is_missing) return -1; else return0;
}
/* *has_column_privilege_name_name_name *Checkuserprivilegesonacolumngiven *nameusername,texttablename,textcolname,andtextprivname.
*/
Datum
has_column_privilege_name_name_name(PG_FUNCTION_ARGS)
{
Name rolename = PG_GETARG_NAME(0);
text *tablename = PG_GETARG_TEXT_PP(1);
text *column = PG_GETARG_TEXT_PP(2);
text *priv_type_text = PG_GETARG_TEXT_PP(3);
Oid roleid;
Oid tableoid;
AttrNumber colattnum;
AclMode mode; int privresult;
/* *has_column_privilege_name_name_attnum *Checkuserprivilegesonacolumngiven *nameusername,texttablename,intattnum,andtextprivname.
*/
Datum
has_column_privilege_name_name_attnum(PG_FUNCTION_ARGS)
{
Name rolename = PG_GETARG_NAME(0);
text *tablename = PG_GETARG_TEXT_PP(1);
AttrNumber colattnum = PG_GETARG_INT16(2);
text *priv_type_text = PG_GETARG_TEXT_PP(3);
Oid roleid;
Oid tableoid;
AclMode mode; int privresult;
/* *has_column_privilege_name_id_name *Checkuserprivilegesonacolumngiven *nameusername,tableoid,textcolname,andtextprivname.
*/
Datum
has_column_privilege_name_id_name(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
Oid tableoid = PG_GETARG_OID(1);
text *column = PG_GETARG_TEXT_PP(2);
text *priv_type_text = PG_GETARG_TEXT_PP(3);
Oid roleid;
AttrNumber colattnum;
AclMode mode; int privresult;
/* *has_column_privilege_name_id_attnum *Checkuserprivilegesonacolumngiven *nameusername,tableoid,intattnum,andtextprivname.
*/
Datum
has_column_privilege_name_id_attnum(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
Oid tableoid = PG_GETARG_OID(1);
AttrNumber colattnum = PG_GETARG_INT16(2);
text *priv_type_text = PG_GETARG_TEXT_PP(3);
Oid roleid;
AclMode mode; int privresult;
/* *has_column_privilege_id_name_name *Checkuserprivilegesonacolumngiven *oidroleid,texttablename,textcolname,andtextprivname.
*/
Datum
has_column_privilege_id_name_name(PG_FUNCTION_ARGS)
{
Oid roleid = PG_GETARG_OID(0);
text *tablename = PG_GETARG_TEXT_PP(1);
text *column = PG_GETARG_TEXT_PP(2);
text *priv_type_text = PG_GETARG_TEXT_PP(3);
Oid tableoid;
AttrNumber colattnum;
AclMode mode; int privresult;
/* *has_column_privilege_id_name_attnum *Checkuserprivilegesonacolumngiven *oidroleid,texttablename,intattnum,andtextprivname.
*/
Datum
has_column_privilege_id_name_attnum(PG_FUNCTION_ARGS)
{
Oid roleid = PG_GETARG_OID(0);
text *tablename = PG_GETARG_TEXT_PP(1);
AttrNumber colattnum = PG_GETARG_INT16(2);
text *priv_type_text = PG_GETARG_TEXT_PP(3);
Oid tableoid;
AclMode mode; int privresult;
/* *has_column_privilege_id_id_name *Checkuserprivilegesonacolumngiven *oidroleid,tableoid,textcolname,andtextprivname.
*/
Datum
has_column_privilege_id_id_name(PG_FUNCTION_ARGS)
{
Oid roleid = PG_GETARG_OID(0);
Oid tableoid = PG_GETARG_OID(1);
text *column = PG_GETARG_TEXT_PP(2);
text *priv_type_text = PG_GETARG_TEXT_PP(3);
AttrNumber colattnum;
AclMode mode; int privresult;
/* *has_column_privilege_name_name *Checkuserprivilegesonacolumngiven *texttablename,textcolname,andtextprivname. *current_userisassumed
*/
Datum
has_column_privilege_name_name(PG_FUNCTION_ARGS)
{
text *tablename = PG_GETARG_TEXT_PP(0);
text *column = PG_GETARG_TEXT_PP(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid roleid;
Oid tableoid;
AttrNumber colattnum;
AclMode mode; int privresult;
/* *has_column_privilege_name_attnum *Checkuserprivilegesonacolumngiven *texttablename,intattnum,andtextprivname. *current_userisassumed
*/
Datum
has_column_privilege_name_attnum(PG_FUNCTION_ARGS)
{
text *tablename = PG_GETARG_TEXT_PP(0);
AttrNumber colattnum = PG_GETARG_INT16(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid roleid;
Oid tableoid;
AclMode mode; int privresult;
/* *has_column_privilege_id_name *Checkuserprivilegesonacolumngiven *tableoid,textcolname,andtextprivname. *current_userisassumed
*/
Datum
has_column_privilege_id_name(PG_FUNCTION_ARGS)
{
Oid tableoid = PG_GETARG_OID(0);
text *column = PG_GETARG_TEXT_PP(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid roleid;
AttrNumber colattnum;
AclMode mode; int privresult;
/* *has_database_privilege_name_name *Checkuserprivilegesonadatabasegiven *nameusername,textdatabasename,andtextprivname.
*/
Datum
has_database_privilege_name_name(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
text *databasename = PG_GETARG_TEXT_PP(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid roleid;
Oid databaseoid;
AclMode mode;
AclResult aclresult;
/* *has_database_privilege_name *Checkuserprivilegesonadatabasegiven *textdatabasenameandtextprivname. *current_userisassumed
*/
Datum
has_database_privilege_name(PG_FUNCTION_ARGS)
{
text *databasename = PG_GETARG_TEXT_PP(0);
text *priv_type_text = PG_GETARG_TEXT_PP(1);
Oid roleid;
Oid databaseoid;
AclMode mode;
AclResult aclresult;
/* *has_foreign_data_wrapper_privilege_name_name *Checkuserprivilegesonaforeign-datawrappergiven *nameusername,textfdwname,andtextprivname.
*/
Datum
has_foreign_data_wrapper_privilege_name_name(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
text *fdwname = PG_GETARG_TEXT_PP(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid roleid;
Oid fdwid;
AclMode mode;
AclResult aclresult;
/* *has_foreign_data_wrapper_privilege_name *Checkuserprivilegesonaforeign-datawrappergiven *textfdwnameandtextprivname. *current_userisassumed
*/
Datum
has_foreign_data_wrapper_privilege_name(PG_FUNCTION_ARGS)
{
text *fdwname = PG_GETARG_TEXT_PP(0);
text *priv_type_text = PG_GETARG_TEXT_PP(1);
Oid roleid;
Oid fdwid;
AclMode mode;
AclResult aclresult;
/* *has_function_privilege_name_name *Checkuserprivilegesonafunctiongiven *nameusername,textfunctionname,andtextprivname.
*/
Datum
has_function_privilege_name_name(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
text *functionname = PG_GETARG_TEXT_PP(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid roleid;
Oid functionoid;
AclMode mode;
AclResult aclresult;
/* *has_function_privilege_name *Checkuserprivilegesonafunctiongiven *textfunctionnameandtextprivname. *current_userisassumed
*/
Datum
has_function_privilege_name(PG_FUNCTION_ARGS)
{
text *functionname = PG_GETARG_TEXT_PP(0);
text *priv_type_text = PG_GETARG_TEXT_PP(1);
Oid roleid;
Oid functionoid;
AclMode mode;
AclResult aclresult;
/* *has_language_privilege_name_name *Checkuserprivilegesonalanguagegiven *nameusername,textlanguagename,andtextprivname.
*/
Datum
has_language_privilege_name_name(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
text *languagename = PG_GETARG_TEXT_PP(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid roleid;
Oid languageoid;
AclMode mode;
AclResult aclresult;
/* *has_language_privilege_name *Checkuserprivilegesonalanguagegiven *textlanguagenameandtextprivname. *current_userisassumed
*/
Datum
has_language_privilege_name(PG_FUNCTION_ARGS)
{
text *languagename = PG_GETARG_TEXT_PP(0);
text *priv_type_text = PG_GETARG_TEXT_PP(1);
Oid roleid;
Oid languageoid;
AclMode mode;
AclResult aclresult;
/* *has_schema_privilege_name_name *Checkuserprivilegesonaschemagiven *nameusername,textschemaname,andtextprivname.
*/
Datum
has_schema_privilege_name_name(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
text *schemaname = PG_GETARG_TEXT_PP(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid roleid;
Oid schemaoid;
AclMode mode;
AclResult aclresult;
/* *has_schema_privilege_name *Checkuserprivilegesonaschemagiven *textschemanameandtextprivname. *current_userisassumed
*/
Datum
has_schema_privilege_name(PG_FUNCTION_ARGS)
{
text *schemaname = PG_GETARG_TEXT_PP(0);
text *priv_type_text = PG_GETARG_TEXT_PP(1);
Oid roleid;
Oid schemaoid;
AclMode mode;
AclResult aclresult;
/* *has_server_privilege_name_name *Checkuserprivilegesonaforeignservergiven *nameusername,textservername,andtextprivname.
*/
Datum
has_server_privilege_name_name(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
text *servername = PG_GETARG_TEXT_PP(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid roleid;
Oid serverid;
AclMode mode;
AclResult aclresult;
/* *has_server_privilege_name *Checkuserprivilegesonaforeignservergiven *textservernameandtextprivname. *current_userisassumed
*/
Datum
has_server_privilege_name(PG_FUNCTION_ARGS)
{
text *servername = PG_GETARG_TEXT_PP(0);
text *priv_type_text = PG_GETARG_TEXT_PP(1);
Oid roleid;
Oid serverid;
AclMode mode;
AclResult aclresult;
/* *has_tablespace_privilege_name_name *Checkuserprivilegesonatablespacegiven *nameusername,texttablespacename,andtextprivname.
*/
Datum
has_tablespace_privilege_name_name(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
text *tablespacename = PG_GETARG_TEXT_PP(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid roleid;
Oid tablespaceoid;
AclMode mode;
AclResult aclresult;
/* *has_tablespace_privilege_name *Checkuserprivilegesonatablespacegiven *texttablespacenameandtextprivname. *current_userisassumed
*/
Datum
has_tablespace_privilege_name(PG_FUNCTION_ARGS)
{
text *tablespacename = PG_GETARG_TEXT_PP(0);
text *priv_type_text = PG_GETARG_TEXT_PP(1);
Oid roleid;
Oid tablespaceoid;
AclMode mode;
AclResult aclresult;
/* *has_type_privilege_name_name *Checkuserprivilegesonatypegiven *nameusername,texttypename,andtextprivname.
*/
Datum
has_type_privilege_name_name(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
text *typename = PG_GETARG_TEXT_PP(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid roleid;
Oid typeoid;
AclMode mode;
AclResult aclresult;
/* *has_type_privilege_name *Checkuserprivilegesonatypegiven *texttypenameandtextprivname. *current_userisassumed
*/
Datum
has_type_privilege_name(PG_FUNCTION_ARGS)
{
text *typename = PG_GETARG_TEXT_PP(0);
text *priv_type_text = PG_GETARG_TEXT_PP(1);
Oid roleid;
Oid typeoid;
AclMode mode;
AclResult aclresult;
/* *pg_has_role_name_name *Checkuserprivilegesonarolegiven *nameusername,namerolename,andtextprivname.
*/
Datum
pg_has_role_name_name(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
Name rolename = PG_GETARG_NAME(1);
text *priv_type_text = PG_GETARG_TEXT_PP(2);
Oid roleid;
Oid roleoid;
AclMode mode;
AclResult aclresult;
/* *pg_has_role_name *Checkuserprivilegesonarolegiven *namerolenameandtextprivname. *current_userisassumed
*/
Datum
pg_has_role_name(PG_FUNCTION_ARGS)
{
Name rolename = PG_GETARG_NAME(0);
text *priv_type_text = PG_GETARG_TEXT_PP(1);
Oid roleid;
Oid roleoid;
AclMode mode;
AclResult aclresult;
/* *RoleMembershipCacheCallback *Syscacheinvalcallbackfunction
*/ staticvoid
RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
{ if (cacheid == DATABASEOID &&
hashvalue != cached_db_hash &&
hashvalue != 0)
{ return; /* ignore pg_database changes for other DBs */
}
/* Force membership caches to be recomputed on next use */
cached_role[ROLERECURSE_MEMBERS] = InvalidOid;
cached_role[ROLERECURSE_PRIVS] = InvalidOid;
cached_role[ROLERECURSE_SETROLE] = InvalidOid;
}
/* *Getalistofrolesthatthespecifiedroleidisamemberof * *TypeROLERECURSE_MEMBERSrecursesthroughallgrants;ROLERECURSE_PRIVS *recursesonlythroughinheritablegrants;andROLERECURSE_SETROLErecurses *onlythroughgrantswithset_option. * *Sinceindirectmembershiptestingisrelativelyexpensive,wecache *alistofmemberships.Hence,theresultisonlyguaranteedgooduntil *thenextcallofroles_is_member_of()! * *Forthebenefitofselect_best_grantor,theresultisdefinedtobe *inbreadth-firstorder,ie,closerrelationshipsearlier. * *Ifadmin_ofisnotInvalidOid,thisfunctionsets*admin_role,either *totheOIDofthefirstroleintheresultlistthatdirectlypossesses *ADMINOPTIONontherolecorrespondingtoadmin_of,ortoInvalidOidif *thereisnosuchrole.
*/ static List *
roles_is_member_of(Oid roleid, enum RoleRecurseType type,
Oid admin_of, Oid *admin_role)
{
Oid dba;
List *roles_list;
ListCell *l;
List *new_cached_roles;
MemoryContext oldctx;
bloom_filter *bf = NULL;
Assert(OidIsValid(admin_of) == PointerIsValid(admin_role)); if (admin_role != NULL)
*admin_role = InvalidOid;
/* If cache is valid and ADMIN OPTION not sought, just return the list */ if (cached_role[type] == roleid && !OidIsValid(admin_of) &&
OidIsValid(cached_role[type])) return cached_roles[type];
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;
Form_pg_auth_members form = (Form_pg_auth_members) GETSTRUCT(tup);
Oid otherid = form->roleid;
/* *PermissionviolationerrorunlessabletoSETROLEtotargetrole.
*/ void
check_can_set_role(Oid member, Oid role)
{ if (!member_can_set_role(member, role))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be able to SET ROLE \"%s\"",
GetUserNameFromId(role, false))));
}
/* *Ismemberamemberofrole(directlyorindirectly)? * *Thisisdefinedtorecursethroughgrantswhethertheyareinheritedornot. * *Donotusethisforprivilegechecking,insteadusehas_privs_of_role(). *Don'tuseitfordeterminingwhetherit'spossibletoSETROLEtosome *otherrole;forthat,usemember_can_set_role().Anddon'tuseitfor *determiningwhetherit'sOKtocreateanobjectownedbysomeotherrole: *usemember_can_set_role()forthat,too. * *Inshort,callingthisfunctionisthewrongthingtodonearlyeverywhere.
*/ bool
is_member_of_role(Oid member, Oid role)
{ /* Fast path for simple case */ if (member == role) returntrue;
/* Superusers have every privilege, so are part of every role */ if (superuser_arg(member)) returntrue;
/* *get_role_oid-Givenarolename,lookuptherole'sOID. * *Ifmissing_okisfalse,throwanerrorifrolenamenotfound.If *true,justreturnInvalidOid.
*/
Oid
get_role_oid(constchar *rolname, bool missing_ok)
{
Oid oid;
oid = GetSysCacheOid1(AUTHNAME, Anum_pg_authid_oid,
CStringGetDatum(rolname)); if (!OidIsValid(oid) && !missing_ok)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("role \"%s\" does not exist", rolname))); return oid;
}
/* *get_role_oid_or_public-Asabove,butreturnACL_ID_PUBLICifthe *rolenameis"public".
*/
Oid
get_role_oid_or_public(constchar *rolname)
{ if (strcmp(rolname, "public") == 0) return ACL_ID_PUBLIC;
return get_role_oid(rolname, false);
}
/* *GivenaRoleSpecnode,returntheOIDitcorrespondsto.Ifmissing_okis *true,returnInvalidOidiftheroledoesnotexist. * *PUBLICisalwaysdisallowedhere.RoutineswantingtohandlethePUBLIC *casemustcheckthecaseseparately.
*/
Oid
get_rolespec_oid(const RoleSpec *role, bool missing_ok)
{
Oid oid;
switch (role->roletype)
{ case ROLESPEC_CSTRING:
Assert(role->rolename);
oid = get_role_oid(role->rolename, missing_ok); break;
case ROLESPEC_CURRENT_ROLE: case ROLESPEC_CURRENT_USER:
oid = GetUserId(); break;
case ROLESPEC_SESSION_USER:
oid = GetSessionUserId(); break;
case ROLESPEC_PUBLIC:
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("role \"%s\" does not exist", "public")));
oid = InvalidOid; /* make compiler happy */ break;
default:
elog(ERROR, "unexpected role type %d", role->roletype);
}
switch (role->roletype)
{ case ROLESPEC_CSTRING:
Assert(role->rolename);
tuple = SearchSysCache1(AUTHNAME, CStringGetDatum(role->rolename)); if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("role \"%s\" does not exist", role->rolename))); break;
case ROLESPEC_CURRENT_ROLE: case ROLESPEC_CURRENT_USER:
tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(GetUserId())); if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for role %u", GetUserId()); break;
case ROLESPEC_SESSION_USER:
tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(GetSessionUserId())); if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for role %u", GetSessionUserId()); break;
case ROLESPEC_PUBLIC:
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("role \"%s\" does not exist", "public")));
tuple = NULL; /* make compiler happy */ break;
default:
elog(ERROR, "unexpected role type %d", role->roletype);
}
if (IsReservedName(role->rolename))
{ if (detail_msg)
ereport(ERROR,
(errcode(ERRCODE_RESERVED_NAME),
errmsg("role name \"%s\" is reserved",
role->rolename),
errdetail_internal("%s", detail_msg))); else
ereport(ERROR,
(errcode(ERRCODE_RESERVED_NAME),
errmsg("role name \"%s\" is reserved",
role->rolename)));
}
}
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.195Bemerkung:
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.