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

📄 user.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
	/*	 * Now we can clean up; but keep locks until commit (to avoid possible	 * deadlock when commit code tries to acquire lock).	 */	heap_close(pg_auth_members_rel, NoLock);	heap_close(pg_authid_rel, NoLock);	/*	 * Set flag to update flat auth file at commit.	 */	auth_file_update_needed();}/* * Rename role */voidRenameRole(const char *oldname, const char *newname){	HeapTuple	oldtuple,				newtuple;	TupleDesc	dsc;	Relation	rel;	Datum		datum;	bool		isnull;	Datum		repl_val[Natts_pg_authid];	char		repl_null[Natts_pg_authid];	char		repl_repl[Natts_pg_authid];	int			i;	Oid			roleid;	/* ExclusiveLock because we need to update the flat auth file */	rel = heap_open(AuthIdRelationId, ExclusiveLock);	dsc = RelationGetDescr(rel);	oldtuple = SearchSysCache(AUTHNAME,							  CStringGetDatum(oldname),							  0, 0, 0);	if (!HeapTupleIsValid(oldtuple))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("role \"%s\" does not exist", oldname)));	/*	 * XXX Client applications probably store the session user somewhere, so	 * renaming it could cause confusion.  On the other hand, there may not be	 * an actual problem besides a little confusion, so think about this and	 * decide.	Same for SET ROLE ... we don't restrict renaming the current	 * effective userid, though.	 */	roleid = HeapTupleGetOid(oldtuple);	if (roleid == GetSessionUserId())		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("session user may not be renamed")));	if (roleid == GetOuterUserId())		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("current user may not be renamed")));	/* make sure the new name doesn't exist */	if (SearchSysCacheExists(AUTHNAME,							 CStringGetDatum(newname),							 0, 0, 0))		ereport(ERROR,				(errcode(ERRCODE_DUPLICATE_OBJECT),				 errmsg("role \"%s\" already exists", newname)));	if (strcmp(newname, "public") == 0 ||		strcmp(newname, "none") == 0)		ereport(ERROR,				(errcode(ERRCODE_RESERVED_NAME),				 errmsg("role name \"%s\" is reserved",						newname)));	/*	 * createrole is enough privilege unless you want to mess with a superuser	 */	if (((Form_pg_authid) GETSTRUCT(oldtuple))->rolsuper)	{		if (!superuser())			ereport(ERROR,					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),					 errmsg("must be superuser to rename superusers")));	}	else	{		if (!have_createrole_privilege())			ereport(ERROR,					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),					 errmsg("permission denied to rename role")));	}	/* OK, construct the modified tuple */	for (i = 0; i < Natts_pg_authid; i++)		repl_repl[i] = ' ';	repl_repl[Anum_pg_authid_rolname - 1] = 'r';	repl_val[Anum_pg_authid_rolname - 1] = DirectFunctionCall1(namein,												   CStringGetDatum(newname));	repl_null[Anum_pg_authid_rolname - 1] = ' ';	datum = heap_getattr(oldtuple, Anum_pg_authid_rolpassword, dsc, &isnull);	if (!isnull && isMD5(DatumGetCString(DirectFunctionCall1(textout, datum))))	{		/* MD5 uses the username as salt, so just clear it on a rename */		repl_repl[Anum_pg_authid_rolpassword - 1] = 'r';		repl_null[Anum_pg_authid_rolpassword - 1] = 'n';		ereport(NOTICE,				(errmsg("MD5 password cleared because of role rename")));	}	newtuple = heap_modifytuple(oldtuple, dsc, repl_val, repl_null, repl_repl);	simple_heap_update(rel, &oldtuple->t_self, newtuple);	CatalogUpdateIndexes(rel, newtuple);	ReleaseSysCache(oldtuple);	heap_close(rel, NoLock);	/*	 * Set flag to update flat auth file at commit.	 */	auth_file_update_needed();}/* * GrantRoleStmt * * Grant/Revoke roles to/from roles */voidGrantRole(GrantRoleStmt *stmt){	Relation	pg_authid_rel;	Oid			grantor;	List	   *grantee_ids;	ListCell   *item;	if (stmt->grantor)		grantor = get_roleid_checked(stmt->grantor);	else		grantor = GetUserId();	grantee_ids = roleNamesToIds(stmt->grantee_roles);	/*	 * Even though this operation doesn't change pg_authid, we must secure	 * exclusive lock on it to protect our update of the flat auth file.	 */	pg_authid_rel = heap_open(AuthIdRelationId, ExclusiveLock);	/*	 * Step through all of the granted roles and add/remove entries for the	 * grantees, or, if admin_opt is set, then just add/remove the admin	 * option.	 *	 * Note: Permissions checking is done by AddRoleMems/DelRoleMems	 */	foreach(item, stmt->granted_roles)	{		char	   *rolename = strVal(lfirst(item));		Oid			roleid = get_roleid_checked(rolename);		if (stmt->is_grant)			AddRoleMems(rolename, roleid,						stmt->grantee_roles, grantee_ids,						grantor, stmt->admin_opt);		else			DelRoleMems(rolename, roleid,						stmt->grantee_roles, grantee_ids,						stmt->admin_opt);	}	heap_close(pg_authid_rel, NoLock);	/*	 * Set flag to update flat auth file at commit.	 */	auth_file_update_needed();}/* * roleNamesToIds * * Given a list of role names (as String nodes), generate a list of role OIDs * in the same order. */static List *roleNamesToIds(List *memberNames){	List	   *result = NIL;	ListCell   *l;	foreach(l, memberNames)	{		char	   *rolename = strVal(lfirst(l));		Oid			roleid = get_roleid_checked(rolename);		result = lappend_oid(result, roleid);	}	return result;}/* * AddRoleMems -- Add given members to the specified role * * rolename: name of role to add to (used only for error messages) * roleid: OID of role to add to * memberNames: list of names of roles to add (used only for error messages) * memberIds: OIDs of roles to add * grantorId: who is granting the membership * admin_opt: granting admin option? * * Note: caller is responsible for holding ExclusiveLock on pg_authid, * and for calling auth_file_update_needed(). */static voidAddRoleMems(const char *rolename, Oid roleid,			List *memberNames, List *memberIds,			Oid grantorId, bool admin_opt){	Relation	pg_authmem_rel;	TupleDesc	pg_authmem_dsc;	ListCell   *nameitem;	ListCell   *iditem;	Assert(list_length(memberNames) == list_length(memberIds));	/* Skip permission check if nothing to do */	if (!memberIds)		return;	/*	 * Check permissions: must have createrole or admin option on the role to	 * be changed.	To mess with a superuser role, you gotta be superuser.	 */	if (superuser_arg(roleid))	{		if (!superuser())			ereport(ERROR,					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),					 errmsg("must be superuser to alter superusers")));	}	else	{		if (!have_createrole_privilege() &&			!is_admin_of_role(grantorId, roleid))			ereport(ERROR,					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),					 errmsg("must have admin option on role \"%s\"",							rolename)));	}	/* XXX not sure about this check */	if (grantorId != GetUserId() && !superuser())		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("must be superuser to set grantor")));	/* We need only regular writer's lock on pg_auth_members */	pg_authmem_rel = heap_open(AuthMemRelationId, RowExclusiveLock);	pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);	forboth(nameitem, memberNames, iditem, memberIds)	{		const char *membername = strVal(lfirst(nameitem));		Oid			memberid = lfirst_oid(iditem);		HeapTuple	authmem_tuple;		HeapTuple	tuple;		Datum		new_record[Natts_pg_auth_members];		char		new_record_nulls[Natts_pg_auth_members];		char		new_record_repl[Natts_pg_auth_members];		/*		 * Refuse creation of membership loops, including the trivial case		 * where a role is made a member of itself.  We do this by checking to		 * see if the target role is already a member of the proposed member		 * role.  We have to ignore possible superuserness, however, else we		 * could never grant membership in a superuser-privileged role.		 */		if (is_member_of_role_nosuper(roleid, memberid))			ereport(ERROR,					(errcode(ERRCODE_INVALID_GRANT_OPERATION),					 (errmsg("role \"%s\" is a member of role \"%s\"",							 rolename, membername))));		/*		 * Check if entry for this role/member already exists; if so, give		 * warning unless we are adding admin option.		 */		authmem_tuple = SearchSysCache(AUTHMEMROLEMEM,									   ObjectIdGetDatum(roleid),									   ObjectIdGetDatum(memberid),									   0, 0);		if (HeapTupleIsValid(authmem_tuple) &&			(!admin_opt ||			 ((Form_pg_auth_members) GETSTRUCT(authmem_tuple))->admin_option))		{			ereport(NOTICE,					(errmsg("role \"%s\" is already a member of role \"%s\"",							membername, rolename)));			ReleaseSysCache(authmem_tuple);			continue;		}		/* Build a tuple to insert or update */		MemSet(new_record, 0, sizeof(new_record));		MemSet(new_record_nulls, ' ', sizeof(new_record_nulls));		MemSet(new_record_repl, ' ', sizeof(new_record_repl));		new_record[Anum_pg_auth_members_roleid - 1] = ObjectIdGetDatum(roleid);		new_record[Anum_pg_auth_members_member - 1] = ObjectIdGetDatum(memberid);		new_record[Anum_pg_auth_members_grantor - 1] = ObjectIdGetDatum(grantorId);		new_record[Anum_pg_auth_members_admin_option - 1] = BoolGetDatum(admin_opt);		if (HeapTupleIsValid(authmem_tuple))		{			new_record_repl[Anum_pg_auth_members_grantor - 1] = 'r';			new_record_repl[Anum_pg_auth_members_admin_option - 1] = 'r';			tuple = heap_modifytuple(authmem_tuple, pg_authmem_dsc,									 new_record,									 new_record_nulls, new_record_repl);			simple_heap_update(pg_authmem_rel, &tuple->t_self, tuple);			CatalogUpdateIndexes(pg_authmem_rel, tuple);			ReleaseSysCache(authmem_tuple);		}		else		{			tuple = heap_formtuple(pg_authmem_dsc,								   new_record, new_record_nulls);			simple_heap_insert(pg_authmem_rel, tuple);			CatalogUpdateIndexes(pg_authmem_rel, tuple);		}		/* CCI after each change, in case there are duplicates in list */		CommandCounterIncrement();	}	/*	 * Now we can clean up; but keep lock until commit (to avoid possible	 * deadlock when commit code tries to acquire lock).	 */	heap_close(pg_authmem_rel, NoLock);}/* * DelRoleMems -- Remove given members from the specified role * * rolename: name of role to del from (used only for error messages) * roleid: OID of role to del from * memberNames: list of names of roles to del (used only for error messages) * memberIds: OIDs of roles to del * admin_opt: remove admin option only? * * Note: caller is responsible for holding ExclusiveLock on pg_authid, * and for calling auth_file_update_needed(). */static voidDelRoleMems(const char *rolename, Oid roleid,			List *memberNames, List *memberIds,			bool admin_opt){	Relation	pg_authmem_rel;	TupleDesc	pg_authmem_dsc;	ListCell   *nameitem;	ListCell   *iditem;	Assert(list_length(memberNames) == list_length(memberIds));	/* Skip permission check if nothing to do */	if (!memberIds)		return;	/*	 * Check permissions: must have createrole or admin option on the role to	 * be changed.	To mess with a superuser role, you gotta be superuser.	 */	if (superuser_arg(roleid))	{		if (!superuser())			ereport(ERROR,					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),					 errmsg("must be superuser to alter superusers")));	}	else	{		if (!have_createrole_privilege() &&			!is_admin_of_role(GetUserId(), roleid))			ereport(ERROR,					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),					 errmsg("must have admin option on role \"%s\"",							rolename)));	}	/* We need only regular writer's lock on pg_auth_members */	pg_authmem_rel = heap_open(AuthMemRelationId, RowExclusiveLock);	pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);	forboth(nameitem, memberNames, iditem, memberIds)	{		const char *membername = strVal(lfirst(nameitem));		Oid			memberid = lfirst_oid(iditem);		HeapTuple	authmem_tuple;		/*		 * Find entry for this role/member		 */		authmem_tuple = SearchSysCache(AUTHMEMROLEMEM,									   ObjectIdGetDatum(roleid),									   ObjectIdGetDatum(memberid),									   0, 0);		if (!HeapTupleIsValid(authmem_tuple))		{			ereport(WARNING,					(errmsg("role \"%s\" is not a member of role \"%s\"",							membername, rolename)));			continue;		}		if (!admin_opt)		{			/* Remove the entry altogether */			simple_heap_delete(pg_authmem_rel, &authmem_tuple->t_self);		}		else		{			/* Just turn off the admin option */			HeapTuple	tuple;			Datum		new_record[Natts_pg_auth_members];			char		new_record_nulls[Natts_pg_auth_members];			char		new_record_repl[Natts_pg_auth_members];			/* Build a tuple to update with */			MemSet(new_record, 0, sizeof(new_record));			MemSet(new_record_nulls, ' ', sizeof(new_record_nulls));			MemSet(new_record_repl, ' ', sizeof(new_record_repl));			new_record[Anum_pg_auth_members_admin_option - 1] = BoolGetDatum(false);			new_record_repl[Anum_pg_auth_members_admin_option - 1] = 'r';			tuple = heap_modifytuple(authmem_tuple, pg_authmem_dsc,									 new_record,									 new_record_nulls, new_record_repl);			simple_heap_update(pg_authmem_rel, &tuple->t_self, tuple);			CatalogUpdateIndexes(pg_authmem_rel, tuple);		}		ReleaseSysCache(authmem_tuple);		/* CCI after each change, in case there are duplicates in list */		CommandCounterIncrement();	}	/*	 * Now we can clean up; but keep lock until commit (to avoid possible	 * deadlock when commit code tries to acquire lock).	 */	heap_close(pg_authmem_rel, NoLock);}

⌨️ 快捷键说明

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