*/
#include "includes.h"
-#include "popt_common.h"
+#include "lib/cmdline/cmdline.h"
#include "winbindd.h"
#include "nsswitch/winbind_client.h"
#include "nsswitch/wb_reqtrans.h"
#include "ntdomain.h"
-#include "../librpc/gen_ndr/srv_lsa.h"
-#include "../librpc/gen_ndr/srv_samr.h"
+#include "librpc/rpc/dcesrv_core.h"
+#include "librpc/gen_ndr/ndr_lsa_scompat.h"
+#include "librpc/gen_ndr/ndr_samr_scompat.h"
+#include "librpc/gen_ndr/ndr_winbind_scompat.h"
#include "secrets.h"
#include "rpc_client/cli_netlogon.h"
#include "idmap.h"
#include "lib/addrchange.h"
-#include "serverid.h"
#include "auth.h"
#include "messages.h"
#include "../lib/util/pidfile.h"
#include "lib/param/param.h"
#include "lib/async_req/async_sock.h"
#include "libsmb/samlogon_cache.h"
+#include "libcli/auth/netlogon_creds_cli.h"
+#include "passdb.h"
+#include "lib/util/tevent_req_profile.h"
+#include "lib/gencache.h"
+#include "rpc_server/rpc_config.h"
+#include "lib/global_contexts.h"
+#include "source3/lib/substitute.h"
+#include "winbindd_traceid.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
static bool client_is_idle(struct winbindd_cli_state *state);
static void remove_client(struct winbindd_cli_state *state);
-static void winbindd_setup_max_fds(void);
-static bool opt_nocache = False;
static bool interactive = False;
-extern bool override_logfile;
-
-struct tevent_context *winbind_event_context(void)
-{
- static struct tevent_context *ev = NULL;
-
- if (ev != NULL) {
- return ev;
- }
-
- /*
- * Note we MUST use the NULL context here, not the autofree context,
- * to avoid side effects in forked children exiting.
- */
- ev = samba_tevent_context_init(NULL);
- if (ev == NULL) {
- smb_panic("Could not init winbindd's messaging context.\n");
- }
- return ev;
-}
-
-struct messaging_context *winbind_messaging_context(void)
-{
- static struct messaging_context *msg = NULL;
-
- if (msg != NULL) {
- return msg;
- }
-
- /*
- * Note we MUST use the NULL context here, not the autofree context,
- * to avoid side effects in forked children exiting.
- */
- msg = messaging_init(NULL, winbind_event_context());
- if (msg == NULL) {
- smb_panic("Could not init winbindd's messaging context.\n");
- }
- return msg;
-}
-
-struct imessaging_context *winbind_imessaging_context(void)
-{
- static struct imessaging_context *msg = NULL;
- struct messaging_context *msg_ctx;
- struct server_id myself;
- struct loadparm_context *lp_ctx;
-
- if (msg != NULL) {
- return msg;
- }
-
- msg_ctx = server_messaging_context();
- if (msg_ctx == NULL) {
- smb_panic("server_messaging_context failed\n");
- }
- myself = messaging_server_id(msg_ctx);
-
- lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
- if (lp_ctx == NULL) {
- smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
- }
-
- /*
- * Note we MUST use the NULL context here, not the autofree context,
- * to avoid side effects in forked children exiting.
- */
- msg = imessaging_init(NULL, lp_ctx, myself, winbind_event_context());
- talloc_unlink(NULL, lp_ctx);
-
- if (msg == NULL) {
- smb_panic("Could not init winbindd's messaging context.\n");
- }
- return msg;
-}
-
/* Reload configuration */
-static bool reload_services_file(const char *lfile)
-{
- bool ret;
-
- if (lp_loaded()) {
- char *fname = lp_next_configfile(talloc_tos());
-
- if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
- set_dyn_CONFIGFILE(fname);
- }
- TALLOC_FREE(fname);
- }
-
- /* if this is a child, restore the logfile to the special
- name - <domain>, idmap, etc. */
- if (lfile && *lfile) {
- lp_set_logfile(lfile);
- }
-
- reopen_logs();
- ret = lp_load_global(get_dyn_CONFIGFILE());
-
- reopen_logs();
- load_interfaces();
- winbindd_setup_max_fds();
-
- return(ret);
-}
static void winbindd_status(void)
}
}
-/* 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. */
-
- if (!wcache_invalidate_cache()) {
- DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
- if (!winbindd_cache_validate_and_initialize()) {
- exit(1);
- }
- }
-}
-
-static void flush_caches_noinit(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.
- * NB
- * Skip uninitialized domains when flush cache.
- * If domain is not initialized, it means it is never
- * used or never become online. look, wcache_invalidate_cache()
- * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
- * for unused domains and large traffic for primay domain's DC if there
- * are many domains..
- */
-
- if (!wcache_invalidate_cache_noinit()) {
- DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
- if (!winbindd_cache_validate_and_initialize()) {
- exit(1);
- }
- }
-}
-
-/* Handle the signal by unlinking socket and exiting */
-
-static void terminate(bool is_parent)
-{
- if (is_parent) {
- /* When parent goes away we should
- * remove the socket file. Not so
- * when children terminate.
- */
- char *path = NULL;
-
- if (asprintf(&path, "%s/%s",
- lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
- unlink(path);
- SAFE_FREE(path);
- }
- }
-
- idmap_close();
-
- gencache_stabilize();
-
-#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
-
- if (is_parent) {
- struct messaging_context *msg = winbind_messaging_context();
- struct server_id self = messaging_server_id(msg);
- serverid_deregister(self);
- pidfile_unlink(lp_pid_directory(), "winbindd");
- }
-
- exit(0);
-}
-
-static void winbindd_sig_term_handler(struct tevent_context *ev,
- struct tevent_signal *se,
- int signum,
- int count,
- void *siginfo,
- void *private_data)
-{
- bool *is_parent = talloc_get_type_abort(private_data, bool);
-
- DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
- signum, (int)*is_parent));
- terminate(*is_parent);
-}
-
/*
handle stdin becoming readable when we are in --foreground mode
*/
parent has exited. Shutdown the server */
DEBUG(0,("EOF on stdin (is_parent=%d)\n",
(int)*is_parent));
- terminate(*is_parent);
- }
-}
-
-bool winbindd_setup_sig_term_handler(bool parent)
-{
- struct tevent_signal *se;
- bool *is_parent;
-
- is_parent = talloc(winbind_event_context(), bool);
- if (!is_parent) {
- return false;
- }
-
- *is_parent = parent;
-
- se = tevent_add_signal(winbind_event_context(),
- is_parent,
- SIGTERM, 0,
- winbindd_sig_term_handler,
- is_parent);
- if (!se) {
- DEBUG(0,("failed to setup SIGTERM handler"));
- talloc_free(is_parent);
- return false;
- }
-
- se = tevent_add_signal(winbind_event_context(),
- is_parent,
- SIGINT, 0,
- winbindd_sig_term_handler,
- is_parent);
- if (!se) {
- DEBUG(0,("failed to setup SIGINT handler"));
- talloc_free(is_parent);
- return false;
- }
-
- se = tevent_add_signal(winbind_event_context(),
- is_parent,
- SIGQUIT, 0,
- winbindd_sig_term_handler,
- is_parent);
- if (!se) {
- DEBUG(0,("failed to setup SIGINT handler"));
- talloc_free(is_parent);
- return false;
+ winbindd_terminate(*is_parent);
}
-
- return true;
}
bool winbindd_setup_stdin_handler(bool parent, bool foreground)
if (foreground) {
struct stat st;
- is_parent = talloc(winbind_event_context(), bool);
+ is_parent = talloc(global_event_context(), bool);
if (!is_parent) {
return false;
}
return false;
}
if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
- tevent_add_fd(winbind_event_context(),
+ tevent_add_fd(global_event_context(),
is_parent,
0,
TEVENT_FD_READ,
return true;
}
-static void winbindd_sig_hup_handler(struct tevent_context *ev,
- struct tevent_signal *se,
- int signum,
- int count,
- void *siginfo,
- void *private_data)
-{
- const char *file = (const char *)private_data;
-
- DEBUG(1,("Reloading services after SIGHUP\n"));
- flush_caches_noinit();
- reload_services_file(file);
-}
-
-bool winbindd_setup_sig_hup_handler(const char *lfile)
-{
- struct tevent_signal *se;
- char *file = NULL;
-
- if (lfile) {
- file = talloc_strdup(winbind_event_context(),
- lfile);
- if (!file) {
- return false;
- }
- }
-
- se = tevent_add_signal(winbind_event_context(),
- winbind_event_context(),
- SIGHUP, 0,
- winbindd_sig_hup_handler,
- file);
- if (!se) {
- return false;
- }
-
- return true;
-}
-
static void winbindd_sig_chld_handler(struct tevent_context *ev,
struct tevent_signal *se,
int signum,
{
struct tevent_signal *se;
- se = tevent_add_signal(winbind_event_context(),
- winbind_event_context(),
+ se = tevent_add_signal(global_event_context(),
+ global_event_context(),
SIGCHLD, 0,
winbindd_sig_chld_handler,
NULL);
{
struct tevent_signal *se;
- se = tevent_add_signal(winbind_event_context(),
- winbind_event_context(),
+ se = tevent_add_signal(global_event_context(),
+ global_event_context(),
SIGUSR2, 0,
winbindd_sig_usr2_handler,
NULL);
return true;
}
-/* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
-static void msg_reload_services(struct messaging_context *msg,
- void *private_data,
- uint32_t msg_type,
- struct server_id server_id,
- DATA_BLOB *data)
-{
- /* Flush various caches */
- flush_caches();
- reload_services_file((const char *) private_data);
-}
-
/* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
static void msg_shutdown(struct messaging_context *msg,
void *private_data,
{
/* only the parent waits for this message */
DEBUG(0,("Got shutdown message\n"));
- terminate(true);
+ winbindd_terminate(true);
}
/* install default SIGCHLD handler: validation code uses fork/waitpid */
CatchSignal(SIGCHLD, SIG_DFL);
+ setproctitle("validate cache child");
+
ret = (uint8_t)winbindd_validate_cache_nobackup();
DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
_exit(0);
}
-static struct winbindd_dispatch_table {
+static struct winbindd_bool_dispatch_table {
enum winbindd_cmd cmd;
- void (*fn)(struct winbindd_cli_state *state);
- const char *winbindd_cmd_name;
-} dispatch_table[] = {
-
- /* Enumeration functions */
-
- { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
- "LIST_TRUSTDOM" },
-
- /* Miscellaneous */
-
- { WINBINDD_INFO, winbindd_info, "INFO" },
- { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
+ bool (*fn)(struct winbindd_cli_state *state);
+ const char *cmd_name;
+} bool_dispatch_table[] = {
+ { 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_DC_INFO, winbindd_dc_info, "DC_INFO" },
- { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
- { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
+ { WINBINDD_INFO,
+ winbindd_info,
+ "INFO" },
+ { WINBINDD_PING,
+ winbindd_ping,
+ "PING" },
+ { WINBINDD_DOMAIN_NAME,
+ winbindd_domain_name,
+ "DOMAIN_NAME" },
+ { WINBINDD_NETBIOS_NAME,
+ winbindd_netbios_name,
+ "NETBIOS_NAME" },
+ { WINBINDD_DC_INFO,
+ winbindd_dc_info,
+ "DC_INFO" },
+ { WINBINDD_CCACHE_NTLMAUTH,
+ winbindd_ccache_ntlm_auth,
+ "NTLMAUTH" },
+ { WINBINDD_CCACHE_SAVE,
+ winbindd_ccache_save,
+ "CCACHE_SAVE" },
+ { WINBINDD_PRIV_PIPE_DIR,
+ winbindd_priv_pipe_dir,
"WINBINDD_PRIV_PIPE_DIR" },
-
- /* Credential cache access */
- { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
- { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
-
- /* End of list */
-
- { WINBINDD_NUM_CMDS, NULL, "NONE" }
+ { WINBINDD_LIST_TRUSTDOM,
+ winbindd_list_trusted_domains,
+ "LIST_TRUSTDOM" },
};
struct winbindd_async_dispatch_table {
};
static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
- { WINBINDD_PING, "PING",
- wb_ping_send, wb_ping_recv },
{ WINBINDD_LOOKUPSID, "LOOKUPSID",
winbindd_lookupsid_send, winbindd_lookupsid_recv },
{ WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
winbindd_wins_byip_send, winbindd_wins_byip_recv },
{ WINBINDD_WINS_BYNAME, "WINS_BYNAME",
winbindd_wins_byname_send, winbindd_wins_byname_recv },
+ { WINBINDD_DOMAIN_INFO, "DOMAIN_INFO",
+ winbindd_domain_info_send, winbindd_domain_info_recv },
{ 0, NULL, NULL, NULL }
};
{ 0, NULL, NULL, NULL }
};
-static void wb_request_done(struct tevent_req *req);
+struct process_request_state {
+ struct winbindd_cli_state *cli_state;
+ struct tevent_context *ev;
+};
+
+static void process_request_done(struct tevent_req *subreq);
+static void process_request_written(struct tevent_req *subreq);
-static void process_request(struct winbindd_cli_state *state)
+static struct tevent_req *process_request_send(
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_cli_state *cli_state)
{
- struct winbindd_dispatch_table *table = dispatch_table;
+ struct tevent_req *req, *subreq;
+ struct process_request_state *state;
struct winbindd_async_dispatch_table *atable;
+ enum winbindd_cmd cmd = cli_state->request->cmd;
+ size_t i;
+ bool ok;
+ static uint64_t request_index = 1;
- state->mem_ctx = talloc_named(state, 0, "winbind request");
- if (state->mem_ctx == NULL)
- return;
+ /*
+ * debug traceid values:
+ * 0 .. inactive
+ * 1 .. not processing a winbind request, but in other code (timers)
+ * >=2 .. winbind request processing
+ */
+ if (debug_traceid_get() != 0) {
+ request_index = ++request_index == 0 ? 2 : request_index;
+ debug_traceid_set(request_index);
+ }
+ req = tevent_req_create(mem_ctx, &state,
+ struct process_request_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->cli_state = cli_state;
+ state->ev = ev;
+
+ ok = tevent_req_set_profile(req);
+ if (!ok) {
+ return tevent_req_post(req, ev);
+ }
+
+ SMB_ASSERT(cli_state->mem_ctx == NULL);
+ cli_state->mem_ctx = talloc_named(cli_state, 0, "winbind request");
+ if (tevent_req_nomem(cli_state->mem_ctx, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ cli_state->response = talloc_zero(
+ cli_state->mem_ctx,
+ struct winbindd_response);
+ if (tevent_req_nomem(cli_state->response, req)) {
+ return tevent_req_post(req, ev);
+ }
+ cli_state->response->result = WINBINDD_PENDING;
+ cli_state->response->length = sizeof(struct winbindd_response);
/* Remember who asked us. */
- state->pid = state->request->pid;
+ cli_state->pid = cli_state->request->pid;
+ memcpy(cli_state->client_name,
+ cli_state->request->client_name,
+ sizeof(cli_state->client_name));
- state->cmd_name = "unknown request";
- state->recv_fn = NULL;
- /* client is newest */
- winbindd_promote_client(state);
+ cli_state->cmd_name = "unknown request";
+ cli_state->recv_fn = NULL;
- /* Process command */
+ /* client is newest */
+ winbindd_promote_client(cli_state);
for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
- if (state->request->cmd == atable->cmd) {
+ if (cmd == atable->cmd) {
break;
}
}
- if ((atable->send_req == NULL) && state->privileged) {
+ if ((atable->send_req == NULL) && cli_state->privileged) {
for (atable = async_priv_table; atable->send_req;
atable += 1) {
- if (state->request->cmd == atable->cmd) {
+ if (cmd == atable->cmd) {
break;
}
}
}
if (atable->send_req != NULL) {
- struct tevent_req *req;
-
- state->cmd_name = atable->cmd_name;
- state->recv_fn = atable->recv_req;
-
- DEBUG(10, ("process_request: Handling async request %d:%s\n",
- (int)state->pid, state->cmd_name));
-
- req = atable->send_req(state->mem_ctx, winbind_event_context(),
- state, state->request);
- if (req == NULL) {
- DEBUG(0, ("process_request: atable->send failed for "
- "%s\n", atable->cmd_name));
- request_error(state);
- return;
+ cli_state->cmd_name = atable->cmd_name;
+ cli_state->recv_fn = atable->recv_req;
+
+ DBG_DEBUG("process_request: "
+ "Handling async request %s(%d):%s\n",
+ cli_state->client_name,
+ (int)cli_state->pid,
+ cli_state->cmd_name);
+
+ subreq = atable->send_req(
+ state,
+ state->ev,
+ cli_state,
+ cli_state->request);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
- tevent_req_set_callback(req, wb_request_done, state);
- return;
+ tevent_req_set_callback(subreq, process_request_done, req);
+ return req;
}
- state->response = talloc_zero(state->mem_ctx,
- struct winbindd_response);
- if (state->response == NULL) {
- DEBUG(10, ("talloc failed\n"));
- remove_client(state);
- return;
- }
- state->response->result = WINBINDD_PENDING;
- state->response->length = sizeof(struct winbindd_response);
-
- 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 ));
- state->cmd_name = table->winbindd_cmd_name;
- table->fn(state);
+ for (i=0; i<ARRAY_SIZE(bool_dispatch_table); i++) {
+ if (cmd == bool_dispatch_table[i].cmd) {
break;
}
}
- if (!table->fn) {
- DEBUG(10,("process_request: unknown request fn number %d\n",
- (int)state->request->cmd ));
- request_error(state);
- }
-}
+ ok = false;
-static void wb_request_done(struct tevent_req *req)
-{
- struct winbindd_cli_state *state = tevent_req_callback_data(
- req, struct winbindd_cli_state);
- NTSTATUS status;
+ if (i < ARRAY_SIZE(bool_dispatch_table)) {
+ cli_state->cmd_name = bool_dispatch_table[i].cmd_name;
- state->response = talloc_zero(state->mem_ctx,
- struct winbindd_response);
- if (state->response == NULL) {
- DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
- (int)state->pid, state->cmd_name));
- remove_client(state);
- return;
+ DBG_DEBUG("process_request: request fn %s\n",
+ bool_dispatch_table[i].cmd_name);
+ ok = bool_dispatch_table[i].fn(cli_state);
}
- state->response->result = WINBINDD_PENDING;
- state->response->length = sizeof(struct winbindd_response);
- status = state->recv_fn(req, state->response);
- TALLOC_FREE(req);
+ cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
- DEBUG(10,("wb_request_done[%d:%s]: %s\n",
- (int)state->pid, state->cmd_name, nt_errstr(status)));
+ TALLOC_FREE(cli_state->io_req);
+ TALLOC_FREE(cli_state->request);
- if (!NT_STATUS_IS_OK(status)) {
- request_error(state);
- return;
+ subreq = wb_resp_write_send(
+ state,
+ state->ev,
+ cli_state->out_queue,
+ cli_state->sock,
+ cli_state->response);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
- request_ok(state);
-}
+ tevent_req_set_callback(subreq, process_request_written, req);
-/*
- * 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_finished(struct winbindd_cli_state *state);
+ cli_state->io_req = subreq;
-static void winbind_client_request_read(struct tevent_req *req);
-static void winbind_client_response_written(struct tevent_req *req);
-static void winbind_client_activity(struct tevent_req *req);
+ return req;
+}
-static void request_finished(struct winbindd_cli_state *state)
+static void process_request_done(struct tevent_req *subreq)
{
- struct tevent_req *req;
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct process_request_state *state = tevent_req_data(
+ req, struct process_request_state);
+ struct winbindd_cli_state *cli_state = state->cli_state;
+ NTSTATUS status;
+ bool ok;
- /* free client socket monitoring request */
- TALLOC_FREE(state->io_req);
+ status = cli_state->recv_fn(subreq, cli_state->response);
+ TALLOC_FREE(subreq);
- TALLOC_FREE(state->request);
+ DBG_DEBUG("[%s(%d):%s]: %s\n",
+ cli_state->client_name,
+ (int)cli_state->pid,
+ cli_state->cmd_name,
+ nt_errstr(status));
- req = wb_resp_write_send(state, winbind_event_context(),
- state->out_queue, state->sock,
- state->response);
- if (req == NULL) {
- DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
- (int)state->pid, state->cmd_name));
- remove_client(state);
+ ok = NT_STATUS_IS_OK(status);
+ cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
+
+ TALLOC_FREE(cli_state->io_req);
+ TALLOC_FREE(cli_state->request);
+
+ subreq = wb_resp_write_send(
+ state,
+ state->ev,
+ cli_state->out_queue,
+ cli_state->sock,
+ cli_state->response);
+ if (tevent_req_nomem(subreq, req)) {
return;
}
- tevent_req_set_callback(req, winbind_client_response_written, state);
- state->io_req = req;
+ tevent_req_set_callback(subreq, process_request_written, req);
+
+ cli_state->io_req = subreq;
}
-static void winbind_client_response_written(struct tevent_req *req)
+static void process_request_written(struct tevent_req *subreq)
{
- struct winbindd_cli_state *state = tevent_req_callback_data(
- req, struct winbindd_cli_state);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct process_request_state *state = tevent_req_data(
+ req, struct process_request_state);
+ struct winbindd_cli_state *cli_state = state->cli_state;
ssize_t ret;
int err;
- state->io_req = NULL;
+ cli_state->io_req = NULL;
- ret = wb_resp_write_recv(req, &err);
- TALLOC_FREE(req);
+ ret = wb_resp_write_recv(subreq, &err);
+ TALLOC_FREE(subreq);
if (ret == -1) {
- close(state->sock);
- state->sock = -1;
- DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
- (int)state->pid, state->cmd_name, strerror(err)));
- remove_client(state);
+ tevent_req_nterror(req, map_nt_error_from_unix(err));
return;
}
- DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
- "to client\n", (int)state->pid, state->cmd_name));
+ DBG_DEBUG("[%s(%d):%s]: delivered response to client\n",
+ cli_state->client_name,
+ (int)cli_state->pid,
+ cli_state->cmd_name);
- TALLOC_FREE(state->mem_ctx);
- state->response = NULL;
- state->cmd_name = "no request";
- state->recv_fn = NULL;
+ TALLOC_FREE(cli_state->mem_ctx);
+ cli_state->response = NULL;
+ cli_state->cmd_name = "no request";
+ cli_state->recv_fn = NULL;
- req = wb_req_read_send(state, winbind_event_context(), state->sock,
- WINBINDD_MAX_EXTRA_DATA);
- if (req == NULL) {
- remove_client(state);
- return;
- }
- tevent_req_set_callback(req, winbind_client_request_read, state);
- state->io_req = req;
+ tevent_req_done(req);
}
-void request_error(struct winbindd_cli_state *state)
+static NTSTATUS process_request_recv(
+ struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ struct tevent_req_profile **profile)
{
- SMB_ASSERT(state->response->result == WINBINDD_PENDING);
- state->response->result = WINBINDD_ERROR;
- request_finished(state);
-}
+ NTSTATUS status;
-void request_ok(struct winbindd_cli_state *state)
-{
- SMB_ASSERT(state->response->result == WINBINDD_PENDING);
- state->response->result = WINBINDD_OK;
- request_finished(state);
+ if (tevent_req_is_nterror(req, &status)) {
+ tevent_req_received(req);
+ return status;
+ }
+
+ *profile = tevent_req_move_profile(req, mem_ctx);
+ tevent_req_received(req);
+ return NT_STATUS_OK;
}
+/*
+ * 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 winbind_client_request_read(struct tevent_req *req);
+static void winbind_client_activity(struct tevent_req *req);
+static void winbind_client_processed(struct tevent_req *req);
+
/* Process a new connection by adding it to the client connection list */
static void new_connection(int listen_sock, bool privileged)
}
return;
}
+ smb_set_close_on_exec(sock);
DEBUG(6,("accepted socket %d\n", sock));
state->privileged = privileged;
- req = wb_req_read_send(state, winbind_event_context(), state->sock,
+ req = wb_req_read_send(state, global_event_context(), state->sock,
WINBINDD_MAX_EXTRA_DATA);
if (req == NULL) {
TALLOC_FREE(state);
return;
}
- req = wait_for_read_send(state, winbind_event_context(), state->sock,
+ req = wait_for_read_send(state, global_event_context(), state->sock,
true);
if (req == NULL) {
DEBUG(0, ("winbind_client_request_read[%d:%s]:"
tevent_req_set_callback(req, winbind_client_activity, state);
state->io_req = req;
- process_request(state);
+ req = process_request_send(state, global_event_context(), state);
+ if (req == NULL) {
+ DBG_ERR("process_request_send failed\n");
+ remove_client(state);
+ return;
+ }
+ tevent_req_set_callback(req, winbind_client_processed, state);
}
static void winbind_client_activity(struct tevent_req *req)
remove_client(state);
}
+static void winbind_client_processed(struct tevent_req *req)
+{
+ struct winbindd_cli_state *cli_state = tevent_req_callback_data(
+ req, struct winbindd_cli_state);
+ struct tevent_req_profile *profile = NULL;
+ struct timeval start, stop, diff;
+ int threshold;
+ NTSTATUS status;
+
+ status = process_request_recv(req, cli_state, &profile);
+ TALLOC_FREE(req);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("process_request failed: %s\n", nt_errstr(status));
+ remove_client(cli_state);
+ return;
+ }
+
+ tevent_req_profile_get_start(profile, NULL, &start);
+ tevent_req_profile_get_stop(profile, NULL, &stop);
+ diff = tevent_timeval_until(&start, &stop);
+
+ threshold = lp_parm_int(-1, "winbind", "request profile threshold", 60);
+
+ if (diff.tv_sec >= threshold) {
+ int depth;
+ char *str;
+
+ depth = lp_parm_int(
+ -1,
+ "winbind",
+ "request profile depth",
+ INT_MAX);
+
+ DBG_ERR("request took %u.%.6u seconds\n",
+ (unsigned)diff.tv_sec, (unsigned)diff.tv_usec);
+
+ str = tevent_req_profile_string(
+ talloc_tos(), profile, 0, depth);
+ if (str != NULL) {
+ /* No "\n", already contained in "str" */
+ DEBUGADD(0, ("%s", str));
+ }
+ TALLOC_FREE(str);
+ }
+
+ TALLOC_FREE(profile);
+
+ req = wb_req_read_send(
+ cli_state,
+ global_event_context(),
+ cli_state->sock,
+ WINBINDD_MAX_EXTRA_DATA);
+ if (req == NULL) {
+ remove_client(cli_state);
+ return;
+ }
+ tevent_req_set_callback(req, winbind_client_request_read, cli_state);
+ cli_state->io_req = req;
+}
+
/* Remove a client connection from client connection list */
static void remove_client(struct winbindd_cli_state *state)
{
- char c = 0;
- int nwritten;
-
/* It's a dead client - hold a funeral */
if (state == NULL) {
* before closing the fd.
*
* Otherwise we might hit a race with close_conns_after_fork() (via
- * winbindd_reinit_after_fork()) where a file description
+ * winbindd_reinit_after_fork()) where a file descriptor
* is still open in a child, which means it's still active in
* the parents epoll queue, but the related tevent_fd is already
* already gone in the parent.
TALLOC_FREE(state->io_req);
if (state->sock != -1) {
+ char c = 0;
+ int nwritten;
+
/* tell client, we are closing ... */
nwritten = write(state->sock, &c, sizeof(c));
if (nwritten == -1) {
prev = winbindd_client_list_prev(state);
expiry_time = state->last_access + timeout_val;
- if (curr_time > expiry_time) {
- if (client_is_idle(state)) {
- DEBUG(5,("Idle client timed out, "
- "shutting down sock %d, pid %u\n",
- state->sock,
- (unsigned int)state->pid));
- } else {
- DEBUG(5,("Client request timed out, "
- "shutting down sock %d, pid %u\n",
- state->sock,
- (unsigned int)state->pid));
- }
- remove_client(state);
- } else {
+ if (curr_time <= expiry_time) {
/* list is sorted, previous clients in
list are newer */
break;
}
+
+ if (client_is_idle(state)) {
+ DEBUG(5,("Idle client timed out, "
+ "shutting down sock %d, pid %u\n",
+ state->sock,
+ (unsigned int)state->pid));
+ } else {
+ DEBUG(5,("Client request timed out, "
+ "shutting down sock %d, pid %u\n",
+ state->sock,
+ (unsigned int)state->pid));
+ }
+
+ remove_client(state);
}
}
* Winbindd socket accessor functions
*/
-char *get_winbind_priv_pipe_dir(void)
-{
- return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
-}
-
-static void winbindd_setup_max_fds(void)
-{
- int num_fds = MAX_OPEN_FUDGEFACTOR;
- int actual_fds;
-
- num_fds += lp_winbind_max_clients();
- /* Add some more to account for 2 sockets open
- when the client transitions from unprivileged
- to privileged socket
- */
- num_fds += lp_winbind_max_clients() / 10;
-
- /* Add one socket per child process
- (yeah there are child processes other than the
- domain children but only domain children can vary
- with configuration
- */
- num_fds += lp_winbind_max_domain_connections() *
- (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
-
- actual_fds = set_maxfiles(num_fds);
-
- if (actual_fds < num_fds) {
- DEBUG(1, ("winbindd_setup_max_fds: Information only: "
- "requested %d open files, %d are available.\n",
- num_fds, actual_fds));
- }
-}
-
static bool winbindd_setup_listeners(void)
{
struct winbindd_listen_state *pub_state = NULL;
int rc;
char *socket_path;
- pub_state = talloc(winbind_event_context(),
+ pub_state = talloc(global_event_context(),
struct winbindd_listen_state);
if (!pub_state) {
goto failed;
goto failed;
}
- fde = tevent_add_fd(winbind_event_context(), pub_state, pub_state->fd,
+ fde = tevent_add_fd(global_event_context(), pub_state, pub_state->fd,
TEVENT_FD_READ, winbindd_listen_fde_handler,
pub_state);
if (fde == NULL) {
}
tevent_fd_set_auto_close(fde);
- priv_state = talloc(winbind_event_context(),
+ priv_state = talloc(global_event_context(),
struct winbindd_listen_state);
if (!priv_state) {
goto failed;
goto failed;
}
- fde = tevent_add_fd(winbind_event_context(), priv_state,
+ fde = tevent_add_fd(global_event_context(), priv_state,
priv_state->fd, TEVENT_FD_READ,
winbindd_listen_fde_handler, priv_state);
if (fde == NULL) {
}
tevent_fd_set_auto_close(fde);
- winbindd_scrub_clients_handler(winbind_event_context(), NULL,
+ winbindd_scrub_clients_handler(global_event_context(), NULL,
timeval_current(), NULL);
return true;
failed:
return false;
}
-bool winbindd_use_idmap_cache(void)
-{
- return !opt_nocache;
-}
-
-bool winbindd_use_cache(void)
-{
- return !opt_nocache;
-}
-
static void winbindd_register_handlers(struct messaging_context *msg_ctx,
bool foreground)
{
+ bool scan_trusts = true;
NTSTATUS status;
+ struct tevent_timer *te = NULL;
+
/* Setup signal handlers */
if (!winbindd_setup_sig_term_handler(true))
exit(1);
}
- /* get broadcast messages */
-
- if (!serverid_register(messaging_server_id(msg_ctx),
- FLAG_MSG_GENERAL |
- FLAG_MSG_WINBIND |
- FLAG_MSG_DBWRAP)) {
- DEBUG(1, ("Could not register myself in serverid.tdb\n"));
- exit(1);
- }
-
/* React on 'smbcontrol winbindd reload-config' in the same way
as to SIGHUP signal */
messaging_register(msg_ctx, NULL,
- MSG_SMB_CONF_UPDATED, msg_reload_services);
+ MSG_SMB_CONF_UPDATED,
+ winbindd_msg_reload_services_parent);
messaging_register(msg_ctx, NULL,
MSG_SHUTDOWN, msg_shutdown);
MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
/* Handle domain online/offline messages for domains */
- messaging_register(winbind_messaging_context(), NULL,
+ messaging_register(global_messaging_context(), NULL,
MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
- messaging_register(winbind_messaging_context(), NULL,
+ messaging_register(global_messaging_context(), NULL,
MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
- messaging_register(msg_ctx, NULL,
- MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
-
messaging_register(msg_ctx, NULL,
MSG_WINBIND_VALIDATE_CACHE,
winbind_msg_validate_cache);
MSG_DEBUG,
winbind_msg_debug);
+ messaging_register(msg_ctx, NULL,
+ MSG_WINBIND_DISCONNECT_DC,
+ winbind_disconnect_dc_parent);
+
netsamlogon_cache_init(); /* Non-critical */
/* clear the cached list of trusted domains */
smb_nscd_flush_user_cache();
smb_nscd_flush_group_cache();
- if (lp_allow_trusted_domains()) {
- if (tevent_add_timer(winbind_event_context(), NULL, timeval_zero(),
+ if (!lp_winbind_scan_trusted_domains()) {
+ scan_trusts = false;
+ }
+
+ if (!lp_allow_trusted_domains()) {
+ scan_trusts = false;
+ }
+
+ if (IS_DC) {
+ scan_trusts = false;
+ }
+
+ if (scan_trusts) {
+ if (tevent_add_timer(global_event_context(), NULL, timeval_zero(),
rescan_trusted_domains, NULL) == NULL) {
DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
exit(1);
}
}
+ te = tevent_add_timer(global_event_context(),
+ NULL,
+ timeval_zero(),
+ winbindd_ping_offline_domains,
+ NULL);
+ if (te == NULL) {
+ DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
+ exit(1);
+ }
+
status = wb_irpc_register();
if (!NT_STATUS_IS_OK(status)) {
int main(int argc, const char **argv)
{
- static bool is_daemon = False;
- static bool Fork = True;
static bool log_stdout = False;
- static bool no_process_group = False;
- enum {
- OPT_DAEMON = 1000,
- OPT_FORK,
- OPT_NO_PROCESS_GROUP,
- OPT_LOG_STDOUT
- };
+ struct samba_cmdline_daemon_cfg *cmdline_daemon_cfg = NULL;
struct poptOption long_options[] = {
POPT_AUTOHELP
- { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
- { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
- { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
- { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
- { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
- { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
+ {
+ .longName = "no-caching",
+ .shortName = 'n',
+ .argInfo = POPT_ARG_NONE,
+ .arg = NULL,
+ .val = 'n',
+ .descrip = "Disable caching",
+ },
POPT_COMMON_SAMBA
+ POPT_COMMON_DAEMON
+ POPT_COMMON_VERSION
POPT_TABLEEND
};
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
poptContext pc;
int opt;
TALLOC_CTX *frame;
NTSTATUS status;
bool ok;
+ const struct dcesrv_endpoint_server *ep_server = NULL;
+ struct dcesrv_context *dce_ctx = NULL;
+ size_t winbindd_socket_dir_len = 0;
+ char *winbindd_priv_socket_dir = NULL;
+ size_t winbindd_priv_socket_dir_len = 0;
+
+ setproctitle_init(argc, discard_const(argv), environ);
/*
* Do this before any other talloc operation
*/
umask(0);
- setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
+ smb_init_locale();
/* 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();
- dump_core_setup("winbindd", lp_logfile(talloc_tos()));
-
- smb_init_locale();
-
- /* 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"));
+ ok = samba_cmdline_init(frame,
+ SAMBA_CMDLINE_CONFIG_SERVER,
+ true /* require_smbconf */);
+ if (!ok) {
+ DBG_ERR("Failed to setup cmdline parser\n");
+ TALLOC_FREE(frame);
exit(1);
}
- /* Initialise samba/rpc client stuff */
+ cmdline_daemon_cfg = samba_cmdline_get_daemon_cfg();
- pc = poptGetContext("winbindd", argc, argv, long_options, 0);
+ pc = samba_popt_get_context(getprogname(), argc, argv, long_options, 0);
+ if (pc == NULL) {
+ DBG_ERR("Failed to setup popt parser!\n");
+ TALLOC_FREE(frame);
+ exit(1);
+ }
while ((opt = poptGetNextOpt(pc)) != -1) {
switch (opt) {
- /* Don't become a daemon */
- case OPT_DAEMON:
- is_daemon = True;
- break;
- case 'i':
- interactive = True;
- log_stdout = True;
- Fork = False;
- break;
- case OPT_FORK:
- Fork = false;
- break;
- case OPT_NO_PROCESS_GROUP:
- no_process_group = true;
- break;
- case OPT_LOG_STDOUT:
- log_stdout = true;
- break;
case 'n':
- opt_nocache = true;
+ winbindd_set_use_cache(false);
break;
default:
d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
}
}
- /* We call dump_core_setup one more time because the command line can
- * set the log file or the log-basename and this will influence where
- * cores are stored. Without this call get_dyn_LOGFILEBASE will be
- * the default value derived from build's prefix. For EOM this value
- * is often not related to the path where winbindd is actually run
- * in production.
- */
- dump_core_setup("winbindd", lp_logfile(talloc_tos()));
- if (is_daemon && interactive) {
+ /* 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 for running in non-root mode */
+ sec_init();
+
+ set_remote_machine_name("winbindd", False);
+
+ dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
+ if (cmdline_daemon_cfg->daemon && cmdline_daemon_cfg->interactive) {
d_fprintf(stderr,"\nERROR: "
"Option -i|--interactive is not allowed together with -D|--daemon\n\n");
poptPrintUsage(pc, stderr, 0);
exit(1);
}
- if (log_stdout && Fork) {
+ log_stdout = (debug_get_log_type() == DEBUG_STDOUT);
+ if (cmdline_daemon_cfg->interactive) {
+ /*
+ * libcmdline POPT_DAEMON callback sets "fork" to false if "-i"
+ * for interactive is passed on the commandline. Set it back to
+ * true. TODO: check if this is correct, smbd and nmbd don't do
+ * this.
+ */
+ cmdline_daemon_cfg->fork = true;
+ log_stdout = true;
+ }
+
+ if (log_stdout && cmdline_daemon_cfg->fork) {
d_fprintf(stderr, "\nERROR: "
- "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
+ "Can't log to stdout (-S) unless daemon is in "
+ "foreground (-F) or interactive (-i)\n\n");
poptPrintUsage(pc, stderr, 0);
exit(1);
}
poptFreeContext(pc);
- if (!override_logfile) {
- char *lfile = NULL;
- if (asprintf(&lfile,"%s/log.winbindd",
- get_dyn_LOGFILEBASE()) > 0) {
- lp_set_logfile(lfile);
- SAFE_FREE(lfile);
- }
- }
-
- if (log_stdout) {
- setup_logging("winbindd", DEBUG_STDOUT);
- } else {
- setup_logging("winbindd", DEBUG_FILE);
- }
reopen_logs();
DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
- if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
- DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
- exit(1);
- }
/* After parsing the configuration file we setup the core path one more time
* as the log file might have been set in the configuration and cores's
* path is by default basename(lp_logfile()).
*/
- dump_core_setup("winbindd", lp_logfile(talloc_tos()));
+ dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
+
+ if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
+ if (!lp_parm_bool(-1, "server role check", "inhibit", false)) {
+ DBG_ERR("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n");
+ DEBUGADD(0, ("You should start 'samba' instead, and it will control starting the internal AD DC winbindd implementation, which is not the same as this one\n"));
+ exit(1);
+ }
+ /* Main 'samba' daemon will notify */
+ daemon_sd_notifications(false);
+ }
+
+ if (lp_security() == SEC_ADS) {
+ const char *realm = lp_realm();
+ const char *workgroup = lp_workgroup();
- if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
- && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
- DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
- DEBUGADD(0, ("You should start 'samba' instead, and it will control starting the internal AD DC winbindd implementation, which is not the same as this one\n"));
+ if (workgroup == NULL || strlen(workgroup) == 0) {
+ DBG_ERR("For 'secuirity = ADS' mode, the 'workgroup' "
+ "parameter is required to be set!\n");
+ exit(1);
+ }
+
+ if (realm == NULL || strlen(realm) == 0) {
+ DBG_ERR("For 'secuirity = ADS' mode, the 'realm' "
+ "parameter is required to be set!\n");
+ exit(1);
+ }
+ }
+
+ winbindd_socket_dir_len = strlen(lp_winbindd_socket_directory());
+ if (winbindd_socket_dir_len > 0) {
+ size_t winbindd_socket_len =
+ winbindd_socket_dir_len + 1 +
+ strlen(WINBINDD_SOCKET_NAME);
+ struct sockaddr_un un = {
+ .sun_family = AF_UNIX,
+ };
+ size_t sun_path_len = sizeof(un.sun_path);
+
+ if (winbindd_socket_len >= sun_path_len) {
+ DBG_ERR("The winbind socket path [%s/%s] is too long "
+ "(%zu >= %zu)\n",
+ lp_winbindd_socket_directory(),
+ WINBINDD_SOCKET_NAME,
+ winbindd_socket_len,
+ sun_path_len);
+ exit(1);
+ }
+ } else {
+ DBG_ERR("'winbindd_socket_directory' parameter is empty\n");
+ exit(1);
+ }
+
+ winbindd_priv_socket_dir = get_winbind_priv_pipe_dir();
+ winbindd_priv_socket_dir_len = strlen(winbindd_priv_socket_dir);
+ if (winbindd_priv_socket_dir_len > 0) {
+ size_t winbindd_priv_socket_len =
+ winbindd_priv_socket_dir_len + 1 +
+ strlen(WINBINDD_SOCKET_NAME);
+ struct sockaddr_un un = {
+ .sun_family = AF_UNIX,
+ };
+ size_t sun_path_len = sizeof(un.sun_path);
+
+ if (winbindd_priv_socket_len >= sun_path_len) {
+ DBG_ERR("The winbind priviliged socket path [%s/%s] is too long "
+ "(%zu >= %zu)\n",
+ winbindd_priv_socket_dir,
+ WINBINDD_SOCKET_NAME,
+ winbindd_priv_socket_len,
+ sun_path_len);
+ exit(1);
+ }
+ } else {
+ DBG_ERR("'winbindd_priv_socket_directory' parameter is empty\n");
exit(1);
}
+ TALLOC_FREE(winbindd_priv_socket_dir);
if (!cluster_probe_ok()) {
exit(1);
/* Initialise messaging system */
- if (winbind_messaging_context() == NULL) {
+ if (global_messaging_context() == NULL) {
exit(1);
}
- if (!reload_services_file(NULL)) {
+ if (!winbindd_reload_services_file(NULL)) {
DEBUG(0, ("error opening config file\n"));
exit(1);
}
exit(1);
}
- /* Setup names. */
-
- if (!init_names())
- exit(1);
-
load_interfaces();
if (!secrets_init()) {
BlockSignals(False, SIGHUP);
BlockSignals(False, SIGCHLD);
- if (!interactive)
- become_daemon(Fork, no_process_group, log_stdout);
+ if (!interactive) {
+ become_daemon(cmdline_daemon_cfg->fork,
+ cmdline_daemon_cfg->no_process_group,
+ log_stdout);
+ } else {
+ daemon_status("winbindd", "Starting process ...");
+ }
pidfile_create(lp_pid_directory(), "winbindd");
-#if HAVE_SETPGID
+#ifdef HAVE_SETPGID
/*
* If we're interactive we want to set our own process group for
* signal management.
*/
- if (interactive && !no_process_group)
+ if (cmdline_daemon_cfg->interactive &&
+ !cmdline_daemon_cfg->no_process_group)
+ {
setpgid( (pid_t)0, (pid_t)0);
+ }
#endif
TimeInit();
* winbindd-specific resources we must free yet. JRA.
*/
- status = reinit_after_fork(winbind_messaging_context(),
- winbind_event_context(),
+ status = reinit_after_fork(global_messaging_context(),
+ global_event_context(),
false, NULL);
if (!NT_STATUS_IS_OK(status)) {
exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
}
+ if (lp_winbind_debug_traceid()) {
+ winbind_debug_traceid_setup(global_event_context());
+ }
+ ok = initialize_password_db(true, global_event_context());
+ if (!ok) {
+ exit_daemon("Failed to initialize passdb backend! "
+ "Check the 'passdb backend' variable in your "
+ "smb.conf file.", EINVAL);
+ }
+
/*
* Do not initialize the parent-child-pipe before becoming
* a daemon: this is used to detect a died parent in the child
exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
}
- winbindd_register_handlers(winbind_messaging_context(), !Fork);
+ winbindd_register_handlers(global_messaging_context(),
+ !cmdline_daemon_cfg->fork);
- if (!messaging_parent_dgm_cleanup_init(winbind_messaging_context())) {
+ if (!messaging_parent_dgm_cleanup_init(global_messaging_context())) {
exit(1);
}
- status = init_system_session_info();
+ status = init_system_session_info(NULL);
if (!NT_STATUS_IS_OK(status)) {
exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
}
- rpc_lsarpc_init(NULL);
- rpc_samr_init(NULL);
+ DBG_INFO("Registering DCE/RPC endpoint servers\n");
- winbindd_init_addrchange(NULL, winbind_event_context(),
- winbind_messaging_context());
+ ep_server = winbind_get_ep_server();
+ if (ep_server == NULL) {
+ DBG_ERR("Failed to get 'winbind' endpoint server\n");
+ exit(1);
+ }
+ status = dcerpc_register_ep_server(ep_server);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_ERR("Failed to register 'winbind' endpoint "
+ "server: %s\n", nt_errstr(status));
+ exit(1);
+ }
+
+ dce_ctx = global_dcesrv_context();
+
+ DBG_INFO("Initializing DCE/RPC registered endpoint servers\n");
+
+ /* Init all registered ep servers */
+ status = dcesrv_init_registered_ep_servers(dce_ctx);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_ERR("Failed to init DCE/RPC endpoint servers: %s\n",
+ nt_errstr(status));
+ exit(1);
+ }
+
+ winbindd_init_addrchange(NULL, global_event_context(),
+ global_messaging_context());
/* setup listen sockets */
daemon_ready("winbindd");
}
+ gpupdate_init();
+
/* Loop waiting for requests */
while (1) {
frame = talloc_stackframe();
- if (tevent_loop_once(winbind_event_context()) == -1) {
+ if (tevent_loop_once(global_event_context()) == -1) {
DEBUG(1, ("tevent_loop_once() failed: %s\n",
strerror(errno)));
return 1;