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

📄 srv_samr_nt.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  Unix SMB/CIFS implementation. *  RPC Pipe client / server routines *  Copyright (C) Andrew Tridgell                   1992-1997, *  Copyright (C) Luke Kenneth Casson Leighton      1996-1997, *  Copyright (C) Paul Ashton                       1997, *  Copyright (C) Marc Jacobsen			    1999, *  Copyright (C) Jeremy Allison                    2001-2005, *  Copyright (C) Jean François Micouleau           1998-2001, *  Copyright (C) Jim McDonough <jmcd@us.ibm.com>   2002, *  Copyright (C) Gerald (Jerry) Carter             2003-2004, *  Copyright (C) Simo Sorce                        2003. *  Copyright (C) Volker Lendecke		    2005. * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* * This is the implementation of the SAMR code. */#include "includes.h"#undef DBGC_CLASS#define DBGC_CLASS DBGC_RPC_SRV#define SAMR_USR_RIGHTS_WRITE_PW \		( READ_CONTROL_ACCESS		| \		  SA_RIGHT_USER_CHANGE_PASSWORD	| \		  SA_RIGHT_USER_SET_LOC_COM )#define DISP_INFO_CACHE_TIMEOUT 10typedef struct disp_info {	struct disp_info *next, *prev;	TALLOC_CTX *mem_ctx;	DOM_SID sid; /* identify which domain this is. */	BOOL builtin_domain; /* Quick flag to check if this is the builtin domain. */	struct pdb_search *users; /* querydispinfo 1 and 4 */	struct pdb_search *machines; /* querydispinfo 2 */	struct pdb_search *groups; /* querydispinfo 3 and 5, enumgroups */	struct pdb_search *aliases; /* enumaliases */	uint16 enum_acb_mask;	struct pdb_search *enum_users; /* enumusers with a mask */	smb_event_id_t di_cache_timeout_event; /* cache idle timeout handler. */} DISP_INFO;/* We keep a static list of these by SID as modern clients close down   all resources between each request in a complete enumeration. */static DISP_INFO *disp_info_list;struct samr_info {	/* for use by the \PIPE\samr policy */	DOM_SID sid;	BOOL builtin_domain; /* Quick flag to check if this is the builtin domain. */	uint32 status; /* some sort of flag.  best to record it.  comes from opnum 0x39 */	uint32 acc_granted;	DISP_INFO *disp_info;	TALLOC_CTX *mem_ctx;};static struct generic_mapping sam_generic_mapping = {	GENERIC_RIGHTS_SAM_READ,	GENERIC_RIGHTS_SAM_WRITE,	GENERIC_RIGHTS_SAM_EXECUTE,	GENERIC_RIGHTS_SAM_ALL_ACCESS};static struct generic_mapping dom_generic_mapping = {	GENERIC_RIGHTS_DOMAIN_READ,	GENERIC_RIGHTS_DOMAIN_WRITE,	GENERIC_RIGHTS_DOMAIN_EXECUTE,	GENERIC_RIGHTS_DOMAIN_ALL_ACCESS};static struct generic_mapping usr_generic_mapping = {	GENERIC_RIGHTS_USER_READ,	GENERIC_RIGHTS_USER_WRITE,	GENERIC_RIGHTS_USER_EXECUTE,	GENERIC_RIGHTS_USER_ALL_ACCESS};static struct generic_mapping grp_generic_mapping = {	GENERIC_RIGHTS_GROUP_READ,	GENERIC_RIGHTS_GROUP_WRITE,	GENERIC_RIGHTS_GROUP_EXECUTE,	GENERIC_RIGHTS_GROUP_ALL_ACCESS};static struct generic_mapping ali_generic_mapping = {	GENERIC_RIGHTS_ALIAS_READ,	GENERIC_RIGHTS_ALIAS_WRITE,	GENERIC_RIGHTS_ALIAS_EXECUTE,	GENERIC_RIGHTS_ALIAS_ALL_ACCESS};/**************************************************************************************************************************************/static NTSTATUS make_samr_object_sd( TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size,                                     struct generic_mapping *map,				     DOM_SID *sid, uint32 sid_access ){	DOM_SID domadmin_sid;	SEC_ACE ace[5];		/* at most 5 entries */	SEC_ACCESS mask;	size_t i = 0;	SEC_ACL *psa = NULL;	/* basic access for Everyone */	init_sec_access(&mask, map->generic_execute | map->generic_read );	init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);	/* add Full Access 'BUILTIN\Administrators' and 'BUILTIN\Account Operators */	init_sec_access(&mask, map->generic_all);		init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);	init_sec_ace(&ace[i++], &global_sid_Builtin_Account_Operators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);	/* Add Full Access for Domain Admins if we are a DC */		if ( IS_DC ) {		sid_copy( &domadmin_sid, get_global_sam_sid() );		sid_append_rid( &domadmin_sid, DOMAIN_GROUP_RID_ADMINS );		init_sec_ace(&ace[i++], &domadmin_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);	}	/* if we have a sid, give it some special access */	if ( sid ) {		init_sec_access( &mask, sid_access );		init_sec_ace(&ace[i++], sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);}	/* create the security descriptor */	if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) == NULL)		return NT_STATUS_NO_MEMORY;	if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL)		return NT_STATUS_NO_MEMORY;	return NT_STATUS_OK;}/******************************************************************* Checks if access to an object should be granted, and returns that level of access for further checks.********************************************************************/static NTSTATUS access_check_samr_object( SEC_DESC *psd, NT_USER_TOKEN *token,                                           SE_PRIV *rights, uint32 rights_mask,                                          uint32 des_access, uint32 *acc_granted, 					  const char *debug ){	NTSTATUS status = NT_STATUS_ACCESS_DENIED;	uint32 saved_mask = 0;	/* check privileges; certain SAM access bits should be overridden 	   by privileges (mostly having to do with creating/modifying/deleting 	   users and groups) */		if ( rights && user_has_any_privilege( token, rights ) ) {			saved_mask = (des_access & rights_mask);		des_access &= ~saved_mask;				DEBUG(4,("access_check_samr_object: user rights access mask [0x%x]\n",			rights_mask));	}				/* check the security descriptor first */		if ( se_access_check(psd, token, des_access, acc_granted, &status) )		goto done;		/* give root a free pass */		if ( geteuid() == sec_initial_uid() ) {			DEBUG(4,("%s: ACCESS should be DENIED  (requested: %#010x)\n", debug, des_access));		DEBUGADD(4,("but overritten by euid == sec_initial_uid()\n"));				*acc_granted = des_access;				status = NT_STATUS_OK;		goto done;	}		done:	/* add in any bits saved during the privilege check (only 	   matters is status is ok) */		*acc_granted |= rights_mask;	DEBUG(4,("%s: access %s (requested: 0x%08x, granted: 0x%08x)\n", 		debug, NT_STATUS_IS_OK(status) ? "GRANTED" : "DENIED", 		des_access, *acc_granted));		return status;}/******************************************************************* Checks if access to a function can be granted********************************************************************/static NTSTATUS access_check_samr_function(uint32 acc_granted, uint32 acc_required, const char *debug){	DEBUG(5,("%s: access check ((granted: %#010x;  required: %#010x)\n",  		debug, acc_granted, acc_required));	/* check the security descriptor first */		if ( (acc_granted&acc_required) == acc_required )		return NT_STATUS_OK;			/* give root a free pass */	if (geteuid() == sec_initial_uid()) {			DEBUG(4,("%s: ACCESS should be DENIED (granted: %#010x;  required: %#010x)\n",			debug, acc_granted, acc_required));		DEBUGADD(4,("but overwritten by euid == 0\n"));				return NT_STATUS_OK;	}		DEBUG(2,("%s: ACCESS DENIED (granted: %#010x;  required: %#010x)\n", 		debug, acc_granted, acc_required));			return NT_STATUS_ACCESS_DENIED;}/******************************************************************* Fetch or create a dispinfo struct.********************************************************************/static DISP_INFO *get_samr_dispinfo_by_sid(DOM_SID *psid, const char *sid_str){	TALLOC_CTX *mem_ctx;	DISP_INFO *dpi;	/* There are two cases to consider here:	   1) The SID is a domain SID and we look for an equality match, or	   2) This is an account SID and so we return the DISP_INFO* for our 	      domain */	if ( psid && sid_check_is_in_our_domain( psid ) ) {		DEBUG(10,("get_samr_dispinfo_by_sid: Replacing %s with our domain SID\n",			sid_str));		psid = get_global_sam_sid();	}	for (dpi = disp_info_list; dpi; dpi = dpi->next) {		if (sid_equal(psid, &dpi->sid)) {			return dpi;		}	}	/* This struct is never free'd - I'm using talloc so we	   can get a list out of smbd using smbcontrol. There will	   be one of these per SID we're authorative for. JRA. */	mem_ctx = talloc_init("DISP_INFO for domain sid %s", sid_str);	if ((dpi = TALLOC_ZERO_P(mem_ctx, DISP_INFO)) == NULL)		return NULL;	dpi->mem_ctx = mem_ctx;	if (psid) {		sid_copy( &dpi->sid, psid);		dpi->builtin_domain = sid_check_is_builtin(psid);	} else {		dpi->builtin_domain = False;	}	DLIST_ADD(disp_info_list, dpi);	return dpi;}/******************************************************************* Create a samr_info struct.********************************************************************/static struct samr_info *get_samr_info_by_sid(DOM_SID *psid){	struct samr_info *info;	fstring sid_str;	TALLOC_CTX *mem_ctx;		if (psid) {		sid_to_string(sid_str, psid);	} else {		fstrcpy(sid_str,"(NULL)");	}	mem_ctx = talloc_init("samr_info for domain sid %s", sid_str);	if ((info = TALLOC_ZERO_P(mem_ctx, struct samr_info)) == NULL)		return NULL;	DEBUG(10,("get_samr_info_by_sid: created new info for sid %s\n", sid_str));	if (psid) {		sid_copy( &info->sid, psid);		info->builtin_domain = sid_check_is_builtin(psid);	} else {		DEBUG(10,("get_samr_info_by_sid: created new info for NULL sid.\n"));		info->builtin_domain = False;	}	info->mem_ctx = mem_ctx;	info->disp_info = get_samr_dispinfo_by_sid(psid, sid_str);	if (!info->disp_info) {		talloc_destroy(mem_ctx);		return NULL;	}	return info;}/******************************************************************* Function to free the per SID data. ********************************************************************/static void free_samr_cache(DISP_INFO *disp_info, const char *sid_str){	DEBUG(10,("free_samr_cache: deleting cache for SID %s\n", sid_str));	/* We need to become root here because the paged search might have to	 * tell the LDAP server we're not interested in the rest anymore. */	become_root();	if (disp_info->users) {		DEBUG(10,("free_samr_cache: deleting users cache\n"));		pdb_search_destroy(disp_info->users);		disp_info->users = NULL;	}	if (disp_info->machines) {		DEBUG(10,("free_samr_cache: deleting machines cache\n"));		pdb_search_destroy(disp_info->machines);		disp_info->machines = NULL;	}	if (disp_info->groups) {		DEBUG(10,("free_samr_cache: deleting groups cache\n"));		pdb_search_destroy(disp_info->groups);		disp_info->groups = NULL;	}	if (disp_info->aliases) {		DEBUG(10,("free_samr_cache: deleting aliases cache\n"));		pdb_search_destroy(disp_info->aliases);		disp_info->aliases = NULL;	}	if (disp_info->enum_users) {		DEBUG(10,("free_samr_cache: deleting enum_users cache\n"));		pdb_search_destroy(disp_info->enum_users);		disp_info->enum_users = NULL;	}	disp_info->enum_acb_mask = 0;	unbecome_root();}/******************************************************************* Function to free the per handle data. ********************************************************************/static void free_samr_info(void *ptr){	struct samr_info *info=(struct samr_info *) ptr;	/* Only free the dispinfo cache if no one bothered to set up	   a timeout. */	if (info->disp_info && info->disp_info->di_cache_timeout_event == (smb_event_id_t)0) {		fstring sid_str;		sid_to_string(sid_str, &info->disp_info->sid);		free_samr_cache(info->disp_info, sid_str);	}	talloc_destroy(info->mem_ctx);}/******************************************************************* Idle event handler. Throw away the disp info cache. ********************************************************************/static void disp_info_cache_idle_timeout_handler(void **private_data,					time_t *ev_interval,					time_t ev_now){	fstring sid_str;	DISP_INFO *disp_info = (DISP_INFO *)(*private_data);	sid_to_string(sid_str, &disp_info->sid);	free_samr_cache(disp_info, sid_str);	/* Remove the event. */	smb_unregister_idle_event(disp_info->di_cache_timeout_event);	disp_info->di_cache_timeout_event = (smb_event_id_t)0;	DEBUG(10,("disp_info_cache_idle_timeout_handler: caching timed out for SID %s at %u\n",		sid_str, (unsigned int)ev_now));}/******************************************************************* Setup cache removal idle event handler. ********************************************************************/static void set_disp_info_cache_timeout(DISP_INFO *disp_info, time_t secs_fromnow){	fstring sid_str;	sid_to_string(sid_str, &disp_info->sid);	/* Remove any pending timeout and update. */	if (disp_info->di_cache_timeout_event) {		smb_unregister_idle_event(disp_info->di_cache_timeout_event);		disp_info->di_cache_timeout_event = (smb_event_id_t)0;	}	DEBUG(10,("set_disp_info_cache_timeout: caching enumeration for SID %s for %u seconds\n",		sid_str, (unsigned int)secs_fromnow ));	disp_info->di_cache_timeout_event =		smb_register_idle_event(disp_info_cache_idle_timeout_handler,					disp_info,					secs_fromnow);}/******************************************************************* Force flush any cache. We do this on any samr_set_xxx call. We must also remove the timeout handler. ********************************************************************/static void force_flush_samr_cache(DISP_INFO *disp_info){	if (disp_info) {		fstring sid_str;		sid_to_string(sid_str, &disp_info->sid);		if (disp_info->di_cache_timeout_event) {			smb_unregister_idle_event(disp_info->di_cache_timeout_event);			disp_info->di_cache_timeout_event = (smb_event_id_t)0;			DEBUG(10,("force_flush_samr_cache: clearing idle event for SID %s\n",

⌨️ 快捷键说明

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