📄 aclchk.c
字号:
if (stmt->privileges == NIL) { all_privs = true; privileges = ACL_ALL_RIGHTS_FUNCTION; } else { all_privs = false; privileges = ACL_NO_RIGHTS; foreach(i, stmt->privileges) { char *privname = strVal(lfirst(i)); AclMode priv = string_to_privilege(privname); if (priv & ~((AclMode) ACL_ALL_RIGHTS_FUNCTION)) ereport(ERROR, (errcode(ERRCODE_INVALID_GRANT_OPERATION), errmsg("invalid privilege type %s for function", privilege_to_string(priv)))); privileges |= priv; } } foreach(i, stmt->objects) { FuncWithArgs *func = (FuncWithArgs *) lfirst(i); Oid oid; Relation relation; HeapTuple tuple; Form_pg_proc pg_proc_tuple; Datum aclDatum; bool isNull; AclMode avail_goptions; AclMode this_privileges; Acl *old_acl; Acl *new_acl; Oid grantorId; Oid ownerId; HeapTuple newtuple; Datum values[Natts_pg_proc]; char nulls[Natts_pg_proc]; char replaces[Natts_pg_proc]; int noldmembers; int nnewmembers; Oid *oldmembers; Oid *newmembers; oid = LookupFuncNameTypeNames(func->funcname, func->funcargs, false); relation = heap_open(ProcedureRelationId, RowExclusiveLock); tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(oid), 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for function %u", oid); pg_proc_tuple = (Form_pg_proc) GETSTRUCT(tuple); /* * Get owner ID and working copy of existing ACL. If there's no ACL, * substitute the proper default. */ ownerId = pg_proc_tuple->proowner; aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl, &isNull); if (isNull) old_acl = acldefault(ACL_OBJECT_FUNCTION, ownerId); else old_acl = DatumGetAclPCopy(aclDatum); /* Determine ID to do the grant as, and available grant options */ select_best_grantor(GetUserId(), privileges, old_acl, ownerId, &grantorId, &avail_goptions); /* * If we found no grant options, consider whether to issue a hard * error. Per spec, having any privilege at all on the object will * get you by here. */ if (avail_goptions == ACL_NO_RIGHTS) { if (pg_proc_aclmask(oid, grantorId, ACL_ALL_RIGHTS_FUNCTION | ACL_GRANT_OPTION_FOR(ACL_ALL_RIGHTS_FUNCTION), ACLMASK_ANY) == ACL_NO_RIGHTS) aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_PROC, NameStr(pg_proc_tuple->proname)); } /* * Restrict the operation to what we can actually grant or revoke, and * issue a warning if appropriate. (For REVOKE this isn't quite what * the spec says to do: the spec seems to want a warning only if no * privilege bits actually change in the ACL. In practice that * behavior seems much too noisy, as well as inconsistent with the * GRANT case.) */ this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions); if (stmt->is_grant) { if (this_privileges == 0) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED), errmsg("no privileges were granted"))); else if (!all_privs && this_privileges != privileges) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED), errmsg("not all privileges were granted"))); } else { if (this_privileges == 0) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED), errmsg("no privileges could be revoked"))); else if (!all_privs && this_privileges != privileges) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED), errmsg("not all privileges could be revoked"))); } /* * Generate new ACL. * * We need the members of both old and new ACLs so we can correct the * shared dependency information. */ noldmembers = aclmembers(old_acl, &oldmembers); new_acl = merge_acl_with_grant(old_acl, stmt->is_grant, stmt->grant_option, stmt->behavior, stmt->grantees, this_privileges, grantorId, ownerId); nnewmembers = aclmembers(new_acl, &newmembers); /* finished building new ACL value, now insert it */ MemSet(values, 0, sizeof(values)); MemSet(nulls, ' ', sizeof(nulls)); MemSet(replaces, ' ', sizeof(replaces)); replaces[Anum_pg_proc_proacl - 1] = 'r'; values[Anum_pg_proc_proacl - 1] = PointerGetDatum(new_acl); newtuple = heap_modifytuple(tuple, RelationGetDescr(relation), values, nulls, replaces); simple_heap_update(relation, &newtuple->t_self, newtuple); /* keep the catalog indexes up to date */ CatalogUpdateIndexes(relation, newtuple); /* Update the shared dependency ACL info */ updateAclDependencies(ProcedureRelationId, oid, ownerId, stmt->is_grant, noldmembers, oldmembers, nnewmembers, newmembers); ReleaseSysCache(tuple); pfree(new_acl); heap_close(relation, RowExclusiveLock); /* prevent error when processing duplicate objects */ CommandCounterIncrement(); }}static voidExecuteGrantStmt_Language(GrantStmt *stmt){ AclMode privileges; bool all_privs; ListCell *i; if (stmt->privileges == NIL) { all_privs = true; privileges = ACL_ALL_RIGHTS_LANGUAGE; } else { all_privs = false; privileges = ACL_NO_RIGHTS; foreach(i, stmt->privileges) { char *privname = strVal(lfirst(i)); AclMode priv = string_to_privilege(privname); if (priv & ~((AclMode) ACL_ALL_RIGHTS_LANGUAGE)) ereport(ERROR, (errcode(ERRCODE_INVALID_GRANT_OPERATION), errmsg("invalid privilege type %s for language", privilege_to_string(priv)))); privileges |= priv; } } foreach(i, stmt->objects) { char *langname = strVal(lfirst(i)); Relation relation; HeapTuple tuple; Form_pg_language pg_language_tuple; Datum aclDatum; bool isNull; AclMode avail_goptions; AclMode this_privileges; Acl *old_acl; Acl *new_acl; Oid grantorId; Oid ownerId; HeapTuple newtuple; Datum values[Natts_pg_language]; char nulls[Natts_pg_language]; char replaces[Natts_pg_language]; int noldmembers; int nnewmembers; Oid *oldmembers; Oid *newmembers; relation = heap_open(LanguageRelationId, RowExclusiveLock); tuple = SearchSysCache(LANGNAME, PointerGetDatum(langname), 0, 0, 0); if (!HeapTupleIsValid(tuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("language \"%s\" does not exist", langname))); pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple); if (!pg_language_tuple->lanpltrusted) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("language \"%s\" is not trusted", langname), errhint("Only superusers may use untrusted languages."))); /* * Get owner ID and working copy of existing ACL. If there's no ACL, * substitute the proper default. * * Note: for now, languages are treated as owned by the bootstrap * user. We should add an owner column to pg_language instead. */ ownerId = BOOTSTRAP_SUPERUSERID; aclDatum = SysCacheGetAttr(LANGNAME, tuple, Anum_pg_language_lanacl, &isNull); if (isNull) old_acl = acldefault(ACL_OBJECT_LANGUAGE, ownerId); else old_acl = DatumGetAclPCopy(aclDatum); /* Determine ID to do the grant as, and available grant options */ select_best_grantor(GetUserId(), privileges, old_acl, ownerId, &grantorId, &avail_goptions); /* * If we found no grant options, consider whether to issue a hard * error. Per spec, having any privilege at all on the object will * get you by here. */ if (avail_goptions == ACL_NO_RIGHTS) { if (pg_language_aclmask(HeapTupleGetOid(tuple), grantorId, ACL_ALL_RIGHTS_LANGUAGE | ACL_GRANT_OPTION_FOR(ACL_ALL_RIGHTS_LANGUAGE), ACLMASK_ANY) == ACL_NO_RIGHTS) aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_LANGUAGE, NameStr(pg_language_tuple->lanname)); } /* * Restrict the operation to what we can actually grant or revoke, and * issue a warning if appropriate. (For REVOKE this isn't quite what * the spec says to do: the spec seems to want a warning only if no * privilege bits actually change in the ACL. In practice that * behavior seems much too noisy, as well as inconsistent with the * GRANT case.) */ this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions); if (stmt->is_grant) { if (this_privileges == 0) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED), errmsg("no privileges were granted"))); else if (!all_privs && this_privileges != privileges) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED), errmsg("not all privileges were granted"))); } else { if (this_privileges == 0) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED), errmsg("no privileges could be revoked"))); else if (!all_privs && this_privileges != privileges) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED), errmsg("not all privileges could be revoked"))); } /* * Generate new ACL. * * We need the members of both old and new ACLs so we can correct the * shared dependency information. */ noldmembers = aclmembers(old_acl, &oldmembers); new_acl = merge_acl_with_grant(old_acl, stmt->is_grant, stmt->grant_option, stmt->behavior, stmt->grantees, this_privileges, grantorId, ownerId); nnewmembers = aclmembers(new_acl, &newmembers); /* finished building new ACL value, now insert it */ MemSet(values, 0, sizeof(values)); MemSet(nulls, ' ', sizeof(nulls)); MemSet(replaces, ' ', sizeof(replaces)); replaces[Anum_pg_language_lanacl - 1] = 'r'; values[Anum_pg_language_lanacl - 1] = PointerGetDatum(new_acl); newtuple = heap_modifytuple(tuple, RelationGetDescr(relation), values, nulls, replaces); simple_heap_update(relation, &newtuple->t_self, newtuple); /* keep the catalog indexes up to date */ CatalogUpdateIndexes(relation, newtuple); /* Update the shared dependency ACL info */ updateAclDependencies(LanguageRelationId, HeapTupleGetOid(tuple), ownerId, stmt->is_grant, noldmembers, oldmembers, nnewmembers, newmembers); ReleaseSysCache(tuple); pfree(new_acl); heap_close(relation, RowExclusiveLock); /* prevent error when processing duplicate objects */ CommandCounterIncrement(); }}static voidExecuteGrantStmt_Namespace(GrantStmt *stmt){ AclMode privileges; bool all_privs; ListCell *i; if (stmt->privileges == NIL) { all_privs = true; privileges = ACL_ALL_RIGHTS_NAMESPACE; } else { all_privs = false; privileges = ACL_NO_RIGHTS; foreach(i, stmt->privileges) { char *privname = strVal(lfirst(i)); AclMode priv = string_to_privilege(privname); if (priv & ~((AclMode) ACL_ALL_RIGHTS_NAMESPACE)) ereport(ERROR, (errcode(ERRCODE_INVALID_GRANT_OPERATION), errmsg("invalid privilege type %s for schema", privilege_to_string(priv)))); privileges |= priv; } } foreach(i, stmt->objects) { char *nspname = strVal(lfirst(i)); Relation relation; HeapTuple tuple; Form_pg_namespace pg_namespace_tuple; Datum aclDatum; bool isNull; AclMode avail_goptions; AclMode this_privileges; Acl *old_acl; Acl *new_acl; Oid grantorId; Oid ownerId; HeapTuple newtuple; Datum values[Natts_pg_namespace]; char nulls[Natts_pg_namespace]; char replaces[Natts_pg_namespace]; int noldmembers; int nnewmembers; Oid *oldmembers; Oid *newmembers; relation = heap_open(NamespaceRelationId, RowExclusiveLock); tuple = SearchSysCache(NAMESPACENAME, CStringGetDatum(nspname), 0, 0, 0); if (!HeapTupleIsValid(tuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_SCHEMA), errmsg("schema \"%s\" does not exist", nspname))); pg_namespace_tuple = (Form_pg_namespace) GETSTRUCT(tuple); /* * Get owner ID and working copy of existing ACL. If there's no ACL, * substitute the proper default. */ ownerId = pg_namespace_tuple->nspowner; aclDatum = SysCacheGetAttr(NAMESPACENAME, tuple, Anum_pg_namespace_nspacl, &isNull); if (isNull) old_acl = acldefault(ACL_OBJECT_NAMESPACE, ownerId); else old_acl = DatumGetAclPCopy(aclDatum); /* Determine ID to do the grant as, and available grant options */ select_best_grantor(GetUserId(), privileges, old_acl, ownerId, &grantorId, &avail_goptions); /* * If we found no grant options, consider whether to issue a hard * error. Per spec, having any privilege at all on the object will * get you by here. */ if (avail_goptions == ACL_NO_RIGHTS) { if (pg_namespace_aclmask(HeapTupleGetOid(tuple), grantorId, ACL_ALL_RIGHTS_NAMESPACE | ACL_GRANT_OPTION_FOR(ACL_ALL_RIGHTS_NAMESPACE), ACLMASK_ANY) == ACL_NO_RIGHTS) aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_NAMESPACE, nspname); } /* * Restrict the operation to what we can actually grant or revoke, and * issue a warning if appropriate. (For REVOKE this isn't quite what * the spec says to do: the spec seems to want a warning only if no * privilege bits actually change in the ACL. In practice that * behavior seems much too noisy, as well as inconsistent with the * GRANT case.) */ this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions); if (stmt->is_grant) { if (this_privileges == 0) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED), errmsg("no privileges were granted"))); else if (!all_privs && this_privileges != privileges) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED), errmsg("not all privileges were granted"))); } else { if (this_privileges == 0) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED), errmsg("no privileges could be revoked"))); else if (!all_privs && this_privileges != privileges) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED), errmsg("not all privileges could be revoked"))); } /* * Generate new ACL. * * We need the members of both old and new ACLs so we can correct the * shared dependency information. */ noldmembers = aclmembers(old_acl, &oldmembers); new_acl = merge_acl_with_grant(old_acl, stmt->is_grant, stmt->grant_option, stmt->behavior, stmt->grantees, this_privileges, grantorId, ownerId); nnewmembers = aclmembers(new_acl, &newmembers); /* finished building new ACL value, now insert it */ MemSet(values, 0, sizeof(values)); MemSet(nulls, ' ', sizeof(nulls)); MemSet(replaces, ' ', sizeof(replaces)); replaces[Anum_pg_namespace_nspacl - 1] = 'r'; values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(new_acl); newtuple = heap_modifytuple(tuple, RelationGetDescr(relation), values, nulls, replaces); simple_heap_update(relation, &newtuple->t_self, newtuple); /* keep the catalog indexes up to date */ CatalogUpdateIndexes(relation, newtuple); /* Update the shared dependency ACL info */ updateAclDependencies(NamespaceRelationId, HeapTupleGetOid(tuple), ownerId, stmt->is_grant, noldmembers, oldmembers, nnewmembers, newmembers); ReleaseSysCache(tuple); pfree(new_acl); heap_close(relation, RowExclusiveLock); /* prevent error when processing duplicate objects */ CommandCounterIncrement(); }}static voidExecuteGrantStmt_Tablespace(GrantStmt *stmt){ AclMode privileges; bool all_privs; ListCell *i; if (stmt->privileges == NIL) { all_privs = true; privileges = ACL_ALL_RIGHTS_TABLESPACE; } else { all_privs = false; privileges = ACL_NO_RIGHTS; foreach(i, stmt->privileges) { char *privname = strVal(lfirst(i)); AclMode priv = string_to_privilege(privname); if (priv & ~((AclMode) ACL_ALL_RIGHTS_TABLESPACE)) ereport(ERROR, (errcode(ERRCODE_INVALID_GRANT_OPERATION), errmsg("invalid privilege type %s for tablespace", privilege_to_string(priv)))); privileges |= priv; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -