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 + -
显示快捷键?