vfs_fruit: filter empty streams
[Samba.git] / source3 / winbindd / winbindd.c
bloba8ffc31778c68a8785c48b381c7647d6bc6ef7cc
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 "popt_common.h"
27 #include "winbindd.h"
28 #include "nsswitch/winbind_client.h"
29 #include "nsswitch/wb_reqtrans.h"
30 #include "ntdomain.h"
31 #include "../librpc/gen_ndr/srv_lsa.h"
32 #include "../librpc/gen_ndr/srv_samr.h"
33 #include "secrets.h"
34 #include "rpc_client/cli_netlogon.h"
35 #include "idmap.h"
36 #include "lib/addrchange.h"
37 #include "auth.h"
38 #include "messages.h"
39 #include "../lib/util/pidfile.h"
40 #include "util_cluster.h"
41 #include "source4/lib/messaging/irpc.h"
42 #include "source4/lib/messaging/messaging.h"
43 #include "lib/param/param.h"
44 #include "lib/async_req/async_sock.h"
45 #include "libsmb/samlogon_cache.h"
46 #include "libcli/auth/netlogon_creds_cli.h"
47 #include "passdb.h"
48 #include "lib/util/tevent_req_profile.h"
50 #undef DBGC_CLASS
51 #define DBGC_CLASS DBGC_WINBIND
53 #define SCRUB_CLIENTS_INTERVAL 5
55 static bool client_is_idle(struct winbindd_cli_state *state);
56 static void remove_client(struct winbindd_cli_state *state);
57 static void winbindd_setup_max_fds(void);
59 static bool opt_nocache = False;
60 static bool interactive = False;
62 extern bool override_logfile;
64 struct imessaging_context *winbind_imessaging_context(void)
66 static struct imessaging_context *msg = NULL;
67 struct messaging_context *msg_ctx;
68 struct server_id myself;
69 struct loadparm_context *lp_ctx;
71 if (msg != NULL) {
72 return msg;
75 msg_ctx = server_messaging_context();
76 if (msg_ctx == NULL) {
77 smb_panic("server_messaging_context failed\n");
79 myself = messaging_server_id(msg_ctx);
81 lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
82 if (lp_ctx == NULL) {
83 smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
87 * Note we MUST use the NULL context here, not the autofree context,
88 * to avoid side effects in forked children exiting.
90 msg = imessaging_init(NULL, lp_ctx, myself, server_event_context());
91 talloc_unlink(NULL, lp_ctx);
93 if (msg == NULL) {
94 smb_panic("Could not init winbindd's messaging context.\n");
96 return msg;
99 /* Reload configuration */
101 static bool reload_services_file(const char *lfile)
103 bool ret;
105 if (lp_loaded()) {
106 char *fname = lp_next_configfile(talloc_tos());
108 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
109 set_dyn_CONFIGFILE(fname);
111 TALLOC_FREE(fname);
114 /* if this is a child, restore the logfile to the special
115 name - <domain>, idmap, etc. */
116 if (lfile && *lfile) {
117 lp_set_logfile(lfile);
120 reopen_logs();
121 ret = lp_load_global(get_dyn_CONFIGFILE());
123 reopen_logs();
124 load_interfaces();
125 winbindd_setup_max_fds();
127 return(ret);
131 static void winbindd_status(void)
133 struct winbindd_cli_state *tmp;
135 DEBUG(0, ("winbindd status:\n"));
137 /* Print client state information */
139 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
141 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
142 DEBUG(2, ("\tclient list:\n"));
143 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
144 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
145 (unsigned long)tmp->pid, tmp->sock,
146 client_is_idle(tmp) ? "idle" : "active"));
151 /* Flush client cache */
153 static void flush_caches(void)
155 /* We need to invalidate cached user list entries on a SIGHUP
156 otherwise cached access denied errors due to restrict anonymous
157 hang around until the sequence number changes. */
159 if (!wcache_invalidate_cache()) {
160 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
161 if (!winbindd_cache_validate_and_initialize()) {
162 exit(1);
167 static void flush_caches_noinit(void)
170 * We need to invalidate cached user list entries on a SIGHUP
171 * otherwise cached access denied errors due to restrict anonymous
172 * hang around until the sequence number changes.
173 * NB
174 * Skip uninitialized domains when flush cache.
175 * If domain is not initialized, it means it is never
176 * used or never become online. look, wcache_invalidate_cache()
177 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
178 * for unused domains and large traffic for primay domain's DC if there
179 * are many domains..
182 if (!wcache_invalidate_cache_noinit()) {
183 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
184 if (!winbindd_cache_validate_and_initialize()) {
185 exit(1);
190 /* Handle the signal by unlinking socket and exiting */
192 static void terminate(bool is_parent)
194 if (is_parent) {
195 /* When parent goes away we should
196 * remove the socket file. Not so
197 * when children terminate.
199 char *path = NULL;
201 if (asprintf(&path, "%s/%s",
202 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
203 unlink(path);
204 SAFE_FREE(path);
208 idmap_close();
210 gencache_stabilize();
212 netlogon_creds_cli_close_global_db();
214 #if 0
215 if (interactive) {
216 TALLOC_CTX *mem_ctx = talloc_init("end_description");
217 char *description = talloc_describe_all(mem_ctx);
219 DEBUG(3, ("tallocs left:\n%s\n", description));
220 talloc_destroy(mem_ctx);
222 #endif
224 if (is_parent) {
225 pidfile_unlink(lp_pid_directory(), "winbindd");
228 exit(0);
231 static void winbindd_sig_term_handler(struct tevent_context *ev,
232 struct tevent_signal *se,
233 int signum,
234 int count,
235 void *siginfo,
236 void *private_data)
238 bool *p = talloc_get_type_abort(private_data, bool);
239 bool is_parent = *p;
241 TALLOC_FREE(p);
243 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
244 signum, is_parent));
245 terminate(is_parent);
249 handle stdin becoming readable when we are in --foreground mode
251 static void winbindd_stdin_handler(struct tevent_context *ev,
252 struct tevent_fd *fde,
253 uint16_t flags,
254 void *private_data)
256 char c;
257 if (read(0, &c, 1) != 1) {
258 bool *is_parent = talloc_get_type_abort(private_data, bool);
260 /* we have reached EOF on stdin, which means the
261 parent has exited. Shutdown the server */
262 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
263 (int)*is_parent));
264 terminate(*is_parent);
268 bool winbindd_setup_sig_term_handler(bool parent)
270 struct tevent_signal *se;
271 bool *is_parent;
273 is_parent = talloc(server_event_context(), bool);
274 if (!is_parent) {
275 return false;
278 *is_parent = parent;
280 se = tevent_add_signal(server_event_context(),
281 is_parent,
282 SIGTERM, 0,
283 winbindd_sig_term_handler,
284 is_parent);
285 if (!se) {
286 DEBUG(0,("failed to setup SIGTERM handler"));
287 talloc_free(is_parent);
288 return false;
291 se = tevent_add_signal(server_event_context(),
292 is_parent,
293 SIGINT, 0,
294 winbindd_sig_term_handler,
295 is_parent);
296 if (!se) {
297 DEBUG(0,("failed to setup SIGINT handler"));
298 talloc_free(is_parent);
299 return false;
302 se = tevent_add_signal(server_event_context(),
303 is_parent,
304 SIGQUIT, 0,
305 winbindd_sig_term_handler,
306 is_parent);
307 if (!se) {
308 DEBUG(0,("failed to setup SIGINT handler"));
309 talloc_free(is_parent);
310 return false;
313 return true;
316 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
318 bool *is_parent;
320 if (foreground) {
321 struct stat st;
323 is_parent = talloc(server_event_context(), bool);
324 if (!is_parent) {
325 return false;
328 *is_parent = parent;
330 /* if we are running in the foreground then look for
331 EOF on stdin, and exit if it happens. This allows
332 us to die if the parent process dies
333 Only do this on a pipe or socket, no other device.
335 if (fstat(0, &st) != 0) {
336 return false;
338 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
339 tevent_add_fd(server_event_context(),
340 is_parent,
342 TEVENT_FD_READ,
343 winbindd_stdin_handler,
344 is_parent);
348 return true;
351 static void winbindd_sig_hup_handler(struct tevent_context *ev,
352 struct tevent_signal *se,
353 int signum,
354 int count,
355 void *siginfo,
356 void *private_data)
358 const char *file = (const char *)private_data;
360 DEBUG(1,("Reloading services after SIGHUP\n"));
361 flush_caches_noinit();
362 reload_services_file(file);
365 bool winbindd_setup_sig_hup_handler(const char *lfile)
367 struct tevent_signal *se;
368 char *file = NULL;
370 if (lfile) {
371 file = talloc_strdup(server_event_context(),
372 lfile);
373 if (!file) {
374 return false;
378 se = tevent_add_signal(server_event_context(),
379 server_event_context(),
380 SIGHUP, 0,
381 winbindd_sig_hup_handler,
382 file);
383 if (!se) {
384 return false;
387 return true;
390 static void winbindd_sig_chld_handler(struct tevent_context *ev,
391 struct tevent_signal *se,
392 int signum,
393 int count,
394 void *siginfo,
395 void *private_data)
397 pid_t pid;
399 while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
400 winbind_child_died(pid);
404 static bool winbindd_setup_sig_chld_handler(void)
406 struct tevent_signal *se;
408 se = tevent_add_signal(server_event_context(),
409 server_event_context(),
410 SIGCHLD, 0,
411 winbindd_sig_chld_handler,
412 NULL);
413 if (!se) {
414 return false;
417 return true;
420 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
421 struct tevent_signal *se,
422 int signum,
423 int count,
424 void *siginfo,
425 void *private_data)
427 winbindd_status();
430 static bool winbindd_setup_sig_usr2_handler(void)
432 struct tevent_signal *se;
434 se = tevent_add_signal(server_event_context(),
435 server_event_context(),
436 SIGUSR2, 0,
437 winbindd_sig_usr2_handler,
438 NULL);
439 if (!se) {
440 return false;
443 return true;
446 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
447 static void msg_reload_services(struct messaging_context *msg,
448 void *private_data,
449 uint32_t msg_type,
450 struct server_id server_id,
451 DATA_BLOB *data)
453 /* Flush various caches */
454 flush_caches();
455 reload_services_file((const char *) private_data);
458 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
459 static void msg_shutdown(struct messaging_context *msg,
460 void *private_data,
461 uint32_t msg_type,
462 struct server_id server_id,
463 DATA_BLOB *data)
465 /* only the parent waits for this message */
466 DEBUG(0,("Got shutdown message\n"));
467 terminate(true);
471 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
472 void *private_data,
473 uint32_t msg_type,
474 struct server_id server_id,
475 DATA_BLOB *data)
477 uint8_t ret;
478 pid_t child_pid;
479 NTSTATUS status;
481 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
482 "message.\n"));
485 * call the validation code from a child:
486 * so we don't block the main winbindd and the validation
487 * code can safely use fork/waitpid...
489 child_pid = fork();
491 if (child_pid == -1) {
492 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
493 strerror(errno)));
494 return;
497 if (child_pid != 0) {
498 /* parent */
499 DEBUG(5, ("winbind_msg_validate_cache: child created with "
500 "pid %d.\n", (int)child_pid));
501 return;
504 /* child */
506 status = winbindd_reinit_after_fork(NULL, NULL);
507 if (!NT_STATUS_IS_OK(status)) {
508 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
509 nt_errstr(status)));
510 _exit(0);
513 /* install default SIGCHLD handler: validation code uses fork/waitpid */
514 CatchSignal(SIGCHLD, SIG_DFL);
516 setproctitle("validate cache child");
518 ret = (uint8_t)winbindd_validate_cache_nobackup();
519 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
520 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
521 (size_t)1);
522 _exit(0);
525 static struct winbindd_bool_dispatch_table {
526 enum winbindd_cmd cmd;
527 bool (*fn)(struct winbindd_cli_state *state);
528 const char *cmd_name;
529 } bool_dispatch_table[] = {
530 { WINBINDD_INTERFACE_VERSION,
531 winbindd_interface_version,
532 "INTERFACE_VERSION" },
533 { WINBINDD_INFO,
534 winbindd_info,
535 "INFO" },
536 { WINBINDD_PING,
537 winbindd_ping,
538 "PING" },
539 { WINBINDD_DOMAIN_NAME,
540 winbindd_domain_name,
541 "DOMAIN_NAME" },
542 { WINBINDD_NETBIOS_NAME,
543 winbindd_netbios_name,
544 "NETBIOS_NAME" },
545 { WINBINDD_DC_INFO,
546 winbindd_dc_info,
547 "DC_INFO" },
548 { WINBINDD_CCACHE_NTLMAUTH,
549 winbindd_ccache_ntlm_auth,
550 "NTLMAUTH" },
551 { WINBINDD_CCACHE_SAVE,
552 winbindd_ccache_save,
553 "CCACHE_SAVE" },
554 { WINBINDD_PRIV_PIPE_DIR,
555 winbindd_priv_pipe_dir,
556 "WINBINDD_PRIV_PIPE_DIR" },
557 { WINBINDD_LIST_TRUSTDOM,
558 winbindd_list_trusted_domains,
559 "LIST_TRUSTDOM" },
562 struct winbindd_async_dispatch_table {
563 enum winbindd_cmd cmd;
564 const char *cmd_name;
565 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
566 struct tevent_context *ev,
567 struct winbindd_cli_state *cli,
568 struct winbindd_request *request);
569 NTSTATUS (*recv_req)(struct tevent_req *req,
570 struct winbindd_response *presp);
573 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
574 { WINBINDD_LOOKUPSID, "LOOKUPSID",
575 winbindd_lookupsid_send, winbindd_lookupsid_recv },
576 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
577 winbindd_lookupsids_send, winbindd_lookupsids_recv },
578 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
579 winbindd_lookupname_send, winbindd_lookupname_recv },
580 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
581 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
582 { WINBINDD_XIDS_TO_SIDS, "XIDS_TO_SIDS",
583 winbindd_xids_to_sids_send, winbindd_xids_to_sids_recv },
584 { WINBINDD_GETPWSID, "GETPWSID",
585 winbindd_getpwsid_send, winbindd_getpwsid_recv },
586 { WINBINDD_GETPWNAM, "GETPWNAM",
587 winbindd_getpwnam_send, winbindd_getpwnam_recv },
588 { WINBINDD_GETPWUID, "GETPWUID",
589 winbindd_getpwuid_send, winbindd_getpwuid_recv },
590 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
591 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
592 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
593 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
594 { WINBINDD_GETGROUPS, "GETGROUPS",
595 winbindd_getgroups_send, winbindd_getgroups_recv },
596 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
597 winbindd_show_sequence_send, winbindd_show_sequence_recv },
598 { WINBINDD_GETGRGID, "GETGRGID",
599 winbindd_getgrgid_send, winbindd_getgrgid_recv },
600 { WINBINDD_GETGRNAM, "GETGRNAM",
601 winbindd_getgrnam_send, winbindd_getgrnam_recv },
602 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
603 winbindd_getusersids_send, winbindd_getusersids_recv },
604 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
605 winbindd_lookuprids_send, winbindd_lookuprids_recv },
606 { WINBINDD_SETPWENT, "SETPWENT",
607 winbindd_setpwent_send, winbindd_setpwent_recv },
608 { WINBINDD_GETPWENT, "GETPWENT",
609 winbindd_getpwent_send, winbindd_getpwent_recv },
610 { WINBINDD_ENDPWENT, "ENDPWENT",
611 winbindd_endpwent_send, winbindd_endpwent_recv },
612 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
613 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
614 { WINBINDD_GETDCNAME, "GETDCNAME",
615 winbindd_getdcname_send, winbindd_getdcname_recv },
616 { WINBINDD_SETGRENT, "SETGRENT",
617 winbindd_setgrent_send, winbindd_setgrent_recv },
618 { WINBINDD_GETGRENT, "GETGRENT",
619 winbindd_getgrent_send, winbindd_getgrent_recv },
620 { WINBINDD_ENDGRENT, "ENDGRENT",
621 winbindd_endgrent_send, winbindd_endgrent_recv },
622 { WINBINDD_LIST_USERS, "LIST_USERS",
623 winbindd_list_users_send, winbindd_list_users_recv },
624 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
625 winbindd_list_groups_send, winbindd_list_groups_recv },
626 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
627 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
628 { WINBINDD_PING_DC, "PING_DC",
629 winbindd_ping_dc_send, winbindd_ping_dc_recv },
630 { WINBINDD_PAM_AUTH, "PAM_AUTH",
631 winbindd_pam_auth_send, winbindd_pam_auth_recv },
632 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
633 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
634 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
635 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
636 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
637 winbindd_pam_chng_pswd_auth_crap_send,
638 winbindd_pam_chng_pswd_auth_crap_recv },
639 { WINBINDD_WINS_BYIP, "WINS_BYIP",
640 winbindd_wins_byip_send, winbindd_wins_byip_recv },
641 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
642 winbindd_wins_byname_send, winbindd_wins_byname_recv },
643 { WINBINDD_DOMAIN_INFO, "DOMAIN_INFO",
644 winbindd_domain_info_send, winbindd_domain_info_recv },
646 { 0, NULL, NULL, NULL }
649 static struct winbindd_async_dispatch_table async_priv_table[] = {
650 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
651 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
652 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
653 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
654 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
655 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
656 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
657 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
659 { 0, NULL, NULL, NULL }
662 struct process_request_state {
663 struct winbindd_cli_state *cli_state;
664 struct tevent_context *ev;
667 static void process_request_done(struct tevent_req *subreq);
668 static void process_request_written(struct tevent_req *subreq);
670 static struct tevent_req *process_request_send(
671 TALLOC_CTX *mem_ctx,
672 struct tevent_context *ev,
673 struct winbindd_cli_state *cli_state)
675 struct tevent_req *req, *subreq;
676 struct process_request_state *state;
677 struct winbindd_async_dispatch_table *atable;
678 enum winbindd_cmd cmd = cli_state->request->cmd;
679 size_t i;
680 bool ok;
682 req = tevent_req_create(mem_ctx, &state,
683 struct process_request_state);
684 if (req == NULL) {
685 return NULL;
687 state->cli_state = cli_state;
688 state->ev = ev;
690 ok = tevent_req_set_profile(req);
691 if (!ok) {
692 return tevent_req_post(req, ev);
695 SMB_ASSERT(cli_state->mem_ctx == NULL);
696 cli_state->mem_ctx = talloc_named(cli_state, 0, "winbind request");
697 if (tevent_req_nomem(cli_state->mem_ctx, req)) {
698 return tevent_req_post(req, ev);
701 cli_state->response = talloc_zero(
702 cli_state->mem_ctx,
703 struct winbindd_response);
704 if (tevent_req_nomem(cli_state->response, req)) {
705 return tevent_req_post(req, ev);
707 cli_state->response->result = WINBINDD_PENDING;
708 cli_state->response->length = sizeof(struct winbindd_response);
710 /* Remember who asked us. */
711 cli_state->pid = cli_state->request->pid;
713 cli_state->cmd_name = "unknown request";
714 cli_state->recv_fn = NULL;
716 /* client is newest */
717 winbindd_promote_client(cli_state);
719 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
720 if (cmd == atable->cmd) {
721 break;
725 if ((atable->send_req == NULL) && cli_state->privileged) {
726 for (atable = async_priv_table; atable->send_req;
727 atable += 1) {
728 if (cmd == atable->cmd) {
729 break;
734 if (atable->send_req != NULL) {
735 cli_state->cmd_name = atable->cmd_name;
736 cli_state->recv_fn = atable->recv_req;
738 DEBUG(10, ("process_request: Handling async request %d:%s\n",
739 (int)cli_state->pid, cli_state->cmd_name));
741 subreq = atable->send_req(
742 state,
743 state->ev,
744 cli_state,
745 cli_state->request);
746 if (tevent_req_nomem(subreq, req)) {
747 return tevent_req_post(req, ev);
749 tevent_req_set_callback(subreq, process_request_done, req);
750 return req;
753 for (i=0; i<ARRAY_SIZE(bool_dispatch_table); i++) {
754 if (cmd == bool_dispatch_table[i].cmd) {
755 break;
759 ok = false;
761 if (i < ARRAY_SIZE(bool_dispatch_table)) {
762 DBG_DEBUG("process_request: request fn %s\n",
763 bool_dispatch_table[i].cmd_name);
764 ok = bool_dispatch_table[i].fn(cli_state);
767 cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
769 TALLOC_FREE(cli_state->io_req);
770 TALLOC_FREE(cli_state->request);
772 subreq = wb_resp_write_send(
773 state,
774 state->ev,
775 cli_state->out_queue,
776 cli_state->sock,
777 cli_state->response);
778 if (tevent_req_nomem(subreq, req)) {
779 return tevent_req_post(req, ev);
781 tevent_req_set_callback(subreq, process_request_written, req);
783 cli_state->io_req = subreq;
785 return req;
788 static void process_request_done(struct tevent_req *subreq)
790 struct tevent_req *req = tevent_req_callback_data(
791 subreq, struct tevent_req);
792 struct process_request_state *state = tevent_req_data(
793 req, struct process_request_state);
794 struct winbindd_cli_state *cli_state = state->cli_state;
795 NTSTATUS status;
796 bool ok;
798 status = cli_state->recv_fn(subreq, cli_state->response);
799 TALLOC_FREE(subreq);
801 DBG_DEBUG("[%d:%s]: %s\n",
802 (int)cli_state->pid,
803 cli_state->cmd_name,
804 nt_errstr(status));
806 ok = NT_STATUS_IS_OK(status);
807 cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
809 TALLOC_FREE(cli_state->io_req);
810 TALLOC_FREE(cli_state->request);
812 subreq = wb_resp_write_send(
813 state,
814 state->ev,
815 cli_state->out_queue,
816 cli_state->sock,
817 cli_state->response);
818 if (tevent_req_nomem(subreq, req)) {
819 return;
821 tevent_req_set_callback(subreq, process_request_written, req);
823 cli_state->io_req = subreq;
826 static void process_request_written(struct tevent_req *subreq)
828 struct tevent_req *req = tevent_req_callback_data(
829 subreq, struct tevent_req);
830 struct process_request_state *state = tevent_req_data(
831 req, struct process_request_state);
832 struct winbindd_cli_state *cli_state = state->cli_state;
833 ssize_t ret;
834 int err;
836 cli_state->io_req = NULL;
838 ret = wb_resp_write_recv(subreq, &err);
839 TALLOC_FREE(subreq);
840 if (ret == -1) {
841 tevent_req_nterror(req, map_nt_error_from_unix(err));
842 return;
845 DBG_DEBUG("[%d:%s]: delivered response to client\n",
846 (int)cli_state->pid, cli_state->cmd_name);
848 TALLOC_FREE(cli_state->mem_ctx);
849 cli_state->response = NULL;
850 cli_state->cmd_name = "no request";
851 cli_state->recv_fn = NULL;
853 tevent_req_done(req);
856 static NTSTATUS process_request_recv(
857 struct tevent_req *req,
858 TALLOC_CTX *mem_ctx,
859 struct tevent_req_profile **profile)
861 NTSTATUS status;
863 if (tevent_req_is_nterror(req, &status)) {
864 tevent_req_received(req);
865 return status;
868 *profile = tevent_req_move_profile(req, mem_ctx);
869 tevent_req_received(req);
870 return NT_STATUS_OK;
874 * This is the main event loop of winbind requests. It goes through a
875 * state-machine of 3 read/write requests, 4 if you have extra data to send.
877 * An idle winbind client has a read request of 4 bytes outstanding,
878 * finalizing function is request_len_recv, checking the length. request_recv
879 * then processes the packet. The processing function then at some point has
880 * to call request_finished which schedules sending the response.
883 static void winbind_client_request_read(struct tevent_req *req);
884 static void winbind_client_activity(struct tevent_req *req);
885 static void winbind_client_processed(struct tevent_req *req);
887 /* Process a new connection by adding it to the client connection list */
889 static void new_connection(int listen_sock, bool privileged)
891 struct sockaddr_un sunaddr;
892 struct winbindd_cli_state *state;
893 struct tevent_req *req;
894 socklen_t len;
895 int sock;
897 /* Accept connection */
899 len = sizeof(sunaddr);
901 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
903 if (sock == -1) {
904 if (errno != EINTR) {
905 DEBUG(0, ("Failed to accept socket - %s\n",
906 strerror(errno)));
908 return;
910 smb_set_close_on_exec(sock);
912 DEBUG(6,("accepted socket %d\n", sock));
914 /* Create new connection structure */
916 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
917 close(sock);
918 return;
921 state->sock = sock;
923 state->out_queue = tevent_queue_create(state, "winbind client reply");
924 if (state->out_queue == NULL) {
925 close(sock);
926 TALLOC_FREE(state);
927 return;
930 state->privileged = privileged;
932 req = wb_req_read_send(state, server_event_context(), state->sock,
933 WINBINDD_MAX_EXTRA_DATA);
934 if (req == NULL) {
935 TALLOC_FREE(state);
936 close(sock);
937 return;
939 tevent_req_set_callback(req, winbind_client_request_read, state);
940 state->io_req = req;
942 /* Add to connection list */
944 winbindd_add_client(state);
947 static void winbind_client_request_read(struct tevent_req *req)
949 struct winbindd_cli_state *state = tevent_req_callback_data(
950 req, struct winbindd_cli_state);
951 ssize_t ret;
952 int err;
954 state->io_req = NULL;
956 ret = wb_req_read_recv(req, state, &state->request, &err);
957 TALLOC_FREE(req);
958 if (ret == -1) {
959 if (err == EPIPE) {
960 DEBUG(6, ("closing socket %d, client exited\n",
961 state->sock));
962 } else {
963 DEBUG(2, ("Could not read client request from fd %d: "
964 "%s\n", state->sock, strerror(err)));
966 close(state->sock);
967 state->sock = -1;
968 remove_client(state);
969 return;
972 req = wait_for_read_send(state, server_event_context(), state->sock,
973 true);
974 if (req == NULL) {
975 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
976 " wait_for_read_send failed - removing client\n",
977 (int)state->pid, state->cmd_name));
978 remove_client(state);
979 return;
981 tevent_req_set_callback(req, winbind_client_activity, state);
982 state->io_req = req;
984 req = process_request_send(state, server_event_context(), state);
985 if (req == NULL) {
986 DBG_ERR("process_request_send failed\n");
987 remove_client(state);
988 return;
990 tevent_req_set_callback(req, winbind_client_processed, state);
993 static void winbind_client_activity(struct tevent_req *req)
995 struct winbindd_cli_state *state =
996 tevent_req_callback_data(req, struct winbindd_cli_state);
997 int err;
998 bool has_data;
1000 has_data = wait_for_read_recv(req, &err);
1002 if (has_data) {
1003 DEBUG(0, ("winbind_client_activity[%d:%s]:"
1004 "unexpected data from client - removing client\n",
1005 (int)state->pid, state->cmd_name));
1006 } else {
1007 if (err == EPIPE) {
1008 DEBUG(6, ("winbind_client_activity[%d:%s]: "
1009 "client has closed connection - removing "
1010 "client\n",
1011 (int)state->pid, state->cmd_name));
1012 } else {
1013 DEBUG(2, ("winbind_client_activity[%d:%s]: "
1014 "client socket error (%s) - removing "
1015 "client\n",
1016 (int)state->pid, state->cmd_name,
1017 strerror(err)));
1021 remove_client(state);
1024 static void winbind_client_processed(struct tevent_req *req)
1026 struct winbindd_cli_state *cli_state = tevent_req_callback_data(
1027 req, struct winbindd_cli_state);
1028 struct tevent_req_profile *profile = NULL;
1029 struct timeval start, stop, diff;
1030 int threshold;
1031 NTSTATUS status;
1033 status = process_request_recv(req, cli_state, &profile);
1034 TALLOC_FREE(req);
1035 if (!NT_STATUS_IS_OK(status)) {
1036 DBG_DEBUG("process_request failed: %s\n", nt_errstr(status));
1037 remove_client(cli_state);
1038 return;
1041 tevent_req_profile_get_start(profile, NULL, &start);
1042 tevent_req_profile_get_stop(profile, NULL, &stop);
1043 diff = tevent_timeval_until(&start, &stop);
1045 threshold = lp_parm_int(-1, "winbind", "request profile threshold", 60);
1047 if (diff.tv_sec >= threshold) {
1048 int depth;
1049 char *str;
1051 depth = lp_parm_int(
1053 "winbind",
1054 "request profile depth",
1055 INT_MAX);
1057 DBG_ERR("request took %u.%.6u seconds\n",
1058 (unsigned)diff.tv_sec, (unsigned)diff.tv_usec);
1060 str = tevent_req_profile_string(profile, talloc_tos(), 0, depth);
1061 if (str != NULL) {
1062 /* No "\n", already contained in "str" */
1063 DEBUGADD(0, ("%s", str));
1065 TALLOC_FREE(str);
1068 TALLOC_FREE(profile);
1070 req = wb_req_read_send(
1071 cli_state,
1072 server_event_context(),
1073 cli_state->sock,
1074 WINBINDD_MAX_EXTRA_DATA);
1075 if (req == NULL) {
1076 remove_client(cli_state);
1077 return;
1079 tevent_req_set_callback(req, winbind_client_request_read, cli_state);
1080 cli_state->io_req = req;
1083 /* Remove a client connection from client connection list */
1085 static void remove_client(struct winbindd_cli_state *state)
1087 char c = 0;
1088 int nwritten;
1090 /* It's a dead client - hold a funeral */
1092 if (state == NULL) {
1093 return;
1097 * We need to remove a pending wb_req_read_*
1098 * or wb_resp_write_* request before closing the
1099 * socket.
1101 * This is important as they might have used tevent_add_fd() and we
1102 * use the epoll * backend on linux. So we must remove the tevent_fd
1103 * before closing the fd.
1105 * Otherwise we might hit a race with close_conns_after_fork() (via
1106 * winbindd_reinit_after_fork()) where a file descriptor
1107 * is still open in a child, which means it's still active in
1108 * the parents epoll queue, but the related tevent_fd is already
1109 * already gone in the parent.
1111 * See bug #11141.
1113 TALLOC_FREE(state->io_req);
1115 if (state->sock != -1) {
1116 /* tell client, we are closing ... */
1117 nwritten = write(state->sock, &c, sizeof(c));
1118 if (nwritten == -1) {
1119 DEBUG(2, ("final write to client failed: %s\n",
1120 strerror(errno)));
1123 /* Close socket */
1125 close(state->sock);
1126 state->sock = -1;
1129 TALLOC_FREE(state->mem_ctx);
1131 /* Remove from list and free */
1133 winbindd_remove_client(state);
1134 TALLOC_FREE(state);
1137 /* Is a client idle? */
1139 static bool client_is_idle(struct winbindd_cli_state *state) {
1140 return (state->request == NULL &&
1141 state->response == NULL &&
1142 !state->pwent_state && !state->grent_state);
1145 /* Shutdown client connection which has been idle for the longest time */
1147 static bool remove_idle_client(void)
1149 struct winbindd_cli_state *state, *remove_state = NULL;
1150 int nidle = 0;
1152 for (state = winbindd_client_list(); state; state = state->next) {
1153 if (client_is_idle(state)) {
1154 nidle++;
1155 /* list is sorted by access time */
1156 remove_state = state;
1160 if (remove_state) {
1161 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1162 nidle, remove_state->sock, (unsigned int)remove_state->pid));
1163 remove_client(remove_state);
1164 return True;
1167 return False;
1171 * Terminate all clients whose requests have taken longer than
1172 * "winbind request timeout" seconds to process, or have been
1173 * idle for more than "winbind request timeout" seconds.
1176 static void remove_timed_out_clients(void)
1178 struct winbindd_cli_state *state, *prev = NULL;
1179 time_t curr_time = time(NULL);
1180 int timeout_val = lp_winbind_request_timeout();
1182 for (state = winbindd_client_list_tail(); state; state = prev) {
1183 time_t expiry_time;
1185 prev = winbindd_client_list_prev(state);
1186 expiry_time = state->last_access + timeout_val;
1188 if (curr_time <= expiry_time) {
1189 /* list is sorted, previous clients in
1190 list are newer */
1191 break;
1194 if (client_is_idle(state)) {
1195 DEBUG(5,("Idle client timed out, "
1196 "shutting down sock %d, pid %u\n",
1197 state->sock,
1198 (unsigned int)state->pid));
1199 } else {
1200 DEBUG(5,("Client request timed out, "
1201 "shutting down sock %d, pid %u\n",
1202 state->sock,
1203 (unsigned int)state->pid));
1206 remove_client(state);
1210 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
1211 struct tevent_timer *te,
1212 struct timeval current_time,
1213 void *private_data)
1215 remove_timed_out_clients();
1216 if (tevent_add_timer(ev, ev,
1217 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
1218 winbindd_scrub_clients_handler, NULL) == NULL) {
1219 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
1220 exit(1);
1224 struct winbindd_listen_state {
1225 bool privileged;
1226 int fd;
1229 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1230 struct tevent_fd *fde,
1231 uint16_t flags,
1232 void *private_data)
1234 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1235 struct winbindd_listen_state);
1237 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1238 DEBUG(5,("winbindd: Exceeding %d client "
1239 "connections, removing idle "
1240 "connection.\n", lp_winbind_max_clients()));
1241 if (!remove_idle_client()) {
1242 DEBUG(0,("winbindd: Exceeding %d "
1243 "client connections, no idle "
1244 "connection found\n",
1245 lp_winbind_max_clients()));
1246 break;
1249 remove_timed_out_clients();
1250 new_connection(s->fd, s->privileged);
1254 * Winbindd socket accessor functions
1257 char *get_winbind_priv_pipe_dir(void)
1259 return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1262 static void winbindd_setup_max_fds(void)
1264 int num_fds = MAX_OPEN_FUDGEFACTOR;
1265 int actual_fds;
1267 num_fds += lp_winbind_max_clients();
1268 /* Add some more to account for 2 sockets open
1269 when the client transitions from unprivileged
1270 to privileged socket
1272 num_fds += lp_winbind_max_clients() / 10;
1274 /* Add one socket per child process
1275 (yeah there are child processes other than the
1276 domain children but only domain children can vary
1277 with configuration
1279 num_fds += lp_winbind_max_domain_connections() *
1280 (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
1282 actual_fds = set_maxfiles(num_fds);
1284 if (actual_fds < num_fds) {
1285 DEBUG(1, ("winbindd_setup_max_fds: Information only: "
1286 "requested %d open files, %d are available.\n",
1287 num_fds, actual_fds));
1291 static bool winbindd_setup_listeners(void)
1293 struct winbindd_listen_state *pub_state = NULL;
1294 struct winbindd_listen_state *priv_state = NULL;
1295 struct tevent_fd *fde;
1296 int rc;
1297 char *socket_path;
1299 pub_state = talloc(server_event_context(),
1300 struct winbindd_listen_state);
1301 if (!pub_state) {
1302 goto failed;
1305 pub_state->privileged = false;
1306 pub_state->fd = create_pipe_sock(
1307 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1308 if (pub_state->fd == -1) {
1309 goto failed;
1311 rc = listen(pub_state->fd, 5);
1312 if (rc < 0) {
1313 goto failed;
1316 fde = tevent_add_fd(server_event_context(), pub_state, pub_state->fd,
1317 TEVENT_FD_READ, winbindd_listen_fde_handler,
1318 pub_state);
1319 if (fde == NULL) {
1320 close(pub_state->fd);
1321 goto failed;
1323 tevent_fd_set_auto_close(fde);
1325 priv_state = talloc(server_event_context(),
1326 struct winbindd_listen_state);
1327 if (!priv_state) {
1328 goto failed;
1331 socket_path = get_winbind_priv_pipe_dir();
1332 if (socket_path == NULL) {
1333 goto failed;
1336 priv_state->privileged = true;
1337 priv_state->fd = create_pipe_sock(
1338 socket_path, WINBINDD_SOCKET_NAME, 0750);
1339 TALLOC_FREE(socket_path);
1340 if (priv_state->fd == -1) {
1341 goto failed;
1343 rc = listen(priv_state->fd, 5);
1344 if (rc < 0) {
1345 goto failed;
1348 fde = tevent_add_fd(server_event_context(), priv_state,
1349 priv_state->fd, TEVENT_FD_READ,
1350 winbindd_listen_fde_handler, priv_state);
1351 if (fde == NULL) {
1352 close(priv_state->fd);
1353 goto failed;
1355 tevent_fd_set_auto_close(fde);
1357 winbindd_scrub_clients_handler(server_event_context(), NULL,
1358 timeval_current(), NULL);
1359 return true;
1360 failed:
1361 TALLOC_FREE(pub_state);
1362 TALLOC_FREE(priv_state);
1363 return false;
1366 bool winbindd_use_idmap_cache(void)
1368 return !opt_nocache;
1371 bool winbindd_use_cache(void)
1373 return !opt_nocache;
1376 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1377 bool foreground)
1379 bool scan_trusts = true;
1380 NTSTATUS status;
1381 /* Setup signal handlers */
1383 if (!winbindd_setup_sig_term_handler(true))
1384 exit(1);
1385 if (!winbindd_setup_stdin_handler(true, foreground))
1386 exit(1);
1387 if (!winbindd_setup_sig_hup_handler(NULL))
1388 exit(1);
1389 if (!winbindd_setup_sig_chld_handler())
1390 exit(1);
1391 if (!winbindd_setup_sig_usr2_handler())
1392 exit(1);
1394 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1397 * Ensure all cache and idmap caches are consistent
1398 * and initialized before we startup.
1400 if (!winbindd_cache_validate_and_initialize()) {
1401 exit(1);
1404 /* React on 'smbcontrol winbindd reload-config' in the same way
1405 as to SIGHUP signal */
1406 messaging_register(msg_ctx, NULL,
1407 MSG_SMB_CONF_UPDATED, msg_reload_services);
1408 messaging_register(msg_ctx, NULL,
1409 MSG_SHUTDOWN, msg_shutdown);
1411 /* Handle online/offline messages. */
1412 messaging_register(msg_ctx, NULL,
1413 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1414 messaging_register(msg_ctx, NULL,
1415 MSG_WINBIND_ONLINE, winbind_msg_online);
1416 messaging_register(msg_ctx, NULL,
1417 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1419 /* Handle domain online/offline messages for domains */
1420 messaging_register(server_messaging_context(), NULL,
1421 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1422 messaging_register(server_messaging_context(), NULL,
1423 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1425 messaging_register(msg_ctx, NULL,
1426 MSG_WINBIND_VALIDATE_CACHE,
1427 winbind_msg_validate_cache);
1429 messaging_register(msg_ctx, NULL,
1430 MSG_WINBIND_DUMP_DOMAIN_LIST,
1431 winbind_msg_dump_domain_list);
1433 messaging_register(msg_ctx, NULL,
1434 MSG_WINBIND_IP_DROPPED,
1435 winbind_msg_ip_dropped_parent);
1437 /* Register handler for MSG_DEBUG. */
1438 messaging_register(msg_ctx, NULL,
1439 MSG_DEBUG,
1440 winbind_msg_debug);
1442 messaging_register(msg_ctx, NULL,
1443 MSG_WINBIND_DISCONNECT_DC,
1444 winbind_disconnect_dc_parent);
1446 netsamlogon_cache_init(); /* Non-critical */
1448 /* clear the cached list of trusted domains */
1450 wcache_tdc_clear();
1452 if (!init_domain_list()) {
1453 DEBUG(0,("unable to initialize domain list\n"));
1454 exit(1);
1457 init_idmap_child();
1458 init_locator_child();
1460 smb_nscd_flush_user_cache();
1461 smb_nscd_flush_group_cache();
1463 if (!lp_winbind_scan_trusted_domains()) {
1464 scan_trusts = false;
1467 if (!lp_allow_trusted_domains()) {
1468 scan_trusts = false;
1471 if (IS_DC) {
1472 scan_trusts = false;
1475 if (scan_trusts) {
1476 if (tevent_add_timer(server_event_context(), NULL, timeval_zero(),
1477 rescan_trusted_domains, NULL) == NULL) {
1478 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1479 exit(1);
1483 status = wb_irpc_register();
1485 if (!NT_STATUS_IS_OK(status)) {
1486 DEBUG(0, ("Could not register IRPC handlers\n"));
1487 exit(1);
1491 struct winbindd_addrchanged_state {
1492 struct addrchange_context *ctx;
1493 struct tevent_context *ev;
1494 struct messaging_context *msg_ctx;
1497 static void winbindd_addr_changed(struct tevent_req *req);
1499 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1500 struct tevent_context *ev,
1501 struct messaging_context *msg_ctx)
1503 struct winbindd_addrchanged_state *state;
1504 struct tevent_req *req;
1505 NTSTATUS status;
1507 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1508 if (state == NULL) {
1509 DEBUG(10, ("talloc failed\n"));
1510 return;
1512 state->ev = ev;
1513 state->msg_ctx = msg_ctx;
1515 status = addrchange_context_create(state, &state->ctx);
1516 if (!NT_STATUS_IS_OK(status)) {
1517 DEBUG(10, ("addrchange_context_create failed: %s\n",
1518 nt_errstr(status)));
1519 TALLOC_FREE(state);
1520 return;
1522 req = addrchange_send(state, ev, state->ctx);
1523 if (req == NULL) {
1524 DEBUG(0, ("addrchange_send failed\n"));
1525 TALLOC_FREE(state);
1526 return;
1528 tevent_req_set_callback(req, winbindd_addr_changed, state);
1531 static void winbindd_addr_changed(struct tevent_req *req)
1533 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1534 req, struct winbindd_addrchanged_state);
1535 enum addrchange_type type;
1536 struct sockaddr_storage addr;
1537 NTSTATUS status;
1539 status = addrchange_recv(req, &type, &addr);
1540 TALLOC_FREE(req);
1541 if (!NT_STATUS_IS_OK(status)) {
1542 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1543 nt_errstr(status)));
1544 TALLOC_FREE(state);
1545 return;
1547 if (type == ADDRCHANGE_DEL) {
1548 char addrstr[INET6_ADDRSTRLEN];
1549 DATA_BLOB blob;
1551 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1553 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1554 addrstr));
1556 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1558 status = messaging_send(state->msg_ctx,
1559 messaging_server_id(state->msg_ctx),
1560 MSG_WINBIND_IP_DROPPED, &blob);
1561 if (!NT_STATUS_IS_OK(status)) {
1562 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1563 nt_errstr(status)));
1566 req = addrchange_send(state, state->ev, state->ctx);
1567 if (req == NULL) {
1568 DEBUG(0, ("addrchange_send failed\n"));
1569 TALLOC_FREE(state);
1570 return;
1572 tevent_req_set_callback(req, winbindd_addr_changed, state);
1575 /* Main function */
1577 int main(int argc, const char **argv)
1579 static bool is_daemon = False;
1580 static bool Fork = True;
1581 static bool log_stdout = False;
1582 static bool no_process_group = False;
1583 enum {
1584 OPT_DAEMON = 1000,
1585 OPT_FORK,
1586 OPT_NO_PROCESS_GROUP,
1587 OPT_LOG_STDOUT
1589 struct poptOption long_options[] = {
1590 POPT_AUTOHELP
1591 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1592 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1593 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1594 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1595 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1596 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1597 POPT_COMMON_SAMBA
1598 POPT_TABLEEND
1600 poptContext pc;
1601 int opt;
1602 TALLOC_CTX *frame;
1603 NTSTATUS status;
1604 bool ok;
1606 setproctitle_init(argc, discard_const(argv), environ);
1609 * Do this before any other talloc operation
1611 talloc_enable_null_tracking();
1612 frame = talloc_stackframe();
1615 * We want total control over the permissions on created files,
1616 * so set our umask to 0.
1618 umask(0);
1620 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1622 /* glibc (?) likes to print "User defined signal 1" and exit if a
1623 SIGUSR[12] is received before a handler is installed */
1625 CatchSignal(SIGUSR1, SIG_IGN);
1626 CatchSignal(SIGUSR2, SIG_IGN);
1628 fault_setup();
1629 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1631 smb_init_locale();
1633 /* Initialise for running in non-root mode */
1635 sec_init();
1637 set_remote_machine_name("winbindd", False);
1639 /* Set environment variable so we don't recursively call ourselves.
1640 This may also be useful interactively. */
1642 if ( !winbind_off() ) {
1643 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1644 exit(1);
1647 /* Initialise samba/rpc client stuff */
1649 pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1651 while ((opt = poptGetNextOpt(pc)) != -1) {
1652 switch (opt) {
1653 /* Don't become a daemon */
1654 case OPT_DAEMON:
1655 is_daemon = True;
1656 break;
1657 case 'i':
1658 interactive = True;
1659 log_stdout = True;
1660 Fork = False;
1661 break;
1662 case OPT_FORK:
1663 Fork = false;
1664 break;
1665 case OPT_NO_PROCESS_GROUP:
1666 no_process_group = true;
1667 break;
1668 case OPT_LOG_STDOUT:
1669 log_stdout = true;
1670 break;
1671 case 'n':
1672 opt_nocache = true;
1673 break;
1674 default:
1675 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1676 poptBadOption(pc, 0), poptStrerror(opt));
1677 poptPrintUsage(pc, stderr, 0);
1678 exit(1);
1682 /* We call dump_core_setup one more time because the command line can
1683 * set the log file or the log-basename and this will influence where
1684 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1685 * the default value derived from build's prefix. For EOM this value
1686 * is often not related to the path where winbindd is actually run
1687 * in production.
1689 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1690 if (is_daemon && interactive) {
1691 d_fprintf(stderr,"\nERROR: "
1692 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1693 poptPrintUsage(pc, stderr, 0);
1694 exit(1);
1697 if (log_stdout && Fork) {
1698 d_fprintf(stderr, "\nERROR: "
1699 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1700 poptPrintUsage(pc, stderr, 0);
1701 exit(1);
1704 poptFreeContext(pc);
1706 if (!override_logfile) {
1707 char *lfile = NULL;
1708 if (asprintf(&lfile,"%s/log.winbindd",
1709 get_dyn_LOGFILEBASE()) > 0) {
1710 lp_set_logfile(lfile);
1711 SAFE_FREE(lfile);
1715 if (log_stdout) {
1716 setup_logging("winbindd", DEBUG_STDOUT);
1717 } else {
1718 setup_logging("winbindd", DEBUG_FILE);
1720 reopen_logs();
1722 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1723 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1725 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1726 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1727 exit(1);
1729 /* After parsing the configuration file we setup the core path one more time
1730 * as the log file might have been set in the configuration and cores's
1731 * path is by default basename(lp_logfile()).
1733 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1735 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1736 && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1737 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1738 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"));
1739 exit(1);
1742 if (!cluster_probe_ok()) {
1743 exit(1);
1746 /* Initialise messaging system */
1748 if (server_messaging_context() == NULL) {
1749 exit(1);
1752 if (!reload_services_file(NULL)) {
1753 DEBUG(0, ("error opening config file\n"));
1754 exit(1);
1758 size_t i;
1759 const char *idmap_backend;
1760 const char *invalid_backends[] = {
1761 "ad", "rfc2307", "rid",
1764 idmap_backend = lp_idmap_default_backend();
1765 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1766 ok = strequal(idmap_backend, invalid_backends[i]);
1767 if (ok) {
1768 DBG_ERR("FATAL: Invalid idmap backend %s "
1769 "configured as the default backend!\n",
1770 idmap_backend);
1771 exit(1);
1776 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1777 if (!ok) {
1778 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1779 lp_lock_directory(), strerror(errno)));
1780 exit(1);
1783 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1784 if (!ok) {
1785 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1786 lp_pid_directory(), strerror(errno)));
1787 exit(1);
1790 /* Setup names. */
1792 if (!init_names())
1793 exit(1);
1795 load_interfaces();
1797 if (!secrets_init()) {
1799 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1800 return False;
1803 status = rpccli_pre_open_netlogon_creds();
1804 if (!NT_STATUS_IS_OK(status)) {
1805 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1806 nt_errstr(status)));
1807 exit(1);
1810 /* Unblock all signals we are interested in as they may have been
1811 blocked by the parent process. */
1813 BlockSignals(False, SIGINT);
1814 BlockSignals(False, SIGQUIT);
1815 BlockSignals(False, SIGTERM);
1816 BlockSignals(False, SIGUSR1);
1817 BlockSignals(False, SIGUSR2);
1818 BlockSignals(False, SIGHUP);
1819 BlockSignals(False, SIGCHLD);
1821 if (!interactive)
1822 become_daemon(Fork, no_process_group, log_stdout);
1824 pidfile_create(lp_pid_directory(), "winbindd");
1826 #if HAVE_SETPGID
1828 * If we're interactive we want to set our own process group for
1829 * signal management.
1831 if (interactive && !no_process_group)
1832 setpgid( (pid_t)0, (pid_t)0);
1833 #endif
1835 TimeInit();
1837 /* Don't use winbindd_reinit_after_fork here as
1838 * we're just starting up and haven't created any
1839 * winbindd-specific resources we must free yet. JRA.
1842 status = reinit_after_fork(server_messaging_context(),
1843 server_event_context(),
1844 false, NULL);
1845 if (!NT_STATUS_IS_OK(status)) {
1846 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1849 ok = initialize_password_db(true, server_event_context());
1850 if (!ok) {
1851 exit_daemon("Failed to initialize passdb backend! "
1852 "Check the 'passdb backend' variable in your "
1853 "smb.conf file.", EINVAL);
1857 * Do not initialize the parent-child-pipe before becoming
1858 * a daemon: this is used to detect a died parent in the child
1859 * process.
1861 status = init_before_fork();
1862 if (!NT_STATUS_IS_OK(status)) {
1863 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1866 winbindd_register_handlers(server_messaging_context(), !Fork);
1868 if (!messaging_parent_dgm_cleanup_init(server_messaging_context())) {
1869 exit(1);
1872 status = init_system_session_info(NULL);
1873 if (!NT_STATUS_IS_OK(status)) {
1874 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1877 rpc_lsarpc_init(NULL);
1878 rpc_samr_init(NULL);
1880 winbindd_init_addrchange(NULL, server_event_context(),
1881 server_messaging_context());
1883 /* setup listen sockets */
1885 if (!winbindd_setup_listeners()) {
1886 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1889 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1891 TALLOC_FREE(frame);
1893 if (!interactive) {
1894 daemon_ready("winbindd");
1897 gpupdate_init();
1899 /* Loop waiting for requests */
1900 while (1) {
1901 frame = talloc_stackframe();
1903 if (tevent_loop_once(server_event_context()) == -1) {
1904 DEBUG(1, ("tevent_loop_once() failed: %s\n",
1905 strerror(errno)));
1906 return 1;
1909 TALLOC_FREE(frame);
1912 return 0;