📄 acl.c
字号:
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;}/* * aclmask_direct --- compute bitmask of all privileges held by roleid. * * This is exactly like aclmask() except that we consider only privileges * held *directly* by roleid, not those inherited via role membership. */static AclModeaclmask_direct(const Acl *acl, Oid roleid, Oid ownerId, AclMode mask, AclMaskHow how){ AclMode result; AclItem *aidat; int i, num; /* * Null ACL should not happen, since caller should have inserted * appropriate default */ if (acl == NULL) elog(ERROR, "null 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) && 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 (and not to public) */ 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 * Find out all the roleids mentioned in an Acl. * Note that we do not distinguish grantors from grantees. * * *roleids is set to point to a palloc'd array containing distinct OIDs * in sorted order. The length of the array is the function result. */intaclmembers(const Acl *acl, Oid **roleids){ Oid *list; const AclItem *acldat; int i, j, k; if (acl == NULL || ACL_NUM(acl) == 0) { *roleids = NULL; return 0; } /* 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;}/* * oidComparator * qsort comparison function for Oids */static intoidComparator(const void *arg1, const void *arg2){ Oid oid1 = *(const Oid *) arg1; Oid oid2 = *(const Oid *) arg2; if (oid1 > oid2) return 1; if (oid1 < oid2) return -1; return 0;}/* * aclinsert (exported function) */Datumaclinsert(PG_FUNCTION_ARGS){ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("aclinsert is no longer supported"))); PG_RETURN_NULL(); /* keep compiler quiet */}Datumaclremove(PG_FUNCTION_ARGS){ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("aclremove is no longer supported"))); PG_RETURN_NULL(); /* keep compiler quiet */}Datumaclcontains(PG_FUNCTION_ARGS){ Acl *acl = PG_GETARG_ACL_P(0); AclItem *aip = PG_GETARG_ACLITEM_P(1); AclItem *aidat; int i, num; 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);}Datummakeaclitem(PG_FUNCTION_ARGS){ 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);}static AclModeconvert_priv_string(text *priv_type_text){ char *priv_type; priv_type = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(priv_type_text))); if (pg_strcasecmp(priv_type, "SELECT") == 0) return ACL_SELECT; if (pg_strcasecmp(priv_type, "INSERT") == 0) return ACL_INSERT; if (pg_strcasecmp(priv_type, "UPDATE") == 0) return ACL_UPDATE; if (pg_strcasecmp(priv_type, "DELETE") == 0) return ACL_DELETE; if (pg_strcasecmp(priv_type, "RULE") == 0) return ACL_RULE; if (pg_strcasecmp(priv_type, "REFERENCES") == 0) return ACL_REFERENCES; if (pg_strcasecmp(priv_type, "TRIGGER") == 0) return ACL_TRIGGER; if (pg_strcasecmp(priv_type, "EXECUTE") == 0) return ACL_EXECUTE; if (pg_strcasecmp(priv_type, "USAGE") == 0) return ACL_USAGE; if (pg_strcasecmp(priv_type, "CREATE") == 0) return ACL_CREATE; if (pg_strcasecmp(priv_type, "TEMP") == 0) return ACL_CREATE_TEMP; if (pg_strcasecmp(priv_type, "TEMPORARY") == 0) return ACL_CREATE_TEMP; ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized privilege type: \"%s\"", priv_type))); return ACL_NO_RIGHTS; /* keep compiler quiet */}/* * has_table_privilege variants * These are all named "has_table_privilege" at the SQL level. * They take various combinations of relation name, relation OID, * user name, user OID, or implicit user = current_user. * * The result is a boolean value: true if user has the indicated * privilege, false if not. *//* * has_table_privilege_name_name * Check user privileges on a table given * name username, text tablename, and text priv name. */Datumhas_table_privilege_name_name(PG_FUNCTION_ARGS){ Name rolename = PG_GETARG_NAME(0); text *tablename = PG_GETARG_TEXT_P(1); text *priv_type_text = PG_GETARG_TEXT_P(2); Oid roleid; Oid tableoid; AclMode mode; AclResult aclresult; roleid = get_roleid_checked(NameStr(*rolename)); tableoid = convert_table_name(tablename); mode = convert_table_priv_string(priv_type_text); aclresult = pg_class_aclcheck(tableoid, roleid, mode); PG_RETURN_BOOL(aclresult == ACLCHECK_OK);}/* * has_table_privilege_name * Check user privileges on a table given * text tablename and text priv name. * current_user is assumed */Datumhas_table_privilege_name(PG_FUNCTION_ARGS){ text *tablename = PG_GETARG_TEXT_P(0); text *priv_type_text = PG_GETARG_TEXT_P(1); Oid roleid; Oid tableoid; AclMode mode; AclResult aclresult; roleid = GetUserId(); tableoid = convert_table_name(tablename); mode = convert_table_priv_string(priv_type_text); aclresult = pg_class_aclcheck(tableoid, roleid, mode); PG_RETURN_BOOL(aclresult == ACLCHECK_OK);}/* * has_table_privilege_name_id * Check user privileges on a table given * name usename, table oid, and text priv name. */Datumhas_table_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_P(2); Oid roleid; AclMode mode; AclResult aclresult; roleid = get_roleid_checked(NameStr(*username)); mode = convert_table_priv_string(priv_type_text); aclresult = pg_class_aclcheck(tableoid, roleid, mode); PG_RETURN_BOOL(aclresult == ACLCHECK_OK);}/* * has_table_privilege_id * Check user privileges on a table given * table oid, and text priv name. * current_user is assumed */Datumhas_table_privilege_id(PG_FUNCTION_ARGS){ Oid tableoid = PG_GETARG_OID(0); text *priv_type_text = PG_GETARG_TEXT_P(1); Oid roleid; AclMode mode; AclResult aclresult; roleid = GetUserId(); mode = convert_table_priv_string(priv_type_text); aclresult = pg_class_aclcheck(tableoid, roleid, mode); PG_RETURN_BOOL(aclresult == ACLCHECK_OK);}/* * has_table_privilege_id_name * Check user privileges on a table given * roleid, text tablename, and text priv name. */Datumhas_table_privilege_id_name(PG_FUNCTION_ARGS){ Oid roleid = PG_GETARG_OID(0); text *tablename = PG_GETARG_TEXT_P(1); text *priv_type_text = PG_GETARG_TEXT_P(2); Oid tableoid; AclMode mode; AclResult aclresult; tableoid = convert_table_name(tablename); mode = convert_table_priv_string(priv_type_text); aclresult = pg_class_aclcheck(tableoid, roleid, mode); PG_RETURN_BOOL(aclresult == ACLCHECK_OK);}/* * has_table_privilege_id_id * Check user privileges on a table given * roleid, table oid, and text priv name. */Datumhas_table_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_P(2); AclMode mode; AclResult aclresult; mode = convert_table_priv_string(priv_type_text); aclresult = pg_class_aclcheck(tableoid, roleid, mode); PG_RETURN_BOOL(aclresult == ACLCHECK_OK);}/* * Support routines for has_table_privilege family. *//* * Given a table name expressed as a string, look it up and return Oid */static Oidconvert_table_name(text *tablename){ RangeVar *relrv; relrv = makeRangeVarFromNameList(textToQualifiedNameList(tablename)); return RangeVarGetRelid(relrv, false);}/* * convert_table_priv_string * Convert text string to AclMode value. */static AclModeconvert_table_priv_string(text *priv_type_text){ char *priv_type; priv_type = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(priv_type_text))); /* * Return mode from priv_type string */ if (pg_strcasecmp(priv_type, "SELECT") == 0) return ACL_SELECT; if (pg_strcasecmp(priv_type, "SELECT WITH GRANT OPTION") == 0) return ACL_GRANT_OPTION_FOR(ACL_SELECT); if (pg_strcasecmp(priv_type, "INSERT") == 0) return ACL_INSERT; if (pg_strcasecmp(priv_type, "INSERT WITH GRANT OPTION") == 0) return ACL_GRANT_OPTION_FOR(ACL_INSERT); if (pg_strcasecmp(priv_type, "UPDATE") == 0) return ACL_UPDATE; if (pg_strcasecmp(priv_type, "UPDATE WITH GRANT OPTION") == 0) return ACL_GRANT_OPTION_FOR(ACL_UPDATE); if (pg_strcasecmp(priv_type, "DELETE") == 0) return ACL_DELETE; if (pg_strcasecmp(priv_type, "DELETE WITH GRANT OPTION") == 0) return ACL_GRANT_OPTION_FOR(ACL_DELETE); if (pg_strcasecmp(priv_type, "RULE") == 0) return ACL_RULE; if (pg_strcasecmp(priv_type, "RULE WITH GRANT OPTION") == 0) return ACL_GRANT_OPTION_FOR(ACL_RULE); if (pg_strcasecmp(priv_type, "REFERENCES") == 0) return ACL_REFERENCES; if (pg_strcasecmp(priv_type, "REFERENCES WITH GRANT OPTION") == 0) return ACL_GRANT_OPTION_FOR(ACL_REFERENCES); if (pg_strcasecmp(priv_type, "TRIGGER") == 0) return ACL_TRIGGER; if (pg_strcasecmp(priv_type, "TRIGGER WITH GRANT OPTION") == 0) return ACL_GRANT_OPTION_FOR(ACL_TRIGGER);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -