|
View:
New views
6 Messages
—
Rating Filter:
Alert me
|
|
|
patch to not overwrite wb- logfile names on reloadIn reloading the smb.conf, if a "log file" is specified in smb.conf,
winbind children will overwrite the logfile name to be the same as the parent. This patch fixes it (though not the prettiest thing). Any feedback? -- Jim McDonough Samba Team jmcd at samba dot org jmcd at themcdonoughs dot org [0001-In-log-file-macro-case-don-t-overwrite-the.patch] From f16e26a6d7ce5e33d6855ee8665761b4a692ea05 Mon Sep 17 00:00:00 2001 From: Jim McDonough <jmcd@...> Date: Thu, 17 Jul 2008 15:27:04 -0400 Subject: [PATCH] In "log file = <macro>" case, don't overwrite the log.wb-<domain> logfile name on smb.conf reload. --- source/nsswitch/winbindd.c | 1124 --------------------------------------- source/nsswitch/winbindd_dual.c | 1104 -------------------------------------- 2 files changed, 0 insertions(+), 2228 deletions(-) delete mode 100644 source/nsswitch/winbindd.c delete mode 100644 source/nsswitch/winbindd_dual.c diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c deleted file mode 100644 index c79bb46..0000000 --- a/source/nsswitch/winbindd.c +++ /dev/null @@ -1,1124 +0,0 @@ -/* - 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" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -BOOL opt_nocache = False; -static BOOL interactive = False; - -extern BOOL override_logfile; - -struct event_context *winbind_event_context(void) -{ - static struct event_context *ctx; - - if (!ctx && !(ctx = event_context_init(NULL))) { - smb_panic("Could not init winbind event context\n"); - } - return ctx; -} - -/* 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,True); - - reopen_logs(); - load_interfaces(); - - return(ret); -} - - -/**************************************************************************** ** - Handle a fault.. - **************************************************************************** */ - -static void fault_quit(void) -{ - dump_core(); -} - -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) { - DEBUGADD(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(bool in_parent) -{ - if (in_parent) { - /* When parent goes away we should - * remove the socket file. Not so - * when children terminate. - */ - - pstring path; - - /* Remove socket file */ - pstr_sprintf(path, "%s/%s", - WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME); - unlink(path); - } - - idmap_close(); - - trustdom_cache_shutdown(); - -#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, void *private_data) -{ - /* 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, void *private_data) -{ - 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" }, - { WINBINDD_PAM_LOGOFF, winbindd_pam_logoff, "PAM_LOGOFF" }, - { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, winbindd_pam_chng_pswd_auth_crap, "CHNG_PSWD_AUTH_CRAP" }, - - /* 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" }, - { WINBINDD_LOOKUPRIDS, winbindd_lookuprids, "LOOKUPRIDS" }, - - /* 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" }, -#if 0 /* DISABLED until we fix the interface in Samba 3.0.26 --jerry */ - { WINBINDD_SIDS_TO_XIDS, winbindd_sids_to_unixids, "SIDS_TO_XIDS" }, -#endif /* end DISABLED */ - { WINBINDD_ALLOCATE_UID, winbindd_allocate_uid, "ALLOCATE_UID" }, - { WINBINDD_ALLOCATE_GID, winbindd_allocate_gid, "ALLOCATE_GID" }, - { WINBINDD_SET_MAPPING, winbindd_set_mapping, "SET_MAPPING" }, - { WINBINDD_SET_HWM, winbindd_set_hwm, "SET_HWMS" }, - - /* Miscellaneous */ - - { WINBINDD_DUMP_MAPS, winbindd_dump_maps, "DUMP_MAPS" }, - - { 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" }, - - /* Credential cache access */ - { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" }, - - /* 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.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; - - /* Remember who asked us. */ - state->pid = state->request.pid; - - /* 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.data); - SAFE_FREE(state->response.extra_data.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.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) -{ - struct winbindd_cli_state *state = - talloc_get_type_abort(private_data, struct winbindd_cli_state); - - if (!success) { - state->finished = True; - return; - } - - if (*(uint32 *)(&state->request) != sizeof(state->request)) { - DEBUG(0,("request_len_recv: Invalid request size received: %d (expected %d)\n", - *(uint32 *)(&state->request), (uint32)sizeof(state->request))); - state->finished = True; - return; - } - - setup_async_read(&state->fd_event, (uint32 *)(&state->request)+1, - sizeof(state->request) - sizeof(uint32), - request_main_recv, state); -} - -static void request_main_recv(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->request.extra_len == 0) { - state->request.extra_data.data = NULL; - request_recv(state, True); - return; - } - - if ((!state->privileged) && - (state->request.extra_len > WINBINDD_MAX_EXTRA_DATA)) { - DEBUG(3, ("Got request with %d bytes extra data on " - "unprivileged socket\n", (int)state->request.extra_len)); - state->request.extra_data.data = NULL; - state->finished = True; - return; - } - - state->request.extra_data.data = - SMB_MALLOC_ARRAY(char, state->request.extra_len + 1); - - if (state->request.extra_data.data == NULL) { - DEBUG(0, ("malloc failed\n")); - state->finished = True; - return; - } - - /* Ensure null termination */ - state->request.extra_data.data[state->request.extra_len] = '\0'; - - setup_async_read(&state->fd_event, state->request.extra_data.data, - state->request.extra_len, request_recv, state); -} - -static void request_recv(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; - } - - process_request(state); -} - -/* Process a new connection by adding it to the client connection list */ - -static void new_connection(int listen_sock, BOOL privileged) -{ - struct sockaddr_un sunaddr; - struct winbindd_cli_state *state; - socklen_t len; - int sock; - - /* Accept connection */ - - len = sizeof(sunaddr); - - do { - sock = accept(listen_sock, (struct sockaddr *)&sunaddr, &len); - } while (sock == -1 && errno == EINTR); - - if (sock == -1) - return; - - DEBUG(6,("accepted socket %d\n", sock)); - - /* Create new connection structure */ - - if ((state = TALLOC_ZERO_P(NULL, struct winbindd_cli_state)) == NULL) { - close(sock); - return; - } - - state->sock = sock; - - state->last_access = time(NULL); - - state->privileged = privileged; - - state->fd_event.fd = state->sock; - state->fd_event.flags = 0; - add_fd_event(&state->fd_event); - - setup_async_read(&state->fd_event, &state->request, sizeof(uint32), - request_len_recv, state); - - /* Add to connection list */ - - winbindd_add_client(state); -} - -/* Remove a client connection from client connection list */ - -static void remove_client(struct winbindd_cli_state *state) -{ - /* It's a dead client - hold a funeral */ - - if (state == NULL) { - return; - } - - /* Close socket */ - - close(state->sock); - - /* Free any getent state */ - - free_getent_state(state->getpwent_state); - free_getent_state(state->getgrent_state); - - /* We may have some extra data that was not freed if the client was - killed unexpectedly */ - - SAFE_FREE(state->response.extra_data.data); - - if (state->mem_ctx != NULL) { - talloc_destroy(state->mem_ctx); - state->mem_ctx = NULL; - } - - remove_fd_event(&state->fd_event); - - /* Remove from list and free */ - - winbindd_remove_client(state); - TALLOC_FREE(state); -} - -/* Shutdown client connection which has been idle for the longest time */ - -static BOOL remove_idle_client(void) -{ - struct winbindd_cli_state *state, *remove_state = NULL; - time_t last_access = 0; - int nidle = 0; - - for (state = winbindd_client_list(); state; state = state->next) { - if (state->response.result != WINBINDD_PENDING && - !state->getpwent_state && !state->getgrent_state) { - nidle++; - if (!last_access || state->last_access < last_access) { - last_access = state->last_access; - remove_state = state; - } - } - } - - if (remove_state) { - DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n", - nidle, remove_state->sock, (unsigned int)remove_state->pid)); - remove_client(remove_state); - return True; - } - - return False; -} - -/* check if HUP has been received and reload files */ -void winbind_check_sighup(void) -{ - if (do_sighup) { - - DEBUG(3, ("got SIGHUP\n")); - - msg_reload_services(MSG_SMB_CONF_UPDATED, pid_to_procid(0), NULL, 0, NULL); - do_sighup = False; - } -} - -/* check if TERM has been received */ -void winbind_check_sigterm(bool in_parent) -{ - if (do_sigterm) - terminate(in_parent); -} - -/* Process incoming clients on listen_sock. We use a tricky non-blocking, - non-forking, non-threaded model which allows us to handle many - simultaneous connections while remaining impervious to many denial of - service attacks. */ - -static void process_loop(void) -{ - struct winbindd_cli_state *state; - struct fd_event *ev; - fd_set r_fds, w_fds; - int maxfd, listen_sock, listen_priv_sock, selret; - struct timeval timeout, ev_timeout; - - /* Open Sockets here to get stuff going ASAP */ - listen_sock = open_winbindd_socket(); - listen_priv_sock = open_winbindd_priv_socket(); - - if (listen_sock == -1 || listen_priv_sock == -1) { - perror("open_winbind_socket"); - exit(1); - } - - /* We'll be doing this a lot */ - - /* Handle messages */ - - message_dispatch(); - - run_events(winbind_event_context(), 0, NULL, NULL); - - /* refresh the trusted domain cache */ - - rescan_trusted_domains(); - - /* Free up temporary memory */ - - lp_TALLOC_FREE(); - main_loop_TALLOC_FREE(); - - /* Initialise fd lists for select() */ - - maxfd = MAX(listen_sock, listen_priv_sock); - - FD_ZERO(&r_fds); - FD_ZERO(&w_fds); - FD_SET(listen_sock, &r_fds); - FD_SET(listen_priv_sock, &r_fds); - - timeout.tv_sec = WINBINDD_ESTABLISH_LOOP; - timeout.tv_usec = 0; - - /* Check for any event timeouts. */ - if (get_timed_events_timeout(winbind_event_context(), &ev_timeout)) { - timeout = timeval_min(&timeout, &ev_timeout); - } - - /* Set up client readers and writers */ - - state = winbindd_client_list(); - - while (state) { - - struct winbindd_cli_state *next = state->next; - - /* Dispose of client connection if it is marked as - finished */ - - if (state->finished) - remove_client(state); - - state = next; - } - - for (ev = fd_events; ev; ev = ev->next) { - if (ev->flags & EVENT_FD_READ) { - FD_SET(ev->fd, &r_fds); - maxfd = MAX(ev->fd, maxfd); - } - if (ev->flags & EVENT_FD_WRITE) { - FD_SET(ev->fd, &w_fds); - maxfd = MAX(ev->fd, maxfd); - } - } - - /* Call select */ - - selret = sys_select(maxfd + 1, &r_fds, &w_fds, NULL, &timeout); - - if (selret == 0) { - goto no_fds_ready; - } - - if (selret == -1) { - if (errno == EINTR) { - goto no_fds_ready; - } - - /* Select error, something is badly wrong */ - - perror("select"); - exit(1); - } - - /* selret > 0 */ - - ev = fd_events; - while (ev != NULL) { - struct fd_event *next = ev->next; - int flags = 0; - if (FD_ISSET(ev->fd, &r_fds)) - flags |= EVENT_FD_READ; - if (FD_ISSET(ev->fd, &w_fds)) - flags |= EVENT_FD_WRITE; - if (flags) - ev->handler(ev, flags); - ev = next; - } - - if (FD_ISSET(listen_sock, &r_fds)) { - while (winbindd_num_clients() > - WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1) { - DEBUG(5,("winbindd: Exceeding %d client " - "connections, removing idle " - "connection.\n", - WINBINDD_MAX_SIMULTANEOUS_CLIENTS)); - if (!remove_idle_client()) { - DEBUG(0,("winbindd: Exceeding %d " - "client connections, no idle " - "connection found\n", - WINBINDD_MAX_SIMULTANEOUS_CLIENTS)); - break; - } - } - /* new, non-privileged connection */ - new_connection(listen_sock, False); - } - - if (FD_ISSET(listen_priv_sock, &r_fds)) { - while (winbindd_num_clients() > - WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1) { - DEBUG(5,("winbindd: Exceeding %d client " - "connections, removing idle " - "connection.\n", - WINBINDD_MAX_SIMULTANEOUS_CLIENTS)); - if (!remove_idle_client()) { - DEBUG(0,("winbindd: Exceeding %d " - "client connections, no idle " - "connection found\n", - WINBINDD_MAX_SIMULTANEOUS_CLIENTS)); - break; - } - } - /* new, privileged connection */ - new_connection(listen_priv_sock, True); - } - - no_fds_ready: - -#if 0 - winbindd_check_cache_size(time(NULL)); -#endif - - /* Check signal handling things */ - - winbind_check_sigterm(true); - winbind_check_sighup(); - - if (do_sigusr2) { - print_winbindd_status(); - do_sigusr2 = False; - } - - if (do_sigchld) { - pid_t pid; - - do_sigchld = False; - - while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) { - winbind_child_died(pid); - } - } -} - -/* Main function */ - -int main(int argc, char **argv, char **envp) -{ - pstring logfile; - static BOOL Fork = True; - static BOOL log_stdout = False; - static BOOL no_process_group = False; - struct poptOption long_options[] = { - POPT_AUTOHELP - { "stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, - { "foreground", 'F', POPT_ARG_VAL, &Fork, False, "Daemon in foreground mode" }, - { "no-process-group", 0, POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" }, - { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" }, - { "no-caching", 'n', POPT_ARG_VAL, &opt_nocache, True, "Disable caching" }, - POPT_COMMON_SAMBA - POPT_TABLEEND - }; - poptContext pc; - int opt; - - /* glibc (?) likes to print "User defined signal 1" and exit if a - SIGUSR[12] is received before a handler is installed */ - - CatchSignal(SIGUSR1, SIG_IGN); - CatchSignal(SIGUSR2, SIG_IGN); - - fault_setup((void (*)(void *))fault_quit ); - dump_core_setup("winbindd"); - - load_case_tables(); - - /* Initialise for running in non-root mode */ - - sec_init(); - - set_remote_machine_name("winbindd", False); - - /* Set environment variable so we don't recursively call ourselves. - This may also be useful interactively. */ - - if ( !winbind_off() ) { - DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n")); - exit(1); - } - - /* Initialise samba/rpc client stuff */ - - pc = poptGetContext("winbindd", argc, (const char **)argv, long_options, - POPT_CONTEXT_KEEP_FIRST); - - while ((opt = poptGetNextOpt(pc)) != -1) { - switch (opt) { - /* Don't become a daemon */ - case 'i': - interactive = True; - log_stdout = True; - Fork = False; - break; - } - } - - - if (log_stdout && Fork) { - printf("Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n"); - poptPrintUsage(pc, stderr, 0); - exit(1); - } - - if (!override_logfile) { - pstr_sprintf(logfile, "%s/log.winbindd", dyn_LOGFILEBASE); - lp_set_logfile(logfile); - } - setup_logging("winbindd", log_stdout); - reopen_logs(); - - DEBUG(1, ("winbindd version %s started.\n%s\n", - SAMBA_VERSION_STRING, - COPYRIGHT_STARTUP_MESSAGE) ); - - if (!reload_services_file()) { - DEBUG(0, ("error opening config file\n")); - exit(1); - } - - if (!directory_exist(lp_lockdir(), NULL)) { - mkdir(lp_lockdir(), 0755); - } - - /* Setup names. */ - - if (!init_names()) - exit(1); - - load_interfaces(); - - if (!secrets_init()) { - - DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n")); - return False; - } - - /* Enable netbios namecache */ - - namecache_enable(); - - /* Winbind daemon initialisation */ - - if ( ! NT_STATUS_IS_OK(idmap_init_cache()) ) { - DEBUG(1, ("Could not init idmap cache!\n")); - } - - /* Unblock all signals we are interested in as they may have been - blocked by the parent process. */ - - BlockSignals(False, SIGINT); - BlockSignals(False, SIGQUIT); - BlockSignals(False, SIGTERM); - BlockSignals(False, SIGUSR1); - BlockSignals(False, SIGUSR2); - BlockSignals(False, SIGHUP); - BlockSignals(False, SIGCHLD); - - /* Setup signal handlers */ - - CatchSignal(SIGINT, termination_handler); /* Exit on these sigs */ - CatchSignal(SIGQUIT, termination_handler); - CatchSignal(SIGTERM, termination_handler); - CatchSignal(SIGCHLD, sigchld_handler); - - CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */ - - CatchSignal(SIGUSR2, sigusr2_handler); /* Debugging sigs */ - CatchSignal(SIGHUP, sighup_handler); - - if (!interactive) - become_daemon(Fork, no_process_group); - - pidfile_create("winbindd"); - -#if HAVE_SETPGID - /* - * If we're interactive we want to set our own process group for - * signal management. - */ - if (interactive && !no_process_group) - setpgid( (pid_t)0, (pid_t)0); -#endif - - TimeInit(); - - /* Initialise messaging system */ - - if (!message_init()) { - DEBUG(0, ("unable to initialize messaging system\n")); - exit(1); - } - - /* Initialize cache (ensure version is correct). */ - if (!initialize_winbindd_cache()) { - exit(1); - } - - /* React on 'smbcontrol winbindd reload-config' in the same way - as to SIGHUP signal */ - message_register(MSG_SMB_CONF_UPDATED, msg_reload_services, NULL); - message_register(MSG_SHUTDOWN, msg_shutdown, NULL); - - /* Handle online/offline messages. */ - message_register(MSG_WINBIND_OFFLINE, winbind_msg_offline, NULL); - message_register(MSG_WINBIND_ONLINE, winbind_msg_online, NULL); - message_register(MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus, - NULL); - - poptFreeContext(pc); - - netsamlogon_cache_init(); /* Non-critical */ - - if (!init_domain_list()) { - DEBUG(0,("unable to initalize domain list\n")); - exit(1); - } - - init_idmap_child(); - - smb_nscd_flush_user_cache(); - smb_nscd_flush_group_cache(); - - /* Loop waiting for requests */ - - while (1) - process_loop(); - - return 0; -} diff --git a/source/nsswitch/winbindd_dual.c b/source/nsswitch/winbindd_dual.c deleted file mode 100644 index 5ba68d6..0000000 --- a/source/nsswitch/winbindd_dual.c +++ /dev/null @@ -1,1104 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind child daemons - - Copyright (C) Andrew Tridgell 2002 - Copyright (C) Volker Lendecke 2004,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. -*/ - -/* - * We fork a child per domain to be able to act non-blocking in the main - * winbind daemon. A domain controller thousands of miles away being being - * slow replying with a 10.000 user list should not hold up netlogon calls - * that can be handled locally. - */ - -#include "includes.h" -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -extern BOOL override_logfile; - -/* Read some data from a client connection */ - -static void child_read_request(struct winbindd_cli_state *state) -{ - ssize_t len; - - /* Read data */ - - len = read_data(state->sock, (char *)&state->request, - sizeof(state->request)); - - if (len != sizeof(state->request)) { - DEBUG(len > 0 ? 0 : 3, ("Got invalid request length: %d\n", (int)len)); - state->finished = True; - return; - } - - if (state->request.extra_len == 0) { - state->request.extra_data.data = NULL; - return; - } - - DEBUG(10, ("Need to read %d extra bytes\n", (int)state->request.extra_len)); - - state->request.extra_data.data = - SMB_MALLOC_ARRAY(char, state->request.extra_len + 1); - - if (state->request.extra_data.data == NULL) { - DEBUG(0, ("malloc failed\n")); - state->finished = True; - return; - } - - /* Ensure null termination */ - state->request.extra_data.data[state->request.extra_len] = '\0'; - - len = read_data(state->sock, state->request.extra_data.data, - state->request.extra_len); - - if (len != state->request.extra_len) { - DEBUG(0, ("Could not read extra data\n")); - state->finished = True; - return; - } -} - -/* - * Machinery for async requests sent to children. You set up a - * winbindd_request, select a child to query, and issue a async_request - * call. When the request is completed, the callback function you specified is - * called back with the private pointer you gave to async_request. - */ - -struct winbindd_async_request { - struct winbindd_async_request *next, *prev; - TALLOC_CTX *mem_ctx; - struct winbindd_child *child; - struct winbindd_request *request; - struct winbindd_response *response; - void (*continuation)(void *private_data, BOOL success); - struct timed_event *reply_timeout_event; - pid_t child_pid; /* pid of the child we're waiting on. Used to detect - a restart of the child (child->pid != child_pid). */ - void *private_data; -}; - -static void async_main_request_sent(void *private_data, BOOL success); -static void async_request_sent(void *private_data, BOOL success); -static void async_reply_recv(void *private_data, BOOL success); -static void schedule_async_request(struct winbindd_child *child); - -void async_request(TALLOC_CTX *mem_ctx, struct winbindd_child *child, - struct winbindd_request *request, - struct winbindd_response *response, - void (*continuation)(void *private_data, BOOL success), - void *private_data) -{ - struct winbindd_async_request *state; - - SMB_ASSERT(continuation != NULL); - - state = TALLOC_P(mem_ctx, struct winbindd_async_request); - - if (state == NULL) { - DEBUG(0, ("talloc failed\n")); - continuation(private_data, False); - return; - } - - state->mem_ctx = mem_ctx; - state->child = child; - state->request = request; - state->response = response; - state->continuation = continuation; - state->private_data = private_data; - - DLIST_ADD_END(child->requests, state, struct winbindd_async_request *); - - schedule_async_request(child); - - return; -} - -static void async_main_request_sent(void *private_data, BOOL success) -{ - struct winbindd_async_request *state = - talloc_get_type_abort(private_data, struct winbindd_async_request); - - if (!success) { - DEBUG(5, ("Could not send async request\n")); - - state->response->length = sizeof(struct winbindd_response); - state->response->result = WINBINDD_ERROR; - state->continuation(state->private_data, False); - return; - } - - if (state->request->extra_len == 0) { - async_request_sent(private_data, True); - return; - } - - setup_async_write(&state->child->event, state->request->extra_data.data, - state->request->extra_len, - async_request_sent, state); -} - -/**************************************************************** - Handler triggered if the child winbindd doesn't respond within - a given timeout. -****************************************************************/ - -static void async_request_timeout_handler(struct event_context *ctx, - struct timed_event *te, - const struct timeval *now, - void *private_data) -{ - struct winbindd_async_request *state = - talloc_get_type_abort(private_data, struct winbindd_async_request); - - DEBUG(0,("async_request_timeout_handler: child pid %u is not responding. " - "Closing connection to it.\n", - state->child_pid )); - - /* Deal with the reply - set to error. */ - async_reply_recv(private_data, False); -} - -/************************************************************** - Common function called on both async send and recv fail. - Cleans up the child and schedules the next request. -**************************************************************/ - -static void async_request_fail(struct winbindd_async_request *state) -{ - DLIST_REMOVE(state->child->requests, state); - - TALLOC_FREE(state->reply_timeout_event); - - SMB_ASSERT(state->child_pid != (pid_t)0); - - /* If not already reaped, send kill signal to child. */ - if (state->child->pid == state->child_pid) { - kill(state->child_pid, SIGTERM); - - /* - * Close the socket to the child. - */ - winbind_child_died(state->child_pid); - } - - state->response->length = sizeof(struct winbindd_response); - state->response->result = WINBINDD_ERROR; - state->continuation(state->private_data, False); -} - -static void async_request_sent(void *private_data_data, BOOL success) -{ - struct winbindd_async_request *state = - talloc_get_type_abort(private_data_data, struct winbindd_async_request); - - if (!success) { - DEBUG(5, ("Could not send async request to child pid %u\n", - (unsigned int)state->child_pid )); - async_request_fail(state); - return; - } - - /* Request successfully sent to the child, setup the wait for reply */ - - setup_async_read(&state->child->event, - &state->response->result, - sizeof(state->response->result), - async_reply_recv, state); - - /* - * Set up a timeout of 300 seconds for the response. - * If we don't get it close the child socket and - * report failure. - */ - - state->reply_timeout_event = event_add_timed(winbind_event_context(), - NULL, - timeval_current_ofs(300,0), - "async_request_timeout", - async_request_timeout_handler, - state); - if (!state->reply_timeout_event) { - smb_panic("async_request_sent: failed to add timeout handler.\n"); - } -} - -static void async_reply_recv(void *private_data, BOOL success) -{ - struct winbindd_async_request *state = - talloc_get_type_abort(private_data, struct winbindd_async_request); - struct winbindd_child *child = state->child; - - TALLOC_FREE(state->reply_timeout_event); - - state->response->length = sizeof(struct winbindd_response); - - if (!success) { - DEBUG(5, ("Could not receive async reply from child pid %u\n", - (unsigned int)state->child_pid )); - - cache_cleanup_response(state->child_pid); - async_request_fail(state); - return; - } - - SMB_ASSERT(cache_retrieve_response(state->child_pid, - state->response)); - - cache_cleanup_response(state->child_pid); - - DLIST_REMOVE(child->requests, state); - - schedule_async_request(child); - - state->continuation(state->private_data, True); -} - -static BOOL fork_domain_child(struct winbindd_child *child); - -static void schedule_async_request(struct winbindd_child *child) -{ - struct winbindd_async_request *request = child->requests; - - if (request == NULL) { - return; - } - - if (child->event.flags != 0) { - return; /* Busy */ - } - - if ((child->pid == 0) && (!fork_domain_child(child))) { - /* Cancel all outstanding requests */ - - while (request != NULL) { - /* request might be free'd in the continuation */ - struct winbindd_async_request *next = request->next; - request->continuation(request->private_data, False); - request = next; - } - return; - } - - /* Now we know who we're sending to - remember the pid. */ - request->child_pid = child->pid; - - setup_async_write(&child->event, request->request, - sizeof(*request->request), - async_main_request_sent, request); - - return; -} - -struct domain_request_state { - TALLOC_CTX *mem_ctx; - struct winbindd_domain *domain; - struct winbindd_request *request; - struct winbindd_response *response; - void (*continuation)(void *private_data_data, BOOL success); - void *private_data_data; -}; - -static void domain_init_recv(void *private_data_data, BOOL success); - -void async_domain_request(TALLOC_CTX *mem_ctx, - struct winbindd_domain *domain, - struct winbindd_request *request, - struct winbindd_response *response, - void (*continuation)(void *private_data_data, BOOL success), - void *private_data_data) -{ - struct domain_request_state *state; - - if (domain->initialized) { - async_request(mem_ctx, &domain->child, request, response, - continuation, private_data_data); - return; - } - - state = TALLOC_P(mem_ctx, struct domain_request_state); - if (state == NULL) { - DEBUG(0, ("talloc failed\n")); - continuation(private_data_data, False); - return; - } - - state->mem_ctx = mem_ctx; - state->domain = domain; - state->request = request; - state->response = response; - state->continuation = continuation; - state->private_data_data = private_data_data; - - init_child_connection(domain, domain_init_recv, state); -} - -static void recvfrom_child(void *private_data_data, BOOL success) -{ - struct winbindd_cli_state *state = - talloc_get_type_abort(private_data_data, struct winbindd_cli_state); - enum winbindd_result result = state->response.result; - - /* This is an optimization: The child has written directly to the - * response buffer. The request itself is still in pending state, - * state that in the result code. */ - - state->response.result = WINBINDD_PENDING; - - if ((!success) || (result != WINBINDD_OK)) { - request_error(state); - return; - } - - request_ok(state); -} - -void sendto_child(struct winbindd_cli_state *state, - struct winbindd_child *child) -{ - async_request(state->mem_ctx, child, &state->request, - &state->response, recvfrom_child, state); -} - -void sendto_domain(struct winbindd_cli_state *state, - struct winbindd_domain *domain) -{ - async_domain_request(state->mem_ctx, domain, - &state->request, &state->response, - recvfrom_child, state); -} - -static void domain_init_recv(void *private_data_data, BOOL success) -{ - struct domain_request_state *state = - talloc_get_type_abort(private_data_data, struct domain_request_state); - - if (!success) { - DEBUG(5, ("Domain init returned an error\n")); - state->continuation(state->private_data_data, False); - return; - } - - async_request(state->mem_ctx, &state->domain->child, - state->request, state->response, - state->continuation, state->private_data_data); -} - -struct winbindd_child_dispatch_table { - enum winbindd_cmd cmd; - enum winbindd_result (*fn)(struct winbindd_domain *domain, - struct winbindd_cli_state *state); - const char *winbindd_cmd_name; -}; - -static struct winbindd_child_dispatch_table child_dispatch_table[] = { - - { WINBINDD_LOOKUPSID, winbindd_dual_lookupsid, "LOOKUPSID" }, - { WINBINDD_LOOKUPNAME, winbindd_dual_lookupname, "LOOKUPNAME" }, - { WINBINDD_LOOKUPRIDS, winbindd_dual_lookuprids, "LOOKUPRIDS" }, - { WINBINDD_LIST_TRUSTDOM, winbindd_dual_list_trusted_domains, "LIST_TRUSTDOM" }, - { WINBINDD_INIT_CONNECTION, winbindd_dual_init_connection, "INIT_CONNECTION" }, - { WINBINDD_GETDCNAME, winbindd_dual_getdcname, "GETDCNAME" }, - { WINBINDD_SHOW_SEQUENCE, winbindd_dual_show_sequence, "SHOW_SEQUENCE" }, - { WINBINDD_PAM_AUTH, winbindd_dual_pam_auth, "PAM_AUTH" }, - { WINBINDD_PAM_AUTH_CRAP, winbindd_dual_pam_auth_crap, "AUTH_CRAP" }, - { WINBINDD_PAM_LOGOFF, winbindd_dual_pam_logoff, "PAM_LOGOFF" }, - { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP,winbindd_dual_pam_chng_pswd_auth_crap,"CHNG_PSWD_AUTH_CRAP" }, - { WINBINDD_PAM_CHAUTHTOK, winbindd_dual_pam_chauthtok, "PAM_CHAUTHTOK" }, - { WINBINDD_CHECK_MACHACC, winbindd_dual_check_machine_acct, "CHECK_MACHACC" }, - { WINBINDD_DUAL_SID2UID, winbindd_dual_sid2uid, "DUAL_SID2UID" }, - { WINBINDD_DUAL_SID2GID, winbindd_dual_sid2gid, "DUAL_SID2GID" }, -#if 0 /* DISABLED until we fix the interface in Samba 3.0.26 --jerry */ - { WINBINDD_DUAL_SIDS2XIDS, winbindd_dual_sids2xids, "DUAL_SIDS2XIDS" }, -#endif /* end DISABLED */ - { WINBINDD_DUAL_UID2SID, winbindd_dual_uid2sid, "DUAL_UID2SID" }, - { WINBINDD_DUAL_GID2SID, winbindd_dual_gid2sid, "DUAL_GID2SID" }, - { WINBINDD_DUAL_UID2NAME, winbindd_dual_uid2name, "DUAL_UID2NAME" }, - { WINBINDD_DUAL_NAME2UID, winbindd_dual_name2uid, "DUAL_NAME2UID" }, - { WINBINDD_DUAL_GID2NAME, winbindd_dual_gid2name, "DUAL_GID2NAME" }, - { WINBINDD_DUAL_NAME2GID, winbindd_dual_name2gid, "DUAL_NAME2GID" }, - { WINBINDD_DUAL_SET_MAPPING, winbindd_dual_set_mapping, "DUAL_SET_MAPPING" }, - { WINBINDD_DUAL_SET_HWM, winbindd_dual_set_hwm, "DUAL_SET_HWMS" }, - { WINBINDD_DUAL_DUMP_MAPS, winbindd_dual_dump_maps, "DUAL_DUMP_MAPS" }, - { WINBINDD_DUAL_USERINFO, winbindd_dual_userinfo, "DUAL_USERINFO" }, - { WINBINDD_ALLOCATE_UID, winbindd_dual_allocate_uid, "ALLOCATE_UID" }, - { WINBINDD_ALLOCATE_GID, winbindd_dual_allocate_gid, "ALLOCATE_GID" }, - { WINBINDD_GETUSERDOMGROUPS, winbindd_dual_getuserdomgroups, "GETUSERDOMGROUPS" }, - { WINBINDD_DUAL_GETSIDALIASES, winbindd_dual_getsidaliases, "GETSIDALIASES" }, - { WINBINDD_CCACHE_NTLMAUTH, winbindd_dual_ccache_ntlm_auth, "CCACHE_NTLM_AUTH" }, - /* End of list */ - - { WINBINDD_NUM_CMDS, NULL, "NONE" } -}; - -static void child_process_request(struct winbindd_domain *domain, - struct winbindd_cli_state *state) -{ - struct winbindd_child_dispatch_table *table; - - /* Free response data - we may be interrupted and receive another - command before being able to send this data off. */ - - state->response.result = WINBINDD_ERROR; - state->response.length = sizeof(struct winbindd_response); - - state->mem_ctx = talloc_init("winbind request"); - if (state->mem_ctx == NULL) - return; - - /* Process command */ - - for (table = child_dispatch_table; table->fn; table++) { - if (state->request.cmd == table->cmd) { - DEBUG(10,("process_request: request fn %s\n", - table->winbindd_cmd_name )); - state->response.result = table->fn(domain, state); - break; - } - } - - if (!table->fn) { - DEBUG(10,("process_request: unknown request fn number %d\n", - (int)state->request.cmd )); - state->response.result = WINBINDD_ERROR; - } - - talloc_destroy(state->mem_ctx); -} - -void setup_domain_child(struct winbindd_domain *domain, - struct winbindd_child *child, - const char *explicit_logfile) -{ - if (explicit_logfile != NULL) { - pstr_sprintf(child->logfilename, "%s/log.winbindd-%s", - dyn_LOGFILEBASE, explicit_logfile); - } else if (domain != NULL) { - pstr_sprintf(child->logfilename, "%s/log.wb-%s", - dyn_LOGFILEBASE, domain->name); - } else { - smb_panic("Internal error: domain == NULL && " - "explicit_logfile == NULL"); - } - - child->domain = domain; -} - -struct winbindd_child *children = NULL; - -void winbind_child_died(pid_t pid) -{ - struct winbindd_child *child; - - for (child = children; child != NULL; child = child->next) { - if (child->pid == pid) { - break; - } - } - - if (child == NULL) { - DEBUG(5, ("Already reaped child %u died\n", (unsigned int)pid)); - return; - } - - /* This will be re-added in fork_domain_child() */ - - DLIST_REMOVE(children, child); - - remove_fd_event(&child->event); - close(child->event.fd); - child->event.fd = 0; - child->event.flags = 0; - child->pid = 0; - - schedule_async_request(child); -} - -/* Ensure any negative cache entries with the netbios or realm names are removed. */ - -void winbindd_flush_negative_conn_cache(struct winbindd_domain *domain) -{ - flush_negative_conn_cache_for_domain(domain->name); - if (*domain->alt_name) { - flush_negative_conn_cache_for_domain(domain->alt_name); - } -} - -/* Set our domains as offline and forward the offline message to our children. */ - -void winbind_msg_offline(int msg_type, struct process_id src, - void *buf, size_t len, void *private_data) -{ - struct winbindd_child *child; - struct winbindd_domain *domain; - - DEBUG(10,("winbind_msg_offline: got offline message.\n")); - - if (!lp_winbind_offline_logon()) { - DEBUG(10,("winbind_msg_offline: rejecting offline message.\n")); - return; - } - - /* Set our global state as offline. */ - if (!set_global_winbindd_state_offline()) { - DEBUG(10,("winbind_msg_offline: offline request failed.\n")); - return; - } - - /* Set all our domains as offline. */ - for (domain = domain_list(); domain; domain = domain->next) { - if (domain->internal) { - continue; - } - DEBUG(5,("winbind_msg_offline: marking %s offline.\n", domain->name)); - set_domain_offline(domain); - - /* Send an offline message to the idmap child when our - primary domain goes offline */ - - if ( domain->primary ) { - struct winbindd_child *idmap = idmap_child(); - - if ( idmap->pid != 0 ) { - message_send_pid(pid_to_procid(idmap->pid), - MSG_WINBIND_OFFLINE, - domain->name, - strlen(domain->name)+1, - False); - } - } - } - - for (child = children; child != NULL; child = child->next) { - /* Don't send message to idmap child. We've already - done so above. */ - if (!child->domain || (child == idmap_child())) { - continue; - } - - /* Or internal domains (this should not be possible....) */ - if (child->domain->internal) { - continue; - } - - /* Each winbindd child should only process requests for one domain - make sure - we only set it online / offline for that domain. */ - - DEBUG(10,("winbind_msg_offline: sending message to pid %u for domain %s.\n", - (unsigned int)child->pid, domain->name )); - - message_send_pid(pid_to_procid(child->pid), MSG_WINBIND_OFFLINE, child->domain->name, - strlen(child->domain->name)+1, False); - } -} - -/* Set our domains as online and forward the online message to our children. */ - -void winbind_msg_online(int msg_type, struct process_id src, - void *buf, size_t len, void *private_data) -{ - struct winbindd_child *child; - struct winbindd_domain *domain; - - DEBUG(10,("winbind_msg_online: got online message.\n")); - - if (!lp_winbind_offline_logon()) { - DEBUG(10,("winbind_msg_online: rejecting online message.\n")); - return; - } - - /* Set our global state as online. */ - set_global_winbindd_state_online(); - - smb_nscd_flush_user_cache(); - smb_nscd_flush_group_cache(); - - /* Set all our domains as online. */ - for (domain = domain_list(); domain; domain = domain->next) { - if (domain->internal) { - continue; - } - DEBUG(5,("winbind_msg_online: requesting %s to go online.\n", domain->name)); - - winbindd_flush_negative_conn_cache(domain); - set_domain_online_request(domain); - - /* Send an online message to the idmap child when our - primary domain comes back online */ - - if ( domain->primary ) { - struct winbindd_child *idmap = idmap_child(); - - if ( idmap->pid != 0 ) { - message_send_pid(pid_to_procid(idmap->pid), - MSG_WINBIND_ONLINE, - domain->name, - strlen(domain->name)+1, - False); - } - - } - } - - for (child = children; child != NULL; child = child->next) { - /* Don't send message to idmap child. */ - if (!child->domain || (child == idmap_child())) { - continue; - } - - /* Or internal domains (this should not be possible....) */ - if (child->domain->internal) { - continue; - } - - /* Each winbindd child should only process requests for one domain - make sure - we only set it online / offline for that domain. */ - - DEBUG(10,("winbind_msg_online: sending message to pid %u for domain %s.\n", - (unsigned int)child->pid, child->domain->name )); - - message_send_pid(pid_to_procid(child->pid), MSG_WINBIND_ONLINE, child->domain->name, - strlen(child->domain->name)+1, False); - } -} - -/* Forward the online/offline messages to our children. */ -void winbind_msg_onlinestatus(int msg_type, struct process_id src, - void *buf, size_t len, void *private_data) -{ - struct winbindd_child *child; - - DEBUG(10,("winbind_msg_onlinestatus: got onlinestatus message.\n")); - - for (child = children; child != NULL; child = child->next) { - if (child->domain && child->domain->primary) { - DEBUG(10,("winbind_msg_onlinestatus: " - "sending message to pid %u of primary domain.\n", - (unsigned int)child->pid)); - message_send_pid(pid_to_procid(child->pid), - MSG_WINBIND_ONLINESTATUS, buf, len, False); - break; - } - } -} - - -static void account_lockout_policy_handler(struct event_context *ctx, - struct timed_event *te, - const struct timeval *now, - void *private_data) -{ - struct winbindd_child *child = - (struct winbindd_child *)private_data; - TALLOC_CTX *mem_ctx = NULL; - struct winbindd_methods *methods; - SAM_UNK_INFO_12 lockout_policy; - NTSTATUS result; - - DEBUG(10,("account_lockout_policy_handler called\n")); - - TALLOC_FREE(child->lockout_policy_event); - - methods = child->domain->methods; - - mem_ctx = talloc_init("account_lockout_policy_handler ctx"); - if (!mem_ctx) { - result = NT_STATUS_NO_MEMORY; - } else { - result = methods->lockout_policy(child->domain, mem_ctx, &lockout_policy); - } - - talloc_destroy(mem_ctx); - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(10,("account_lockout_policy_handler: lockout_policy failed error %s\n", - nt_errstr(result))); - } - - child->lockout_policy_event = event_add_timed(winbind_event_context(), NULL, - timeval_current_ofs(3600, 0), - "account_lockout_policy_handler", - account_lockout_policy_handler, - child); -} - -/* Deal with a request to go offline. */ - -static void child_msg_offline(int msg_type, struct process_id src, - void *buf, size_t len, void *private_data) -{ - struct winbindd_domain *domain; - const char *domainname = (const char *)buf; - - if (buf == NULL || len == 0) { - return; - } - - DEBUG(5,("child_msg_offline received for domain %s.\n", domainname)); - - if (!lp_winbind_offline_logon()) { - DEBUG(10,("child_msg_offline: rejecting offline message.\n")); - return; - } - - /* Set our global state as offline. */ - if (!set_global_winbindd_state_offline()) { - DEBUG(10,("child_msg_offline: offline request failed.\n")); - return; - } - - /* Mark the requested domain offline. */ - - for (domain = domain_list(); domain; domain = domain->next) { - if (domain->internal) { - continue; - } - if (strequal(domain->name, domainname)) { - DEBUG(5,("child_msg_offline: marking %s offline.\n", domain->name)); - set_domain_offline(domain); - } - } -} - -/* Deal with a request to go online. */ - -static void child_msg_online(int msg_type, struct process_id src, - void *buf, size_t len, void *private_data) -{ - struct winbindd_domain *domain; - const char *domainname = (const char *)buf; - - if (buf == NULL || len == 0) { - return; - } - - DEBUG(5,("child_msg_online received for domain %s.\n", domainname)); - - if (!lp_winbind_offline_logon()) { - DEBUG(10,("child_msg_online: rejecting online message.\n")); - return; - } - - /* Set our global state as online. */ - set_global_winbindd_state_online(); - - /* Try and mark everything online - delete any negative cache entries - to force a reconnect now. */ - - for (domain = domain_list(); domain; domain = domain->next) { - if (domain->internal) { - continue; - } - if (strequal(domain->name, domainname)) { - DEBUG(5,("child_msg_online: requesting %s to go online.\n", domain->name)); - winbindd_flush_negative_conn_cache(domain); - set_domain_online_request(domain); - } - } -} - -static const char *collect_onlinestatus(TALLOC_CTX *mem_ctx) -{ - struct winbindd_domain *domain; - char *buf = NULL; - - if ((buf = talloc_asprintf(mem_ctx, "global:%s ", - get_global_winbindd_state_offline() ? - "Offline":"Online")) == NULL) { - return NULL; - } - - for (domain = domain_list(); domain; domain = domain->next) { - if ((buf = talloc_asprintf_append(buf, "%s:%s ", - domain->name, - domain->online ? - "Online":"Offline")) == NULL) { - return NULL; - } - } - - buf = talloc_asprintf_append(buf, "\n"); - - DEBUG(5,("collect_onlinestatus: %s", buf)); - - return buf; -} - -static void child_msg_onlinestatus(int msg_type, struct process_id src, - void *buf, size_t len, void *private_data) -{ - TALLOC_CTX *mem_ctx; - const char *message; - struct process_id *sender; - - DEBUG(5,("winbind_msg_onlinestatus received.\n")); - - if (!buf) { - return; - } - - sender = (struct process_id *)buf; - - mem_ctx = talloc_init("winbind_msg_onlinestatus"); - if (mem_ctx == NULL) { - return; - } - - message = collect_onlinestatus(mem_ctx); - if (message == NULL) { - talloc_destroy(mem_ctx); - return; - } - - message_send_pid(*sender, MSG_WINBIND_ONLINESTATUS, - message, strlen(message) + 1, True); - - talloc_destroy(mem_ctx); -} - -static BOOL fork_domain_child(struct winbindd_child *child) -{ - int fdpair[2]; - struct winbindd_cli_state state; - struct winbindd_domain *domain; - struct winbindd_domain *primary_domain = NULL; - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) != 0) { - DEBUG(0, ("Could not open child pipe: %s\n", - strerror(errno))); - return False; - } - - ZERO_STRUCT(state); - state.pid = sys_getpid(); - - /* Ensure we don't process messages whilst we're - changing the disposition for the child. */ - message_block(); - - child->pid = sys_fork(); - - if (child->pid == -1) { - DEBUG(0, ("Could not fork: %s\n", strerror(errno))); - message_unblock(); - return False; - } - - if (child->pid != 0) { - /* Parent */ - close(fdpair[0]); - child->next = child->prev = NULL; - DLIST_ADD(children, child); - child->event.fd = fdpair[1]; - child->event.flags = 0; - child->requests = NULL; - add_fd_event(&child->event); - /* We're ok with online/offline messages now. */ - message_unblock(); - return True; - } - - /* Child */ - - /* Stop zombies in children */ - CatchChild(); - - state.sock = fdpair[0]; - close(fdpair[1]); - - /* tdb needs special fork handling */ - if (tdb_reopen_all(1) == -1) { - DEBUG(0,("tdb_reopen_all failed.\n")); - _exit(0); - } - - close_conns_after_fork(); - - if (!override_logfile) { - lp_set_logfile(child->logfilename); - reopen_logs(); - } - - /* Don't handle the same messages as our parent. */ - message_deregister(MSG_SMB_CONF_UPDATED); - message_deregister(MSG_SHUTDOWN); - message_deregister(MSG_WINBIND_OFFLINE); - message_deregister(MSG_WINBIND_ONLINE); - message_deregister(MSG_WINBIND_ONLINESTATUS); - - /* The child is ok with online/offline messages now. */ - message_unblock(); - - /* Handle online/offline messages. */ - message_register(MSG_WINBIND_OFFLINE, child_msg_offline, NULL); - message_register(MSG_WINBIND_ONLINE, child_msg_online, NULL); - message_register(MSG_WINBIND_ONLINESTATUS, child_msg_onlinestatus, - NULL); - - if ( child->domain ) { - child->domain->startup = True; - child->domain->startup_time = time(NULL); - } - - /* Ensure we have no pending check_online events other - than one for this domain or the primary domain. */ - - for (domain = domain_list(); domain; domain = domain->next) { - if (domain->primary) { - primary_domain = domain; - } - if ((domain != child->domain) && !domain->primary) { - TALLOC_FREE(domain->check_online_event); - } - } - - /* Ensure we're not handling an event inherited from - our parent. */ - - cancel_named_event(winbind_event_context(), - "krb5_ticket_refresh_handler"); - - /* We might be in the idmap child...*/ - if (child->domain && !(child->domain->internal) && - lp_winbind_offline_logon()) { - - set_domain_online_request(child->domain); - - if (primary_domain != child->domain) { - /* We need to talk to the primary - * domain as well as the trusted - * domain inside a trusted domain - * child. - * See the code in : - * winbindd_dual_pam_auth_samlogon() - * especially the calling of - * contact_domain = find_our_domain() - * in the non-DC case for details. - */ - set_domain_online_request(primary_domain); - } - - child->lockout_policy_event = event_add_timed( - winbind_event_context(), NULL, timeval_zero(), - "account_lockout_policy_handler", - account_lockout_policy_handler, - child); - } - - while (1) { - - int ret; - fd_set read_fds; - struct timeval t; - struct timeval *tp; - struct timeval now; - - /* free up any talloc memory */ - lp_TALLOC_FREE(); - main_loop_TALLOC_FREE(); - - /* check for signals */ - winbind_check_sigterm(false); - winbind_check_sighup(); - - run_events(winbind_event_context(), 0, NULL, NULL); - - GetTimeOfDay(&now); - - if (child->domain && child->domain->startup && - (now.tv_sec > child->domain->startup_time + 30)) { - /* No longer in "startup" mode. */ - DEBUG(10,("fork_domain_child: domain %s no longer in 'startup' mode.\n", - child->domain->name )); - child->domain->startup = False; - } - - tp = get_timed_events_timeout(winbind_event_context(), &t); - if (tp) { - DEBUG(11,("select will use timeout of %u.%u seconds\n", - (unsigned int)tp->tv_sec, (unsigned int)tp->tv_usec )); - } - - /* Handle messages */ - - message_dispatch(); - - FD_ZERO(&read_fds); - FD_SET(state.sock, &read_fds); - - ret = sys_select(state.sock + 1, &read_fds, NULL, NULL, tp); - - if (ret == 0) { - DEBUG(11,("nothing is ready yet, continue\n")); - continue; - } - - if (ret == -1 && errno == EINTR) { - /* We got a signal - continue. */ - continue; - } - - if (ret == -1 && errno != EINTR) { - DEBUG(0,("select error occured\n")); - perror("select"); - return False; - } - - /* fetch a request from the main daemon */ - child_read_request(&state); - - if (state.finished) { - /* we lost contact with our parent */ - exit(0); - } - - DEBUG(4,("child daemon request %d\n", (int)state.request.cmd)); - - ZERO_STRUCT(state.response); - state.request.null_term = '\0'; - child_process_request(child->domain, &state); - - SAFE_FREE(state.request.extra_data.data); - - cache_store_response(sys_getpid(), &state.response); - - SAFE_FREE(state.response.extra_data.data); - - /* We just send the result code back, the result - * structure needs to be fetched via the - * winbindd_cache. Hmm. That needs fixing... */ - - if (write_data(state.sock, - (const char *)&state.response.result, - sizeof(state.response.result)) != - sizeof(state.response.result)) { - DEBUG(0, ("Could not write result\n")); - exit(1); - } - } -} -- 1.5.2.4 |
|
|
Re: patch to not overwrite wb- logfile names on reloadOn Thu, Jul 17, 2008 at 3:30 PM, Jim McDonough <jmcd@...> wrote:
> In reloading the smb.conf, if a "log file" is specified in smb.conf, > winbind children will overwrite the logfile name to be the same as the > parent. This patch fixes it (though not the prettiest thing). ummm, ignore that first one, i messed up on formatting it. I'll repost. -- Jim McDonough Samba Team jmcd at samba dot org jmcd at themcdonoughs dot org |
|
|
Re: patch to not overwrite wb- logfile names on reloadOn Thu, Jul 17, 2008 at 3:48 PM, Jim McDonough <jmcd@...> wrote:
>> In reloading the smb.conf, if a "log file" is specified in smb.conf, >> winbind children will overwrite the logfile name to be the same as the >> parent. This patch fixes it (though not the prettiest thing). > ummm, ignore that first one, i messed up on formatting it. I'll repost. Here's the real one... -- Jim McDonough Samba Team jmcd at samba dot org jmcd at themcdonoughs dot org [0001-In-the-log-file-case-don-t-overwrite-the.patch] From ba75f24c3b8011aa8040b70150c18980b3addd63 Mon Sep 17 00:00:00 2001 From: Jim McDonough <jmcd@...> Date: Thu, 17 Jul 2008 15:54:13 -0400 Subject: [PATCH] In the "log file = " case, don't overwrite the log.wb-<domain> logfile name on smb.conf reload. --- source/nsswitch/winbindd.c | 17 +++++++++++------ source/nsswitch/winbindd_dual.c | 3 ++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c index c79bb46..9cf4bea 100644 --- a/source/nsswitch/winbindd.c +++ b/source/nsswitch/winbindd.c @@ -46,7 +46,7 @@ struct event_context *winbind_event_context(void) /* Reload configuration */ -static BOOL reload_services_file(void) +static BOOL reload_services_file(const char *logfile) { BOOL ret; @@ -62,6 +62,11 @@ static BOOL reload_services_file(void) reopen_logs(); ret = lp_load(dyn_CONFIGFILE,False,False,True,True); + /* if this is a child, restore the logfile to the special + name - <domain>, idmap, etc. */ + if (logfile && *logfile) + lp_set_logfile(logfile); + reopen_logs(); load_interfaces(); @@ -188,7 +193,7 @@ static void msg_reload_services(int msg_type, struct process_id src, { /* Flush various caches */ flush_caches(); - reload_services_file(); + reload_services_file((const char *) private_data); } /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/ @@ -726,13 +731,13 @@ static BOOL remove_idle_client(void) } /* check if HUP has been received and reload files */ -void winbind_check_sighup(void) +void winbind_check_sighup(const char *logfile) { if (do_sighup) { DEBUG(3, ("got SIGHUP\n")); - msg_reload_services(MSG_SMB_CONF_UPDATED, pid_to_procid(0), NULL, 0, NULL); + msg_reload_services(MSG_SMB_CONF_UPDATED, pid_to_procid(0), NULL, 0, logfile); do_sighup = False; } } @@ -909,7 +914,7 @@ static void process_loop(void) /* Check signal handling things */ winbind_check_sigterm(true); - winbind_check_sighup(); + winbind_check_sighup(NULL); if (do_sigusr2) { print_winbindd_status(); @@ -1007,7 +1012,7 @@ int main(int argc, char **argv, char **envp) SAMBA_VERSION_STRING, COPYRIGHT_STARTUP_MESSAGE) ); - if (!reload_services_file()) { + if (!reload_services_file(NULL)) { DEBUG(0, ("error opening config file\n")); exit(1); } diff --git a/source/nsswitch/winbindd_dual.c b/source/nsswitch/winbindd_dual.c index 5ba68d6..40ebf54 100644 --- a/source/nsswitch/winbindd_dual.c +++ b/source/nsswitch/winbindd_dual.c @@ -1024,7 +1024,8 @@ static BOOL fork_domain_child(struct winbindd_child *child) /* check for signals */ winbind_check_sigterm(false); - winbind_check_sighup(); + winbind_check_sighup(override_logfile ? NULL : + child->logfilename); run_events(winbind_event_context(), 0, NULL, NULL); -- 1.5.2.4 |
|
|
Re: patch to not overwrite wb- logfile names on reloadOn Thu, Jul 17, 2008 at 03:55:08PM -0400, Jim McDonough wrote:
> On Thu, Jul 17, 2008 at 3:48 PM, Jim McDonough <jmcd@...> wrote: > >> In reloading the smb.conf, if a "log file" is specified in smb.conf, > >> winbind children will overwrite the logfile name to be the same as the > >> parent. This patch fixes it (though not the prettiest thing). > > ummm, ignore that first one, i messed up on formatting it. I'll repost. > Here's the real one... Uses Samba 3.0.x pathnames (nsswitch/*.c) instead of Samba 3.2/3.3 names (winbindd/*.c). Can you port to 3.x please and then I'll apply (LGTM). Jeremy. |
|
|
Re: patch to not overwrite wb- logfile names on reloadOn Thu, Jul 17, 2008 at 07:40:48PM -0700, Jeremy Allison wrote:
> On Thu, Jul 17, 2008 at 03:55:08PM -0400, Jim McDonough wrote: > > On Thu, Jul 17, 2008 at 3:48 PM, Jim McDonough <jmcd@...> wrote: > > >> In reloading the smb.conf, if a "log file" is specified in smb.conf, > > >> winbind children will overwrite the logfile name to be the same as the > > >> parent. This patch fixes it (though not the prettiest thing). > > > ummm, ignore that first one, i messed up on formatting it. I'll repost. > > Here's the real one... > > Uses Samba 3.0.x pathnames (nsswitch/*.c) instead > of Samba 3.2/3.3 names (winbindd/*.c). Can you > port to 3.x please and then I'll apply (LGTM). Never mind, did it myself whilst waiting for (delayed) plane. Bloody United :-). Good patch though, thanks ! Jeremy. |
|
|
Re: patch to not overwrite wb- logfile names on reloadsamba-technical-bounces+bmarsh=us.ibm.com@... wrote on
07/17/2008 09:59:04 PM: > On Thu, Jul 17, 2008 at 07:40:48PM -0700, Jeremy Allison wrote: > > On Thu, Jul 17, 2008 at 03:55:08PM -0400, Jim McDonough wrote: > > > On Thu, Jul 17, 2008 at 3:48 PM, Jim McDonough <jmcd@...> wrote: > > > >> In reloading the smb.conf, if a "log file" is specified in smb.conf, > > > >> winbind children will overwrite the logfile name to be the same as the > > > >> parent. This patch fixes it (though not the prettiest thing). > > > > ummm, ignore that first one, i messed up on formatting it. I'll repost. > > > Here's the real one... > > > > Uses Samba 3.0.x pathnames (nsswitch/*.c) instead > > of Samba 3.2/3.3 names (winbindd/*.c). Can you > > port to 3.x please and then I'll apply (LGTM). The other thing we noticed while testing in this area is that the winbind parent will follow the log file parm in the smb.conf, but the children do not. If you set log file = /tmp/log.%m, log.winbind will go into /tmp and (on a SLES build) the wb-files are still in /var/log/samba. If you use winbindd -l /tmp, lsof shows all the processes are writing to /tmp/log.winbindd. There are no wb-files. Bill Marshall |
| Free Forum Powered by Nabble | Forum Help |