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 + -
显示快捷键?