winbindd_util.c

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

C
1,210
字号
/*    Unix SMB/CIFS implementation.   Winbind daemon for ntdom nss module   Copyright (C) Tim Potter 2000-2001   Copyright (C) 2001 by Martin Pool <mbp@samba.org>      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.*/#include "includes.h"#include "winbindd.h"#undef DBGC_CLASS#define DBGC_CLASS DBGC_WINBIND/** * @file winbindd_util.c * * Winbind daemon for NT domain authentication nss module. **//** * Used to clobber name fields that have an undefined value. * * Correct code should never look at a field that has this value. **/static const fstring name_deadbeef = "<deadbeef>";/* The list of trusted domains.  Note that the list can be deleted and   recreated using the init_domain_list() function so pointers to   individual winbindd_domain structures cannot be made.  Keep a copy of   the domain name instead. */static struct winbindd_domain *_domain_list;/**   When was the last scan of trusted domains done?      0 == not ever*/static time_t last_trustdom_scan;struct winbindd_domain *domain_list(void){	/* Initialise list */	if (!_domain_list) 		init_domain_list();	return _domain_list;}/* Free all entries in the trusted domain list */void free_domain_list(void){	struct winbindd_domain *domain = _domain_list;	while(domain) {		struct winbindd_domain *next = domain->next;				DLIST_REMOVE(_domain_list, domain);		SAFE_FREE(domain);		domain = next;	}}static BOOL is_internal_domain(const DOM_SID *sid){	if (sid == NULL)		return False;	return (sid_check_is_domain(sid) || sid_check_is_builtin(sid));}static BOOL is_in_internal_domain(const DOM_SID *sid){	if (sid == NULL)		return False;	return (sid_check_is_in_our_domain(sid) || sid_check_is_in_builtin(sid));}/* Add a trusted domain to our list of domains */static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name,						  struct winbindd_methods *methods,						  const DOM_SID *sid){	struct winbindd_domain *domain;	const char *alternative_name = NULL;		/* ignore alt_name if we are not in an AD domain */		if ( (lp_security() == SEC_ADS) && alt_name && *alt_name) {		alternative_name = alt_name;	}        	/* We can't call domain_list() as this function is called from	   init_domain_list() and we'll get stuck in a loop. */	for (domain = _domain_list; domain; domain = domain->next) {		if (strequal(domain_name, domain->name) ||		    strequal(domain_name, domain->alt_name)) {			return domain;		}		if (alternative_name && *alternative_name) {			if (strequal(alternative_name, domain->name) ||			    strequal(alternative_name, domain->alt_name)) {				return domain;			}		}		if (sid) {			if (is_null_sid(sid)) {							} else if (sid_equal(sid, &domain->sid)) {				return domain;			}		}	}        	/* Create new domain entry */	if ((domain = SMB_MALLOC_P(struct winbindd_domain)) == NULL)		return NULL;	/* Fill in fields */        	ZERO_STRUCTP(domain);	/* prioritise the short name */	if (strchr_m(domain_name, '.') && alternative_name && *alternative_name) {		fstrcpy(domain->name, alternative_name);		fstrcpy(domain->alt_name, domain_name);	} else {		fstrcpy(domain->name, domain_name);		if (alternative_name) {			fstrcpy(domain->alt_name, alternative_name);		}	}	domain->methods = methods;	domain->backend = NULL;	domain->internal = is_internal_domain(sid);	domain->sequence_number = DOM_SEQUENCE_NONE;	domain->last_seq_check = 0;	domain->initialized = False;	if (sid) {		sid_copy(&domain->sid, sid);	}		/* Link to domain list */	DLIST_ADD(_domain_list, domain);        	DEBUG(2,("Added domain %s %s %s\n", 		 domain->name, domain->alt_name,		 &domain->sid?sid_string_static(&domain->sid):""));        	return domain;}/********************************************************************  rescan our domains looking for new trusted domains********************************************************************/struct trustdom_state {	TALLOC_CTX *mem_ctx;	struct winbindd_response *response;};static void trustdom_recv(void *private_data, BOOL success);static void add_trusted_domains( struct winbindd_domain *domain ){	TALLOC_CTX *mem_ctx;	struct winbindd_request *request;	struct winbindd_response *response;	struct trustdom_state *state;	mem_ctx = talloc_init("add_trusted_domains");	if (mem_ctx == NULL) {		DEBUG(0, ("talloc_init failed\n"));		return;	}	request = TALLOC_ZERO_P(mem_ctx, struct winbindd_request);	response = TALLOC_P(mem_ctx, struct winbindd_response);	state = TALLOC_P(mem_ctx, struct trustdom_state);	if ((request == NULL) || (response == NULL) || (state == NULL)) {		DEBUG(0, ("talloc failed\n"));		talloc_destroy(mem_ctx);		return;	}	state->mem_ctx = mem_ctx;	state->response = response;	request->length = sizeof(*request);	request->cmd = WINBINDD_LIST_TRUSTDOM;	async_domain_request(mem_ctx, domain, request, response,			     trustdom_recv, state);}static void trustdom_recv(void *private_data, BOOL success){	extern struct winbindd_methods cache_methods;	struct trustdom_state *state =		talloc_get_type_abort(private_data, struct trustdom_state);	struct winbindd_response *response = state->response;	char *p;	if ((!success) || (response->result != WINBINDD_OK)) {		DEBUG(1, ("Could not receive trustdoms\n"));		talloc_destroy(state->mem_ctx);		return;	}	p = response->extra_data;	while ((p != NULL) && (*p != '\0')) {		char *q, *sidstr, *alt_name;		DOM_SID sid;		alt_name = strchr(p, '\\');		if (alt_name == NULL) {			DEBUG(0, ("Got invalid trustdom response\n"));			break;		}		*alt_name = '\0';		alt_name += 1;		sidstr = strchr(alt_name, '\\');		if (sidstr == NULL) {			DEBUG(0, ("Got invalid trustdom response\n"));			break;		}		*sidstr = '\0';		sidstr += 1;		q = strchr(sidstr, '\n');		if (q != NULL)			*q = '\0';		if (!string_to_sid(&sid, sidstr)) {			DEBUG(0, ("Got invalid trustdom response\n"));			break;		}		if (find_domain_from_name_noinit(p) == NULL) {			struct winbindd_domain *domain;			char *alternate_name = NULL;						/* use the real alt_name if we have one, else pass in NULL */			if ( !strequal( alt_name, "(null)" ) )				alternate_name = alt_name;			domain = add_trusted_domain(p, alternate_name,						    &cache_methods,						    &sid);			setup_domain_child(domain, &domain->child, NULL);		}		p=q;		if (p != NULL)			p += 1;	}	SAFE_FREE(response->extra_data);	talloc_destroy(state->mem_ctx);}/******************************************************************** Periodically we need to refresh the trusted domain cache for smbd ********************************************************************/void rescan_trusted_domains( void ){	time_t now = time(NULL);		/* see if the time has come... */		if ((now >= last_trustdom_scan) &&	    ((now-last_trustdom_scan) < WINBINDD_RESCAN_FREQ) )		return;			/* this will only add new domains we didn't already know about */		add_trusted_domains( find_our_domain() );	last_trustdom_scan = now;		return;	}struct init_child_state {	TALLOC_CTX *mem_ctx;	struct winbindd_domain *domain;	struct winbindd_request *request;	struct winbindd_response *response;	void (*continuation)(void *private_data, BOOL success);	void *private_data;};static void init_child_recv(void *private_data, BOOL success);static void init_child_getdc_recv(void *private_data, BOOL success);enum winbindd_result init_child_connection(struct winbindd_domain *domain,					   void (*continuation)(void *private_data,								BOOL success),					   void *private_data){	TALLOC_CTX *mem_ctx;	struct winbindd_request *request;	struct winbindd_response *response;	struct init_child_state *state;	mem_ctx = talloc_init("init_child_connection");	if (mem_ctx == NULL) {		DEBUG(0, ("talloc_init failed\n"));		return WINBINDD_ERROR;	}	request = TALLOC_ZERO_P(mem_ctx, struct winbindd_request);	response = TALLOC_P(mem_ctx, struct winbindd_response);	state = TALLOC_P(mem_ctx, struct init_child_state);	if ((request == NULL) || (response == NULL) || (state == NULL)) {		DEBUG(0, ("talloc failed\n"));		continuation(private_data, False);		return WINBINDD_ERROR;	}	request->length = sizeof(*request);	state->mem_ctx = mem_ctx;	state->domain = domain;	state->request = request;	state->response = response;	state->continuation = continuation;	state->private_data = private_data;	if (domain->primary) {		/* The primary domain has to find the DC name itself */		request->cmd = WINBINDD_INIT_CONNECTION;		fstrcpy(request->domain_name, domain->name);		request->data.init_conn.is_primary = True;		fstrcpy(request->data.init_conn.dcname, "");		async_request(mem_ctx, &domain->child, request, response,			      init_child_recv, state);		return WINBINDD_PENDING;	}	/* This is *not* the primary domain, let's ask our DC about a DC	 * name */	request->cmd = WINBINDD_GETDCNAME;	fstrcpy(request->domain_name, domain->name);	async_domain_request(mem_ctx, find_our_domain(), request, response,			     init_child_getdc_recv, state);	return WINBINDD_PENDING;}static void init_child_getdc_recv(void *private_data, BOOL success){	struct init_child_state *state =		talloc_get_type_abort(private_data, struct init_child_state);	const char *dcname = "";	DEBUG(10, ("Received getdcname response\n"));	if (success && (state->response->result == WINBINDD_OK)) {		dcname = state->response->data.dc_name;	}	state->request->cmd = WINBINDD_INIT_CONNECTION;	fstrcpy(state->request->domain_name, state->domain->name);	state->request->data.init_conn.is_primary = False;	fstrcpy(state->request->data.init_conn.dcname, dcname);	async_request(state->mem_ctx, &state->domain->child,		      state->request, state->response,		      init_child_recv, state);}static void init_child_recv(void *private_data, BOOL success){	struct init_child_state *state =		talloc_get_type_abort(private_data, struct init_child_state);	DEBUG(5, ("Received child initialization response for domain %s\n",		  state->domain->name));	if ((!success) || (state->response->result != WINBINDD_OK)) {		DEBUG(3, ("Could not init child\n"));		state->continuation(state->private_data, False);		talloc_destroy(state->mem_ctx);		return;	}	fstrcpy(state->domain->name,		state->response->data.domain_info.name);	fstrcpy(state->domain->alt_name,		state->response->data.domain_info.alt_name);	string_to_sid(&state->domain->sid,		      state->response->data.domain_info.sid);	state->domain->native_mode =		state->response->data.domain_info.native_mode;	state->domain->active_directory =		state->response->data.domain_info.active_directory;	state->domain->sequence_number =		state->response->data.domain_info.sequence_number;	state->domain->initialized = 1;	if (state->continuation != NULL)		state->continuation(state->private_data, True);	talloc_destroy(state->mem_ctx);}enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain,						   struct winbindd_cli_state *state){	struct in_addr ipaddr;	/* Ensure null termination */	state->request.domain_name		[sizeof(state->request.domain_name)-1]='\0';	state->request.data.init_conn.dcname		[sizeof(state->request.data.init_conn.dcname)-1]='\0';	if (strlen(state->request.data.init_conn.dcname) > 0) {		fstrcpy(domain->dcname, state->request.data.init_conn.dcname);	}	if (strlen(domain->dcname) > 0) {		if (!resolve_name(domain->dcname, &ipaddr, 0x20)) {			DEBUG(2, ("Could not resolve DC name %s for domain %s\n",				  domain->dcname, domain->name));			return WINBINDD_ERROR;		}		domain->dcaddr.sin_family = PF_INET;		putip((char *)&(domain->dcaddr.sin_addr), (char *)&ipaddr);		domain->dcaddr.sin_port = 0;	}	set_dc_type_and_flags(domain);	if (!domain->initialized) {		DEBUG(1, ("Could not initialize domain %s\n",			  state->request.domain_name));		return WINBINDD_ERROR;	}	fstrcpy(state->response.data.domain_info.name, domain->name);	fstrcpy(state->response.data.domain_info.alt_name, domain->alt_name);	fstrcpy(state->response.data.domain_info.sid,		sid_string_static(&domain->sid));		state->response.data.domain_info.native_mode		= domain->native_mode;	state->response.data.domain_info.active_directory		= domain->active_directory;	state->response.data.domain_info.primary		= domain->primary;	state->response.data.domain_info.sequence_number =		domain->sequence_number;	return WINBINDD_OK;}/* Look up global info for the winbind daemon */void init_domain_list(void){	extern struct winbindd_methods cache_methods;	extern struct winbindd_methods passdb_methods;	struct winbindd_domain *domain;	/* Free existing list */	free_domain_list();	/* Add ourselves as the first entry. */	if (IS_DC) {		domain = add_trusted_domain(get_global_sam_name(), NULL,					    &passdb_methods,					    get_global_sam_sid());	} else {		DOM_SID our_sid;		if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {			smb_panic("Could not fetch our SID - did we join?\n");		}			domain = add_trusted_domain( lp_workgroup(), lp_realm(),					     &cache_methods, &our_sid);	}	domain->primary = True;	setup_domain_child(domain, &domain->child, NULL);	/* Add our local SAM domains */	domain = add_trusted_domain("BUILTIN", NULL, &passdb_methods,				    &global_sid_Builtin);	setup_domain_child(domain, &domain->child, NULL);	if (!IS_DC) {		domain = add_trusted_domain(get_global_sam_name(), NULL,					    &passdb_methods,					    get_global_sam_sid());		setup_domain_child(domain, &domain->child, NULL);	}}/**  * Given a domain name, return the struct winbindd domain info for it  * * @note Do *not* pass lp_workgroup() to this function.  domain_list *       may modify it's value, and free that pointer.  Instead, our local *       domain may be found by calling find_our_domain(). *       directly. * * * @return The domain structure for the named domain, if it is working. */struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name){	struct winbindd_domain *domain;	/* Search through list */	for (domain = domain_list(); domain != NULL; domain = domain->next) {		if (strequal(domain_name, domain->name) ||		    (domain->alt_name[0] &&		     strequal(domain_name, domain->alt_name))) {			return domain;		}	}	/* Not found */	return NULL;}struct winbindd_domain *find_domain_from_name(const char *domain_name){	struct winbindd_domain *domain;	domain = find_domain_from_name_noinit(domain_name);	if (domain == NULL)		return NULL;	if (!domain->initialized)		set_dc_type_and_flags(domain);	return domain;}/* Given a domain sid, return the struct winbindd domain info for it */struct winbindd_domain *find_domain_from_sid_noinit(const DOM_SID *sid){	struct winbindd_domain *domain;	/* Search through list */	for (domain = domain_list(); domain != NULL; domain = domain->next) {		if (sid_compare_domain(sid, &domain->sid) == 0)			return domain;	}	/* Not found */	return NULL;}/* Given a domain sid, return the struct winbindd domain info for it */

⌨️ 快捷键说明

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