s3:winbind: Move imessaging context init function to winbindd-lib subsystem
[Samba.git] / source3 / winbindd / winbindd.c
bloba226be5c48eed65f541b7fe01259a18607ba4dfc
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind daemon for ntdom nss module
6 Copyright (C) by Tim Potter 2000-2002
7 Copyright (C) Andrew Tridgell 2002
8 Copyright (C) Jelmer Vernooij 2003
9 Copyright (C) Volker Lendecke 2004
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "lib/cmdline/cmdline.h"
27 #include "winbindd.h"
28 #include "nsswitch/winbind_client.h"
29 #include "nsswitch/wb_reqtrans.h"
30 #include "ntdomain.h"
31 #include "librpc/rpc/dcesrv_core.h"
32 #include "librpc/gen_ndr/ndr_lsa_scompat.h"
33 #include "librpc/gen_ndr/ndr_samr_scompat.h"
34 #include "librpc/gen_ndr/ndr_winbind_scompat.h"
35 #include "secrets.h"
36 #include "rpc_client/cli_netlogon.h"
37 #include "idmap.h"
38 #include "lib/addrchange.h"
39 #include "auth.h"
40 #include "messages.h"
41 #include "../lib/util/pidfile.h"
42 #include "util_cluster.h"
43 #include "source4/lib/messaging/irpc.h"
44 #include "source4/lib/messaging/messaging.h"
45 #include "lib/param/param.h"
46 #include "lib/async_req/async_sock.h"
47 #include "libsmb/samlogon_cache.h"
48 #include "libcli/auth/netlogon_creds_cli.h"
49 #include "passdb.h"
50 #include "lib/util/tevent_req_profile.h"
51 #include "lib/gencache.h"
52 #include "rpc_server/rpc_config.h"
53 #include "lib/global_contexts.h"
54 #include "source3/lib/substitute.h"
56 #undef DBGC_CLASS
57 #define DBGC_CLASS DBGC_WINBIND
59 #define SCRUB_CLIENTS_INTERVAL 5
61 static bool client_is_idle(struct winbindd_cli_state *state);
62 static void remove_client(struct winbindd_cli_state *state);
63 static void winbindd_setup_max_fds(void);
65 static bool interactive = False;
67 /* Reload configuration */
69 bool winbindd_reload_services_file(const char *lfile)
71 const struct loadparm_substitution *lp_sub =
72 loadparm_s3_global_substitution();
73 bool ret;
75 if (lp_loaded()) {
76 char *fname = lp_next_configfile(talloc_tos(), lp_sub);
78 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
79 set_dyn_CONFIGFILE(fname);
81 TALLOC_FREE(fname);
84 reopen_logs();
85 ret = lp_load_global(get_dyn_CONFIGFILE());
87 /* if this is a child, restore the logfile to the special
88 name - <domain>, idmap, etc. */
89 if (lfile && *lfile) {
90 lp_set_logfile(lfile);
93 reopen_logs();
94 load_interfaces();
95 winbindd_setup_max_fds();
97 return(ret);
101 static void winbindd_status(void)
103 struct winbindd_cli_state *tmp;
105 DEBUG(0, ("winbindd status:\n"));
107 /* Print client state information */
109 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
111 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
112 DEBUG(2, ("\tclient list:\n"));
113 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
114 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
115 (unsigned long)tmp->pid, tmp->sock,
116 client_is_idle(tmp) ? "idle" : "active"));
121 /* Flush client cache */
123 void winbindd_flush_caches(void)
125 /* We need to invalidate cached user list entries on a SIGHUP
126 otherwise cached access denied errors due to restrict anonymous
127 hang around until the sequence number changes. */
129 if (!wcache_invalidate_cache()) {
130 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
131 if (!winbindd_cache_validate_and_initialize()) {
132 exit(1);
137 static void flush_caches_noinit(void)
140 * We need to invalidate cached user list entries on a SIGHUP
141 * otherwise cached access denied errors due to restrict anonymous
142 * hang around until the sequence number changes.
143 * NB
144 * Skip uninitialized domains when flush cache.
145 * If domain is not initialized, it means it is never
146 * used or never become online. look, wcache_invalidate_cache()
147 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
148 * for unused domains and large traffic for primay domain's DC if there
149 * are many domains..
152 if (!wcache_invalidate_cache_noinit()) {
153 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
154 if (!winbindd_cache_validate_and_initialize()) {
155 exit(1);
160 /* Handle the signal by unlinking socket and exiting */
162 static void terminate(bool is_parent)
164 if (is_parent) {
165 /* When parent goes away we should
166 * remove the socket file. Not so
167 * when children terminate.
169 char *path = NULL;
171 if (asprintf(&path, "%s/%s",
172 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
173 unlink(path);
174 SAFE_FREE(path);
178 idmap_close();
180 netlogon_creds_cli_close_global_db();
182 #if 0
183 if (interactive) {
184 TALLOC_CTX *mem_ctx = talloc_init("end_description");
185 char *description = talloc_describe_all(mem_ctx);
187 DEBUG(3, ("tallocs left:\n%s\n", description));
188 talloc_destroy(mem_ctx);
190 #endif
192 if (is_parent) {
193 pidfile_unlink(lp_pid_directory(), "winbindd");
196 exit(0);
199 static void winbindd_sig_term_handler(struct tevent_context *ev,
200 struct tevent_signal *se,
201 int signum,
202 int count,
203 void *siginfo,
204 void *private_data)
206 bool *p = talloc_get_type_abort(private_data, bool);
207 bool is_parent = *p;
209 TALLOC_FREE(p);
211 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
212 signum, is_parent));
213 terminate(is_parent);
217 handle stdin becoming readable when we are in --foreground mode
219 static void winbindd_stdin_handler(struct tevent_context *ev,
220 struct tevent_fd *fde,
221 uint16_t flags,
222 void *private_data)
224 char c;
225 if (read(0, &c, 1) != 1) {
226 bool *is_parent = talloc_get_type_abort(private_data, bool);
228 /* we have reached EOF on stdin, which means the
229 parent has exited. Shutdown the server */
230 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
231 (int)*is_parent));
232 terminate(*is_parent);
236 bool winbindd_setup_sig_term_handler(bool parent)
238 struct tevent_signal *se;
239 bool *is_parent;
241 is_parent = talloc(global_event_context(), bool);
242 if (!is_parent) {
243 return false;
246 *is_parent = parent;
248 se = tevent_add_signal(global_event_context(),
249 is_parent,
250 SIGTERM, 0,
251 winbindd_sig_term_handler,
252 is_parent);
253 if (!se) {
254 DEBUG(0,("failed to setup SIGTERM handler"));
255 talloc_free(is_parent);
256 return false;
259 se = tevent_add_signal(global_event_context(),
260 is_parent,
261 SIGINT, 0,
262 winbindd_sig_term_handler,
263 is_parent);
264 if (!se) {
265 DEBUG(0,("failed to setup SIGINT handler"));
266 talloc_free(is_parent);
267 return false;
270 se = tevent_add_signal(global_event_context(),
271 is_parent,
272 SIGQUIT, 0,
273 winbindd_sig_term_handler,
274 is_parent);
275 if (!se) {
276 DEBUG(0,("failed to setup SIGINT handler"));
277 talloc_free(is_parent);
278 return false;
281 return true;
284 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
286 bool *is_parent;
288 if (foreground) {
289 struct stat st;
291 is_parent = talloc(global_event_context(), bool);
292 if (!is_parent) {
293 return false;
296 *is_parent = parent;
298 /* if we are running in the foreground then look for
299 EOF on stdin, and exit if it happens. This allows
300 us to die if the parent process dies
301 Only do this on a pipe or socket, no other device.
303 if (fstat(0, &st) != 0) {
304 return false;
306 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
307 tevent_add_fd(global_event_context(),
308 is_parent,
310 TEVENT_FD_READ,
311 winbindd_stdin_handler,
312 is_parent);
316 return true;
319 static void winbindd_sig_hup_handler(struct tevent_context *ev,
320 struct tevent_signal *se,
321 int signum,
322 int count,
323 void *siginfo,
324 void *private_data)
326 const char *file = (const char *)private_data;
328 DEBUG(1,("Reloading services after SIGHUP\n"));
329 flush_caches_noinit();
330 winbindd_reload_services_file(file);
333 bool winbindd_setup_sig_hup_handler(const char *lfile)
335 struct tevent_signal *se;
336 char *file = NULL;
338 if (lfile) {
339 file = talloc_strdup(global_event_context(),
340 lfile);
341 if (!file) {
342 return false;
346 se = tevent_add_signal(global_event_context(),
347 global_event_context(),
348 SIGHUP, 0,
349 winbindd_sig_hup_handler,
350 file);
351 if (!se) {
352 return false;
355 return true;
358 static void winbindd_sig_chld_handler(struct tevent_context *ev,
359 struct tevent_signal *se,
360 int signum,
361 int count,
362 void *siginfo,
363 void *private_data)
365 pid_t pid;
367 while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
368 winbind_child_died(pid);
372 static bool winbindd_setup_sig_chld_handler(void)
374 struct tevent_signal *se;
376 se = tevent_add_signal(global_event_context(),
377 global_event_context(),
378 SIGCHLD, 0,
379 winbindd_sig_chld_handler,
380 NULL);
381 if (!se) {
382 return false;
385 return true;
388 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
389 struct tevent_signal *se,
390 int signum,
391 int count,
392 void *siginfo,
393 void *private_data)
395 winbindd_status();
398 static bool winbindd_setup_sig_usr2_handler(void)
400 struct tevent_signal *se;
402 se = tevent_add_signal(global_event_context(),
403 global_event_context(),
404 SIGUSR2, 0,
405 winbindd_sig_usr2_handler,
406 NULL);
407 if (!se) {
408 return false;
411 return true;
414 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
415 static void msg_shutdown(struct messaging_context *msg,
416 void *private_data,
417 uint32_t msg_type,
418 struct server_id server_id,
419 DATA_BLOB *data)
421 /* only the parent waits for this message */
422 DEBUG(0,("Got shutdown message\n"));
423 terminate(true);
427 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
428 void *private_data,
429 uint32_t msg_type,
430 struct server_id server_id,
431 DATA_BLOB *data)
433 uint8_t ret;
434 pid_t child_pid;
435 NTSTATUS status;
437 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
438 "message.\n"));
441 * call the validation code from a child:
442 * so we don't block the main winbindd and the validation
443 * code can safely use fork/waitpid...
445 child_pid = fork();
447 if (child_pid == -1) {
448 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
449 strerror(errno)));
450 return;
453 if (child_pid != 0) {
454 /* parent */
455 DEBUG(5, ("winbind_msg_validate_cache: child created with "
456 "pid %d.\n", (int)child_pid));
457 return;
460 /* child */
462 status = winbindd_reinit_after_fork(NULL, NULL);
463 if (!NT_STATUS_IS_OK(status)) {
464 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
465 nt_errstr(status)));
466 _exit(0);
469 /* install default SIGCHLD handler: validation code uses fork/waitpid */
470 CatchSignal(SIGCHLD, SIG_DFL);
472 setproctitle("validate cache child");
474 ret = (uint8_t)winbindd_validate_cache_nobackup();
475 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
476 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
477 (size_t)1);
478 _exit(0);
481 static struct winbindd_bool_dispatch_table {
482 enum winbindd_cmd cmd;
483 bool (*fn)(struct winbindd_cli_state *state);
484 const char *cmd_name;
485 } bool_dispatch_table[] = {
486 { WINBINDD_INTERFACE_VERSION,
487 winbindd_interface_version,
488 "INTERFACE_VERSION" },
489 { WINBINDD_INFO,
490 winbindd_info,
491 "INFO" },
492 { WINBINDD_PING,
493 winbindd_ping,
494 "PING" },
495 { WINBINDD_DOMAIN_NAME,
496 winbindd_domain_name,
497 "DOMAIN_NAME" },
498 { WINBINDD_NETBIOS_NAME,
499 winbindd_netbios_name,
500 "NETBIOS_NAME" },
501 { WINBINDD_DC_INFO,
502 winbindd_dc_info,
503 "DC_INFO" },
504 { WINBINDD_CCACHE_NTLMAUTH,
505 winbindd_ccache_ntlm_auth,
506 "NTLMAUTH" },
507 { WINBINDD_CCACHE_SAVE,
508 winbindd_ccache_save,
509 "CCACHE_SAVE" },
510 { WINBINDD_PRIV_PIPE_DIR,
511 winbindd_priv_pipe_dir,
512 "WINBINDD_PRIV_PIPE_DIR" },
513 { WINBINDD_LIST_TRUSTDOM,
514 winbindd_list_trusted_domains,
515 "LIST_TRUSTDOM" },
518 struct winbindd_async_dispatch_table {
519 enum winbindd_cmd cmd;
520 const char *cmd_name;
521 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
522 struct tevent_context *ev,
523 struct winbindd_cli_state *cli,
524 struct winbindd_request *request);
525 NTSTATUS (*recv_req)(struct tevent_req *req,
526 struct winbindd_response *presp);
529 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
530 { WINBINDD_LOOKUPSID, "LOOKUPSID",
531 winbindd_lookupsid_send, winbindd_lookupsid_recv },
532 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
533 winbindd_lookupsids_send, winbindd_lookupsids_recv },
534 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
535 winbindd_lookupname_send, winbindd_lookupname_recv },
536 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
537 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
538 { WINBINDD_XIDS_TO_SIDS, "XIDS_TO_SIDS",
539 winbindd_xids_to_sids_send, winbindd_xids_to_sids_recv },
540 { WINBINDD_GETPWSID, "GETPWSID",
541 winbindd_getpwsid_send, winbindd_getpwsid_recv },
542 { WINBINDD_GETPWNAM, "GETPWNAM",
543 winbindd_getpwnam_send, winbindd_getpwnam_recv },
544 { WINBINDD_GETPWUID, "GETPWUID",
545 winbindd_getpwuid_send, winbindd_getpwuid_recv },
546 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
547 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
548 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
549 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
550 { WINBINDD_GETGROUPS, "GETGROUPS",
551 winbindd_getgroups_send, winbindd_getgroups_recv },
552 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
553 winbindd_show_sequence_send, winbindd_show_sequence_recv },
554 { WINBINDD_GETGRGID, "GETGRGID",
555 winbindd_getgrgid_send, winbindd_getgrgid_recv },
556 { WINBINDD_GETGRNAM, "GETGRNAM",
557 winbindd_getgrnam_send, winbindd_getgrnam_recv },
558 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
559 winbindd_getusersids_send, winbindd_getusersids_recv },
560 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
561 winbindd_lookuprids_send, winbindd_lookuprids_recv },
562 { WINBINDD_SETPWENT, "SETPWENT",
563 winbindd_setpwent_send, winbindd_setpwent_recv },
564 { WINBINDD_GETPWENT, "GETPWENT",
565 winbindd_getpwent_send, winbindd_getpwent_recv },
566 { WINBINDD_ENDPWENT, "ENDPWENT",
567 winbindd_endpwent_send, winbindd_endpwent_recv },
568 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
569 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
570 { WINBINDD_GETDCNAME, "GETDCNAME",
571 winbindd_getdcname_send, winbindd_getdcname_recv },
572 { WINBINDD_SETGRENT, "SETGRENT",
573 winbindd_setgrent_send, winbindd_setgrent_recv },
574 { WINBINDD_GETGRENT, "GETGRENT",
575 winbindd_getgrent_send, winbindd_getgrent_recv },
576 { WINBINDD_ENDGRENT, "ENDGRENT",
577 winbindd_endgrent_send, winbindd_endgrent_recv },
578 { WINBINDD_LIST_USERS, "LIST_USERS",
579 winbindd_list_users_send, winbindd_list_users_recv },
580 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
581 winbindd_list_groups_send, winbindd_list_groups_recv },
582 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
583 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
584 { WINBINDD_PING_DC, "PING_DC",
585 winbindd_ping_dc_send, winbindd_ping_dc_recv },
586 { WINBINDD_PAM_AUTH, "PAM_AUTH",
587 winbindd_pam_auth_send, winbindd_pam_auth_recv },
588 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
589 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
590 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
591 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
592 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
593 winbindd_pam_chng_pswd_auth_crap_send,
594 winbindd_pam_chng_pswd_auth_crap_recv },
595 { WINBINDD_WINS_BYIP, "WINS_BYIP",
596 winbindd_wins_byip_send, winbindd_wins_byip_recv },
597 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
598 winbindd_wins_byname_send, winbindd_wins_byname_recv },
599 { WINBINDD_DOMAIN_INFO, "DOMAIN_INFO",
600 winbindd_domain_info_send, winbindd_domain_info_recv },
602 { 0, NULL, NULL, NULL }
605 static struct winbindd_async_dispatch_table async_priv_table[] = {
606 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
607 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
608 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
609 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
610 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
611 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
612 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
613 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
615 { 0, NULL, NULL, NULL }
618 struct process_request_state {
619 struct winbindd_cli_state *cli_state;
620 struct tevent_context *ev;
623 static void process_request_done(struct tevent_req *subreq);
624 static void process_request_written(struct tevent_req *subreq);
626 static struct tevent_req *process_request_send(
627 TALLOC_CTX *mem_ctx,
628 struct tevent_context *ev,
629 struct winbindd_cli_state *cli_state)
631 struct tevent_req *req, *subreq;
632 struct process_request_state *state;
633 struct winbindd_async_dispatch_table *atable;
634 enum winbindd_cmd cmd = cli_state->request->cmd;
635 size_t i;
636 bool ok;
638 req = tevent_req_create(mem_ctx, &state,
639 struct process_request_state);
640 if (req == NULL) {
641 return NULL;
643 state->cli_state = cli_state;
644 state->ev = ev;
646 ok = tevent_req_set_profile(req);
647 if (!ok) {
648 return tevent_req_post(req, ev);
651 SMB_ASSERT(cli_state->mem_ctx == NULL);
652 cli_state->mem_ctx = talloc_named(cli_state, 0, "winbind request");
653 if (tevent_req_nomem(cli_state->mem_ctx, req)) {
654 return tevent_req_post(req, ev);
657 cli_state->response = talloc_zero(
658 cli_state->mem_ctx,
659 struct winbindd_response);
660 if (tevent_req_nomem(cli_state->response, req)) {
661 return tevent_req_post(req, ev);
663 cli_state->response->result = WINBINDD_PENDING;
664 cli_state->response->length = sizeof(struct winbindd_response);
666 /* Remember who asked us. */
667 cli_state->pid = cli_state->request->pid;
668 memcpy(cli_state->client_name,
669 cli_state->request->client_name,
670 sizeof(cli_state->client_name));
672 cli_state->cmd_name = "unknown request";
673 cli_state->recv_fn = NULL;
675 /* client is newest */
676 winbindd_promote_client(cli_state);
678 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
679 if (cmd == atable->cmd) {
680 break;
684 if ((atable->send_req == NULL) && cli_state->privileged) {
685 for (atable = async_priv_table; atable->send_req;
686 atable += 1) {
687 if (cmd == atable->cmd) {
688 break;
693 if (atable->send_req != NULL) {
694 cli_state->cmd_name = atable->cmd_name;
695 cli_state->recv_fn = atable->recv_req;
697 DBG_DEBUG("process_request: "
698 "Handling async request %s(%d):%s\n",
699 cli_state->client_name,
700 (int)cli_state->pid,
701 cli_state->cmd_name);
703 subreq = atable->send_req(
704 state,
705 state->ev,
706 cli_state,
707 cli_state->request);
708 if (tevent_req_nomem(subreq, req)) {
709 return tevent_req_post(req, ev);
711 tevent_req_set_callback(subreq, process_request_done, req);
712 return req;
715 for (i=0; i<ARRAY_SIZE(bool_dispatch_table); i++) {
716 if (cmd == bool_dispatch_table[i].cmd) {
717 break;
721 ok = false;
723 if (i < ARRAY_SIZE(bool_dispatch_table)) {
724 cli_state->cmd_name = bool_dispatch_table[i].cmd_name;
726 DBG_DEBUG("process_request: request fn %s\n",
727 bool_dispatch_table[i].cmd_name);
728 ok = bool_dispatch_table[i].fn(cli_state);
731 cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
733 TALLOC_FREE(cli_state->io_req);
734 TALLOC_FREE(cli_state->request);
736 subreq = wb_resp_write_send(
737 state,
738 state->ev,
739 cli_state->out_queue,
740 cli_state->sock,
741 cli_state->response);
742 if (tevent_req_nomem(subreq, req)) {
743 return tevent_req_post(req, ev);
745 tevent_req_set_callback(subreq, process_request_written, req);
747 cli_state->io_req = subreq;
749 return req;
752 static void process_request_done(struct tevent_req *subreq)
754 struct tevent_req *req = tevent_req_callback_data(
755 subreq, struct tevent_req);
756 struct process_request_state *state = tevent_req_data(
757 req, struct process_request_state);
758 struct winbindd_cli_state *cli_state = state->cli_state;
759 NTSTATUS status;
760 bool ok;
762 status = cli_state->recv_fn(subreq, cli_state->response);
763 TALLOC_FREE(subreq);
765 DBG_DEBUG("[%s(%d):%s]: %s\n",
766 cli_state->client_name,
767 (int)cli_state->pid,
768 cli_state->cmd_name,
769 nt_errstr(status));
771 ok = NT_STATUS_IS_OK(status);
772 cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
774 TALLOC_FREE(cli_state->io_req);
775 TALLOC_FREE(cli_state->request);
777 subreq = wb_resp_write_send(
778 state,
779 state->ev,
780 cli_state->out_queue,
781 cli_state->sock,
782 cli_state->response);
783 if (tevent_req_nomem(subreq, req)) {
784 return;
786 tevent_req_set_callback(subreq, process_request_written, req);
788 cli_state->io_req = subreq;
791 static void process_request_written(struct tevent_req *subreq)
793 struct tevent_req *req = tevent_req_callback_data(
794 subreq, struct tevent_req);
795 struct process_request_state *state = tevent_req_data(
796 req, struct process_request_state);
797 struct winbindd_cli_state *cli_state = state->cli_state;
798 ssize_t ret;
799 int err;
801 cli_state->io_req = NULL;
803 ret = wb_resp_write_recv(subreq, &err);
804 TALLOC_FREE(subreq);
805 if (ret == -1) {
806 tevent_req_nterror(req, map_nt_error_from_unix(err));
807 return;
810 DBG_DEBUG("[%s(%d):%s]: delivered response to client\n",
811 cli_state->client_name,
812 (int)cli_state->pid,
813 cli_state->cmd_name);
815 TALLOC_FREE(cli_state->mem_ctx);
816 cli_state->response = NULL;
817 cli_state->cmd_name = "no request";
818 cli_state->recv_fn = NULL;
820 tevent_req_done(req);
823 static NTSTATUS process_request_recv(
824 struct tevent_req *req,
825 TALLOC_CTX *mem_ctx,
826 struct tevent_req_profile **profile)
828 NTSTATUS status;
830 if (tevent_req_is_nterror(req, &status)) {
831 tevent_req_received(req);
832 return status;
835 *profile = tevent_req_move_profile(req, mem_ctx);
836 tevent_req_received(req);
837 return NT_STATUS_OK;
841 * This is the main event loop of winbind requests. It goes through a
842 * state-machine of 3 read/write requests, 4 if you have extra data to send.
844 * An idle winbind client has a read request of 4 bytes outstanding,
845 * finalizing function is request_len_recv, checking the length. request_recv
846 * then processes the packet. The processing function then at some point has
847 * to call request_finished which schedules sending the response.
850 static void winbind_client_request_read(struct tevent_req *req);
851 static void winbind_client_activity(struct tevent_req *req);
852 static void winbind_client_processed(struct tevent_req *req);
854 /* Process a new connection by adding it to the client connection list */
856 static void new_connection(int listen_sock, bool privileged)
858 struct sockaddr_un sunaddr;
859 struct winbindd_cli_state *state;
860 struct tevent_req *req;
861 socklen_t len;
862 int sock;
864 /* Accept connection */
866 len = sizeof(sunaddr);
868 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
870 if (sock == -1) {
871 if (errno != EINTR) {
872 DEBUG(0, ("Failed to accept socket - %s\n",
873 strerror(errno)));
875 return;
877 smb_set_close_on_exec(sock);
879 DEBUG(6,("accepted socket %d\n", sock));
881 /* Create new connection structure */
883 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
884 close(sock);
885 return;
888 state->sock = sock;
890 state->out_queue = tevent_queue_create(state, "winbind client reply");
891 if (state->out_queue == NULL) {
892 close(sock);
893 TALLOC_FREE(state);
894 return;
897 state->privileged = privileged;
899 req = wb_req_read_send(state, global_event_context(), state->sock,
900 WINBINDD_MAX_EXTRA_DATA);
901 if (req == NULL) {
902 TALLOC_FREE(state);
903 close(sock);
904 return;
906 tevent_req_set_callback(req, winbind_client_request_read, state);
907 state->io_req = req;
909 /* Add to connection list */
911 winbindd_add_client(state);
914 static void winbind_client_request_read(struct tevent_req *req)
916 struct winbindd_cli_state *state = tevent_req_callback_data(
917 req, struct winbindd_cli_state);
918 ssize_t ret;
919 int err;
921 state->io_req = NULL;
923 ret = wb_req_read_recv(req, state, &state->request, &err);
924 TALLOC_FREE(req);
925 if (ret == -1) {
926 if (err == EPIPE) {
927 DEBUG(6, ("closing socket %d, client exited\n",
928 state->sock));
929 } else {
930 DEBUG(2, ("Could not read client request from fd %d: "
931 "%s\n", state->sock, strerror(err)));
933 close(state->sock);
934 state->sock = -1;
935 remove_client(state);
936 return;
939 req = wait_for_read_send(state, global_event_context(), state->sock,
940 true);
941 if (req == NULL) {
942 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
943 " wait_for_read_send failed - removing client\n",
944 (int)state->pid, state->cmd_name));
945 remove_client(state);
946 return;
948 tevent_req_set_callback(req, winbind_client_activity, state);
949 state->io_req = req;
951 req = process_request_send(state, global_event_context(), state);
952 if (req == NULL) {
953 DBG_ERR("process_request_send failed\n");
954 remove_client(state);
955 return;
957 tevent_req_set_callback(req, winbind_client_processed, state);
960 static void winbind_client_activity(struct tevent_req *req)
962 struct winbindd_cli_state *state =
963 tevent_req_callback_data(req, struct winbindd_cli_state);
964 int err;
965 bool has_data;
967 has_data = wait_for_read_recv(req, &err);
969 if (has_data) {
970 DEBUG(0, ("winbind_client_activity[%d:%s]:"
971 "unexpected data from client - removing client\n",
972 (int)state->pid, state->cmd_name));
973 } else {
974 if (err == EPIPE) {
975 DEBUG(6, ("winbind_client_activity[%d:%s]: "
976 "client has closed connection - removing "
977 "client\n",
978 (int)state->pid, state->cmd_name));
979 } else {
980 DEBUG(2, ("winbind_client_activity[%d:%s]: "
981 "client socket error (%s) - removing "
982 "client\n",
983 (int)state->pid, state->cmd_name,
984 strerror(err)));
988 remove_client(state);
991 static void winbind_client_processed(struct tevent_req *req)
993 struct winbindd_cli_state *cli_state = tevent_req_callback_data(
994 req, struct winbindd_cli_state);
995 struct tevent_req_profile *profile = NULL;
996 struct timeval start, stop, diff;
997 int threshold;
998 NTSTATUS status;
1000 status = process_request_recv(req, cli_state, &profile);
1001 TALLOC_FREE(req);
1002 if (!NT_STATUS_IS_OK(status)) {
1003 DBG_DEBUG("process_request failed: %s\n", nt_errstr(status));
1004 remove_client(cli_state);
1005 return;
1008 tevent_req_profile_get_start(profile, NULL, &start);
1009 tevent_req_profile_get_stop(profile, NULL, &stop);
1010 diff = tevent_timeval_until(&start, &stop);
1012 threshold = lp_parm_int(-1, "winbind", "request profile threshold", 60);
1014 if (diff.tv_sec >= threshold) {
1015 int depth;
1016 char *str;
1018 depth = lp_parm_int(
1020 "winbind",
1021 "request profile depth",
1022 INT_MAX);
1024 DBG_ERR("request took %u.%.6u seconds\n",
1025 (unsigned)diff.tv_sec, (unsigned)diff.tv_usec);
1027 str = tevent_req_profile_string(
1028 talloc_tos(), profile, 0, depth);
1029 if (str != NULL) {
1030 /* No "\n", already contained in "str" */
1031 DEBUGADD(0, ("%s", str));
1033 TALLOC_FREE(str);
1036 TALLOC_FREE(profile);
1038 req = wb_req_read_send(
1039 cli_state,
1040 global_event_context(),
1041 cli_state->sock,
1042 WINBINDD_MAX_EXTRA_DATA);
1043 if (req == NULL) {
1044 remove_client(cli_state);
1045 return;
1047 tevent_req_set_callback(req, winbind_client_request_read, cli_state);
1048 cli_state->io_req = req;
1051 /* Remove a client connection from client connection list */
1053 static void remove_client(struct winbindd_cli_state *state)
1055 /* It's a dead client - hold a funeral */
1057 if (state == NULL) {
1058 return;
1062 * We need to remove a pending wb_req_read_*
1063 * or wb_resp_write_* request before closing the
1064 * socket.
1066 * This is important as they might have used tevent_add_fd() and we
1067 * use the epoll * backend on linux. So we must remove the tevent_fd
1068 * before closing the fd.
1070 * Otherwise we might hit a race with close_conns_after_fork() (via
1071 * winbindd_reinit_after_fork()) where a file descriptor
1072 * is still open in a child, which means it's still active in
1073 * the parents epoll queue, but the related tevent_fd is already
1074 * already gone in the parent.
1076 * See bug #11141.
1078 TALLOC_FREE(state->io_req);
1080 if (state->sock != -1) {
1081 char c = 0;
1082 int nwritten;
1084 /* tell client, we are closing ... */
1085 nwritten = write(state->sock, &c, sizeof(c));
1086 if (nwritten == -1) {
1087 DEBUG(2, ("final write to client failed: %s\n",
1088 strerror(errno)));
1091 /* Close socket */
1093 close(state->sock);
1094 state->sock = -1;
1097 TALLOC_FREE(state->mem_ctx);
1099 /* Remove from list and free */
1101 winbindd_remove_client(state);
1102 TALLOC_FREE(state);
1105 /* Is a client idle? */
1107 static bool client_is_idle(struct winbindd_cli_state *state) {
1108 return (state->request == NULL &&
1109 state->response == NULL &&
1110 !state->pwent_state && !state->grent_state);
1113 /* Shutdown client connection which has been idle for the longest time */
1115 static bool remove_idle_client(void)
1117 struct winbindd_cli_state *state, *remove_state = NULL;
1118 int nidle = 0;
1120 for (state = winbindd_client_list(); state; state = state->next) {
1121 if (client_is_idle(state)) {
1122 nidle++;
1123 /* list is sorted by access time */
1124 remove_state = state;
1128 if (remove_state) {
1129 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1130 nidle, remove_state->sock, (unsigned int)remove_state->pid));
1131 remove_client(remove_state);
1132 return True;
1135 return False;
1139 * Terminate all clients whose requests have taken longer than
1140 * "winbind request timeout" seconds to process, or have been
1141 * idle for more than "winbind request timeout" seconds.
1144 static void remove_timed_out_clients(void)
1146 struct winbindd_cli_state *state, *prev = NULL;
1147 time_t curr_time = time(NULL);
1148 int timeout_val = lp_winbind_request_timeout();
1150 for (state = winbindd_client_list_tail(); state; state = prev) {
1151 time_t expiry_time;
1153 prev = winbindd_client_list_prev(state);
1154 expiry_time = state->last_access + timeout_val;
1156 if (curr_time <= expiry_time) {
1157 /* list is sorted, previous clients in
1158 list are newer */
1159 break;
1162 if (client_is_idle(state)) {
1163 DEBUG(5,("Idle client timed out, "
1164 "shutting down sock %d, pid %u\n",
1165 state->sock,
1166 (unsigned int)state->pid));
1167 } else {
1168 DEBUG(5,("Client request timed out, "
1169 "shutting down sock %d, pid %u\n",
1170 state->sock,
1171 (unsigned int)state->pid));
1174 remove_client(state);
1178 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
1179 struct tevent_timer *te,
1180 struct timeval current_time,
1181 void *private_data)
1183 remove_timed_out_clients();
1184 if (tevent_add_timer(ev, ev,
1185 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
1186 winbindd_scrub_clients_handler, NULL) == NULL) {
1187 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
1188 exit(1);
1192 struct winbindd_listen_state {
1193 bool privileged;
1194 int fd;
1197 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1198 struct tevent_fd *fde,
1199 uint16_t flags,
1200 void *private_data)
1202 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1203 struct winbindd_listen_state);
1205 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1206 DEBUG(5,("winbindd: Exceeding %d client "
1207 "connections, removing idle "
1208 "connection.\n", lp_winbind_max_clients()));
1209 if (!remove_idle_client()) {
1210 DEBUG(0,("winbindd: Exceeding %d "
1211 "client connections, no idle "
1212 "connection found\n",
1213 lp_winbind_max_clients()));
1214 break;
1217 remove_timed_out_clients();
1218 new_connection(s->fd, s->privileged);
1222 * Winbindd socket accessor functions
1225 char *get_winbind_priv_pipe_dir(void)
1227 return state_path(talloc_tos(), WINBINDD_PRIV_SOCKET_SUBDIR);
1230 static void winbindd_setup_max_fds(void)
1232 int num_fds = MAX_OPEN_FUDGEFACTOR;
1233 int actual_fds;
1235 num_fds += lp_winbind_max_clients();
1236 /* Add some more to account for 2 sockets open
1237 when the client transitions from unprivileged
1238 to privileged socket
1240 num_fds += lp_winbind_max_clients() / 10;
1242 /* Add one socket per child process
1243 (yeah there are child processes other than the
1244 domain children but only domain children can vary
1245 with configuration
1247 num_fds += lp_winbind_max_domain_connections() *
1248 (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
1250 actual_fds = set_maxfiles(num_fds);
1252 if (actual_fds < num_fds) {
1253 DEBUG(1, ("winbindd_setup_max_fds: Information only: "
1254 "requested %d open files, %d are available.\n",
1255 num_fds, actual_fds));
1259 static bool winbindd_setup_listeners(void)
1261 struct winbindd_listen_state *pub_state = NULL;
1262 struct winbindd_listen_state *priv_state = NULL;
1263 struct tevent_fd *fde;
1264 int rc;
1265 char *socket_path;
1267 pub_state = talloc(global_event_context(),
1268 struct winbindd_listen_state);
1269 if (!pub_state) {
1270 goto failed;
1273 pub_state->privileged = false;
1274 pub_state->fd = create_pipe_sock(
1275 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1276 if (pub_state->fd == -1) {
1277 goto failed;
1279 rc = listen(pub_state->fd, 5);
1280 if (rc < 0) {
1281 goto failed;
1284 fde = tevent_add_fd(global_event_context(), pub_state, pub_state->fd,
1285 TEVENT_FD_READ, winbindd_listen_fde_handler,
1286 pub_state);
1287 if (fde == NULL) {
1288 close(pub_state->fd);
1289 goto failed;
1291 tevent_fd_set_auto_close(fde);
1293 priv_state = talloc(global_event_context(),
1294 struct winbindd_listen_state);
1295 if (!priv_state) {
1296 goto failed;
1299 socket_path = get_winbind_priv_pipe_dir();
1300 if (socket_path == NULL) {
1301 goto failed;
1304 priv_state->privileged = true;
1305 priv_state->fd = create_pipe_sock(
1306 socket_path, WINBINDD_SOCKET_NAME, 0750);
1307 TALLOC_FREE(socket_path);
1308 if (priv_state->fd == -1) {
1309 goto failed;
1311 rc = listen(priv_state->fd, 5);
1312 if (rc < 0) {
1313 goto failed;
1316 fde = tevent_add_fd(global_event_context(), priv_state,
1317 priv_state->fd, TEVENT_FD_READ,
1318 winbindd_listen_fde_handler, priv_state);
1319 if (fde == NULL) {
1320 close(priv_state->fd);
1321 goto failed;
1323 tevent_fd_set_auto_close(fde);
1325 winbindd_scrub_clients_handler(global_event_context(), NULL,
1326 timeval_current(), NULL);
1327 return true;
1328 failed:
1329 TALLOC_FREE(pub_state);
1330 TALLOC_FREE(priv_state);
1331 return false;
1334 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1335 bool foreground)
1337 bool scan_trusts = true;
1338 NTSTATUS status;
1339 struct tevent_timer *te = NULL;
1341 /* Setup signal handlers */
1343 if (!winbindd_setup_sig_term_handler(true))
1344 exit(1);
1345 if (!winbindd_setup_stdin_handler(true, foreground))
1346 exit(1);
1347 if (!winbindd_setup_sig_hup_handler(NULL))
1348 exit(1);
1349 if (!winbindd_setup_sig_chld_handler())
1350 exit(1);
1351 if (!winbindd_setup_sig_usr2_handler())
1352 exit(1);
1354 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1357 * Ensure all cache and idmap caches are consistent
1358 * and initialized before we startup.
1360 if (!winbindd_cache_validate_and_initialize()) {
1361 exit(1);
1364 /* React on 'smbcontrol winbindd reload-config' in the same way
1365 as to SIGHUP signal */
1366 messaging_register(msg_ctx, NULL,
1367 MSG_SMB_CONF_UPDATED,
1368 winbindd_msg_reload_services_parent);
1369 messaging_register(msg_ctx, NULL,
1370 MSG_SHUTDOWN, msg_shutdown);
1372 /* Handle online/offline messages. */
1373 messaging_register(msg_ctx, NULL,
1374 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1375 messaging_register(msg_ctx, NULL,
1376 MSG_WINBIND_ONLINE, winbind_msg_online);
1377 messaging_register(msg_ctx, NULL,
1378 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1380 /* Handle domain online/offline messages for domains */
1381 messaging_register(global_messaging_context(), NULL,
1382 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1383 messaging_register(global_messaging_context(), NULL,
1384 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1386 messaging_register(msg_ctx, NULL,
1387 MSG_WINBIND_VALIDATE_CACHE,
1388 winbind_msg_validate_cache);
1390 messaging_register(msg_ctx, NULL,
1391 MSG_WINBIND_DUMP_DOMAIN_LIST,
1392 winbind_msg_dump_domain_list);
1394 messaging_register(msg_ctx, NULL,
1395 MSG_WINBIND_IP_DROPPED,
1396 winbind_msg_ip_dropped_parent);
1398 /* Register handler for MSG_DEBUG. */
1399 messaging_register(msg_ctx, NULL,
1400 MSG_DEBUG,
1401 winbind_msg_debug);
1403 messaging_register(msg_ctx, NULL,
1404 MSG_WINBIND_DISCONNECT_DC,
1405 winbind_disconnect_dc_parent);
1407 netsamlogon_cache_init(); /* Non-critical */
1409 /* clear the cached list of trusted domains */
1411 wcache_tdc_clear();
1413 if (!init_domain_list()) {
1414 DEBUG(0,("unable to initialize domain list\n"));
1415 exit(1);
1418 init_idmap_child();
1419 init_locator_child();
1421 smb_nscd_flush_user_cache();
1422 smb_nscd_flush_group_cache();
1424 if (!lp_winbind_scan_trusted_domains()) {
1425 scan_trusts = false;
1428 if (!lp_allow_trusted_domains()) {
1429 scan_trusts = false;
1432 if (IS_DC) {
1433 scan_trusts = false;
1436 if (scan_trusts) {
1437 if (tevent_add_timer(global_event_context(), NULL, timeval_zero(),
1438 rescan_trusted_domains, NULL) == NULL) {
1439 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1440 exit(1);
1444 te = tevent_add_timer(global_event_context(),
1445 NULL,
1446 timeval_zero(),
1447 winbindd_ping_offline_domains,
1448 NULL);
1449 if (te == NULL) {
1450 DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
1451 exit(1);
1454 status = wb_irpc_register();
1456 if (!NT_STATUS_IS_OK(status)) {
1457 DEBUG(0, ("Could not register IRPC handlers\n"));
1458 exit(1);
1462 struct winbindd_addrchanged_state {
1463 struct addrchange_context *ctx;
1464 struct tevent_context *ev;
1465 struct messaging_context *msg_ctx;
1468 static void winbindd_addr_changed(struct tevent_req *req);
1470 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1471 struct tevent_context *ev,
1472 struct messaging_context *msg_ctx)
1474 struct winbindd_addrchanged_state *state;
1475 struct tevent_req *req;
1476 NTSTATUS status;
1478 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1479 if (state == NULL) {
1480 DEBUG(10, ("talloc failed\n"));
1481 return;
1483 state->ev = ev;
1484 state->msg_ctx = msg_ctx;
1486 status = addrchange_context_create(state, &state->ctx);
1487 if (!NT_STATUS_IS_OK(status)) {
1488 DEBUG(10, ("addrchange_context_create failed: %s\n",
1489 nt_errstr(status)));
1490 TALLOC_FREE(state);
1491 return;
1493 req = addrchange_send(state, ev, state->ctx);
1494 if (req == NULL) {
1495 DEBUG(0, ("addrchange_send failed\n"));
1496 TALLOC_FREE(state);
1497 return;
1499 tevent_req_set_callback(req, winbindd_addr_changed, state);
1502 static void winbindd_addr_changed(struct tevent_req *req)
1504 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1505 req, struct winbindd_addrchanged_state);
1506 enum addrchange_type type;
1507 struct sockaddr_storage addr;
1508 NTSTATUS status;
1510 status = addrchange_recv(req, &type, &addr);
1511 TALLOC_FREE(req);
1512 if (!NT_STATUS_IS_OK(status)) {
1513 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1514 nt_errstr(status)));
1515 TALLOC_FREE(state);
1516 return;
1518 if (type == ADDRCHANGE_DEL) {
1519 char addrstr[INET6_ADDRSTRLEN];
1520 DATA_BLOB blob;
1522 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1524 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1525 addrstr));
1527 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1529 status = messaging_send(state->msg_ctx,
1530 messaging_server_id(state->msg_ctx),
1531 MSG_WINBIND_IP_DROPPED, &blob);
1532 if (!NT_STATUS_IS_OK(status)) {
1533 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1534 nt_errstr(status)));
1537 req = addrchange_send(state, state->ev, state->ctx);
1538 if (req == NULL) {
1539 DEBUG(0, ("addrchange_send failed\n"));
1540 TALLOC_FREE(state);
1541 return;
1543 tevent_req_set_callback(req, winbindd_addr_changed, state);
1546 /* Main function */
1548 int main(int argc, const char **argv)
1550 static bool log_stdout = False;
1551 struct samba_cmdline_daemon_cfg *cmdline_daemon_cfg = NULL;
1552 struct poptOption long_options[] = {
1553 POPT_AUTOHELP
1555 .longName = "no-caching",
1556 .shortName = 'n',
1557 .argInfo = POPT_ARG_NONE,
1558 .arg = NULL,
1559 .val = 'n',
1560 .descrip = "Disable caching",
1562 POPT_COMMON_SAMBA
1563 POPT_COMMON_DAEMON
1564 POPT_COMMON_VERSION
1565 POPT_TABLEEND
1567 const struct loadparm_substitution *lp_sub =
1568 loadparm_s3_global_substitution();
1569 poptContext pc;
1570 int opt;
1571 TALLOC_CTX *frame;
1572 NTSTATUS status;
1573 bool ok;
1574 const struct dcesrv_endpoint_server *ep_server = NULL;
1575 struct dcesrv_context *dce_ctx = NULL;
1576 size_t winbindd_socket_dir_len = 0;
1577 char *winbindd_priv_socket_dir = NULL;
1578 size_t winbindd_priv_socket_dir_len = 0;
1580 setproctitle_init(argc, discard_const(argv), environ);
1583 * Do this before any other talloc operation
1585 talloc_enable_null_tracking();
1586 frame = talloc_stackframe();
1589 * We want total control over the permissions on created files,
1590 * so set our umask to 0.
1592 umask(0);
1594 smb_init_locale();
1596 /* glibc (?) likes to print "User defined signal 1" and exit if a
1597 SIGUSR[12] is received before a handler is installed */
1599 CatchSignal(SIGUSR1, SIG_IGN);
1600 CatchSignal(SIGUSR2, SIG_IGN);
1602 ok = samba_cmdline_init(frame,
1603 SAMBA_CMDLINE_CONFIG_SERVER,
1604 true /* require_smbconf */);
1605 if (!ok) {
1606 DBG_ERR("Failed to setup cmdline parser\n");
1607 TALLOC_FREE(frame);
1608 exit(1);
1611 cmdline_daemon_cfg = samba_cmdline_get_daemon_cfg();
1613 pc = samba_popt_get_context(getprogname(), argc, argv, long_options, 0);
1614 if (pc == NULL) {
1615 DBG_ERR("Failed to setup popt parser!\n");
1616 TALLOC_FREE(frame);
1617 exit(1);
1620 while ((opt = poptGetNextOpt(pc)) != -1) {
1621 switch (opt) {
1622 case 'n':
1623 winbindd_set_use_cache(false);
1624 break;
1625 default:
1626 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1627 poptBadOption(pc, 0), poptStrerror(opt));
1628 poptPrintUsage(pc, stderr, 0);
1629 exit(1);
1633 /* Set environment variable so we don't recursively call ourselves.
1634 This may also be useful interactively. */
1635 if ( !winbind_off() ) {
1636 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1637 exit(1);
1640 /* Initialise for running in non-root mode */
1641 sec_init();
1643 set_remote_machine_name("winbindd", False);
1645 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1646 if (cmdline_daemon_cfg->daemon && cmdline_daemon_cfg->interactive) {
1647 d_fprintf(stderr,"\nERROR: "
1648 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1649 poptPrintUsage(pc, stderr, 0);
1650 exit(1);
1653 log_stdout = (debug_get_log_type() == DEBUG_STDOUT);
1654 if (cmdline_daemon_cfg->interactive) {
1656 * libcmdline POPT_DAEMON callback sets "fork" to false if "-i"
1657 * for interactive is passed on the commandline. Set it back to
1658 * true. TODO: check if this is correct, smbd and nmbd don't do
1659 * this.
1661 cmdline_daemon_cfg->fork = true;
1662 log_stdout = true;
1665 if (log_stdout && cmdline_daemon_cfg->fork) {
1666 d_fprintf(stderr, "\nERROR: "
1667 "Can't log to stdout (-S) unless daemon is in "
1668 "foreground (-F) or interactive (-i)\n\n");
1669 poptPrintUsage(pc, stderr, 0);
1670 exit(1);
1673 poptFreeContext(pc);
1675 reopen_logs();
1677 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1678 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1680 /* After parsing the configuration file we setup the core path one more time
1681 * as the log file might have been set in the configuration and cores's
1682 * path is by default basename(lp_logfile()).
1684 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1686 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1687 if (!lp_parm_bool(-1, "server role check", "inhibit", false)) {
1688 DBG_ERR("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n");
1689 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"));
1690 exit(1);
1692 /* Main 'samba' daemon will notify */
1693 daemon_sd_notifications(false);
1696 if (lp_security() == SEC_ADS) {
1697 const char *realm = lp_realm();
1698 const char *workgroup = lp_workgroup();
1700 if (workgroup == NULL || strlen(workgroup) == 0) {
1701 DBG_ERR("For 'secuirity = ADS' mode, the 'workgroup' "
1702 "parameter is required to be set!\n");
1703 exit(1);
1706 if (realm == NULL || strlen(realm) == 0) {
1707 DBG_ERR("For 'secuirity = ADS' mode, the 'realm' "
1708 "parameter is required to be set!\n");
1709 exit(1);
1713 winbindd_socket_dir_len = strlen(lp_winbindd_socket_directory());
1714 if (winbindd_socket_dir_len > 0) {
1715 size_t winbindd_socket_len =
1716 winbindd_socket_dir_len + 1 +
1717 strlen(WINBINDD_SOCKET_NAME);
1718 struct sockaddr_un un = {
1719 .sun_family = AF_UNIX,
1721 size_t sun_path_len = sizeof(un.sun_path);
1723 if (winbindd_socket_len >= sun_path_len) {
1724 DBG_ERR("The winbind socket path [%s/%s] is too long "
1725 "(%zu >= %zu)\n",
1726 lp_winbindd_socket_directory(),
1727 WINBINDD_SOCKET_NAME,
1728 winbindd_socket_len,
1729 sun_path_len);
1730 exit(1);
1732 } else {
1733 DBG_ERR("'winbindd_socket_directory' parameter is empty\n");
1734 exit(1);
1737 winbindd_priv_socket_dir = get_winbind_priv_pipe_dir();
1738 winbindd_priv_socket_dir_len = strlen(winbindd_priv_socket_dir);
1739 if (winbindd_priv_socket_dir_len > 0) {
1740 size_t winbindd_priv_socket_len =
1741 winbindd_priv_socket_dir_len + 1 +
1742 strlen(WINBINDD_SOCKET_NAME);
1743 struct sockaddr_un un = {
1744 .sun_family = AF_UNIX,
1746 size_t sun_path_len = sizeof(un.sun_path);
1748 if (winbindd_priv_socket_len >= sun_path_len) {
1749 DBG_ERR("The winbind priviliged socket path [%s/%s] is too long "
1750 "(%zu >= %zu)\n",
1751 winbindd_priv_socket_dir,
1752 WINBINDD_SOCKET_NAME,
1753 winbindd_priv_socket_len,
1754 sun_path_len);
1755 exit(1);
1757 } else {
1758 DBG_ERR("'winbindd_priv_socket_directory' parameter is empty\n");
1759 exit(1);
1761 TALLOC_FREE(winbindd_priv_socket_dir);
1763 if (!cluster_probe_ok()) {
1764 exit(1);
1767 /* Initialise messaging system */
1769 if (global_messaging_context() == NULL) {
1770 exit(1);
1773 if (!winbindd_reload_services_file(NULL)) {
1774 DEBUG(0, ("error opening config file\n"));
1775 exit(1);
1779 size_t i;
1780 const char *idmap_backend;
1781 const char *invalid_backends[] = {
1782 "ad", "rfc2307", "rid",
1785 idmap_backend = lp_idmap_default_backend();
1786 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1787 ok = strequal(idmap_backend, invalid_backends[i]);
1788 if (ok) {
1789 DBG_ERR("FATAL: Invalid idmap backend %s "
1790 "configured as the default backend!\n",
1791 idmap_backend);
1792 exit(1);
1797 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1798 if (!ok) {
1799 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1800 lp_lock_directory(), strerror(errno)));
1801 exit(1);
1804 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1805 if (!ok) {
1806 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1807 lp_pid_directory(), strerror(errno)));
1808 exit(1);
1811 load_interfaces();
1813 if (!secrets_init()) {
1815 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1816 return False;
1819 status = rpccli_pre_open_netlogon_creds();
1820 if (!NT_STATUS_IS_OK(status)) {
1821 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1822 nt_errstr(status)));
1823 exit(1);
1826 /* Unblock all signals we are interested in as they may have been
1827 blocked by the parent process. */
1829 BlockSignals(False, SIGINT);
1830 BlockSignals(False, SIGQUIT);
1831 BlockSignals(False, SIGTERM);
1832 BlockSignals(False, SIGUSR1);
1833 BlockSignals(False, SIGUSR2);
1834 BlockSignals(False, SIGHUP);
1835 BlockSignals(False, SIGCHLD);
1837 if (!interactive) {
1838 become_daemon(cmdline_daemon_cfg->fork,
1839 cmdline_daemon_cfg->no_process_group,
1840 log_stdout);
1841 } else {
1842 daemon_status("winbindd", "Starting process ...");
1845 pidfile_create(lp_pid_directory(), "winbindd");
1847 #ifdef HAVE_SETPGID
1849 * If we're interactive we want to set our own process group for
1850 * signal management.
1852 if (cmdline_daemon_cfg->interactive &&
1853 !cmdline_daemon_cfg->no_process_group)
1855 setpgid( (pid_t)0, (pid_t)0);
1857 #endif
1859 TimeInit();
1861 /* Don't use winbindd_reinit_after_fork here as
1862 * we're just starting up and haven't created any
1863 * winbindd-specific resources we must free yet. JRA.
1866 status = reinit_after_fork(global_messaging_context(),
1867 global_event_context(),
1868 false, NULL);
1869 if (!NT_STATUS_IS_OK(status)) {
1870 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1873 ok = initialize_password_db(true, global_event_context());
1874 if (!ok) {
1875 exit_daemon("Failed to initialize passdb backend! "
1876 "Check the 'passdb backend' variable in your "
1877 "smb.conf file.", EINVAL);
1881 * Do not initialize the parent-child-pipe before becoming
1882 * a daemon: this is used to detect a died parent in the child
1883 * process.
1885 status = init_before_fork();
1886 if (!NT_STATUS_IS_OK(status)) {
1887 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1890 winbindd_register_handlers(global_messaging_context(),
1891 !cmdline_daemon_cfg->fork);
1893 if (!messaging_parent_dgm_cleanup_init(global_messaging_context())) {
1894 exit(1);
1897 status = init_system_session_info(NULL);
1898 if (!NT_STATUS_IS_OK(status)) {
1899 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1902 DBG_INFO("Registering DCE/RPC endpoint servers\n");
1904 ep_server = winbind_get_ep_server();
1905 if (ep_server == NULL) {
1906 DBG_ERR("Failed to get 'winbind' endpoint server\n");
1907 exit(1);
1909 status = dcerpc_register_ep_server(ep_server);
1910 if (!NT_STATUS_IS_OK(status)) {
1911 DBG_ERR("Failed to register 'winbind' endpoint "
1912 "server: %s\n", nt_errstr(status));
1913 exit(1);
1916 dce_ctx = global_dcesrv_context();
1918 DBG_INFO("Initializing DCE/RPC registered endpoint servers\n");
1920 /* Init all registered ep servers */
1921 status = dcesrv_init_registered_ep_servers(dce_ctx);
1922 if (!NT_STATUS_IS_OK(status)) {
1923 DBG_ERR("Failed to init DCE/RPC endpoint servers: %s\n",
1924 nt_errstr(status));
1925 exit(1);
1928 winbindd_init_addrchange(NULL, global_event_context(),
1929 global_messaging_context());
1931 /* setup listen sockets */
1933 if (!winbindd_setup_listeners()) {
1934 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1937 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1939 TALLOC_FREE(frame);
1941 if (!interactive) {
1942 daemon_ready("winbindd");
1945 gpupdate_init();
1947 /* Loop waiting for requests */
1948 while (1) {
1949 frame = talloc_stackframe();
1951 if (tevent_loop_once(global_event_context()) == -1) {
1952 DEBUG(1, ("tevent_loop_once() failed: %s\n",
1953 strerror(errno)));
1954 return 1;
1957 TALLOC_FREE(frame);
1960 return 0;