⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aclchk.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 4 页
字号:
	foreach(i, stmt->objects)	{		char	   *spcname = strVal(lfirst(i));		Relation	relation;		ScanKeyData entry[1];		HeapScanDesc scan;		HeapTuple	tuple;		Form_pg_tablespace pg_tablespace_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_tablespace];		char		nulls[Natts_pg_tablespace];		char		replaces[Natts_pg_tablespace];		int			noldmembers;		int			nnewmembers;		Oid		   *oldmembers;		Oid		   *newmembers;		relation = heap_open(TableSpaceRelationId, RowExclusiveLock);		ScanKeyInit(&entry[0],					Anum_pg_tablespace_spcname,					BTEqualStrategyNumber, F_NAMEEQ,					CStringGetDatum(spcname));		scan = heap_beginscan(relation, SnapshotNow, 1, entry);		tuple = heap_getnext(scan, ForwardScanDirection);		if (!HeapTupleIsValid(tuple))			ereport(ERROR,					(errcode(ERRCODE_UNDEFINED_OBJECT),					 errmsg("tablespace \"%s\" does not exist", spcname)));		pg_tablespace_tuple = (Form_pg_tablespace) GETSTRUCT(tuple);		/*		 * Get owner ID and working copy of existing ACL. If there's no ACL,		 * substitute the proper default.		 */		ownerId = pg_tablespace_tuple->spcowner;		aclDatum = heap_getattr(tuple, Anum_pg_tablespace_spcacl,								RelationGetDescr(relation), &isNull);		if (isNull)			old_acl = acldefault(ACL_OBJECT_TABLESPACE, 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_tablespace_aclmask(HeapTupleGetOid(tuple),									  grantorId,									  ACL_ALL_RIGHTS_TABLESPACE | ACL_GRANT_OPTION_FOR(ACL_ALL_RIGHTS_TABLESPACE),									  ACLMASK_ANY) == ACL_NO_RIGHTS)				aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE,							   spcname);		}		/*		 * 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_tablespace_spcacl - 1] = 'r';		values[Anum_pg_tablespace_spcacl - 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(TableSpaceRelationId, HeapTupleGetOid(tuple),							  ownerId, stmt->is_grant,							  noldmembers, oldmembers,							  nnewmembers, newmembers);		pfree(new_acl);		heap_endscan(scan);		heap_close(relation, RowExclusiveLock);		/* prevent error when processing duplicate objects */		CommandCounterIncrement();	}}static AclModestring_to_privilege(const char *privname){	if (strcmp(privname, "insert") == 0)		return ACL_INSERT;	if (strcmp(privname, "select") == 0)		return ACL_SELECT;	if (strcmp(privname, "update") == 0)		return ACL_UPDATE;	if (strcmp(privname, "delete") == 0)		return ACL_DELETE;	if (strcmp(privname, "rule") == 0)		return ACL_RULE;	if (strcmp(privname, "references") == 0)		return ACL_REFERENCES;	if (strcmp(privname, "trigger") == 0)		return ACL_TRIGGER;	if (strcmp(privname, "execute") == 0)		return ACL_EXECUTE;	if (strcmp(privname, "usage") == 0)		return ACL_USAGE;	if (strcmp(privname, "create") == 0)		return ACL_CREATE;	if (strcmp(privname, "temporary") == 0)		return ACL_CREATE_TEMP;	if (strcmp(privname, "temp") == 0)		return ACL_CREATE_TEMP;	ereport(ERROR,			(errcode(ERRCODE_SYNTAX_ERROR),			 errmsg("unrecognized privilege type \"%s\"", privname)));	return 0;					/* appease compiler */}static const char *privilege_to_string(AclMode privilege){	switch (privilege)	{		case ACL_INSERT:			return "INSERT";		case ACL_SELECT:			return "SELECT";		case ACL_UPDATE:			return "UPDATE";		case ACL_DELETE:			return "DELETE";		case ACL_RULE:			return "RULE";		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 "TEMP";		default:			elog(ERROR, "unrecognized privilege: %d", (int) privilege);	}	return NULL;				/* appease compiler */}/* * Standardized reporting of aclcheck permissions failures. * * Note: we do not double-quote the %s's below, because many callers * supply strings that might be already quoted. */static const char *const no_priv_msg[MAX_ACL_KIND] ={	/* ACL_KIND_CLASS */	gettext_noop("permission denied for relation %s"),	/* ACL_KIND_DATABASE */	gettext_noop("permission denied for database %s"),	/* ACL_KIND_PROC */	gettext_noop("permission denied for function %s"),	/* ACL_KIND_OPER */	gettext_noop("permission denied for operator %s"),	/* ACL_KIND_TYPE */	gettext_noop("permission denied for type %s"),	/* ACL_KIND_LANGUAGE */	gettext_noop("permission denied for language %s"),	/* ACL_KIND_NAMESPACE */	gettext_noop("permission denied for schema %s"),	/* ACL_KIND_OPCLASS */	gettext_noop("permission denied for operator class %s"),	/* ACL_KIND_CONVERSION */	gettext_noop("permission denied for conversion %s"),	/* ACL_KIND_TABLESPACE */	gettext_noop("permission denied for tablespace %s")};static const char *const not_owner_msg[MAX_ACL_KIND] ={	/* ACL_KIND_CLASS */	gettext_noop("must be owner of relation %s"),	/* ACL_KIND_DATABASE */	gettext_noop("must be owner of database %s"),	/* ACL_KIND_PROC */	gettext_noop("must be owner of function %s"),	/* ACL_KIND_OPER */	gettext_noop("must be owner of operator %s"),	/* ACL_KIND_TYPE */	gettext_noop("must be owner of type %s"),	/* ACL_KIND_LANGUAGE */	gettext_noop("must be owner of language %s"),	/* ACL_KIND_NAMESPACE */	gettext_noop("must be owner of schema %s"),	/* ACL_KIND_OPCLASS */	gettext_noop("must be owner of operator class %s"),	/* ACL_KIND_CONVERSION */	gettext_noop("must be owner of conversion %s"),	/* ACL_KIND_TABLESPACE */	gettext_noop("must be owner of tablespace %s")};voidaclcheck_error(AclResult aclerr, AclObjectKind objectkind,			   const char *objectname){	switch (aclerr)	{		case ACLCHECK_OK:			/* no error, so return to caller */			break;		case ACLCHECK_NO_PRIV:			ereport(ERROR,					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),					 errmsg(no_priv_msg[objectkind], objectname)));			break;		case ACLCHECK_NOT_OWNER:			ereport(ERROR,					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),					 errmsg(not_owner_msg[objectkind], objectname)));			break;		default:			elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);			break;	}}/* Check if given user has rolcatupdate privilege according to pg_authid */static boolhas_rolcatupdate(Oid roleid){	bool		rolcatupdate;	HeapTuple	tuple;	tuple = SearchSysCache(AUTHOID,						   ObjectIdGetDatum(roleid),						   0, 0, 0);	if (!HeapTupleIsValid(tuple))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("role with OID %u does not exist", roleid)));	rolcatupdate = ((Form_pg_authid) GETSTRUCT(tuple))->rolcatupdate;	ReleaseSysCache(tuple);	return rolcatupdate;}/* * Exported routine for examining a user's privileges for a table * * See aclmask() for a description of the API. * * Note: we give lookup failure the full ereport treatment because the * has_table_privilege() family of functions allow users to pass * any random OID to this function.  Likewise for the sibling functions * below. */AclModepg_class_aclmask(Oid table_oid, Oid roleid,				 AclMode mask, AclMaskHow how){	AclMode		result;	HeapTuple	tuple;	Form_pg_class classForm;	Datum		aclDatum;	bool		isNull;	Acl		   *acl;	Oid			ownerId;	/*	 * Must get the relation's tuple from pg_class	 */	tuple = SearchSysCache(RELOID,						   ObjectIdGetDatum(table_oid),						   0, 0, 0);	if (!HeapTupleIsValid(tuple))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_TABLE),				 errmsg("relation with OID %u does not exist",						table_oid)));	classForm = (Form_pg_class) GETSTRUCT(tuple);	/*	 * Deny anyone permission to update a system catalog unless	 * pg_authid.rolcatupdate is set.	(This is to let superusers protect	 * themselves from themselves.)  Also allow it if allowSystemTableMods.	 *	 * As of 7.4 we have some updatable system views; those shouldn't be	 * protected in this way.  Assume the view rules can take care of	 * themselves.	 */	if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) &&		IsSystemClass(classForm) &&		classForm->relkind != RELKIND_VIEW &&		!has_rolcatupdate(roleid) &&		!allowSystemTableMods)	{#ifdef ACLDEBUG		elog(DEBUG2, "permission denied for system catalog update");#endif		mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE);	}	/*	 * Otherwise, superusers bypass all permission-checking.	 */	if (superuser_arg(roleid))	{#ifdef ACLDEBUG		elog(DEBUG2, "OID %u is superuser, home free", roleid);#endif		ReleaseSysCache(tuple);		return mask;	}	/*	 * Normal case: get the relation's ACL from pg_class	 */	ownerId = classForm->relowner;	aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,							   &isNull);	if (isNull)	{		/* No ACL, so build default ACL */		acl = acldefault(ACL_OBJECT_RELATION, ownerId);		aclDatum = (Datum) 0;	}	else	{		/* detoast rel's ACL if necessary */		acl = DatumGetAclP(aclDatum);	}	result = aclmask(acl, roleid, ownerId, mask, how);	/* if we have a detoasted copy, free it */	if (acl && (Pointer) acl != DatumGetPointer(aclDatum))		pfree(acl);	ReleaseSysCache(tuple);	return result;}/* * Exported routine for examining a user's privileges for a database */AclModepg_database_aclmask(Oid db_oid, Oid roleid,					AclMode mask, AclMaskHow how){	AclMode		result;	Relation	pg_database;	ScanKeyData entry[1];	HeapScanDesc scan;	HeapTuple	tuple;	Datum		aclDatum;	bool		isNull;	Acl		   *acl;	Oid			ownerId;	/* Superusers bypass all permission checking. */	if (superuser_arg(roleid))		return mask;	/*	 * Get the database's ACL from pg_database	 *	 * There's no syscache for pg_database, so must look the hard way	 */	pg_database = heap_open(DatabaseRelationId, AccessShareLock);	ScanKeyInit(&entry[0],				ObjectIdAttributeNumber,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(db_oid));	scan = heap_beginscan(pg_database, SnapshotNow, 1, entry);	tuple = heap_getnext(scan, ForwardScanDirection);	if (!HeapTupleIsValid(tuple))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_DATABASE),				 errmsg("database with OID %u does not exist", db_oid)));	ownerId = ((Form_pg_database) GETSTRUCT(tuple))->datdba;	aclDatum = heap_getattr(tuple, Anum_pg_database_datacl,							RelationGetDescr(pg_database), &isNull);	if (isNull)	{		/* No ACL, so build default ACL */		acl = acldefault(ACL_OBJECT_DATABASE, ownerId);		aclDatum = (Datum) 0;	}	else	{		/* detoast ACL if necessary */		acl = DatumGetAclP(aclDatum);	}	result = aclmask(acl, roleid, ownerId, mask, how);	/* if we have a detoasted copy, free it */	if (acl && (Pointer) acl != DatumGetPointer(aclDatum))		pfree(acl);	heap_endscan(scan);	heap_close(pg_database, AccessShareLock);	return result;}/* * Exported routine for examining a user's privileges for a function */AclModepg_proc_aclmask(Oid proc_oid, Oid roleid,				AclMode mask, AclMaskHow how){	AclMode		result;	HeapTuple	tuple;	Datum		aclDatum;	bool		isNull;	Acl		   *acl;	Oid			ownerId;	/* Superusers bypass all permission checking. */	if (superuser_arg(roleid))		return mask;	/*	 * Get the function's ACL from pg_proc	 */	tuple = SearchSysCache(PROCOID,						   ObjectIdGetDatum(proc_oid),						   0, 0, 0);	if (!HeapTupleIsValid(tuple))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_FUNCTION),				 errmsg("function with OID %u does not exist", proc_oid)));	ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;	aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,							   &isNull);	if (isNull)	{		/* No ACL, so build default ACL */		acl = acldefault(ACL_OBJECT_FUNCTION, ownerId);		aclDatum = (Datum) 0;	}	else	{		/* detoast ACL if necessary */		acl = DatumGetAclP(aclDatum);	}	result = aclmask(acl, roleid, ownerId, mask, how);	/* if we have a detoasted copy, free it */	if (acl && (Pointer) acl != DatumGetPointer(aclDatum))		pfree(acl);	ReleaseSysCache(tuple);	return result;}/* * Exported routine for examining a user's privileges for a language */AclModepg_language_aclmask(Oid lang_oid, Oid roleid,					AclMode mask, AclMaskHow how){	AclMode		result;	HeapTuple	tuple;	Datum		aclDatum;	bool		isNull;	Acl		   *acl;	Oid			ownerId;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -