-/*
+/*
Unix SMB/CIFS implementation.
Winbind daemon for ntdom nss module
#include "../librpc/gen_ndr/srv_lsa.h"
#include "../librpc/gen_ndr/srv_samr.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 "util_cluster.h"
+#include "source4/lib/messaging/irpc.h"
+#include "source4/lib/messaging/messaging.h"
+#include "lib/param/param.h"
+#include "librpc/gen_ndr/ndr_winbind.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
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)
{
- struct messaging_context *msg_ctx = server_messaging_context();
- if (likely(msg_ctx != NULL)) {
- return msg_ctx;
+ 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 loadparm_context *lp_ctx;
+
+ if (msg != NULL) {
+ return msg;
+ }
+
+ 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");
}
- smb_panic("Could not init winbindd's messaging context.\n");
- return NULL;
+
+ /*
+ * 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, procid_self(), winbind_event_context(), false);
+ talloc_unlink(NULL, lp_ctx);
+
+ if (msg == NULL) {
+ smb_panic("Could not init winbindd's messaging context.\n");
+ }
+ return msg;
}
/* Reload configuration */
bool ret;
if (lp_loaded()) {
- const char *fname = lp_configfile();
+ 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
char *path = NULL;
if (asprintf(&path, "%s/%s",
- get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME) > 0) {
+ lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
unlink(path);
SAFE_FREE(path);
}
#endif
if (is_parent) {
- serverid_deregister(procid_self());
- pidfile_unlink();
+ 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);
char c;
if (read(0, &c, 1) != 1) {
bool *is_parent = talloc_get_type_abort(private_data, bool);
-
+
/* we have reached EOF on stdin, which means the
parent has exited. Shutdown the server */
DEBUG(0,("EOF on stdin (is_parent=%d)\n",
bool *is_parent;
if (foreground) {
+ struct stat st;
+
is_parent = talloc(winbind_event_context(), bool);
if (!is_parent) {
return false;
}
-
+
*is_parent = parent;
/* if we are running in the foreground then look for
EOF on stdin, and exit if it happens. This allows
us to die if the parent process dies
+ Only do this on a pipe or socket, no other device.
*/
- tevent_add_fd(winbind_event_context(), is_parent, 0, TEVENT_FD_READ, winbindd_stdin_handler, is_parent);
+ if (fstat(0, &st) != 0) {
+ return false;
+ }
+ if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
+ tevent_add_fd(winbind_event_context(),
+ is_parent,
+ 0,
+ TEVENT_FD_READ,
+ winbindd_stdin_handler,
+ is_parent);
+ }
}
-
+
return true;
}
* so we don't block the main winbindd and the validation
* code can safely use fork/waitpid...
*/
- child_pid = sys_fork();
+ child_pid = fork();
if (child_pid == -1) {
DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
state->cmd_name = "unknown request";
state->recv_fn = NULL;
+ state->last_access = time(NULL);
/* Process command */
if (sock == -1) {
if (errno != EINTR) {
- DEBUG(0, ("Faild to accept socket - %s\n",
+ DEBUG(0, ("Failed to accept socket - %s\n",
strerror(errno)));
}
return;
/* Is a client idle? */
static bool client_is_idle(struct winbindd_cli_state *state) {
- return (state->response == NULL &&
+ return (state->request == NULL &&
+ state->response == NULL &&
!state->pwent_state && !state->grent_state);
}
* Winbindd socket accessor functions
*/
-const char *get_winbind_pipe_dir(void)
-{
- return lp_parm_const_string(-1, "winbindd", "socket dir", get_dyn_WINBINDD_SOCKET_DIR());
-}
-
char *get_winbind_priv_pipe_dir(void)
{
return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
pub_state->privileged = false;
pub_state->fd = create_pipe_sock(
- get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME, 0755);
+ lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
if (pub_state->fd == -1) {
goto failed;
}
return !opt_nocache;
}
-void winbindd_register_handlers(bool foreground)
+static void winbindd_register_handlers(struct messaging_context *msg_ctx,
+ bool foreground)
{
+ NTSTATUS status;
/* Setup signal handlers */
if (!winbindd_setup_sig_term_handler(true))
/* get broadcast messages */
- if (!serverid_register(procid_self(),
+ if (!serverid_register(messaging_server_id(msg_ctx),
FLAG_MSG_GENERAL |
FLAG_MSG_WINBIND |
FLAG_MSG_DBWRAP)) {
/* React on 'smbcontrol winbindd reload-config' in the same way
as to SIGHUP signal */
- messaging_register(winbind_messaging_context(), NULL,
+ messaging_register(msg_ctx, NULL,
MSG_SMB_CONF_UPDATED, msg_reload_services);
- messaging_register(winbind_messaging_context(), NULL,
+ messaging_register(msg_ctx, NULL,
MSG_SHUTDOWN, msg_shutdown);
/* Handle online/offline messages. */
- messaging_register(winbind_messaging_context(), NULL,
+ messaging_register(msg_ctx, NULL,
MSG_WINBIND_OFFLINE, winbind_msg_offline);
- messaging_register(winbind_messaging_context(), NULL,
+ messaging_register(msg_ctx, NULL,
MSG_WINBIND_ONLINE, winbind_msg_online);
- messaging_register(winbind_messaging_context(), NULL,
+ messaging_register(msg_ctx, NULL,
MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
+ /* Handle domain online/offline messages for domains */
+ messaging_register(winbind_messaging_context(), NULL,
+ MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
messaging_register(winbind_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(winbind_messaging_context(), NULL,
+ messaging_register(msg_ctx, NULL,
MSG_WINBIND_VALIDATE_CACHE,
winbind_msg_validate_cache);
- messaging_register(winbind_messaging_context(), NULL,
+ messaging_register(msg_ctx, NULL,
MSG_WINBIND_DUMP_DOMAIN_LIST,
winbind_msg_dump_domain_list);
- messaging_register(winbind_messaging_context(), NULL,
+ messaging_register(msg_ctx, NULL,
MSG_WINBIND_IP_DROPPED,
winbind_msg_ip_dropped_parent);
/* Register handler for MSG_DEBUG. */
- messaging_register(winbind_messaging_context(), NULL,
+ messaging_register(msg_ctx, NULL,
MSG_DEBUG,
winbind_msg_debug);
}
}
+ status = IRPC_REGISTER(winbind_imessaging_context(), winbind, WINBIND_DSRUPDATEREADONLYSERVERDNSRECORDS,
+ wb_irpc_DsrUpdateReadOnlyServerDnsRecords, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("Could not register IRPC handler for wb_irpc_DsrUpdateReadOnlyServerDnsRecords\n"));
+ exit(1);
+ }
}
struct winbindd_addrchanged_state {
/* Main function */
-int main(int argc, char **argv, char **envp)
+int main(int argc, const char **argv)
{
static bool is_daemon = False;
static bool Fork = True;
int opt;
TALLOC_CTX *frame;
NTSTATUS status;
+ bool ok;
/*
* Do this before any other talloc operation
talloc_enable_null_tracking();
frame = talloc_stackframe();
+ /*
+ * We want total control over the permissions on created files,
+ * so set our umask to 0.
+ */
+ umask(0);
+
setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
/* glibc (?) likes to print "User defined signal 1" and exit if a
CatchSignal(SIGUSR2, SIG_IGN);
fault_setup();
- dump_core_setup("winbindd", lp_logfile());
+ dump_core_setup("winbindd", lp_logfile(talloc_tos()));
load_case_tables();
/* Initialise samba/rpc client stuff */
- pc = poptGetContext("winbindd", argc, (const char **)argv, long_options, 0);
+ pc = poptGetContext("winbindd", argc, argv, long_options, 0);
while ((opt = poptGetNextOpt(pc)) != -1) {
switch (opt) {
}
}
+ /* 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) {
d_fprintf(stderr,"\nERROR: "
"Option -i|--interactive is not allowed together with -D|--daemon\n\n");
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()));
+
+ 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"));
+ exit(1);
+ }
+
+ if (!cluster_probe_ok()) {
+ exit(1);
+ }
/* Initialise messaging system */
exit(1);
}
- if (!directory_exist(lp_lockdir())) {
- mkdir(lp_lockdir(), 0755);
+ ok = directory_create_or_exist(lp_lock_directory(), geteuid(), 0755);
+ if (!ok) {
+ DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
+ lp_lock_directory(), strerror(errno)));
+ exit(1);
+ }
+
+ ok = directory_create_or_exist(lp_pid_directory(), geteuid(), 0755);
+ if (!ok) {
+ DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
+ lp_pid_directory(), strerror(errno)));
+ exit(1);
}
/* Setup names. */
return False;
}
+ status = rpccli_pre_open_netlogon_creds();
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
+ nt_errstr(status)));
+ exit(1);
+ }
+
/* Unblock all signals we are interested in as they may have been
blocked by the parent process. */
if (!interactive)
become_daemon(Fork, no_process_group, log_stdout);
- pidfile_create("winbindd");
+ pidfile_create(lp_pid_directory(), "winbindd");
#if HAVE_SETPGID
/*
winbind_event_context(),
false);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("reinit_after_fork() failed\n"));
- exit(1);
+ exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
}
- winbindd_register_handlers(!Fork);
-
- status = init_system_info();
+ /*
+ * Do not initialize the parent-child-pipe before becoming
+ * a daemon: this is used to detect a died parent in the child
+ * process.
+ */
+ status = init_before_fork();
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("ERROR: failed to setup system user info: %s.\n",
- nt_errstr(status)));
+ exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
+ }
+
+ winbindd_register_handlers(winbind_messaging_context(), !Fork);
+
+ if (!messaging_parent_dgm_cleanup_init(winbind_messaging_context())) {
exit(1);
}
+ status = init_system_session_info();
+ 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);
/* setup listen sockets */
if (!winbindd_setup_listeners()) {
- DEBUG(0,("winbindd_setup_listeners() failed\n"));
- exit(1);
+ exit_daemon("Winbindd failed to setup listeners", EPIPE);
}
+ irpc_add_name(winbind_imessaging_context(), "winbind_server");
+
TALLOC_FREE(frame);
+
+ if (!interactive) {
+ daemon_ready("winbindd");
+ }
+
/* Loop waiting for requests */
while (1) {
frame = talloc_stackframe();