auth_util.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 1,706 行 · 第 1/4 页

C
1,706
字号
{	fstring sid_str;	size_t     i;		if (!token) {		DEBUGC(dbg_class, dbg_lev, ("NT user token: (NULL)\n"));		return;	}		DEBUGC(dbg_class, dbg_lev, ("NT user token of user %s\n",				    sid_to_string(sid_str, &token->user_sids[0]) ));	DEBUGADDC(dbg_class, dbg_lev, ("contains %lu SIDs\n", (unsigned long)token->num_sids));	for (i = 0; i < token->num_sids; i++)		DEBUGADDC(dbg_class, dbg_lev, ("SID[%3lu]: %s\n", (unsigned long)i, 					       sid_to_string(sid_str, &token->user_sids[i])));	dump_se_priv( dbg_class, dbg_lev, &token->privileges );}/**************************************************************************** prints a UNIX 'token' to debug output.****************************************************************************/void debug_unix_user_token(int dbg_class, int dbg_lev, uid_t uid, gid_t gid, int n_groups, gid_t *groups){	int     i;	DEBUGC(dbg_class, dbg_lev, ("UNIX token of user %ld\n", (long int)uid));	DEBUGADDC(dbg_class, dbg_lev, ("Primary group is %ld and contains %i supplementary groups\n", (long int)gid, n_groups));	for (i = 0; i < n_groups; i++)		DEBUGADDC(dbg_class, dbg_lev, ("Group[%3i]: %ld\n", i, 			(long int)groups[i]));}/**************************************************************************** Create the SID list for this user.****************************************************************************/static NTSTATUS create_nt_user_token(const DOM_SID *user_sid, const DOM_SID *group_sid, 				     int n_groupSIDs, DOM_SID *groupSIDs, 				     BOOL is_guest, NT_USER_TOKEN **token){	NTSTATUS       nt_status = NT_STATUS_OK;	NT_USER_TOKEN *ptoken;	int i;	int sid_ndx;	DOM_SID domadm;	BOOL is_domain_admin = False;	BOOL domain_mode = False;		if ((ptoken = SMB_MALLOC_P(NT_USER_TOKEN)) == NULL) {		DEBUG(0, ("create_nt_user_token: Out of memory allocating token\n"));		nt_status = NT_STATUS_NO_MEMORY;		return nt_status;	}	ZERO_STRUCTP(ptoken);	ptoken->num_sids = n_groupSIDs + 5;	if ((ptoken->user_sids = SMB_MALLOC_ARRAY( DOM_SID, ptoken->num_sids )) == NULL) {		DEBUG(0, ("create_nt_user_token: Out of memory allocating SIDs\n"));		nt_status = NT_STATUS_NO_MEMORY;		return nt_status;	}		memset((char*)ptoken->user_sids,0,sizeof(DOM_SID) * ptoken->num_sids);		/*	 * Note - user SID *MUST* be first in token !	 * se_access_check depends on this.	 *	 * Primary group SID is second in token. Convention.	 */	sid_copy(&ptoken->user_sids[PRIMARY_USER_SID_INDEX], user_sid);	if (group_sid)		sid_copy(&ptoken->user_sids[PRIMARY_GROUP_SID_INDEX], group_sid);	/*	 * Finally add the "standard" SIDs.	 * The only difference between guest and "anonymous" (which we	 * don't really support) is the addition of Authenticated_Users.	 */	sid_copy(&ptoken->user_sids[2], &global_sid_World);	sid_copy(&ptoken->user_sids[3], &global_sid_Network);	if (is_guest)		sid_copy(&ptoken->user_sids[4], &global_sid_Builtin_Guests);	else		sid_copy(&ptoken->user_sids[4], &global_sid_Authenticated_Users);		sid_ndx = 5; /* next available spot */	/* this is where we construct the domain admins SID if we can	   so that we can add the BUILTIN\Administrators SID to the token */	ZERO_STRUCT( domadm );	if ( IS_DC || lp_server_role()==ROLE_DOMAIN_MEMBER ) {		domain_mode = True;		if ( IS_DC ) 			sid_copy( &domadm, get_global_sam_sid() );		else {			/* if we a re a member server and cannot find			   out domain SID then reset the domain_mode flag */			if ( !secrets_fetch_domain_sid( lp_workgroup(), &domadm ) )				domain_mode = False;		}		sid_append_rid( &domadm, DOMAIN_GROUP_RID_ADMINS );	}		/* add the group SIDs to teh token */		for (i = 0; i < n_groupSIDs; i++) {		size_t check_sid_idx;		for (check_sid_idx = 1; check_sid_idx < ptoken->num_sids; check_sid_idx++) {			if (sid_equal(&ptoken->user_sids[check_sid_idx], 				      &groupSIDs[i])) {				break;			}		}				if (check_sid_idx >= ptoken->num_sids) /* Not found already */ {			sid_copy(&ptoken->user_sids[sid_ndx++], &groupSIDs[i]);		} else {			ptoken->num_sids--;		}				/* here we check if the user is a domain admin and add the		   BUILTIN\Administrators SID to the token the group membership		   check succeeds. */		if ( domain_mode ) {			if ( sid_equal( &domadm, &groupSIDs[i] ) )				is_domain_admin = True;		}			}	/* finally realloc the SID array and add the BUILTIN\Administrators 	   SID if necessary */	if ( is_domain_admin ) {		DOM_SID *sids;		if ( !(sids = SMB_REALLOC_ARRAY( ptoken->user_sids, DOM_SID, ptoken->num_sids+1 )) ) 			DEBUG(0,("create_nt_user_token: Failed to realloc SID arry of size %d\n", ptoken->num_sids+1));		else  {			ptoken->user_sids = sids;			sid_copy( &(ptoken->user_sids)[ptoken->num_sids++], &global_sid_Builtin_Administrators );		}	}	/* add privileges assigned to this user */	get_privileges_for_sids( &ptoken->privileges, ptoken->user_sids, ptoken->num_sids );		debug_nt_user_token(DBGC_AUTH, 10, ptoken);		if ((lp_log_nt_token_command() != NULL) &&	    (strlen(lp_log_nt_token_command()) > 0)) {		TALLOC_CTX *mem_ctx;		char *command;		fstring sidstr;		char *user_sidstr, *group_sidstr;		mem_ctx = talloc_init("setnttoken");		if (mem_ctx == NULL)			return NT_STATUS_NO_MEMORY;		sid_to_string(sidstr, &ptoken->user_sids[0]);		user_sidstr = talloc_strdup(mem_ctx, sidstr);		group_sidstr = talloc_strdup(mem_ctx, "");		for (i=1; i<ptoken->num_sids; i++) {			sid_to_string(sidstr, &ptoken->user_sids[i]);			group_sidstr = talloc_asprintf(mem_ctx, "%s %s",						       group_sidstr, sidstr);		}		command = SMB_STRDUP(lp_log_nt_token_command());		command = realloc_string_sub(command, "%s", user_sidstr);		command = realloc_string_sub(command, "%t", group_sidstr);		DEBUG(8, ("running command: [%s]\n", command));		if (smbrun(command, NULL) != 0) {			DEBUG(0, ("Could not log NT token\n"));			nt_status = NT_STATUS_ACCESS_DENIED;		}		talloc_destroy(mem_ctx);		SAFE_FREE(command);	}	*token = ptoken;	return nt_status;}/**************************************************************************** Create the SID list for this user.****************************************************************************/NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, BOOL is_guest){	DOM_SID user_sid;	DOM_SID group_sid;	DOM_SID *group_sids;	NT_USER_TOKEN *token;	int i;	if (!NT_STATUS_IS_OK(uid_to_sid(&user_sid, uid))) {		return NULL;	}	if (!NT_STATUS_IS_OK(gid_to_sid(&group_sid, gid))) {		return NULL;	}	group_sids = SMB_MALLOC_ARRAY(DOM_SID, ngroups);	if (!group_sids) {		DEBUG(0, ("create_nt_token: malloc() failed for DOM_SID list!\n"));		return NULL;	}	/* convert the Unix group ids to SIDS */	for (i = 0; i < ngroups; i++) {		if (!NT_STATUS_IS_OK(gid_to_sid(&(group_sids)[i], (groups)[i]))) {			DEBUG(1, ("create_nt_token: failed to convert gid %ld to a sid!\n", (long int)groups[i]));			SAFE_FREE(group_sids);			return NULL;		}	}	if (!NT_STATUS_IS_OK(create_nt_user_token(&user_sid, &group_sid, 						  ngroups, group_sids, is_guest, &token))) {		SAFE_FREE(group_sids);		return NULL;	}	SAFE_FREE(group_sids);	return token;}/****************************************************************************** Create a token for the root user to be used internally by smbd. This is similar to running under the context of the LOCAL_SYSTEM account in Windows.  This is a read-only token.  Do not modify it or free() it. Create a copy if your need to change it.******************************************************************************/NT_USER_TOKEN *get_root_nt_token( void ){	static NT_USER_TOKEN *token = NULL;	DOM_SID u_sid, g_sid;	DOM_SID g_sids[1];	struct passwd *pw;	NTSTATUS result;		if ( token )		return token;			if ( !(pw = getpwnam( "root" )) ) {		DEBUG(0,("get_root_nt_token: getpwnam\"root\") failed!\n"));		return NULL;	}		/* get the user and primary group SIDs; although the 	   BUILTIN\Administrators SId is really the one that matters here */	   	if ( !NT_STATUS_IS_OK(uid_to_sid(&u_sid, pw->pw_uid)) )		return NULL;	if ( !NT_STATUS_IS_OK(gid_to_sid(&g_sid, pw->pw_gid)) )		return NULL;			sid_copy( &g_sids[0], &global_sid_Builtin_Administrators );		result = create_nt_user_token( &u_sid, &g_sid, 1, g_sids, False, &token);		return NT_STATUS_IS_OK(result) ? token : NULL;}/****************************************************************************** * this function returns the groups (SIDs) of the local SAM the user is in. * If this samba server is a DC of the domain the user belongs to, it returns  * both domain groups and local / builtin groups. If the user is in a trusted * domain, or samba is a member server of a domain, then this function returns * local and builtin groups the user is a member of. * * currently this is a hack, as there is no sam implementation that is capable * of groups. * * NOTE!! This function will fail if you pass in a winbind user without  * the domain   --jerry ******************************************************************************/static NTSTATUS get_user_groups(const char *username, uid_t uid, gid_t gid,                                size_t *n_groups, DOM_SID **groups, gid_t **unix_groups){	int		n_unix_groups;	int		i;	*n_groups = 0;	*groups   = NULL;	if (strchr(username, *lp_winbind_separator()) == NULL) {		NTSTATUS result;		become_root();		result = pdb_enum_group_memberships(username, gid, groups,						    unix_groups, n_groups);		unbecome_root();		return result;	}	/* We have the separator, this must be winbind */		n_unix_groups = winbind_getgroups( username, unix_groups );	DEBUG(10,("get_user_groups: winbind_getgroups(%s): result = %s\n",		  username,  n_unix_groups == -1 ? "FAIL" : "SUCCESS"));			  	if ( n_unix_groups == -1 )		return NT_STATUS_NO_SUCH_USER; /* what should this return						* value be? */		debug_unix_user_token(DBGC_CLASS, 5, uid, gid, n_unix_groups, *unix_groups);		/* now setup the space for storing the SIDS */		if (n_unix_groups > 0) {			*groups   = SMB_MALLOC_ARRAY(DOM_SID, n_unix_groups);				if (!*groups) {			DEBUG(0, ("get_user_group: malloc() failed for DOM_SID list!\n"));			SAFE_FREE(*unix_groups);			return NT_STATUS_NO_MEMORY;		}	}	*n_groups = n_unix_groups;	for (i = 0; i < *n_groups; i++) {		if (!NT_STATUS_IS_OK(gid_to_sid(&(*groups)[i], (*unix_groups)[i]))) {			DEBUG(1, ("get_user_groups: failed to convert gid %ld to a sid!\n", 				(long int)(*unix_groups)[i+1]));			SAFE_FREE(*groups);			SAFE_FREE(*unix_groups);			return NT_STATUS_NO_SUCH_USER;		}	}		     	return NT_STATUS_OK;}/*************************************************************************** Make a user_info struct***************************************************************************/static NTSTATUS make_server_info(auth_serversupplied_info **server_info){	*server_info = SMB_MALLOC_P(auth_serversupplied_info);	if (!*server_info) {		DEBUG(0,("make_server_info: malloc failed!\n"));		return NT_STATUS_NO_MEMORY;	}	ZERO_STRUCTP(*server_info);	/* Initialise the uid and gid values to something non-zero	   which may save us from giving away root access if there	   is a bug in allocating these fields. */	(*server_info)->uid = -1;	(*server_info)->gid = -1;	return NT_STATUS_OK;}/***************************************************************************Fill a server_info struct from a SAM_ACCOUNT with their groups***************************************************************************/static NTSTATUS add_user_groups(auth_serversupplied_info **server_info, 				const char * unix_username,				SAM_ACCOUNT *sampass,				uid_t uid, gid_t gid){	NTSTATUS nt_status;	const DOM_SID *user_sid = pdb_get_user_sid(sampass);	const DOM_SID *group_sid = pdb_get_group_sid(sampass);	size_t       n_groupSIDs = 0;	DOM_SID  *groupSIDs   = NULL;	gid_t    *unix_groups = NULL;	NT_USER_TOKEN *token;	BOOL is_guest;	uint32 rid;	nt_status = get_user_groups(unix_username, uid, gid, 		&n_groupSIDs, &groupSIDs, &unix_groups);			if (!NT_STATUS_IS_OK(nt_status)) {		DEBUG(4,("get_user_groups_from_local_sam failed\n"));		free_server_info(server_info);		return nt_status;	}		is_guest = (sid_peek_rid(user_sid, &rid) && rid == DOMAIN_USER_RID_GUEST);	if (!NT_STATUS_IS_OK(nt_status = create_nt_user_token(user_sid, group_sid,							      n_groupSIDs, groupSIDs, is_guest, 							      &token)))	{		DEBUG(4,("create_nt_user_token failed\n"));		SAFE_FREE(groupSIDs);		SAFE_FREE(unix_groups);		free_server_info(server_info);		return nt_status;	}		SAFE_FREE(groupSIDs);	(*server_info)->n_groups = n_groupSIDs;	(*server_info)->groups = unix_groups;	(*server_info)->ptok = token;

⌨️ 快捷键说明

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