winbindd.c

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

C
1,083
字号
/*    Unix SMB/CIFS implementation.   Winbind daemon for ntdom nss module   Copyright (C) by Tim Potter 2000-2002   Copyright (C) Andrew Tridgell 2002   Copyright (C) Jelmer Vernooij 2003   Copyright (C) Volker Lendecke 2004      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"BOOL opt_nocache = False;static BOOL interactive = False;extern BOOL override_logfile;/* Reload configuration */static BOOL reload_services_file(void){	BOOL ret;	if (lp_loaded()) {		pstring fname;		pstrcpy(fname,lp_configfile());		if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) {			pstrcpy(dyn_CONFIGFILE,fname);		}	}	reopen_logs();	ret = lp_load(dyn_CONFIGFILE,False,False,True);	reopen_logs();	load_interfaces();	return(ret);}#if DUMP_CORE/**************************************************************************** ** Prepare to dump a core file - carefully! **************************************************************************** */static BOOL dump_core(void){	char *p;	pstring dname;	pstrcpy( dname, lp_logfile() );	if ((p=strrchr(dname,'/')))		*p=0;	pstrcat( dname, "/corefiles" );	mkdir( dname, 0700 );	sys_chown( dname, getuid(), getgid() );	chmod( dname, 0700 );	if ( chdir(dname) )		return( False );	umask( ~(0700) ); #ifdef HAVE_GETRLIMIT#ifdef RLIMIT_CORE	{		struct rlimit rlp;		getrlimit( RLIMIT_CORE, &rlp );		rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur );		setrlimit( RLIMIT_CORE, &rlp );		getrlimit( RLIMIT_CORE, &rlp );		DEBUG( 3, ( "Core limits now %d %d\n", (int)rlp.rlim_cur, (int)rlp.rlim_max ) );	}#endif#endif 	DEBUG(0,("Dumping core in %s\n",dname));	abort();	return( True );} /* dump_core */#endif/**************************************************************************** ** Handle a fault.. **************************************************************************** */static void fault_quit(void){#if DUMP_CORE	dump_core();#endif}static void winbindd_status(void){	struct winbindd_cli_state *tmp;	DEBUG(0, ("winbindd status:\n"));	/* Print client state information */		DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));		if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {		DEBUG(2, ("\tclient list:\n"));		for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {			DEBUG(2, ("\t\tpid %lu, sock %d\n",				  (unsigned long)tmp->pid, tmp->sock));		}	}}/* Print winbindd status to log file */static void print_winbindd_status(void){	winbindd_status();}/* Flush client cache */static void flush_caches(void){	/* We need to invalidate cached user list entries on a SIGHUP            otherwise cached access denied errors due to restrict anonymous           hang around until the sequence number changes. */	wcache_invalidate_cache();}/* Handle the signal by unlinking socket and exiting */static void terminate(void){	pstring path;	idmap_close();		/* Remove socket file */	pstr_sprintf(path, "%s/%s", 		 WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME);	unlink(path);#if 0	if (interactive) {		TALLOC_CTX *mem_ctx = talloc_init("end_description");		char *description = talloc_describe_all(mem_ctx);		DEBUG(3, ("tallocs left:\n%s\n", description));		talloc_destroy(mem_ctx);	}#endif	exit(0);}static BOOL do_sigterm;static void termination_handler(int signum){	do_sigterm = True;	sys_select_signal(signum);}static BOOL do_sigusr2;static void sigusr2_handler(int signum){	do_sigusr2 = True;	sys_select_signal(SIGUSR2);}static BOOL do_sighup;static void sighup_handler(int signum){	do_sighup = True;	sys_select_signal(SIGHUP);}static BOOL do_sigchld;static void sigchld_handler(int signum){	do_sigchld = True;	sys_select_signal(SIGCHLD);}/* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/static void msg_reload_services(int msg_type, struct process_id src, void *buf, size_t len){        /* Flush various caches */	flush_caches();	reload_services_file();}/* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/static void msg_shutdown(int msg_type, struct process_id src, void *buf, size_t len){	do_sigterm = True;}static struct winbindd_dispatch_table {	enum winbindd_cmd cmd;	void (*fn)(struct winbindd_cli_state *state);	const char *winbindd_cmd_name;} dispatch_table[] = {		/* User functions */	{ WINBINDD_GETPWNAM, winbindd_getpwnam, "GETPWNAM" },	{ WINBINDD_GETPWUID, winbindd_getpwuid, "GETPWUID" },	{ WINBINDD_SETPWENT, winbindd_setpwent, "SETPWENT" },	{ WINBINDD_ENDPWENT, winbindd_endpwent, "ENDPWENT" },	{ WINBINDD_GETPWENT, winbindd_getpwent, "GETPWENT" },	{ WINBINDD_GETGROUPS, winbindd_getgroups, "GETGROUPS" },	{ WINBINDD_GETUSERSIDS, winbindd_getusersids, "GETUSERSIDS" },	{ WINBINDD_GETUSERDOMGROUPS, winbindd_getuserdomgroups,	  "GETUSERDOMGROUPS" },	/* Group functions */	{ WINBINDD_GETGRNAM, winbindd_getgrnam, "GETGRNAM" },	{ WINBINDD_GETGRGID, winbindd_getgrgid, "GETGRGID" },	{ WINBINDD_SETGRENT, winbindd_setgrent, "SETGRENT" },	{ WINBINDD_ENDGRENT, winbindd_endgrent, "ENDGRENT" },	{ WINBINDD_GETGRENT, winbindd_getgrent, "GETGRENT" },	{ WINBINDD_GETGRLST, winbindd_getgrent, "GETGRLST" },	/* PAM auth functions */	{ WINBINDD_PAM_AUTH, winbindd_pam_auth, "PAM_AUTH" },	{ WINBINDD_PAM_AUTH_CRAP, winbindd_pam_auth_crap, "AUTH_CRAP" },	{ WINBINDD_PAM_CHAUTHTOK, winbindd_pam_chauthtok, "CHAUTHTOK" },	/* Enumeration functions */	{ WINBINDD_LIST_USERS, winbindd_list_users, "LIST_USERS" },	{ WINBINDD_LIST_GROUPS, winbindd_list_groups, "LIST_GROUPS" },	{ WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,	  "LIST_TRUSTDOM" },	{ WINBINDD_SHOW_SEQUENCE, winbindd_show_sequence, "SHOW_SEQUENCE" },	/* SID related functions */	{ WINBINDD_LOOKUPSID, winbindd_lookupsid, "LOOKUPSID" },	{ WINBINDD_LOOKUPNAME, winbindd_lookupname, "LOOKUPNAME" },	/* Lookup related functions */	{ WINBINDD_SID_TO_UID, winbindd_sid_to_uid, "SID_TO_UID" },	{ WINBINDD_SID_TO_GID, winbindd_sid_to_gid, "SID_TO_GID" },	{ WINBINDD_UID_TO_SID, winbindd_uid_to_sid, "UID_TO_SID" },	{ WINBINDD_GID_TO_SID, winbindd_gid_to_sid, "GID_TO_SID" },	{ WINBINDD_ALLOCATE_RID, winbindd_allocate_rid, "ALLOCATE_RID" },	{ WINBINDD_ALLOCATE_RID_AND_GID, winbindd_allocate_rid_and_gid,	  "ALLOCATE_RID_AND_GID" },	/* Miscellaneous */	{ WINBINDD_CHECK_MACHACC, winbindd_check_machine_acct, "CHECK_MACHACC" },	{ WINBINDD_PING, winbindd_ping, "PING" },	{ WINBINDD_INFO, winbindd_info, "INFO" },	{ WINBINDD_INTERFACE_VERSION, winbindd_interface_version,	  "INTERFACE_VERSION" },	{ WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },	{ WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },	{ WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },	{ WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,	  "WINBINDD_PRIV_PIPE_DIR" },	{ WINBINDD_GETDCNAME, winbindd_getdcname, "GETDCNAME" },	/* WINS functions */	{ WINBINDD_WINS_BYNAME, winbindd_wins_byname, "WINS_BYNAME" },	{ WINBINDD_WINS_BYIP, winbindd_wins_byip, "WINS_BYIP" },		/* End of list */	{ WINBINDD_NUM_CMDS, NULL, "NONE" }};static void process_request(struct winbindd_cli_state *state){	struct winbindd_dispatch_table *table = dispatch_table;	/* Free response data - we may be interrupted and receive another	   command before being able to send this data off. */	SAFE_FREE(state->response.extra_data);  	ZERO_STRUCT(state->response);	state->response.result = WINBINDD_PENDING;	state->response.length = sizeof(struct winbindd_response);	state->mem_ctx = talloc_init("winbind request");	if (state->mem_ctx == NULL)		return;	/* Process command */	for (table = dispatch_table; table->fn; table++) {		if (state->request.cmd == table->cmd) {			DEBUG(10,("process_request: request fn %s\n",				  table->winbindd_cmd_name ));			table->fn(state);			break;		}	}	if (!table->fn) {		DEBUG(10,("process_request: unknown request fn number %d\n",			  (int)state->request.cmd ));		request_error(state);	}}/* * A list of file descriptors being monitored by select in the main processing * loop. fd_event->handler is called whenever the socket is readable/writable. */static struct fd_event *fd_events = NULL;void add_fd_event(struct fd_event *ev){	struct fd_event *match;	/* only add unique fd_event structs */	for (match=fd_events; match; match=match->next ) {#ifdef DEVELOPER		SMB_ASSERT( match != ev );#else		if ( match == ev )			return;#endif	}	DLIST_ADD(fd_events, ev);}void remove_fd_event(struct fd_event *ev){	DLIST_REMOVE(fd_events, ev);}/* * Handler for fd_events to complete a read/write request, set up by * setup_async_read/setup_async_write. */static void rw_callback(struct fd_event *event, int flags){	size_t todo;	ssize_t done = 0;	todo = event->length - event->done;	if (event->flags & EVENT_FD_WRITE) {		SMB_ASSERT(flags == EVENT_FD_WRITE);		done = sys_write(event->fd,				 &((char *)event->data)[event->done],				 todo);		if (done <= 0) {			event->flags = 0;			event->finished(event->private_data, False);			return;		}	}	if (event->flags & EVENT_FD_READ) {		SMB_ASSERT(flags == EVENT_FD_READ);		done = sys_read(event->fd, &((char *)event->data)[event->done],				todo);		if (done <= 0) {			event->flags = 0;			event->finished(event->private_data, False);			return;		}	}	event->done += done;	if (event->done == event->length) {		event->flags = 0;		event->finished(event->private_data, True);	}}/* * Request an async read/write on a fd_event structure. (*finished) is called * when the request is completed or an error had occurred. */void setup_async_read(struct fd_event *event, void *data, size_t length,		      void (*finished)(void *private_data, BOOL success),		      void *private_data){	SMB_ASSERT(event->flags == 0);	event->data = data;	event->length = length;	event->done = 0;	event->handler = rw_callback;	event->finished = finished;	event->private_data = private_data;	event->flags = EVENT_FD_READ;}void setup_async_write(struct fd_event *event, void *data, size_t length,		       void (*finished)(void *private_data, BOOL success),		       void *private_data){	SMB_ASSERT(event->flags == 0);	event->data = data;	event->length = length;	event->done = 0;	event->handler = rw_callback;	event->finished = finished;	event->private_data = private_data;	event->flags = EVENT_FD_WRITE;}/* * This is the main event loop of winbind requests. It goes through a * state-machine of 3 read/write requests, 4 if you have extra data to send. * * An idle winbind client has a read request of 4 bytes outstanding, * finalizing function is request_len_recv, checking the length. request_recv * then processes the packet. The processing function then at some point has * to call request_finished which schedules sending the response. */static void request_len_recv(void *private_data, BOOL success);static void request_recv(void *private_data, BOOL success);static void request_main_recv(void *private_data, BOOL success);static void request_finished(struct winbindd_cli_state *state);void request_finished_cont(void *private_data, BOOL success);static void response_main_sent(void *private_data, BOOL success);static void response_extra_sent(void *private_data, BOOL success);static void response_extra_sent(void *private_data, BOOL success){	struct winbindd_cli_state *state =		talloc_get_type_abort(private_data, struct winbindd_cli_state);	if (state->mem_ctx != NULL) {		talloc_destroy(state->mem_ctx);		state->mem_ctx = NULL;	}	if (!success) {		state->finished = True;		return;	}	SAFE_FREE(state->request.extra_data);	SAFE_FREE(state->response.extra_data);	setup_async_read(&state->fd_event, &state->request, sizeof(uint32),			 request_len_recv, state);}static void response_main_sent(void *private_data, BOOL success){	struct winbindd_cli_state *state =		talloc_get_type_abort(private_data, struct winbindd_cli_state);	if (!success) {		state->finished = True;		return;	}	if (state->response.length == sizeof(state->response)) {		if (state->mem_ctx != NULL) {			talloc_destroy(state->mem_ctx);			state->mem_ctx = NULL;		}		setup_async_read(&state->fd_event, &state->request,				 sizeof(uint32), request_len_recv, state);		return;	}	setup_async_write(&state->fd_event, state->response.extra_data,			  state->response.length - sizeof(state->response),			  response_extra_sent, state);}static void request_finished(struct winbindd_cli_state *state){	setup_async_write(&state->fd_event, &state->response,			  sizeof(state->response), response_main_sent, state);}void request_error(struct winbindd_cli_state *state){	SMB_ASSERT(state->response.result == WINBINDD_PENDING);	state->response.result = WINBINDD_ERROR;	request_finished(state);}void request_ok(struct winbindd_cli_state *state){	SMB_ASSERT(state->response.result == WINBINDD_PENDING);	state->response.result = WINBINDD_OK;	request_finished(state);}void request_finished_cont(void *private_data, BOOL success){	struct winbindd_cli_state *state =		talloc_get_type_abort(private_data, struct winbindd_cli_state);	if (success)		request_ok(state);	else		request_error(state);}static void request_len_recv(void *private_data, BOOL success)

⌨️ 快捷键说明

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