gpo: Add CSE for applying smb.conf
[Samba.git] / source3 / winbindd / winbindd.c
blob4397a1bc0d12699e006ba62b0d79b791a30f34f2
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/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"
54 #undef DBGC_CLASS
55 #define DBGC_CLASS DBGC_WINBIND
57 #define SCRUB_CLIENTS_INTERVAL 5
59 static bool client_is_idle(struct winbindd_cli_state *state);
60 static void remove_client(struct winbindd_cli_state *state);
61 static void winbindd_setup_max_fds(void);
63 static bool opt_nocache = False;
64 static bool interactive = False;
66 extern bool override_logfile;
68 struct imessaging_context *winbind_imessaging_context(void)
70 static struct imessaging_context *msg = NULL;
71 struct messaging_context *msg_ctx;
72 struct server_id myself;
73 struct loadparm_context *lp_ctx;
75 if (msg != NULL) {
76 return msg;
79 msg_ctx = global_messaging_context();
80 if (msg_ctx == NULL) {
81 smb_panic("global_messaging_context failed\n");
83 myself = messaging_server_id(msg_ctx);
85 lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
86 if (lp_ctx == NULL) {
87 smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
91 * Note we MUST use the NULL context here, not the autofree context,
92 * to avoid side effects in forked children exiting.
94 msg = imessaging_init(NULL, lp_ctx, myself, global_event_context());
95 talloc_unlink(NULL, lp_ctx);
97 if (msg == NULL) {
98 smb_panic("Could not init winbindd's messaging context.\n");
100 return msg;
103 /* Reload configuration */
105 static bool reload_services_file(const char *lfile)
107 const struct loadparm_substitution *lp_sub =
108 loadparm_s3_global_substitution();
109 bool ret;
111 if (lp_loaded()) {
112 char *fname = lp_next_configfile(talloc_tos(), lp_sub);
114 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
115 set_dyn_CONFIGFILE(fname);
117 TALLOC_FREE(fname);
120 /* if this is a child, restore the logfile to the special
121 name - <domain>, idmap, etc. */
122 if (lfile && *lfile) {
123 lp_set_logfile(lfile);
126 reopen_logs();
127 ret = lp_load_global(get_dyn_CONFIGFILE());
129 reopen_logs();
130 load_interfaces();
131 winbindd_setup_max_fds();
133 return(ret);
137 static void winbindd_status(void)
139 struct winbindd_cli_state *tmp;
141 DEBUG(0, ("winbindd status:\n"));
143 /* Print client state information */
145 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
147 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
148 DEBUG(2, ("\tclient list:\n"));
149 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
150 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
151 (unsigned long)tmp->pid, tmp->sock,
152 client_is_idle(tmp) ? "idle" : "active"));
157 /* Flush client cache */
159 static void flush_caches(void)
161 /* We need to invalidate cached user list entries on a SIGHUP
162 otherwise cached access denied errors due to restrict anonymous
163 hang around until the sequence number changes. */
165 if (!wcache_invalidate_cache()) {
166 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
167 if (!winbindd_cache_validate_and_initialize()) {
168 exit(1);
173 static void flush_caches_noinit(void)
176 * We need to invalidate cached user list entries on a SIGHUP
177 * otherwise cached access denied errors due to restrict anonymous
178 * hang around until the sequence number changes.
179 * NB
180 * Skip uninitialized domains when flush cache.
181 * If domain is not initialized, it means it is never
182 * used or never become online. look, wcache_invalidate_cache()
183 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
184 * for unused domains and large traffic for primay domain's DC if there
185 * are many domains..
188 if (!wcache_invalidate_cache_noinit()) {
189 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
190 if (!winbindd_cache_validate_and_initialize()) {
191 exit(1);
196 /* Handle the signal by unlinking socket and exiting */
198 static void terminate(bool is_parent)
200 if (is_parent) {
201 /* When parent goes away we should
202 * remove the socket file. Not so
203 * when children terminate.
205 char *path = NULL;
207 if (asprintf(&path, "%s/%s",
208 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
209 unlink(path);
210 SAFE_FREE(path);
214 idmap_close();
216 netlogon_creds_cli_close_global_db();
218 #if 0
219 if (interactive) {
220 TALLOC_CTX *mem_ctx = talloc_init("end_description");
221 char *description = talloc_describe_all(mem_ctx);
223 DEBUG(3, ("tallocs left:\n%s\n", description));
224 talloc_destroy(mem_ctx);
226 #endif
228 if (is_parent) {
229 pidfile_unlink(lp_pid_directory(), "winbindd");
232 exit(0);
235 static void winbindd_sig_term_handler(struct tevent_context *ev,
236 struct tevent_signal *se,
237 int signum,
238 int count,
239 void *siginfo,
240 void *private_data)
242 bool *p = talloc_get_type_abort(private_data, bool);
243 bool is_parent = *p;
245 TALLOC_FREE(p);
247 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
248 signum, is_parent));
249 terminate(is_parent);
253 handle stdin becoming readable when we are in --foreground mode
255 static void winbindd_stdin_handler(struct tevent_context *ev,
256 struct tevent_fd *fde,
257 uint16_t flags,
258 void *private_data)
260 char c;
261 if (read(0, &c, 1) != 1) {
262 bool *is_parent = talloc_get_type_abort(private_data, bool);
264 /* we have reached EOF on stdin, which means the
265 parent has exited. Shutdown the server */
266 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
267 (int)*is_parent));
268 terminate(*is_parent);
272 bool winbindd_setup_sig_term_handler(bool parent)
274 struct tevent_signal *se;
275 bool *is_parent;
277 is_parent = talloc(global_event_context(), bool);
278 if (!is_parent) {
279 return false;
282 *is_parent = parent;
284 se = tevent_add_signal(global_event_context(),
285 is_parent,
286 SIGTERM, 0,
287 winbindd_sig_term_handler,
288 is_parent);
289 if (!se) {
290 DEBUG(0,("failed to setup SIGTERM handler"));
291 talloc_free(is_parent);
292 return false;
295 se = tevent_add_signal(global_event_context(),
296 is_parent,
297 SIGINT, 0,
298 winbindd_sig_term_handler,
299 is_parent);
300 if (!se) {
301 DEBUG(0,("failed to setup SIGINT handler"));
302 talloc_free(is_parent);
303 return false;
306 se = tevent_add_signal(global_event_context(),
307 is_parent,
308 SIGQUIT, 0,
309 winbindd_sig_term_handler,
310 is_parent);
311 if (!se) {
312 DEBUG(0,("failed to setup SIGINT handler"));
313 talloc_free(is_parent);
314 return false;
317 return true;
320 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
322 bool *is_parent;
324 if (foreground) {
325 struct stat st;
327 is_parent = talloc(global_event_context(), bool);
328 if (!is_parent) {
329 return false;
332 *is_parent = parent;
334 /* if we are running in the foreground then look for
335 EOF on stdin, and exit if it happens. This allows
336 us to die if the parent process dies
337 Only do this on a pipe or socket, no other device.
339 if (fstat(0, &st) != 0) {
340 return false;
342 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
343 tevent_add_fd(global_event_context(),
344 is_parent,
346 TEVENT_FD_READ,
347 winbindd_stdin_handler,
348 is_parent);
352 return true;
355 static void winbindd_sig_hup_handler(struct tevent_context *ev,
356 struct tevent_signal *se,
357 int signum,
358 int count,
359 void *siginfo,
360 void *private_data)
362 const char *file = (const char *)private_data;
364 DEBUG(1,("Reloading services after SIGHUP\n"));
365 flush_caches_noinit();
366 reload_services_file(file);
369 bool winbindd_setup_sig_hup_handler(const char *lfile)
371 struct tevent_signal *se;
372 char *file = NULL;
374 if (lfile) {
375 file = talloc_strdup(global_event_context(),
376 lfile);
377 if (!file) {
378 return false;
382 se = tevent_add_signal(global_event_context(),
383 global_event_context(),
384 SIGHUP, 0,
385 winbindd_sig_hup_handler,
386 file);
387 if (!se) {
388 return false;
391 return true;
394 static void winbindd_sig_chld_handler(struct tevent_context *ev,
395 struct tevent_signal *se,
396 int signum,
397 int count,
398 void *siginfo,
399 void *private_data)
401 pid_t pid;
403 while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
404 winbind_child_died(pid);
408 static bool winbindd_setup_sig_chld_handler(void)
410 struct tevent_signal *se;
412 se = tevent_add_signal(global_event_context(),
413 global_event_context(),
414 SIGCHLD, 0,
415 winbindd_sig_chld_handler,
416 NULL);
417 if (!se) {
418 return false;
421 return true;
424 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
425 struct tevent_signal *se,
426 int signum,
427 int count,
428 void *siginfo,
429 void *private_data)
431 winbindd_status();
434 static bool winbindd_setup_sig_usr2_handler(void)
436 struct tevent_signal *se;
438 se = tevent_add_signal(global_event_context(),
439 global_event_context(),
440 SIGUSR2, 0,
441 winbindd_sig_usr2_handler,
442 NULL);
443 if (!se) {
444 return false;
447 return true;
450 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
451 static void msg_reload_services(struct messaging_context *msg,
452 void *private_data,
453 uint32_t msg_type,
454 struct server_id server_id,
455 DATA_BLOB *data)
457 /* Flush various caches */
458 flush_caches();
459 reload_services_file((const char *) private_data);
462 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
463 static void msg_shutdown(struct messaging_context *msg,
464 void *private_data,
465 uint32_t msg_type,
466 struct server_id server_id,
467 DATA_BLOB *data)
469 /* only the parent waits for this message */
470 DEBUG(0,("Got shutdown message\n"));
471 terminate(true);
475 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
476 void *private_data,
477 uint32_t msg_type,
478 struct server_id server_id,
479 DATA_BLOB *data)
481 uint8_t ret;
482 pid_t child_pid;
483 NTSTATUS status;
485 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
486 "message.\n"));
489 * call the validation code from a child:
490 * so we don't block the main winbindd and the validation
491 * code can safely use fork/waitpid...
493 child_pid = fork();
495 if (child_pid == -1) {
496 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
497 strerror(errno)));
498 return;
501 if (child_pid != 0) {
502 /* parent */
503 DEBUG(5, ("winbind_msg_validate_cache: child created with "
504 "pid %d.\n", (int)child_pid));
505 return;
508 /* child */
510 status = winbindd_reinit_after_fork(NULL, NULL);
511 if (!NT_STATUS_IS_OK(status)) {
512 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
513 nt_errstr(status)));
514 _exit(0);
517 /* install default SIGCHLD handler: validation code uses fork/waitpid */
518 CatchSignal(SIGCHLD, SIG_DFL);
520 setproctitle("validate cache child");
522 ret = (uint8_t)winbindd_validate_cache_nobackup();
523 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
524 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
525 (size_t)1);
526 _exit(0);
529 static struct winbindd_bool_dispatch_table {
530 enum winbindd_cmd cmd;
531 bool (*fn)(struct winbindd_cli_state *state);
532 const char *cmd_name;
533 } bool_dispatch_table[] = {
534 { WINBINDD_INTERFACE_VERSION,
535 winbindd_interface_version,
536 "INTERFACE_VERSION" },
537 { WINBINDD_INFO,
538 winbindd_info,
539 "INFO" },
540 { WINBINDD_PING,
541 winbindd_ping,
542 "PING" },
543 { WINBINDD_DOMAIN_NAME,
544 winbindd_domain_name,
545 "DOMAIN_NAME" },
546 { WINBINDD_NETBIOS_NAME,
547 winbindd_netbios_name,
548 "NETBIOS_NAME" },
549 { WINBINDD_DC_INFO,
550 winbindd_dc_info,
551 "DC_INFO" },
552 { WINBINDD_CCACHE_NTLMAUTH,
553 winbindd_ccache_ntlm_auth,
554 "NTLMAUTH" },
555 { WINBINDD_CCACHE_SAVE,
556 winbindd_ccache_save,
557 "CCACHE_SAVE" },
558 { WINBINDD_PRIV_PIPE_DIR,
559 winbindd_priv_pipe_dir,
560 "WINBINDD_PRIV_PIPE_DIR" },
561 { WINBINDD_LIST_TRUSTDOM,
562 winbindd_list_trusted_domains,
563 "LIST_TRUSTDOM" },
566 struct winbindd_async_dispatch_table {
567 enum winbindd_cmd cmd;
568 const char *cmd_name;
569 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
570 struct tevent_context *ev,
571 struct winbindd_cli_state *cli,
572 struct winbindd_request *request);
573 NTSTATUS (*recv_req)(struct tevent_req *req,
574 struct winbindd_response *presp);
577 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
578 { WINBINDD_LOOKUPSID, "LOOKUPSID",
579 winbindd_lookupsid_send, winbindd_lookupsid_recv },
580 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
581 winbindd_lookupsids_send, winbindd_lookupsids_recv },
582 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
583 winbindd_lookupname_send, winbindd_lookupname_recv },
584 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
585 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
586 { WINBINDD_XIDS_TO_SIDS, "XIDS_TO_SIDS",
587 winbindd_xids_to_sids_send, winbindd_xids_to_sids_recv },
588 { WINBINDD_GETPWSID, "GETPWSID",
589 winbindd_getpwsid_send, winbindd_getpwsid_recv },
590 { WINBINDD_GETPWNAM, "GETPWNAM",
591 winbindd_getpwnam_send, winbindd_getpwnam_recv },
592 { WINBINDD_GETPWUID, "GETPWUID",
593 winbindd_getpwuid_send, winbindd_getpwuid_recv },
594 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
595 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
596 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
597 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
598 { WINBINDD_GETGROUPS, "GETGROUPS",
599 winbindd_getgroups_send, winbindd_getgroups_recv },
600 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
601 winbindd_show_sequence_send, winbindd_show_sequence_recv },
602 { WINBINDD_GETGRGID, "GETGRGID",
603 winbindd_getgrgid_send, winbindd_getgrgid_recv },
604 { WINBINDD_GETGRNAM, "GETGRNAM",
605 winbindd_getgrnam_send, winbindd_getgrnam_recv },
606 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
607 winbindd_getusersids_send, winbindd_getusersids_recv },
608 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
609 winbindd_lookuprids_send, winbindd_lookuprids_recv },
610 { WINBINDD_SETPWENT, "SETPWENT",
611 winbindd_setpwent_send, winbindd_setpwent_recv },
612 { WINBINDD_GETPWENT, "GETPWENT",
613 winbindd_getpwent_send, winbindd_getpwent_recv },
614 { WINBINDD_ENDPWENT, "ENDPWENT",
615 winbindd_endpwent_send, winbindd_endpwent_recv },
616 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
617 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
618 { WINBINDD_GETDCNAME, "GETDCNAME",
619 winbindd_getdcname_send, winbindd_getdcname_recv },
620 { WINBINDD_SETGRENT, "SETGRENT",
621 winbindd_setgrent_send, winbindd_setgrent_recv },
622 { WINBINDD_GETGRENT, "GETGRENT",
623 winbindd_getgrent_send, winbindd_getgrent_recv },
624 { WINBINDD_ENDGRENT, "ENDGRENT",
625 winbindd_endgrent_send, winbindd_endgrent_recv },
626 { WINBINDD_LIST_USERS, "LIST_USERS",
627 winbindd_list_users_send, winbindd_list_users_recv },
628 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
629 winbindd_list_groups_send, winbindd_list_groups_recv },
630 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
631 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
632 { WINBINDD_PING_DC, "PING_DC",
633 winbindd_ping_dc_send, winbindd_ping_dc_recv },
634 { WINBINDD_PAM_AUTH, "PAM_AUTH",
635 winbindd_pam_auth_send, winbindd_pam_auth_recv },
636 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
637 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
638 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
639 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
640 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
641 winbindd_pam_chng_pswd_auth_crap_send,
642 winbindd_pam_chng_pswd_auth_crap_recv },
643 { WINBINDD_WINS_BYIP, "WINS_BYIP",
644 winbindd_wins_byip_send, winbindd_wins_byip_recv },
645 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
646 winbindd_wins_byname_send, winbindd_wins_byname_recv },
647 { WINBINDD_DOMAIN_INFO, "DOMAIN_INFO",
648 winbindd_domain_info_send, winbindd_domain_info_recv },
650 { 0, NULL, NULL, NULL }
653 static struct winbindd_async_dispatch_table async_priv_table[] = {
654 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
655 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
656 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
657 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
658 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
659 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
660 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
661 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
663 { 0, NULL, NULL, NULL }
666 struct process_request_state {
667 struct winbindd_cli_state *cli_state;
668 struct tevent_context *ev;
671 static void process_request_done(struct tevent_req *subreq);
672 static void process_request_written(struct tevent_req *subreq);
674 static struct tevent_req *process_request_send(
675 TALLOC_CTX *mem_ctx,
676 struct tevent_context *ev,
677 struct winbindd_cli_state *cli_state)
679 struct tevent_req *req, *subreq;
680 struct process_request_state *state;
681 struct winbindd_async_dispatch_table *atable;
682 enum winbindd_cmd cmd = cli_state->request->cmd;
683 size_t i;
684 bool ok;
686 req = tevent_req_create(mem_ctx, &state,
687 struct process_request_state);
688 if (req == NULL) {
689 return NULL;
691 state->cli_state = cli_state;
692 state->ev = ev;
694 ok = tevent_req_set_profile(req);
695 if (!ok) {
696 return tevent_req_post(req, ev);
699 SMB_ASSERT(cli_state->mem_ctx == NULL);
700 cli_state->mem_ctx = talloc_named(cli_state, 0, "winbind request");
701 if (tevent_req_nomem(cli_state->mem_ctx, req)) {
702 return tevent_req_post(req, ev);
705 cli_state->response = talloc_zero(
706 cli_state->mem_ctx,
707 struct winbindd_response);
708 if (tevent_req_nomem(cli_state->response, req)) {
709 return tevent_req_post(req, ev);
711 cli_state->response->result = WINBINDD_PENDING;
712 cli_state->response->length = sizeof(struct winbindd_response);
714 /* Remember who asked us. */
715 cli_state->pid = cli_state->request->pid;
716 memcpy(cli_state->client_name,
717 cli_state->request->client_name,
718 sizeof(cli_state->client_name));
720 cli_state->cmd_name = "unknown request";
721 cli_state->recv_fn = NULL;
723 /* client is newest */
724 winbindd_promote_client(cli_state);
726 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
727 if (cmd == atable->cmd) {
728 break;
732 if ((atable->send_req == NULL) && cli_state->privileged) {
733 for (atable = async_priv_table; atable->send_req;
734 atable += 1) {
735 if (cmd == atable->cmd) {
736 break;
741 if (atable->send_req != NULL) {
742 cli_state->cmd_name = atable->cmd_name;
743 cli_state->recv_fn = atable->recv_req;
745 DBG_DEBUG("process_request: "
746 "Handling async request %s(%d):%s\n",
747 cli_state->client_name,
748 (int)cli_state->pid,
749 cli_state->cmd_name);
751 subreq = atable->send_req(
752 state,
753 state->ev,
754 cli_state,
755 cli_state->request);
756 if (tevent_req_nomem(subreq, req)) {
757 return tevent_req_post(req, ev);
759 tevent_req_set_callback(subreq, process_request_done, req);
760 return req;
763 for (i=0; i<ARRAY_SIZE(bool_dispatch_table); i++) {
764 if (cmd == bool_dispatch_table[i].cmd) {
765 break;
769 ok = false;
771 if (i < ARRAY_SIZE(bool_dispatch_table)) {
772 cli_state->cmd_name = bool_dispatch_table[i].cmd_name;
774 DBG_DEBUG("process_request: request fn %s\n",
775 bool_dispatch_table[i].cmd_name);
776 ok = bool_dispatch_table[i].fn(cli_state);
779 cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
781 TALLOC_FREE(cli_state->io_req);
782 TALLOC_FREE(cli_state->request);
784 subreq = wb_resp_write_send(
785 state,
786 state->ev,
787 cli_state->out_queue,
788 cli_state->sock,
789 cli_state->response);
790 if (tevent_req_nomem(subreq, req)) {
791 return tevent_req_post(req, ev);
793 tevent_req_set_callback(subreq, process_request_written, req);
795 cli_state->io_req = subreq;
797 return req;
800 static void process_request_done(struct tevent_req *subreq)
802 struct tevent_req *req = tevent_req_callback_data(
803 subreq, struct tevent_req);
804 struct process_request_state *state = tevent_req_data(
805 req, struct process_request_state);
806 struct winbindd_cli_state *cli_state = state->cli_state;
807 NTSTATUS status;
808 bool ok;
810 status = cli_state->recv_fn(subreq, cli_state->response);
811 TALLOC_FREE(subreq);
813 DBG_DEBUG("[%s(%d):%s]: %s\n",
814 cli_state->client_name,
815 (int)cli_state->pid,
816 cli_state->cmd_name,
817 nt_errstr(status));
819 ok = NT_STATUS_IS_OK(status);
820 cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
822 TALLOC_FREE(cli_state->io_req);
823 TALLOC_FREE(cli_state->request);
825 subreq = wb_resp_write_send(
826 state,
827 state->ev,
828 cli_state->out_queue,
829 cli_state->sock,
830 cli_state->response);
831 if (tevent_req_nomem(subreq, req)) {
832 return;
834 tevent_req_set_callback(subreq, process_request_written, req);
836 cli_state->io_req = subreq;
839 static void process_request_written(struct tevent_req *subreq)
841 struct tevent_req *req = tevent_req_callback_data(
842 subreq, struct tevent_req);
843 struct process_request_state *state = tevent_req_data(
844 req, struct process_request_state);
845 struct winbindd_cli_state *cli_state = state->cli_state;
846 ssize_t ret;
847 int err;
849 cli_state->io_req = NULL;
851 ret = wb_resp_write_recv(subreq, &err);
852 TALLOC_FREE(subreq);
853 if (ret == -1) {
854 tevent_req_nterror(req, map_nt_error_from_unix(err));
855 return;
858 DBG_DEBUG("[%s(%d):%s]: delivered response to client\n",
859 cli_state->client_name,
860 (int)cli_state->pid,
861 cli_state->cmd_name);
863 TALLOC_FREE(cli_state->mem_ctx);
864 cli_state->response = NULL;
865 cli_state->cmd_name = "no request";
866 cli_state->recv_fn = NULL;
868 tevent_req_done(req);
871 static NTSTATUS process_request_recv(
872 struct tevent_req *req,
873 TALLOC_CTX *mem_ctx,
874 struct tevent_req_profile **profile)
876 NTSTATUS status;
878 if (tevent_req_is_nterror(req, &status)) {
879 tevent_req_received(req);
880 return status;
883 *profile = tevent_req_move_profile(req, mem_ctx);
884 tevent_req_received(req);
885 return NT_STATUS_OK;
889 * This is the main event loop of winbind requests. It goes through a
890 * state-machine of 3 read/write requests, 4 if you have extra data to send.
892 * An idle winbind client has a read request of 4 bytes outstanding,
893 * finalizing function is request_len_recv, checking the length. request_recv
894 * then processes the packet. The processing function then at some point has
895 * to call request_finished which schedules sending the response.
898 static void winbind_client_request_read(struct tevent_req *req);
899 static void winbind_client_activity(struct tevent_req *req);
900 static void winbind_client_processed(struct tevent_req *req);
902 /* Process a new connection by adding it to the client connection list */
904 static void new_connection(int listen_sock, bool privileged)
906 struct sockaddr_un sunaddr;
907 struct winbindd_cli_state *state;
908 struct tevent_req *req;
909 socklen_t len;
910 int sock;
912 /* Accept connection */
914 len = sizeof(sunaddr);
916 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
918 if (sock == -1) {
919 if (errno != EINTR) {
920 DEBUG(0, ("Failed to accept socket - %s\n",
921 strerror(errno)));
923 return;
925 smb_set_close_on_exec(sock);
927 DEBUG(6,("accepted socket %d\n", sock));
929 /* Create new connection structure */
931 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
932 close(sock);
933 return;
936 state->sock = sock;
938 state->out_queue = tevent_queue_create(state, "winbind client reply");
939 if (state->out_queue == NULL) {
940 close(sock);
941 TALLOC_FREE(state);
942 return;
945 state->privileged = privileged;
947 req = wb_req_read_send(state, global_event_context(), state->sock,
948 WINBINDD_MAX_EXTRA_DATA);
949 if (req == NULL) {
950 TALLOC_FREE(state);
951 close(sock);
952 return;
954 tevent_req_set_callback(req, winbind_client_request_read, state);
955 state->io_req = req;
957 /* Add to connection list */
959 winbindd_add_client(state);
962 static void winbind_client_request_read(struct tevent_req *req)
964 struct winbindd_cli_state *state = tevent_req_callback_data(
965 req, struct winbindd_cli_state);
966 ssize_t ret;
967 int err;
969 state->io_req = NULL;
971 ret = wb_req_read_recv(req, state, &state->request, &err);
972 TALLOC_FREE(req);
973 if (ret == -1) {
974 if (err == EPIPE) {
975 DEBUG(6, ("closing socket %d, client exited\n",
976 state->sock));
977 } else {
978 DEBUG(2, ("Could not read client request from fd %d: "
979 "%s\n", state->sock, strerror(err)));
981 close(state->sock);
982 state->sock = -1;
983 remove_client(state);
984 return;
987 req = wait_for_read_send(state, global_event_context(), state->sock,
988 true);
989 if (req == NULL) {
990 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
991 " wait_for_read_send failed - removing client\n",
992 (int)state->pid, state->cmd_name));
993 remove_client(state);
994 return;
996 tevent_req_set_callback(req, winbind_client_activity, state);
997 state->io_req = req;
999 req = process_request_send(state, global_event_context(), state);
1000 if (req == NULL) {
1001 DBG_ERR("process_request_send failed\n");
1002 remove_client(state);
1003 return;
1005 tevent_req_set_callback(req, winbind_client_processed, state);
1008 static void winbind_client_activity(struct tevent_req *req)
1010 struct winbindd_cli_state *state =
1011 tevent_req_callback_data(req, struct winbindd_cli_state);
1012 int err;
1013 bool has_data;
1015 has_data = wait_for_read_recv(req, &err);
1017 if (has_data) {
1018 DEBUG(0, ("winbind_client_activity[%d:%s]:"
1019 "unexpected data from client - removing client\n",
1020 (int)state->pid, state->cmd_name));
1021 } else {
1022 if (err == EPIPE) {
1023 DEBUG(6, ("winbind_client_activity[%d:%s]: "
1024 "client has closed connection - removing "
1025 "client\n",
1026 (int)state->pid, state->cmd_name));
1027 } else {
1028 DEBUG(2, ("winbind_client_activity[%d:%s]: "
1029 "client socket error (%s) - removing "
1030 "client\n",
1031 (int)state->pid, state->cmd_name,
1032 strerror(err)));
1036 remove_client(state);
1039 static void winbind_client_processed(struct tevent_req *req)
1041 struct winbindd_cli_state *cli_state = tevent_req_callback_data(
1042 req, struct winbindd_cli_state);
1043 struct tevent_req_profile *profile = NULL;
1044 struct timeval start, stop, diff;
1045 int threshold;
1046 NTSTATUS status;
1048 status = process_request_recv(req, cli_state, &profile);
1049 TALLOC_FREE(req);
1050 if (!NT_STATUS_IS_OK(status)) {
1051 DBG_DEBUG("process_request failed: %s\n", nt_errstr(status));
1052 remove_client(cli_state);
1053 return;
1056 tevent_req_profile_get_start(profile, NULL, &start);
1057 tevent_req_profile_get_stop(profile, NULL, &stop);
1058 diff = tevent_timeval_until(&start, &stop);
1060 threshold = lp_parm_int(-1, "winbind", "request profile threshold", 60);
1062 if (diff.tv_sec >= threshold) {
1063 int depth;
1064 char *str;
1066 depth = lp_parm_int(
1068 "winbind",
1069 "request profile depth",
1070 INT_MAX);
1072 DBG_ERR("request took %u.%.6u seconds\n",
1073 (unsigned)diff.tv_sec, (unsigned)diff.tv_usec);
1075 str = tevent_req_profile_string(
1076 talloc_tos(), profile, 0, depth);
1077 if (str != NULL) {
1078 /* No "\n", already contained in "str" */
1079 DEBUGADD(0, ("%s", str));
1081 TALLOC_FREE(str);
1084 TALLOC_FREE(profile);
1086 req = wb_req_read_send(
1087 cli_state,
1088 global_event_context(),
1089 cli_state->sock,
1090 WINBINDD_MAX_EXTRA_DATA);
1091 if (req == NULL) {
1092 remove_client(cli_state);
1093 return;
1095 tevent_req_set_callback(req, winbind_client_request_read, cli_state);
1096 cli_state->io_req = req;
1099 /* Remove a client connection from client connection list */
1101 static void remove_client(struct winbindd_cli_state *state)
1103 /* It's a dead client - hold a funeral */
1105 if (state == NULL) {
1106 return;
1110 * We need to remove a pending wb_req_read_*
1111 * or wb_resp_write_* request before closing the
1112 * socket.
1114 * This is important as they might have used tevent_add_fd() and we
1115 * use the epoll * backend on linux. So we must remove the tevent_fd
1116 * before closing the fd.
1118 * Otherwise we might hit a race with close_conns_after_fork() (via
1119 * winbindd_reinit_after_fork()) where a file descriptor
1120 * is still open in a child, which means it's still active in
1121 * the parents epoll queue, but the related tevent_fd is already
1122 * already gone in the parent.
1124 * See bug #11141.
1126 TALLOC_FREE(state->io_req);
1128 if (state->sock != -1) {
1129 char c = 0;
1130 int nwritten;
1132 /* tell client, we are closing ... */
1133 nwritten = write(state->sock, &c, sizeof(c));
1134 if (nwritten == -1) {
1135 DEBUG(2, ("final write to client failed: %s\n",
1136 strerror(errno)));
1139 /* Close socket */
1141 close(state->sock);
1142 state->sock = -1;
1145 TALLOC_FREE(state->mem_ctx);
1147 /* Remove from list and free */
1149 winbindd_remove_client(state);
1150 TALLOC_FREE(state);
1153 /* Is a client idle? */
1155 static bool client_is_idle(struct winbindd_cli_state *state) {
1156 return (state->request == NULL &&
1157 state->response == NULL &&
1158 !state->pwent_state && !state->grent_state);
1161 /* Shutdown client connection which has been idle for the longest time */
1163 static bool remove_idle_client(void)
1165 struct winbindd_cli_state *state, *remove_state = NULL;
1166 int nidle = 0;
1168 for (state = winbindd_client_list(); state; state = state->next) {
1169 if (client_is_idle(state)) {
1170 nidle++;
1171 /* list is sorted by access time */
1172 remove_state = state;
1176 if (remove_state) {
1177 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1178 nidle, remove_state->sock, (unsigned int)remove_state->pid));
1179 remove_client(remove_state);
1180 return True;
1183 return False;
1187 * Terminate all clients whose requests have taken longer than
1188 * "winbind request timeout" seconds to process, or have been
1189 * idle for more than "winbind request timeout" seconds.
1192 static void remove_timed_out_clients(void)
1194 struct winbindd_cli_state *state, *prev = NULL;
1195 time_t curr_time = time(NULL);
1196 int timeout_val = lp_winbind_request_timeout();
1198 for (state = winbindd_client_list_tail(); state; state = prev) {
1199 time_t expiry_time;
1201 prev = winbindd_client_list_prev(state);
1202 expiry_time = state->last_access + timeout_val;
1204 if (curr_time <= expiry_time) {
1205 /* list is sorted, previous clients in
1206 list are newer */
1207 break;
1210 if (client_is_idle(state)) {
1211 DEBUG(5,("Idle client timed out, "
1212 "shutting down sock %d, pid %u\n",
1213 state->sock,
1214 (unsigned int)state->pid));
1215 } else {
1216 DEBUG(5,("Client request timed out, "
1217 "shutting down sock %d, pid %u\n",
1218 state->sock,
1219 (unsigned int)state->pid));
1222 remove_client(state);
1226 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
1227 struct tevent_timer *te,
1228 struct timeval current_time,
1229 void *private_data)
1231 remove_timed_out_clients();
1232 if (tevent_add_timer(ev, ev,
1233 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
1234 winbindd_scrub_clients_handler, NULL) == NULL) {
1235 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
1236 exit(1);
1240 struct winbindd_listen_state {
1241 bool privileged;
1242 int fd;
1245 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1246 struct tevent_fd *fde,
1247 uint16_t flags,
1248 void *private_data)
1250 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1251 struct winbindd_listen_state);
1253 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1254 DEBUG(5,("winbindd: Exceeding %d client "
1255 "connections, removing idle "
1256 "connection.\n", lp_winbind_max_clients()));
1257 if (!remove_idle_client()) {
1258 DEBUG(0,("winbindd: Exceeding %d "
1259 "client connections, no idle "
1260 "connection found\n",
1261 lp_winbind_max_clients()));
1262 break;
1265 remove_timed_out_clients();
1266 new_connection(s->fd, s->privileged);
1270 * Winbindd socket accessor functions
1273 char *get_winbind_priv_pipe_dir(void)
1275 return state_path(talloc_tos(), WINBINDD_PRIV_SOCKET_SUBDIR);
1278 static void winbindd_setup_max_fds(void)
1280 int num_fds = MAX_OPEN_FUDGEFACTOR;
1281 int actual_fds;
1283 num_fds += lp_winbind_max_clients();
1284 /* Add some more to account for 2 sockets open
1285 when the client transitions from unprivileged
1286 to privileged socket
1288 num_fds += lp_winbind_max_clients() / 10;
1290 /* Add one socket per child process
1291 (yeah there are child processes other than the
1292 domain children but only domain children can vary
1293 with configuration
1295 num_fds += lp_winbind_max_domain_connections() *
1296 (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
1298 actual_fds = set_maxfiles(num_fds);
1300 if (actual_fds < num_fds) {
1301 DEBUG(1, ("winbindd_setup_max_fds: Information only: "
1302 "requested %d open files, %d are available.\n",
1303 num_fds, actual_fds));
1307 static bool winbindd_setup_listeners(void)
1309 struct winbindd_listen_state *pub_state = NULL;
1310 struct winbindd_listen_state *priv_state = NULL;
1311 struct tevent_fd *fde;
1312 int rc;
1313 char *socket_path;
1315 pub_state = talloc(global_event_context(),
1316 struct winbindd_listen_state);
1317 if (!pub_state) {
1318 goto failed;
1321 pub_state->privileged = false;
1322 pub_state->fd = create_pipe_sock(
1323 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1324 if (pub_state->fd == -1) {
1325 goto failed;
1327 rc = listen(pub_state->fd, 5);
1328 if (rc < 0) {
1329 goto failed;
1332 fde = tevent_add_fd(global_event_context(), pub_state, pub_state->fd,
1333 TEVENT_FD_READ, winbindd_listen_fde_handler,
1334 pub_state);
1335 if (fde == NULL) {
1336 close(pub_state->fd);
1337 goto failed;
1339 tevent_fd_set_auto_close(fde);
1341 priv_state = talloc(global_event_context(),
1342 struct winbindd_listen_state);
1343 if (!priv_state) {
1344 goto failed;
1347 socket_path = get_winbind_priv_pipe_dir();
1348 if (socket_path == NULL) {
1349 goto failed;
1352 priv_state->privileged = true;
1353 priv_state->fd = create_pipe_sock(
1354 socket_path, WINBINDD_SOCKET_NAME, 0750);
1355 TALLOC_FREE(socket_path);
1356 if (priv_state->fd == -1) {
1357 goto failed;
1359 rc = listen(priv_state->fd, 5);
1360 if (rc < 0) {
1361 goto failed;
1364 fde = tevent_add_fd(global_event_context(), priv_state,
1365 priv_state->fd, TEVENT_FD_READ,
1366 winbindd_listen_fde_handler, priv_state);
1367 if (fde == NULL) {
1368 close(priv_state->fd);
1369 goto failed;
1371 tevent_fd_set_auto_close(fde);
1373 winbindd_scrub_clients_handler(global_event_context(), NULL,
1374 timeval_current(), NULL);
1375 return true;
1376 failed:
1377 TALLOC_FREE(pub_state);
1378 TALLOC_FREE(priv_state);
1379 return false;
1382 bool winbindd_use_idmap_cache(void)
1384 return !opt_nocache;
1387 bool winbindd_use_cache(void)
1389 return !opt_nocache;
1392 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1393 bool foreground)
1395 bool scan_trusts = true;
1396 NTSTATUS status;
1397 /* Setup signal handlers */
1399 if (!winbindd_setup_sig_term_handler(true))
1400 exit(1);
1401 if (!winbindd_setup_stdin_handler(true, foreground))
1402 exit(1);
1403 if (!winbindd_setup_sig_hup_handler(NULL))
1404 exit(1);
1405 if (!winbindd_setup_sig_chld_handler())
1406 exit(1);
1407 if (!winbindd_setup_sig_usr2_handler())
1408 exit(1);
1410 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1413 * Ensure all cache and idmap caches are consistent
1414 * and initialized before we startup.
1416 if (!winbindd_cache_validate_and_initialize()) {
1417 exit(1);
1420 /* React on 'smbcontrol winbindd reload-config' in the same way
1421 as to SIGHUP signal */
1422 messaging_register(msg_ctx, NULL,
1423 MSG_SMB_CONF_UPDATED, msg_reload_services);
1424 messaging_register(msg_ctx, NULL,
1425 MSG_SHUTDOWN, msg_shutdown);
1427 /* Handle online/offline messages. */
1428 messaging_register(msg_ctx, NULL,
1429 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1430 messaging_register(msg_ctx, NULL,
1431 MSG_WINBIND_ONLINE, winbind_msg_online);
1432 messaging_register(msg_ctx, NULL,
1433 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1435 /* Handle domain online/offline messages for domains */
1436 messaging_register(global_messaging_context(), NULL,
1437 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1438 messaging_register(global_messaging_context(), NULL,
1439 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1441 messaging_register(msg_ctx, NULL,
1442 MSG_WINBIND_VALIDATE_CACHE,
1443 winbind_msg_validate_cache);
1445 messaging_register(msg_ctx, NULL,
1446 MSG_WINBIND_DUMP_DOMAIN_LIST,
1447 winbind_msg_dump_domain_list);
1449 messaging_register(msg_ctx, NULL,
1450 MSG_WINBIND_IP_DROPPED,
1451 winbind_msg_ip_dropped_parent);
1453 /* Register handler for MSG_DEBUG. */
1454 messaging_register(msg_ctx, NULL,
1455 MSG_DEBUG,
1456 winbind_msg_debug);
1458 messaging_register(msg_ctx, NULL,
1459 MSG_WINBIND_DISCONNECT_DC,
1460 winbind_disconnect_dc_parent);
1462 netsamlogon_cache_init(); /* Non-critical */
1464 /* clear the cached list of trusted domains */
1466 wcache_tdc_clear();
1468 if (!init_domain_list()) {
1469 DEBUG(0,("unable to initialize domain list\n"));
1470 exit(1);
1473 init_idmap_child();
1474 init_locator_child();
1476 smb_nscd_flush_user_cache();
1477 smb_nscd_flush_group_cache();
1479 if (!lp_winbind_scan_trusted_domains()) {
1480 scan_trusts = false;
1483 if (!lp_allow_trusted_domains()) {
1484 scan_trusts = false;
1487 if (IS_DC) {
1488 scan_trusts = false;
1491 if (scan_trusts) {
1492 if (tevent_add_timer(global_event_context(), NULL, timeval_zero(),
1493 rescan_trusted_domains, NULL) == NULL) {
1494 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1495 exit(1);
1499 status = wb_irpc_register();
1501 if (!NT_STATUS_IS_OK(status)) {
1502 DEBUG(0, ("Could not register IRPC handlers\n"));
1503 exit(1);
1507 struct winbindd_addrchanged_state {
1508 struct addrchange_context *ctx;
1509 struct tevent_context *ev;
1510 struct messaging_context *msg_ctx;
1513 static void winbindd_addr_changed(struct tevent_req *req);
1515 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1516 struct tevent_context *ev,
1517 struct messaging_context *msg_ctx)
1519 struct winbindd_addrchanged_state *state;
1520 struct tevent_req *req;
1521 NTSTATUS status;
1523 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1524 if (state == NULL) {
1525 DEBUG(10, ("talloc failed\n"));
1526 return;
1528 state->ev = ev;
1529 state->msg_ctx = msg_ctx;
1531 status = addrchange_context_create(state, &state->ctx);
1532 if (!NT_STATUS_IS_OK(status)) {
1533 DEBUG(10, ("addrchange_context_create failed: %s\n",
1534 nt_errstr(status)));
1535 TALLOC_FREE(state);
1536 return;
1538 req = addrchange_send(state, ev, state->ctx);
1539 if (req == NULL) {
1540 DEBUG(0, ("addrchange_send failed\n"));
1541 TALLOC_FREE(state);
1542 return;
1544 tevent_req_set_callback(req, winbindd_addr_changed, state);
1547 static void winbindd_addr_changed(struct tevent_req *req)
1549 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1550 req, struct winbindd_addrchanged_state);
1551 enum addrchange_type type;
1552 struct sockaddr_storage addr;
1553 NTSTATUS status;
1555 status = addrchange_recv(req, &type, &addr);
1556 TALLOC_FREE(req);
1557 if (!NT_STATUS_IS_OK(status)) {
1558 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1559 nt_errstr(status)));
1560 TALLOC_FREE(state);
1561 return;
1563 if (type == ADDRCHANGE_DEL) {
1564 char addrstr[INET6_ADDRSTRLEN];
1565 DATA_BLOB blob;
1567 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1569 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1570 addrstr));
1572 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1574 status = messaging_send(state->msg_ctx,
1575 messaging_server_id(state->msg_ctx),
1576 MSG_WINBIND_IP_DROPPED, &blob);
1577 if (!NT_STATUS_IS_OK(status)) {
1578 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1579 nt_errstr(status)));
1582 req = addrchange_send(state, state->ev, state->ctx);
1583 if (req == NULL) {
1584 DEBUG(0, ("addrchange_send failed\n"));
1585 TALLOC_FREE(state);
1586 return;
1588 tevent_req_set_callback(req, winbindd_addr_changed, state);
1591 /* Main function */
1593 int main(int argc, const char **argv)
1595 static bool is_daemon = False;
1596 static bool Fork = True;
1597 static bool log_stdout = False;
1598 static bool no_process_group = False;
1599 enum {
1600 OPT_DAEMON = 1000,
1601 OPT_FORK,
1602 OPT_NO_PROCESS_GROUP,
1603 OPT_LOG_STDOUT
1605 struct poptOption long_options[] = {
1606 POPT_AUTOHELP
1608 .longName = "stdout",
1609 .shortName = 'S',
1610 .argInfo = POPT_ARG_NONE,
1611 .arg = NULL,
1612 .val = OPT_LOG_STDOUT,
1613 .descrip = "Log to stdout",
1616 .longName = "foreground",
1617 .shortName = 'F',
1618 .argInfo = POPT_ARG_NONE,
1619 .arg = NULL,
1620 .val = OPT_FORK,
1621 .descrip = "Daemon in foreground mode",
1624 .longName = "no-process-group",
1625 .shortName = 0,
1626 .argInfo = POPT_ARG_NONE,
1627 .arg = NULL,
1628 .val = OPT_NO_PROCESS_GROUP,
1629 .descrip = "Don't create a new process group",
1632 .longName = "daemon",
1633 .shortName = 'D',
1634 .argInfo = POPT_ARG_NONE,
1635 .arg = NULL,
1636 .val = OPT_DAEMON,
1637 .descrip = "Become a daemon (default)",
1640 .longName = "interactive",
1641 .shortName = 'i',
1642 .argInfo = POPT_ARG_NONE,
1643 .arg = NULL,
1644 .val = 'i',
1645 .descrip = "Interactive mode",
1648 .longName = "no-caching",
1649 .shortName = 'n',
1650 .argInfo = POPT_ARG_NONE,
1651 .arg = NULL,
1652 .val = 'n',
1653 .descrip = "Disable caching",
1655 POPT_COMMON_SAMBA
1656 POPT_TABLEEND
1658 const struct loadparm_substitution *lp_sub =
1659 loadparm_s3_global_substitution();
1660 poptContext pc;
1661 int opt;
1662 TALLOC_CTX *frame;
1663 NTSTATUS status;
1664 bool ok;
1665 const struct dcesrv_endpoint_server *ep_server = NULL;
1666 struct dcesrv_context *dce_ctx = NULL;
1668 setproctitle_init(argc, discard_const(argv), environ);
1671 * Do this before any other talloc operation
1673 talloc_enable_null_tracking();
1674 frame = talloc_stackframe();
1677 * We want total control over the permissions on created files,
1678 * so set our umask to 0.
1680 umask(0);
1682 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1684 /* glibc (?) likes to print "User defined signal 1" and exit if a
1685 SIGUSR[12] is received before a handler is installed */
1687 CatchSignal(SIGUSR1, SIG_IGN);
1688 CatchSignal(SIGUSR2, SIG_IGN);
1690 fault_setup();
1691 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1693 smb_init_locale();
1695 /* Initialise for running in non-root mode */
1697 sec_init();
1699 set_remote_machine_name("winbindd", False);
1701 /* Set environment variable so we don't recursively call ourselves.
1702 This may also be useful interactively. */
1704 if ( !winbind_off() ) {
1705 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1706 exit(1);
1709 /* Initialise samba/rpc client stuff */
1711 pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1713 while ((opt = poptGetNextOpt(pc)) != -1) {
1714 switch (opt) {
1715 /* Don't become a daemon */
1716 case OPT_DAEMON:
1717 is_daemon = True;
1718 break;
1719 case 'i':
1720 interactive = True;
1721 log_stdout = True;
1722 Fork = False;
1723 break;
1724 case OPT_FORK:
1725 Fork = false;
1726 break;
1727 case OPT_NO_PROCESS_GROUP:
1728 no_process_group = true;
1729 break;
1730 case OPT_LOG_STDOUT:
1731 log_stdout = true;
1732 break;
1733 case 'n':
1734 opt_nocache = true;
1735 break;
1736 default:
1737 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1738 poptBadOption(pc, 0), poptStrerror(opt));
1739 poptPrintUsage(pc, stderr, 0);
1740 exit(1);
1744 /* We call dump_core_setup one more time because the command line can
1745 * set the log file or the log-basename and this will influence where
1746 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1747 * the default value derived from build's prefix. For EOM this value
1748 * is often not related to the path where winbindd is actually run
1749 * in production.
1751 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1752 if (is_daemon && interactive) {
1753 d_fprintf(stderr,"\nERROR: "
1754 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1755 poptPrintUsage(pc, stderr, 0);
1756 exit(1);
1759 if (log_stdout && Fork) {
1760 d_fprintf(stderr, "\nERROR: "
1761 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1762 poptPrintUsage(pc, stderr, 0);
1763 exit(1);
1766 poptFreeContext(pc);
1768 if (!override_logfile) {
1769 char *lfile = NULL;
1770 if (asprintf(&lfile,"%s/log.winbindd",
1771 get_dyn_LOGFILEBASE()) > 0) {
1772 lp_set_logfile(lfile);
1773 SAFE_FREE(lfile);
1777 if (log_stdout) {
1778 setup_logging("winbindd", DEBUG_STDOUT);
1779 } else {
1780 setup_logging("winbindd", DEBUG_FILE);
1782 reopen_logs();
1784 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1785 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1787 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1788 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1789 exit(1);
1791 /* After parsing the configuration file we setup the core path one more time
1792 * as the log file might have been set in the configuration and cores's
1793 * path is by default basename(lp_logfile()).
1795 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1797 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1798 && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1799 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1800 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"));
1801 exit(1);
1804 if (!cluster_probe_ok()) {
1805 exit(1);
1808 /* Initialise messaging system */
1810 if (global_messaging_context() == NULL) {
1811 exit(1);
1814 if (!reload_services_file(NULL)) {
1815 DEBUG(0, ("error opening config file\n"));
1816 exit(1);
1820 size_t i;
1821 const char *idmap_backend;
1822 const char *invalid_backends[] = {
1823 "ad", "rfc2307", "rid",
1826 idmap_backend = lp_idmap_default_backend();
1827 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1828 ok = strequal(idmap_backend, invalid_backends[i]);
1829 if (ok) {
1830 DBG_ERR("FATAL: Invalid idmap backend %s "
1831 "configured as the default backend!\n",
1832 idmap_backend);
1833 exit(1);
1838 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1839 if (!ok) {
1840 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1841 lp_lock_directory(), strerror(errno)));
1842 exit(1);
1845 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1846 if (!ok) {
1847 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1848 lp_pid_directory(), strerror(errno)));
1849 exit(1);
1852 /* Setup names. */
1854 if (!init_names())
1855 exit(1);
1857 load_interfaces();
1859 if (!secrets_init()) {
1861 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1862 return False;
1865 status = rpccli_pre_open_netlogon_creds();
1866 if (!NT_STATUS_IS_OK(status)) {
1867 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1868 nt_errstr(status)));
1869 exit(1);
1872 /* Unblock all signals we are interested in as they may have been
1873 blocked by the parent process. */
1875 BlockSignals(False, SIGINT);
1876 BlockSignals(False, SIGQUIT);
1877 BlockSignals(False, SIGTERM);
1878 BlockSignals(False, SIGUSR1);
1879 BlockSignals(False, SIGUSR2);
1880 BlockSignals(False, SIGHUP);
1881 BlockSignals(False, SIGCHLD);
1883 if (!interactive)
1884 become_daemon(Fork, no_process_group, log_stdout);
1886 pidfile_create(lp_pid_directory(), "winbindd");
1888 #ifdef HAVE_SETPGID
1890 * If we're interactive we want to set our own process group for
1891 * signal management.
1893 if (interactive && !no_process_group)
1894 setpgid( (pid_t)0, (pid_t)0);
1895 #endif
1897 TimeInit();
1899 /* Don't use winbindd_reinit_after_fork here as
1900 * we're just starting up and haven't created any
1901 * winbindd-specific resources we must free yet. JRA.
1904 status = reinit_after_fork(global_messaging_context(),
1905 global_event_context(),
1906 false, NULL);
1907 if (!NT_STATUS_IS_OK(status)) {
1908 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1911 ok = initialize_password_db(true, global_event_context());
1912 if (!ok) {
1913 exit_daemon("Failed to initialize passdb backend! "
1914 "Check the 'passdb backend' variable in your "
1915 "smb.conf file.", EINVAL);
1919 * Do not initialize the parent-child-pipe before becoming
1920 * a daemon: this is used to detect a died parent in the child
1921 * process.
1923 status = init_before_fork();
1924 if (!NT_STATUS_IS_OK(status)) {
1925 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1928 winbindd_register_handlers(global_messaging_context(), !Fork);
1930 if (!messaging_parent_dgm_cleanup_init(global_messaging_context())) {
1931 exit(1);
1934 status = init_system_session_info(NULL);
1935 if (!NT_STATUS_IS_OK(status)) {
1936 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1939 DBG_INFO("Registering DCE/RPC endpoint servers\n");
1941 /* Register the endpoint server to dispatch calls locally through
1942 * the legacy api_struct */
1943 ep_server = lsarpc_get_ep_server();
1944 if (ep_server == NULL) {
1945 DBG_ERR("Failed to get 'lsarpc' endpoint server\n");
1946 exit(1);
1948 status = dcerpc_register_ep_server(ep_server);
1949 if (!NT_STATUS_IS_OK(status)) {
1950 DBG_ERR("Failed to register 'lsarpc' endpoint "
1951 "server: %s\n", nt_errstr(status));
1952 exit(1);
1955 /* Register the endpoint server to dispatch calls locally through
1956 * the legacy api_struct */
1957 ep_server = samr_get_ep_server();
1958 if (ep_server == NULL) {
1959 DBG_ERR("Failed to get 'samr' endpoint server\n");
1960 exit(1);
1962 status = dcerpc_register_ep_server(ep_server);
1963 if (!NT_STATUS_IS_OK(status)) {
1964 DBG_ERR("Failed to register 'samr' endpoint "
1965 "server: %s\n", nt_errstr(status));
1966 exit(1);
1969 ep_server = winbind_get_ep_server();
1970 if (ep_server == NULL) {
1971 DBG_ERR("Failed to get 'winbind' endpoint server\n");
1972 exit(1);
1974 status = dcerpc_register_ep_server(ep_server);
1975 if (!NT_STATUS_IS_OK(status)) {
1976 DBG_ERR("Failed to register 'winbind' endpoint "
1977 "server: %s\n", nt_errstr(status));
1978 exit(1);
1981 dce_ctx = global_dcesrv_context();
1983 DBG_INFO("Initializing DCE/RPC registered endpoint servers\n");
1985 /* Init all registered ep servers */
1986 status = dcesrv_init_registered_ep_servers(dce_ctx);
1987 if (!NT_STATUS_IS_OK(status)) {
1988 DBG_ERR("Failed to init DCE/RPC endpoint servers: %s\n",
1989 nt_errstr(status));
1990 exit(1);
1993 winbindd_init_addrchange(NULL, global_event_context(),
1994 global_messaging_context());
1996 /* setup listen sockets */
1998 if (!winbindd_setup_listeners()) {
1999 exit_daemon("Winbindd failed to setup listeners", EPIPE);
2002 irpc_add_name(winbind_imessaging_context(), "winbind_server");
2004 TALLOC_FREE(frame);
2006 if (!interactive) {
2007 daemon_ready("winbindd");
2010 gpupdate_init();
2012 /* Loop waiting for requests */
2013 while (1) {
2014 frame = talloc_stackframe();
2016 if (tevent_loop_once(global_event_context()) == -1) {
2017 DEBUG(1, ("tevent_loop_once() failed: %s\n",
2018 strerror(errno)));
2019 return 1;
2022 TALLOC_FREE(frame);
2025 return 0;