acl.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 1,969 行 · 第 1/4 页
C
1,969 行
/* not very bright, but avoids any issue of padding in struct */ PG_RETURN_UINT32((uint32) (a->ai_privs + a->ai_grantee + a->ai_grantor));}/* * acldefault() --- create an ACL describing default access permissions * * Change this routine if you want to alter the default access policy for * newly-created objects (or any object with a NULL acl entry). */Acl *acldefault(GrantObjectType objtype, AclId ownerid){ AclMode world_default; AclMode owner_default; Acl *acl; AclItem *aip; switch (objtype) { case ACL_OBJECT_RELATION: world_default = ACL_NO_RIGHTS; owner_default = ACL_ALL_RIGHTS_RELATION; break; case ACL_OBJECT_DATABASE: world_default = ACL_CREATE_TEMP; /* not NO_RIGHTS! */ 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_NAMESPACE: world_default = ACL_NO_RIGHTS; owner_default = ACL_ALL_RIGHTS_NAMESPACE; break; default: elog(ERROR, "unrecognized objtype: %d", (int) objtype); world_default = ACL_NO_RIGHTS; /* keep compiler quiet */ owner_default = ACL_NO_RIGHTS; break; } acl = allocacl((world_default != ACL_NO_RIGHTS) ? 2 : 1); aip = ACL_DAT(acl); if (world_default != ACL_NO_RIGHTS) { aip->ai_grantee = ACL_ID_WORLD; aip->ai_grantor = ownerid; ACLITEM_SET_PRIVS_IDTYPE(*aip, world_default, ACL_NO_RIGHTS, ACL_IDTYPE_WORLD); aip++; } aip->ai_grantee = ownerid; aip->ai_grantor = ownerid; /* owner gets default privileges with grant option */ ACLITEM_SET_PRIVS_IDTYPE(*aip, owner_default, owner_default, ACL_IDTYPE_UID); return acl;}/* * Add or replace an item in an ACL array. The result is a modified copy; * the input object is not changed. * * NB: caller is responsible for having detoasted the input ACL, if needed. */Acl *aclinsert3(const Acl *old_acl, const AclItem *mod_aip, unsigned modechg, DropBehavior behavior){ Acl *new_acl = NULL; AclItem *old_aip, *new_aip = NULL; AclMode old_privs, old_goptions, new_privs, new_goptions; int dst, num; /* These checks for null input are probably dead code, but... */ if (!old_acl || ACL_NUM(old_acl) < 0) old_acl = allocacl(0); if (!mod_aip) { new_acl = allocacl(ACL_NUM(old_acl)); memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); return new_acl; } 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_IDTYPE(new_aip[dst], ACL_NO_RIGHTS, ACL_NO_RIGHTS, ACLITEM_GET_IDTYPE(*mod_aip)); num++; /* set num to the size of new_acl */ } old_privs = ACLITEM_GET_PRIVS(new_aip[dst]); old_goptions = ACLITEM_GET_GOPTIONS(new_aip[dst]); /* apply the specified permissions change */ switch (modechg) { case ACL_MODECHG_ADD: ACLITEM_SET_PRIVS(new_aip[dst], old_privs | ACLITEM_GET_PRIVS(*mod_aip)); ACLITEM_SET_GOPTIONS(new_aip[dst], old_goptions | ACLITEM_GET_GOPTIONS(*mod_aip)); break; case ACL_MODECHG_DEL: ACLITEM_SET_PRIVS(new_aip[dst], old_privs & ~ACLITEM_GET_PRIVS(*mod_aip)); ACLITEM_SET_GOPTIONS(new_aip[dst], old_goptions & ~ACLITEM_GET_GOPTIONS(*mod_aip)); break; case ACL_MODECHG_EQL: ACLITEM_SET_PRIVS_IDTYPE(new_aip[dst], ACLITEM_GET_PRIVS(*mod_aip), ACLITEM_GET_GOPTIONS(*mod_aip), ACLITEM_GET_IDTYPE(new_aip[dst])); break; } new_privs = ACLITEM_GET_PRIVS(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_privs == ACL_NO_RIGHTS && new_goptions == ACL_NO_RIGHTS) { memmove(new_aip + dst, new_aip + dst + 1, (num - dst - 1) * sizeof(AclItem)); ARR_DIMS(new_acl)[0] = num - 1; ARR_SIZE(new_acl) -= sizeof(AclItem); } /* * Remove abandoned privileges (cascading revoke). Currently we * can only handle this when the grantee is a user. */ if ((old_goptions & ~new_goptions) != 0 && ACLITEM_GET_IDTYPE(*mod_aip) == ACL_IDTYPE_UID) new_acl = recursive_revoke(new_acl, mod_aip->ai_grantee, (old_goptions & ~new_goptions), behavior); return new_acl;}/* * Ensure that no privilege is "abandoned". A privilege is abandoned * if the user that granted the privilege loses the grant option. (So * the chain through which it was granted is broken.) Either the * abandoned privileges are revoked as well, or an error message is * printed, depending on the drop behavior option. */static Acl *recursive_revoke(Acl *acl, AclId grantee, AclMode revoke_privs, DropBehavior behavior){ int i;restart: for (i = 0; i < ACL_NUM(acl); i++) { AclItem *aip = ACL_DAT(acl); if (aip[i].ai_grantor == grantee && (ACLITEM_GET_PRIVS(aip[i]) & revoke_privs) != 0) { AclItem mod_acl; if (behavior == DROP_RESTRICT) ereport(ERROR, (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST), errmsg("dependent privileges exist"), errhint("Use CASCADE to revoke them too."))); mod_acl.ai_grantor = grantee; mod_acl.ai_grantee = aip[i].ai_grantee; ACLITEM_SET_PRIVS_IDTYPE(mod_acl, revoke_privs, revoke_privs, ACLITEM_GET_IDTYPE(aip[i])); acl = aclinsert3(acl, &mod_acl, ACL_MODECHG_DEL, behavior); goto restart; } } return acl;}/* * aclinsert (exported function) */Datumaclinsert(PG_FUNCTION_ARGS){ Acl *old_acl = PG_GETARG_ACL_P(0); AclItem *mod_aip = PG_GETARG_ACLITEM_P(1); PG_RETURN_ACL_P(aclinsert3(old_acl, mod_aip, ACL_MODECHG_EQL, DROP_CASCADE));}Datumaclremove(PG_FUNCTION_ARGS){ Acl *old_acl = PG_GETARG_ACL_P(0); AclItem *mod_aip = PG_GETARG_ACLITEM_P(1); Acl *new_acl; AclItem *old_aip, *new_aip; int dst, old_num, new_num; /* These checks for null input should be dead code, but... */ if (!old_acl || ACL_NUM(old_acl) < 0) old_acl = allocacl(0); if (!mod_aip) { new_acl = allocacl(ACL_NUM(old_acl)); memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); PG_RETURN_ACL_P(new_acl); } old_num = ACL_NUM(old_acl); old_aip = ACL_DAT(old_acl); /* Search for the matching entry */ for (dst = 0; dst < old_num && !aclitem_match(mod_aip, old_aip + dst); ++dst) /* continue */ ; if (dst >= old_num) { /* Not found, so return copy of source ACL */ new_acl = allocacl(old_num); memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); } else { new_num = old_num - 1; new_acl = allocacl(new_num); new_aip = ACL_DAT(new_acl); if (dst > 0) memcpy((char *) new_aip, (char *) old_aip, dst * sizeof(AclItem)); if (dst < new_num) memcpy((char *) (new_aip + dst), (char *) (old_aip + dst + 1), (new_num - dst) * sizeof(AclItem)); } PG_RETURN_ACL_P(new_acl);}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 && ACLITEM_GET_IDTYPE(*aip) == ACLITEM_GET_IDTYPE(aidat[i]) && aip->ai_grantor == aidat[i].ai_grantor && (ACLITEM_GET_PRIVS(*aip) & ACLITEM_GET_PRIVS(aidat[i])) == ACLITEM_GET_PRIVS(*aip) && (ACLITEM_GET_GOPTIONS(*aip) & ACLITEM_GET_GOPTIONS(aidat[i])) == ACLITEM_GET_GOPTIONS(*aip)) PG_RETURN_BOOL(true); } PG_RETURN_BOOL(false);}Datummakeaclitem(PG_FUNCTION_ARGS){ int32 u_grantee = PG_GETARG_INT32(0); int32 g_grantee = PG_GETARG_INT32(1); int32 grantor = PG_GETARG_INT32(2); text *privtext = PG_GETARG_TEXT_P(3); bool goption = PG_GETARG_BOOL(4); AclItem *aclitem; AclMode priv; priv = convert_priv_string(privtext); aclitem = (AclItem *) palloc(sizeof(*aclitem)); if (u_grantee == 0 && g_grantee == 0) { aclitem->ai_grantee = ACL_ID_WORLD; ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_WORLD); } else if (u_grantee != 0 && g_grantee != 0) { ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("cannot specify both user and group"))); } else if (u_grantee != 0) { aclitem->ai_grantee = u_grantee; ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_UID); } else /* (g_grantee != 0) */ { aclitem->ai_grantee = g_grantee; ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_GID); } aclitem->ai_grantor = grantor; ACLITEM_SET_PRIVS(*aclitem, priv); if (goption) ACLITEM_SET_GOPTIONS(*aclitem, priv); else ACLITEM_SET_GOPTIONS(*aclitem, ACL_NO_RIGHTS); PG_RETURN_ACLITEM_P(aclitem);}static AclModeconvert_priv_string(text *priv_type_text){ char *priv_type; priv_type = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(priv_type_text))); if (strcasecmp(priv_type, "SELECT") == 0) return ACL_SELECT; if (strcasecmp(priv_type, "INSERT") == 0) return ACL_INSERT; if (strcasecmp(priv_type, "UPDATE") == 0) return ACL_UPDATE; if (strcasecmp(priv_type, "DELETE") == 0) return ACL_DELETE; if (strcasecmp(priv_type, "RULE") == 0) return ACL_RULE; if (strcasecmp(priv_type, "REFERENCES") == 0) return ACL_REFERENCES; if (strcasecmp(priv_type, "TRIGGER") == 0) return ACL_TRIGGER; if (strcasecmp(priv_type, "EXECUTE") == 0) return ACL_EXECUTE; if (strcasecmp(priv_type, "USAGE") == 0) return ACL_USAGE; if (strcasecmp(priv_type, "CREATE") == 0) return ACL_CREATE; if (strcasecmp(priv_type, "TEMP") == 0) return ACL_CREATE_TEMP; if (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 sysid, 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 username = PG_GETARG_NAME(0); text *tablename = PG_GETARG_TEXT_P(1); text *priv_type_text = PG_GETARG_TEXT_P(2); int32 usesysid; Oid tableoid; AclMode mode; AclResult aclresult; usesysid = get_usesysid(NameStr(*username)); tableoid = convert_table_name(tablename); mode = convert_table_priv_string(priv_type_text); aclresult = pg_class_aclcheck(tableoid, usesysid, 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); AclId usesysid; Oid tableoid; AclMode mode; AclResult aclresult; usesysid = GetUserId(); tableoid = convert_table_name(tablename); mode = convert_table_priv_string(priv_type_text); aclresult = pg_class_aclcheck(tableoid, usesysid, 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);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?