idmap: Remove "domname" from idmap_backends_unixid_to_sid
[Samba.git] / source3 / winbindd / winbindd.c
blobc878ce2e220ff93708af21104ea59d09249b5384
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 "serverid.h"
38 #include "auth.h"
39 #include "messages.h"
40 #include "../lib/util/pidfile.h"
41 #include "util_cluster.h"
42 #include "source4/lib/messaging/irpc.h"
43 #include "source4/lib/messaging/messaging.h"
44 #include "lib/param/param.h"
45 #include "lib/async_req/async_sock.h"
47 #undef DBGC_CLASS
48 #define DBGC_CLASS DBGC_WINBIND
50 #define SCRUB_CLIENTS_INTERVAL 5
52 static bool client_is_idle(struct winbindd_cli_state *state);
53 static void remove_client(struct winbindd_cli_state *state);
54 static void winbindd_setup_max_fds(void);
56 static bool opt_nocache = False;
57 static bool interactive = False;
59 extern bool override_logfile;
61 struct tevent_context *winbind_event_context(void)
63 static struct tevent_context *ev = NULL;
65 if (ev != NULL) {
66 return ev;
70 * Note we MUST use the NULL context here, not the autofree context,
71 * to avoid side effects in forked children exiting.
73 ev = samba_tevent_context_init(NULL);
74 if (ev == NULL) {
75 smb_panic("Could not init winbindd's messaging context.\n");
77 return ev;
80 struct messaging_context *winbind_messaging_context(void)
82 static struct messaging_context *msg = NULL;
84 if (msg != NULL) {
85 return msg;
89 * Note we MUST use the NULL context here, not the autofree context,
90 * to avoid side effects in forked children exiting.
92 msg = messaging_init(NULL, winbind_event_context());
93 if (msg == NULL) {
94 smb_panic("Could not init winbindd's messaging context.\n");
96 return msg;
99 struct imessaging_context *winbind_imessaging_context(void)
101 static struct imessaging_context *msg = NULL;
102 struct loadparm_context *lp_ctx;
104 if (msg != NULL) {
105 return msg;
108 lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
109 if (lp_ctx == NULL) {
110 smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
114 * Note we MUST use the NULL context here, not the autofree context,
115 * to avoid side effects in forked children exiting.
117 msg = imessaging_init(NULL, lp_ctx, procid_self(), winbind_event_context(), false);
118 talloc_unlink(NULL, lp_ctx);
120 if (msg == NULL) {
121 smb_panic("Could not init winbindd's messaging context.\n");
123 return msg;
126 /* Reload configuration */
128 static bool reload_services_file(const char *lfile)
130 bool ret;
132 if (lp_loaded()) {
133 char *fname = lp_next_configfile(talloc_tos());
135 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
136 set_dyn_CONFIGFILE(fname);
138 TALLOC_FREE(fname);
141 /* if this is a child, restore the logfile to the special
142 name - <domain>, idmap, etc. */
143 if (lfile && *lfile) {
144 lp_set_logfile(lfile);
147 reopen_logs();
148 ret = lp_load_global(get_dyn_CONFIGFILE());
150 reopen_logs();
151 load_interfaces();
152 winbindd_setup_max_fds();
154 return(ret);
158 static void winbindd_status(void)
160 struct winbindd_cli_state *tmp;
162 DEBUG(0, ("winbindd status:\n"));
164 /* Print client state information */
166 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
168 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
169 DEBUG(2, ("\tclient list:\n"));
170 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
171 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
172 (unsigned long)tmp->pid, tmp->sock,
173 client_is_idle(tmp) ? "idle" : "active"));
178 /* Flush client cache */
180 static void flush_caches(void)
182 /* We need to invalidate cached user list entries on a SIGHUP
183 otherwise cached access denied errors due to restrict anonymous
184 hang around until the sequence number changes. */
186 if (!wcache_invalidate_cache()) {
187 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
188 if (!winbindd_cache_validate_and_initialize()) {
189 exit(1);
194 static void flush_caches_noinit(void)
197 * We need to invalidate cached user list entries on a SIGHUP
198 * otherwise cached access denied errors due to restrict anonymous
199 * hang around until the sequence number changes.
200 * NB
201 * Skip uninitialized domains when flush cache.
202 * If domain is not initialized, it means it is never
203 * used or never become online. look, wcache_invalidate_cache()
204 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
205 * for unused domains and large traffic for primay domain's DC if there
206 * are many domains..
209 if (!wcache_invalidate_cache_noinit()) {
210 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
211 if (!winbindd_cache_validate_and_initialize()) {
212 exit(1);
217 /* Handle the signal by unlinking socket and exiting */
219 static void terminate(bool is_parent)
221 if (is_parent) {
222 /* When parent goes away we should
223 * remove the socket file. Not so
224 * when children terminate.
226 char *path = NULL;
228 if (asprintf(&path, "%s/%s",
229 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
230 unlink(path);
231 SAFE_FREE(path);
235 idmap_close();
237 trustdom_cache_shutdown();
239 gencache_stabilize();
241 #if 0
242 if (interactive) {
243 TALLOC_CTX *mem_ctx = talloc_init("end_description");
244 char *description = talloc_describe_all(mem_ctx);
246 DEBUG(3, ("tallocs left:\n%s\n", description));
247 talloc_destroy(mem_ctx);
249 #endif
251 if (is_parent) {
252 struct messaging_context *msg = winbind_messaging_context();
253 struct server_id self = messaging_server_id(msg);
254 serverid_deregister(self);
255 pidfile_unlink(lp_pid_directory(), "winbindd");
258 exit(0);
261 static void winbindd_sig_term_handler(struct tevent_context *ev,
262 struct tevent_signal *se,
263 int signum,
264 int count,
265 void *siginfo,
266 void *private_data)
268 bool *is_parent = talloc_get_type_abort(private_data, bool);
270 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
271 signum, (int)*is_parent));
272 terminate(*is_parent);
276 handle stdin becoming readable when we are in --foreground mode
278 static void winbindd_stdin_handler(struct tevent_context *ev,
279 struct tevent_fd *fde,
280 uint16_t flags,
281 void *private_data)
283 char c;
284 if (read(0, &c, 1) != 1) {
285 bool *is_parent = talloc_get_type_abort(private_data, bool);
287 /* we have reached EOF on stdin, which means the
288 parent has exited. Shutdown the server */
289 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
290 (int)*is_parent));
291 terminate(*is_parent);
295 bool winbindd_setup_sig_term_handler(bool parent)
297 struct tevent_signal *se;
298 bool *is_parent;
300 is_parent = talloc(winbind_event_context(), bool);
301 if (!is_parent) {
302 return false;
305 *is_parent = parent;
307 se = tevent_add_signal(winbind_event_context(),
308 is_parent,
309 SIGTERM, 0,
310 winbindd_sig_term_handler,
311 is_parent);
312 if (!se) {
313 DEBUG(0,("failed to setup SIGTERM handler"));
314 talloc_free(is_parent);
315 return false;
318 se = tevent_add_signal(winbind_event_context(),
319 is_parent,
320 SIGINT, 0,
321 winbindd_sig_term_handler,
322 is_parent);
323 if (!se) {
324 DEBUG(0,("failed to setup SIGINT handler"));
325 talloc_free(is_parent);
326 return false;
329 se = tevent_add_signal(winbind_event_context(),
330 is_parent,
331 SIGQUIT, 0,
332 winbindd_sig_term_handler,
333 is_parent);
334 if (!se) {
335 DEBUG(0,("failed to setup SIGINT handler"));
336 talloc_free(is_parent);
337 return false;
340 return true;
343 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
345 bool *is_parent;
347 if (foreground) {
348 struct stat st;
350 is_parent = talloc(winbind_event_context(), bool);
351 if (!is_parent) {
352 return false;
355 *is_parent = parent;
357 /* if we are running in the foreground then look for
358 EOF on stdin, and exit if it happens. This allows
359 us to die if the parent process dies
360 Only do this on a pipe or socket, no other device.
362 if (fstat(0, &st) != 0) {
363 return false;
365 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
366 tevent_add_fd(winbind_event_context(),
367 is_parent,
369 TEVENT_FD_READ,
370 winbindd_stdin_handler,
371 is_parent);
375 return true;
378 static void winbindd_sig_hup_handler(struct tevent_context *ev,
379 struct tevent_signal *se,
380 int signum,
381 int count,
382 void *siginfo,
383 void *private_data)
385 const char *file = (const char *)private_data;
387 DEBUG(1,("Reloading services after SIGHUP\n"));
388 flush_caches_noinit();
389 reload_services_file(file);
392 bool winbindd_setup_sig_hup_handler(const char *lfile)
394 struct tevent_signal *se;
395 char *file = NULL;
397 if (lfile) {
398 file = talloc_strdup(winbind_event_context(),
399 lfile);
400 if (!file) {
401 return false;
405 se = tevent_add_signal(winbind_event_context(),
406 winbind_event_context(),
407 SIGHUP, 0,
408 winbindd_sig_hup_handler,
409 file);
410 if (!se) {
411 return false;
414 return true;
417 static void winbindd_sig_chld_handler(struct tevent_context *ev,
418 struct tevent_signal *se,
419 int signum,
420 int count,
421 void *siginfo,
422 void *private_data)
424 pid_t pid;
426 while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) {
427 winbind_child_died(pid);
431 static bool winbindd_setup_sig_chld_handler(void)
433 struct tevent_signal *se;
435 se = tevent_add_signal(winbind_event_context(),
436 winbind_event_context(),
437 SIGCHLD, 0,
438 winbindd_sig_chld_handler,
439 NULL);
440 if (!se) {
441 return false;
444 return true;
447 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
448 struct tevent_signal *se,
449 int signum,
450 int count,
451 void *siginfo,
452 void *private_data)
454 winbindd_status();
457 static bool winbindd_setup_sig_usr2_handler(void)
459 struct tevent_signal *se;
461 se = tevent_add_signal(winbind_event_context(),
462 winbind_event_context(),
463 SIGUSR2, 0,
464 winbindd_sig_usr2_handler,
465 NULL);
466 if (!se) {
467 return false;
470 return true;
473 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
474 static void msg_reload_services(struct messaging_context *msg,
475 void *private_data,
476 uint32_t msg_type,
477 struct server_id server_id,
478 DATA_BLOB *data)
480 /* Flush various caches */
481 flush_caches();
482 reload_services_file((const char *) private_data);
485 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
486 static void msg_shutdown(struct messaging_context *msg,
487 void *private_data,
488 uint32_t msg_type,
489 struct server_id server_id,
490 DATA_BLOB *data)
492 /* only the parent waits for this message */
493 DEBUG(0,("Got shutdown message\n"));
494 terminate(true);
498 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
499 void *private_data,
500 uint32_t msg_type,
501 struct server_id server_id,
502 DATA_BLOB *data)
504 uint8_t ret;
505 pid_t child_pid;
506 NTSTATUS status;
508 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
509 "message.\n"));
512 * call the validation code from a child:
513 * so we don't block the main winbindd and the validation
514 * code can safely use fork/waitpid...
516 child_pid = fork();
518 if (child_pid == -1) {
519 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
520 strerror(errno)));
521 return;
524 if (child_pid != 0) {
525 /* parent */
526 DEBUG(5, ("winbind_msg_validate_cache: child created with "
527 "pid %d.\n", (int)child_pid));
528 return;
531 /* child */
533 status = winbindd_reinit_after_fork(NULL, NULL);
534 if (!NT_STATUS_IS_OK(status)) {
535 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
536 nt_errstr(status)));
537 _exit(0);
540 /* install default SIGCHLD handler: validation code uses fork/waitpid */
541 CatchSignal(SIGCHLD, SIG_DFL);
543 ret = (uint8_t)winbindd_validate_cache_nobackup();
544 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
545 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
546 (size_t)1);
547 _exit(0);
550 static struct winbindd_dispatch_table {
551 enum winbindd_cmd cmd;
552 void (*fn)(struct winbindd_cli_state *state);
553 const char *winbindd_cmd_name;
554 } dispatch_table[] = {
556 /* Enumeration functions */
558 { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
559 "LIST_TRUSTDOM" },
561 /* Miscellaneous */
563 { WINBINDD_INFO, winbindd_info, "INFO" },
564 { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
565 "INTERFACE_VERSION" },
566 { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
567 { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
568 { WINBINDD_DC_INFO, winbindd_dc_info, "DC_INFO" },
569 { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
570 { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
571 "WINBINDD_PRIV_PIPE_DIR" },
573 /* Credential cache access */
574 { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
575 { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
577 /* End of list */
579 { WINBINDD_NUM_CMDS, NULL, "NONE" }
582 struct winbindd_async_dispatch_table {
583 enum winbindd_cmd cmd;
584 const char *cmd_name;
585 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
586 struct tevent_context *ev,
587 struct winbindd_cli_state *cli,
588 struct winbindd_request *request);
589 NTSTATUS (*recv_req)(struct tevent_req *req,
590 struct winbindd_response *presp);
593 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
594 { WINBINDD_PING, "PING",
595 wb_ping_send, wb_ping_recv },
596 { WINBINDD_LOOKUPSID, "LOOKUPSID",
597 winbindd_lookupsid_send, winbindd_lookupsid_recv },
598 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
599 winbindd_lookupsids_send, winbindd_lookupsids_recv },
600 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
601 winbindd_lookupname_send, winbindd_lookupname_recv },
602 { WINBINDD_SID_TO_UID, "SID_TO_UID",
603 winbindd_sid_to_uid_send, winbindd_sid_to_uid_recv },
604 { WINBINDD_SID_TO_GID, "SID_TO_GID",
605 winbindd_sid_to_gid_send, winbindd_sid_to_gid_recv },
606 { WINBINDD_UID_TO_SID, "UID_TO_SID",
607 winbindd_uid_to_sid_send, winbindd_uid_to_sid_recv },
608 { WINBINDD_GID_TO_SID, "GID_TO_SID",
609 winbindd_gid_to_sid_send, winbindd_gid_to_sid_recv },
610 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
611 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
612 { WINBINDD_GETPWSID, "GETPWSID",
613 winbindd_getpwsid_send, winbindd_getpwsid_recv },
614 { WINBINDD_GETPWNAM, "GETPWNAM",
615 winbindd_getpwnam_send, winbindd_getpwnam_recv },
616 { WINBINDD_GETPWUID, "GETPWUID",
617 winbindd_getpwuid_send, winbindd_getpwuid_recv },
618 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
619 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
620 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
621 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
622 { WINBINDD_GETGROUPS, "GETGROUPS",
623 winbindd_getgroups_send, winbindd_getgroups_recv },
624 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
625 winbindd_show_sequence_send, winbindd_show_sequence_recv },
626 { WINBINDD_GETGRGID, "GETGRGID",
627 winbindd_getgrgid_send, winbindd_getgrgid_recv },
628 { WINBINDD_GETGRNAM, "GETGRNAM",
629 winbindd_getgrnam_send, winbindd_getgrnam_recv },
630 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
631 winbindd_getusersids_send, winbindd_getusersids_recv },
632 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
633 winbindd_lookuprids_send, winbindd_lookuprids_recv },
634 { WINBINDD_SETPWENT, "SETPWENT",
635 winbindd_setpwent_send, winbindd_setpwent_recv },
636 { WINBINDD_GETPWENT, "GETPWENT",
637 winbindd_getpwent_send, winbindd_getpwent_recv },
638 { WINBINDD_ENDPWENT, "ENDPWENT",
639 winbindd_endpwent_send, winbindd_endpwent_recv },
640 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
641 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
642 { WINBINDD_GETDCNAME, "GETDCNAME",
643 winbindd_getdcname_send, winbindd_getdcname_recv },
644 { WINBINDD_SETGRENT, "SETGRENT",
645 winbindd_setgrent_send, winbindd_setgrent_recv },
646 { WINBINDD_GETGRENT, "GETGRENT",
647 winbindd_getgrent_send, winbindd_getgrent_recv },
648 { WINBINDD_ENDGRENT, "ENDGRENT",
649 winbindd_endgrent_send, winbindd_endgrent_recv },
650 { WINBINDD_LIST_USERS, "LIST_USERS",
651 winbindd_list_users_send, winbindd_list_users_recv },
652 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
653 winbindd_list_groups_send, winbindd_list_groups_recv },
654 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
655 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
656 { WINBINDD_PING_DC, "PING_DC",
657 winbindd_ping_dc_send, winbindd_ping_dc_recv },
658 { WINBINDD_PAM_AUTH, "PAM_AUTH",
659 winbindd_pam_auth_send, winbindd_pam_auth_recv },
660 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
661 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
662 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
663 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
664 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
665 winbindd_pam_chng_pswd_auth_crap_send,
666 winbindd_pam_chng_pswd_auth_crap_recv },
667 { WINBINDD_WINS_BYIP, "WINS_BYIP",
668 winbindd_wins_byip_send, winbindd_wins_byip_recv },
669 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
670 winbindd_wins_byname_send, winbindd_wins_byname_recv },
672 { 0, NULL, NULL, NULL }
675 static struct winbindd_async_dispatch_table async_priv_table[] = {
676 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
677 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
678 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
679 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
680 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
681 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
682 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
683 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
685 { 0, NULL, NULL, NULL }
688 static void wb_request_done(struct tevent_req *req);
690 static void process_request(struct winbindd_cli_state *state)
692 struct winbindd_dispatch_table *table = dispatch_table;
693 struct winbindd_async_dispatch_table *atable;
695 state->mem_ctx = talloc_named(state, 0, "winbind request");
696 if (state->mem_ctx == NULL)
697 return;
699 /* Remember who asked us. */
700 state->pid = state->request->pid;
702 state->cmd_name = "unknown request";
703 state->recv_fn = NULL;
704 /* client is newest */
705 winbindd_promote_client(state);
707 /* Process command */
709 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
710 if (state->request->cmd == atable->cmd) {
711 break;
715 if ((atable->send_req == NULL) && state->privileged) {
716 for (atable = async_priv_table; atable->send_req;
717 atable += 1) {
718 if (state->request->cmd == atable->cmd) {
719 break;
724 if (atable->send_req != NULL) {
725 struct tevent_req *req;
727 state->cmd_name = atable->cmd_name;
728 state->recv_fn = atable->recv_req;
730 DEBUG(10, ("process_request: Handling async request %d:%s\n",
731 (int)state->pid, state->cmd_name));
733 req = atable->send_req(state->mem_ctx, winbind_event_context(),
734 state, state->request);
735 if (req == NULL) {
736 DEBUG(0, ("process_request: atable->send failed for "
737 "%s\n", atable->cmd_name));
738 request_error(state);
739 return;
741 tevent_req_set_callback(req, wb_request_done, state);
742 return;
745 state->response = talloc_zero(state->mem_ctx,
746 struct winbindd_response);
747 if (state->response == NULL) {
748 DEBUG(10, ("talloc failed\n"));
749 remove_client(state);
750 return;
752 state->response->result = WINBINDD_PENDING;
753 state->response->length = sizeof(struct winbindd_response);
755 for (table = dispatch_table; table->fn; table++) {
756 if (state->request->cmd == table->cmd) {
757 DEBUG(10,("process_request: request fn %s\n",
758 table->winbindd_cmd_name ));
759 state->cmd_name = table->winbindd_cmd_name;
760 table->fn(state);
761 break;
765 if (!table->fn) {
766 DEBUG(10,("process_request: unknown request fn number %d\n",
767 (int)state->request->cmd ));
768 request_error(state);
772 static void wb_request_done(struct tevent_req *req)
774 struct winbindd_cli_state *state = tevent_req_callback_data(
775 req, struct winbindd_cli_state);
776 NTSTATUS status;
778 state->response = talloc_zero(state->mem_ctx,
779 struct winbindd_response);
780 if (state->response == NULL) {
781 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
782 (int)state->pid, state->cmd_name));
783 remove_client(state);
784 return;
786 state->response->result = WINBINDD_PENDING;
787 state->response->length = sizeof(struct winbindd_response);
789 status = state->recv_fn(req, state->response);
790 TALLOC_FREE(req);
792 DEBUG(10,("wb_request_done[%d:%s]: %s\n",
793 (int)state->pid, state->cmd_name, nt_errstr(status)));
795 if (!NT_STATUS_IS_OK(status)) {
796 request_error(state);
797 return;
799 request_ok(state);
803 * This is the main event loop of winbind requests. It goes through a
804 * state-machine of 3 read/write requests, 4 if you have extra data to send.
806 * An idle winbind client has a read request of 4 bytes outstanding,
807 * finalizing function is request_len_recv, checking the length. request_recv
808 * then processes the packet. The processing function then at some point has
809 * to call request_finished which schedules sending the response.
812 static void request_finished(struct winbindd_cli_state *state);
814 static void winbind_client_request_read(struct tevent_req *req);
815 static void winbind_client_response_written(struct tevent_req *req);
816 static void winbind_client_activity(struct tevent_req *req);
818 static void request_finished(struct winbindd_cli_state *state)
820 struct tevent_req *req;
822 /* free client socket monitoring request */
823 TALLOC_FREE(state->io_req);
825 TALLOC_FREE(state->request);
827 req = wb_resp_write_send(state, winbind_event_context(),
828 state->out_queue, state->sock,
829 state->response);
830 if (req == NULL) {
831 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
832 (int)state->pid, state->cmd_name));
833 remove_client(state);
834 return;
836 tevent_req_set_callback(req, winbind_client_response_written, state);
837 state->io_req = req;
840 static void winbind_client_response_written(struct tevent_req *req)
842 struct winbindd_cli_state *state = tevent_req_callback_data(
843 req, struct winbindd_cli_state);
844 ssize_t ret;
845 int err;
847 state->io_req = NULL;
849 ret = wb_resp_write_recv(req, &err);
850 TALLOC_FREE(req);
851 if (ret == -1) {
852 close(state->sock);
853 state->sock = -1;
854 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
855 (int)state->pid, state->cmd_name, strerror(err)));
856 remove_client(state);
857 return;
860 DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
861 "to client\n", (int)state->pid, state->cmd_name));
863 TALLOC_FREE(state->mem_ctx);
864 state->response = NULL;
865 state->cmd_name = "no request";
866 state->recv_fn = NULL;
868 req = wb_req_read_send(state, winbind_event_context(), state->sock,
869 WINBINDD_MAX_EXTRA_DATA);
870 if (req == NULL) {
871 remove_client(state);
872 return;
874 tevent_req_set_callback(req, winbind_client_request_read, state);
875 state->io_req = req;
878 void request_error(struct winbindd_cli_state *state)
880 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
881 state->response->result = WINBINDD_ERROR;
882 request_finished(state);
885 void request_ok(struct winbindd_cli_state *state)
887 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
888 state->response->result = WINBINDD_OK;
889 request_finished(state);
892 /* Process a new connection by adding it to the client connection list */
894 static void new_connection(int listen_sock, bool privileged)
896 struct sockaddr_un sunaddr;
897 struct winbindd_cli_state *state;
898 struct tevent_req *req;
899 socklen_t len;
900 int sock;
902 /* Accept connection */
904 len = sizeof(sunaddr);
906 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
908 if (sock == -1) {
909 if (errno != EINTR) {
910 DEBUG(0, ("Failed to accept socket - %s\n",
911 strerror(errno)));
913 return;
916 DEBUG(6,("accepted socket %d\n", sock));
918 /* Create new connection structure */
920 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
921 close(sock);
922 return;
925 state->sock = sock;
927 state->out_queue = tevent_queue_create(state, "winbind client reply");
928 if (state->out_queue == NULL) {
929 close(sock);
930 TALLOC_FREE(state);
931 return;
934 state->privileged = privileged;
936 req = wb_req_read_send(state, winbind_event_context(), state->sock,
937 WINBINDD_MAX_EXTRA_DATA);
938 if (req == NULL) {
939 TALLOC_FREE(state);
940 close(sock);
941 return;
943 tevent_req_set_callback(req, winbind_client_request_read, state);
944 state->io_req = req;
946 /* Add to connection list */
948 winbindd_add_client(state);
951 static void winbind_client_request_read(struct tevent_req *req)
953 struct winbindd_cli_state *state = tevent_req_callback_data(
954 req, struct winbindd_cli_state);
955 ssize_t ret;
956 int err;
958 state->io_req = NULL;
960 ret = wb_req_read_recv(req, state, &state->request, &err);
961 TALLOC_FREE(req);
962 if (ret == -1) {
963 if (err == EPIPE) {
964 DEBUG(6, ("closing socket %d, client exited\n",
965 state->sock));
966 } else {
967 DEBUG(2, ("Could not read client request from fd %d: "
968 "%s\n", state->sock, strerror(err)));
970 close(state->sock);
971 state->sock = -1;
972 remove_client(state);
973 return;
976 req = wait_for_read_send(state, winbind_event_context(), state->sock,
977 true);
978 if (req == NULL) {
979 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
980 " wait_for_read_send failed - removing client\n",
981 (int)state->pid, state->cmd_name));
982 remove_client(state);
983 return;
985 tevent_req_set_callback(req, winbind_client_activity, state);
986 state->io_req = req;
988 process_request(state);
991 static void winbind_client_activity(struct tevent_req *req)
993 struct winbindd_cli_state *state =
994 tevent_req_callback_data(req, struct winbindd_cli_state);
995 int err;
996 bool has_data;
998 has_data = wait_for_read_recv(req, &err);
1000 if (has_data) {
1001 DEBUG(0, ("winbind_client_activity[%d:%s]:"
1002 "unexpected data from client - removing client\n",
1003 (int)state->pid, state->cmd_name));
1004 } else {
1005 if (err == EPIPE) {
1006 DEBUG(6, ("winbind_client_activity[%d:%s]: "
1007 "client has closed connection - removing "
1008 "client\n",
1009 (int)state->pid, state->cmd_name));
1010 } else {
1011 DEBUG(2, ("winbind_client_activity[%d:%s]: "
1012 "client socket error (%s) - removing "
1013 "client\n",
1014 (int)state->pid, state->cmd_name,
1015 strerror(err)));
1019 remove_client(state);
1022 /* Remove a client connection from client connection list */
1024 static void remove_client(struct winbindd_cli_state *state)
1026 char c = 0;
1027 int nwritten;
1029 /* It's a dead client - hold a funeral */
1031 if (state == NULL) {
1032 return;
1036 * We need to remove a pending wb_req_read_*
1037 * or wb_resp_write_* request before closing the
1038 * socket.
1040 * This is important as they might have used tevent_add_fd() and we
1041 * use the epoll * backend on linux. So we must remove the tevent_fd
1042 * before closing the fd.
1044 * Otherwise we might hit a race with close_conns_after_fork() (via
1045 * winbindd_reinit_after_fork()) where a file description
1046 * is still open in a child, which means it's still active in
1047 * the parents epoll queue, but the related tevent_fd is already
1048 * already gone in the parent.
1050 * See bug #11141.
1052 TALLOC_FREE(state->io_req);
1054 if (state->sock != -1) {
1055 /* tell client, we are closing ... */
1056 nwritten = write(state->sock, &c, sizeof(c));
1057 if (nwritten == -1) {
1058 DEBUG(2, ("final write to client failed: %s\n",
1059 strerror(errno)));
1062 /* Close socket */
1064 close(state->sock);
1065 state->sock = -1;
1068 TALLOC_FREE(state->mem_ctx);
1070 /* Remove from list and free */
1072 winbindd_remove_client(state);
1073 TALLOC_FREE(state);
1076 /* Is a client idle? */
1078 static bool client_is_idle(struct winbindd_cli_state *state) {
1079 return (state->request == NULL &&
1080 state->response == NULL &&
1081 !state->pwent_state && !state->grent_state);
1084 /* Shutdown client connection which has been idle for the longest time */
1086 static bool remove_idle_client(void)
1088 struct winbindd_cli_state *state, *remove_state = NULL;
1089 int nidle = 0;
1091 for (state = winbindd_client_list(); state; state = state->next) {
1092 if (client_is_idle(state)) {
1093 nidle++;
1094 /* list is sorted by access time */
1095 remove_state = state;
1099 if (remove_state) {
1100 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1101 nidle, remove_state->sock, (unsigned int)remove_state->pid));
1102 remove_client(remove_state);
1103 return True;
1106 return False;
1110 * Terminate all clients whose requests have taken longer than
1111 * "winbind request timeout" seconds to process, or have been
1112 * idle for more than "winbind request timeout" seconds.
1115 static void remove_timed_out_clients(void)
1117 struct winbindd_cli_state *state, *prev = NULL;
1118 time_t curr_time = time(NULL);
1119 int timeout_val = lp_winbind_request_timeout();
1121 for (state = winbindd_client_list_tail(); state; state = prev) {
1122 time_t expiry_time;
1124 prev = winbindd_client_list_prev(state);
1125 expiry_time = state->last_access + timeout_val;
1127 if (curr_time > expiry_time) {
1128 if (client_is_idle(state)) {
1129 DEBUG(5,("Idle client timed out, "
1130 "shutting down sock %d, pid %u\n",
1131 state->sock,
1132 (unsigned int)state->pid));
1133 } else {
1134 DEBUG(5,("Client request timed out, "
1135 "shutting down sock %d, pid %u\n",
1136 state->sock,
1137 (unsigned int)state->pid));
1139 remove_client(state);
1140 } else {
1141 /* list is sorted, previous clients in
1142 list are newer */
1143 break;
1148 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
1149 struct tevent_timer *te,
1150 struct timeval current_time,
1151 void *private_data)
1153 remove_timed_out_clients();
1154 if (tevent_add_timer(ev, ev,
1155 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
1156 winbindd_scrub_clients_handler, NULL) == NULL) {
1157 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
1158 exit(1);
1162 struct winbindd_listen_state {
1163 bool privileged;
1164 int fd;
1167 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1168 struct tevent_fd *fde,
1169 uint16_t flags,
1170 void *private_data)
1172 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1173 struct winbindd_listen_state);
1175 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1176 DEBUG(5,("winbindd: Exceeding %d client "
1177 "connections, removing idle "
1178 "connection.\n", lp_winbind_max_clients()));
1179 if (!remove_idle_client()) {
1180 DEBUG(0,("winbindd: Exceeding %d "
1181 "client connections, no idle "
1182 "connection found\n",
1183 lp_winbind_max_clients()));
1184 break;
1187 remove_timed_out_clients();
1188 new_connection(s->fd, s->privileged);
1192 * Winbindd socket accessor functions
1195 char *get_winbind_priv_pipe_dir(void)
1197 return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1200 static void winbindd_setup_max_fds(void)
1202 int num_fds = MAX_OPEN_FUDGEFACTOR;
1203 int actual_fds;
1205 num_fds += lp_winbind_max_clients();
1206 /* Add some more to account for 2 sockets open
1207 when the client transitions from unprivileged
1208 to privileged socket
1210 num_fds += lp_winbind_max_clients() / 10;
1212 /* Add one socket per child process
1213 (yeah there are child processes other than the
1214 domain children but only domain children can vary
1215 with configuration
1217 num_fds += lp_winbind_max_domain_connections() *
1218 (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
1220 actual_fds = set_maxfiles(num_fds);
1222 if (actual_fds < num_fds) {
1223 DEBUG(1, ("winbindd_setup_max_fds: Information only: "
1224 "requested %d open files, %d are available.\n",
1225 num_fds, actual_fds));
1229 static bool winbindd_setup_listeners(void)
1231 struct winbindd_listen_state *pub_state = NULL;
1232 struct winbindd_listen_state *priv_state = NULL;
1233 struct tevent_fd *fde;
1234 int rc;
1235 char *socket_path;
1237 pub_state = talloc(winbind_event_context(),
1238 struct winbindd_listen_state);
1239 if (!pub_state) {
1240 goto failed;
1243 pub_state->privileged = false;
1244 pub_state->fd = create_pipe_sock(
1245 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1246 if (pub_state->fd == -1) {
1247 goto failed;
1249 rc = listen(pub_state->fd, 5);
1250 if (rc < 0) {
1251 goto failed;
1254 fde = tevent_add_fd(winbind_event_context(), pub_state, pub_state->fd,
1255 TEVENT_FD_READ, winbindd_listen_fde_handler,
1256 pub_state);
1257 if (fde == NULL) {
1258 close(pub_state->fd);
1259 goto failed;
1261 tevent_fd_set_auto_close(fde);
1263 priv_state = talloc(winbind_event_context(),
1264 struct winbindd_listen_state);
1265 if (!priv_state) {
1266 goto failed;
1269 socket_path = get_winbind_priv_pipe_dir();
1270 if (socket_path == NULL) {
1271 goto failed;
1274 priv_state->privileged = true;
1275 priv_state->fd = create_pipe_sock(
1276 socket_path, WINBINDD_SOCKET_NAME, 0750);
1277 TALLOC_FREE(socket_path);
1278 if (priv_state->fd == -1) {
1279 goto failed;
1281 rc = listen(priv_state->fd, 5);
1282 if (rc < 0) {
1283 goto failed;
1286 fde = tevent_add_fd(winbind_event_context(), priv_state,
1287 priv_state->fd, TEVENT_FD_READ,
1288 winbindd_listen_fde_handler, priv_state);
1289 if (fde == NULL) {
1290 close(priv_state->fd);
1291 goto failed;
1293 tevent_fd_set_auto_close(fde);
1295 winbindd_scrub_clients_handler(winbind_event_context(), NULL,
1296 timeval_current(), NULL);
1297 return true;
1298 failed:
1299 TALLOC_FREE(pub_state);
1300 TALLOC_FREE(priv_state);
1301 return false;
1304 bool winbindd_use_idmap_cache(void)
1306 return !opt_nocache;
1309 bool winbindd_use_cache(void)
1311 return !opt_nocache;
1314 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1315 bool foreground)
1317 NTSTATUS status;
1318 /* Setup signal handlers */
1320 if (!winbindd_setup_sig_term_handler(true))
1321 exit(1);
1322 if (!winbindd_setup_stdin_handler(true, foreground))
1323 exit(1);
1324 if (!winbindd_setup_sig_hup_handler(NULL))
1325 exit(1);
1326 if (!winbindd_setup_sig_chld_handler())
1327 exit(1);
1328 if (!winbindd_setup_sig_usr2_handler())
1329 exit(1);
1331 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1334 * Ensure all cache and idmap caches are consistent
1335 * and initialized before we startup.
1337 if (!winbindd_cache_validate_and_initialize()) {
1338 exit(1);
1341 /* get broadcast messages */
1343 if (!serverid_register(messaging_server_id(msg_ctx),
1344 FLAG_MSG_GENERAL |
1345 FLAG_MSG_WINBIND |
1346 FLAG_MSG_DBWRAP)) {
1347 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
1348 exit(1);
1351 /* React on 'smbcontrol winbindd reload-config' in the same way
1352 as to SIGHUP signal */
1353 messaging_register(msg_ctx, NULL,
1354 MSG_SMB_CONF_UPDATED, msg_reload_services);
1355 messaging_register(msg_ctx, NULL,
1356 MSG_SHUTDOWN, msg_shutdown);
1358 /* Handle online/offline messages. */
1359 messaging_register(msg_ctx, NULL,
1360 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1361 messaging_register(msg_ctx, NULL,
1362 MSG_WINBIND_ONLINE, winbind_msg_online);
1363 messaging_register(msg_ctx, NULL,
1364 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1366 /* Handle domain online/offline messages for domains */
1367 messaging_register(winbind_messaging_context(), NULL,
1368 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1369 messaging_register(winbind_messaging_context(), NULL,
1370 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1372 messaging_register(msg_ctx, NULL,
1373 MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
1375 messaging_register(msg_ctx, NULL,
1376 MSG_WINBIND_VALIDATE_CACHE,
1377 winbind_msg_validate_cache);
1379 messaging_register(msg_ctx, NULL,
1380 MSG_WINBIND_DUMP_DOMAIN_LIST,
1381 winbind_msg_dump_domain_list);
1383 messaging_register(msg_ctx, NULL,
1384 MSG_WINBIND_IP_DROPPED,
1385 winbind_msg_ip_dropped_parent);
1387 /* Register handler for MSG_DEBUG. */
1388 messaging_register(msg_ctx, NULL,
1389 MSG_DEBUG,
1390 winbind_msg_debug);
1392 netsamlogon_cache_init(); /* Non-critical */
1394 /* clear the cached list of trusted domains */
1396 wcache_tdc_clear();
1398 if (!init_domain_list()) {
1399 DEBUG(0,("unable to initialize domain list\n"));
1400 exit(1);
1403 init_idmap_child();
1404 init_locator_child();
1406 smb_nscd_flush_user_cache();
1407 smb_nscd_flush_group_cache();
1409 if (lp_allow_trusted_domains()) {
1410 if (tevent_add_timer(winbind_event_context(), NULL, timeval_zero(),
1411 rescan_trusted_domains, NULL) == NULL) {
1412 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1413 exit(1);
1417 status = wb_irpc_register();
1419 if (!NT_STATUS_IS_OK(status)) {
1420 DEBUG(0, ("Could not register IRPC handlers\n"));
1421 exit(1);
1425 struct winbindd_addrchanged_state {
1426 struct addrchange_context *ctx;
1427 struct tevent_context *ev;
1428 struct messaging_context *msg_ctx;
1431 static void winbindd_addr_changed(struct tevent_req *req);
1433 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1434 struct tevent_context *ev,
1435 struct messaging_context *msg_ctx)
1437 struct winbindd_addrchanged_state *state;
1438 struct tevent_req *req;
1439 NTSTATUS status;
1441 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1442 if (state == NULL) {
1443 DEBUG(10, ("talloc failed\n"));
1444 return;
1446 state->ev = ev;
1447 state->msg_ctx = msg_ctx;
1449 status = addrchange_context_create(state, &state->ctx);
1450 if (!NT_STATUS_IS_OK(status)) {
1451 DEBUG(10, ("addrchange_context_create failed: %s\n",
1452 nt_errstr(status)));
1453 TALLOC_FREE(state);
1454 return;
1456 req = addrchange_send(state, ev, state->ctx);
1457 if (req == NULL) {
1458 DEBUG(0, ("addrchange_send failed\n"));
1459 TALLOC_FREE(state);
1460 return;
1462 tevent_req_set_callback(req, winbindd_addr_changed, state);
1465 static void winbindd_addr_changed(struct tevent_req *req)
1467 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1468 req, struct winbindd_addrchanged_state);
1469 enum addrchange_type type;
1470 struct sockaddr_storage addr;
1471 NTSTATUS status;
1473 status = addrchange_recv(req, &type, &addr);
1474 TALLOC_FREE(req);
1475 if (!NT_STATUS_IS_OK(status)) {
1476 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1477 nt_errstr(status)));
1478 TALLOC_FREE(state);
1479 return;
1481 if (type == ADDRCHANGE_DEL) {
1482 char addrstr[INET6_ADDRSTRLEN];
1483 DATA_BLOB blob;
1485 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1487 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1488 addrstr));
1490 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1492 status = messaging_send(state->msg_ctx,
1493 messaging_server_id(state->msg_ctx),
1494 MSG_WINBIND_IP_DROPPED, &blob);
1495 if (!NT_STATUS_IS_OK(status)) {
1496 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1497 nt_errstr(status)));
1500 req = addrchange_send(state, state->ev, state->ctx);
1501 if (req == NULL) {
1502 DEBUG(0, ("addrchange_send failed\n"));
1503 TALLOC_FREE(state);
1504 return;
1506 tevent_req_set_callback(req, winbindd_addr_changed, state);
1509 /* Main function */
1511 int main(int argc, const char **argv)
1513 static bool is_daemon = False;
1514 static bool Fork = True;
1515 static bool log_stdout = False;
1516 static bool no_process_group = False;
1517 enum {
1518 OPT_DAEMON = 1000,
1519 OPT_FORK,
1520 OPT_NO_PROCESS_GROUP,
1521 OPT_LOG_STDOUT
1523 struct poptOption long_options[] = {
1524 POPT_AUTOHELP
1525 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1526 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1527 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1528 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1529 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1530 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1531 POPT_COMMON_SAMBA
1532 POPT_TABLEEND
1534 poptContext pc;
1535 int opt;
1536 TALLOC_CTX *frame;
1537 NTSTATUS status;
1538 bool ok;
1541 * Do this before any other talloc operation
1543 talloc_enable_null_tracking();
1544 frame = talloc_stackframe();
1547 * We want total control over the permissions on created files,
1548 * so set our umask to 0.
1550 umask(0);
1552 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1554 /* glibc (?) likes to print "User defined signal 1" and exit if a
1555 SIGUSR[12] is received before a handler is installed */
1557 CatchSignal(SIGUSR1, SIG_IGN);
1558 CatchSignal(SIGUSR2, SIG_IGN);
1560 fault_setup();
1561 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1563 smb_init_locale();
1565 /* Initialise for running in non-root mode */
1567 sec_init();
1569 set_remote_machine_name("winbindd", False);
1571 /* Set environment variable so we don't recursively call ourselves.
1572 This may also be useful interactively. */
1574 if ( !winbind_off() ) {
1575 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1576 exit(1);
1579 /* Initialise samba/rpc client stuff */
1581 pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1583 while ((opt = poptGetNextOpt(pc)) != -1) {
1584 switch (opt) {
1585 /* Don't become a daemon */
1586 case OPT_DAEMON:
1587 is_daemon = True;
1588 break;
1589 case 'i':
1590 interactive = True;
1591 log_stdout = True;
1592 Fork = False;
1593 break;
1594 case OPT_FORK:
1595 Fork = false;
1596 break;
1597 case OPT_NO_PROCESS_GROUP:
1598 no_process_group = true;
1599 break;
1600 case OPT_LOG_STDOUT:
1601 log_stdout = true;
1602 break;
1603 case 'n':
1604 opt_nocache = true;
1605 break;
1606 default:
1607 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1608 poptBadOption(pc, 0), poptStrerror(opt));
1609 poptPrintUsage(pc, stderr, 0);
1610 exit(1);
1614 /* We call dump_core_setup one more time because the command line can
1615 * set the log file or the log-basename and this will influence where
1616 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1617 * the default value derived from build's prefix. For EOM this value
1618 * is often not related to the path where winbindd is actually run
1619 * in production.
1621 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1622 if (is_daemon && interactive) {
1623 d_fprintf(stderr,"\nERROR: "
1624 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1625 poptPrintUsage(pc, stderr, 0);
1626 exit(1);
1629 if (log_stdout && Fork) {
1630 d_fprintf(stderr, "\nERROR: "
1631 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1632 poptPrintUsage(pc, stderr, 0);
1633 exit(1);
1636 poptFreeContext(pc);
1638 if (!override_logfile) {
1639 char *lfile = NULL;
1640 if (asprintf(&lfile,"%s/log.winbindd",
1641 get_dyn_LOGFILEBASE()) > 0) {
1642 lp_set_logfile(lfile);
1643 SAFE_FREE(lfile);
1647 if (log_stdout) {
1648 setup_logging("winbindd", DEBUG_STDOUT);
1649 } else {
1650 setup_logging("winbindd", DEBUG_FILE);
1652 reopen_logs();
1654 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1655 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1657 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1658 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1659 exit(1);
1661 /* After parsing the configuration file we setup the core path one more time
1662 * as the log file might have been set in the configuration and cores's
1663 * path is by default basename(lp_logfile()).
1665 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1667 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1668 && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1669 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1670 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"));
1671 exit(1);
1674 if (!cluster_probe_ok()) {
1675 exit(1);
1678 /* Initialise messaging system */
1680 if (winbind_messaging_context() == NULL) {
1681 exit(1);
1684 if (!reload_services_file(NULL)) {
1685 DEBUG(0, ("error opening config file\n"));
1686 exit(1);
1689 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1690 if (!ok) {
1691 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1692 lp_lock_directory(), strerror(errno)));
1693 exit(1);
1696 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1697 if (!ok) {
1698 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1699 lp_pid_directory(), strerror(errno)));
1700 exit(1);
1703 /* Setup names. */
1705 if (!init_names())
1706 exit(1);
1708 load_interfaces();
1710 if (!secrets_init()) {
1712 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1713 return False;
1716 status = rpccli_pre_open_netlogon_creds();
1717 if (!NT_STATUS_IS_OK(status)) {
1718 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1719 nt_errstr(status)));
1720 exit(1);
1723 /* Unblock all signals we are interested in as they may have been
1724 blocked by the parent process. */
1726 BlockSignals(False, SIGINT);
1727 BlockSignals(False, SIGQUIT);
1728 BlockSignals(False, SIGTERM);
1729 BlockSignals(False, SIGUSR1);
1730 BlockSignals(False, SIGUSR2);
1731 BlockSignals(False, SIGHUP);
1732 BlockSignals(False, SIGCHLD);
1734 if (!interactive)
1735 become_daemon(Fork, no_process_group, log_stdout);
1737 pidfile_create(lp_pid_directory(), "winbindd");
1739 #if HAVE_SETPGID
1741 * If we're interactive we want to set our own process group for
1742 * signal management.
1744 if (interactive && !no_process_group)
1745 setpgid( (pid_t)0, (pid_t)0);
1746 #endif
1748 TimeInit();
1750 /* Don't use winbindd_reinit_after_fork here as
1751 * we're just starting up and haven't created any
1752 * winbindd-specific resources we must free yet. JRA.
1755 status = reinit_after_fork(winbind_messaging_context(),
1756 winbind_event_context(),
1757 false);
1758 if (!NT_STATUS_IS_OK(status)) {
1759 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1763 * Do not initialize the parent-child-pipe before becoming
1764 * a daemon: this is used to detect a died parent in the child
1765 * process.
1767 status = init_before_fork();
1768 if (!NT_STATUS_IS_OK(status)) {
1769 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1772 winbindd_register_handlers(winbind_messaging_context(), !Fork);
1774 if (!messaging_parent_dgm_cleanup_init(winbind_messaging_context())) {
1775 exit(1);
1778 status = init_system_session_info();
1779 if (!NT_STATUS_IS_OK(status)) {
1780 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1783 rpc_lsarpc_init(NULL);
1784 rpc_samr_init(NULL);
1786 winbindd_init_addrchange(NULL, winbind_event_context(),
1787 winbind_messaging_context());
1789 /* setup listen sockets */
1791 if (!winbindd_setup_listeners()) {
1792 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1795 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1797 TALLOC_FREE(frame);
1799 if (!interactive) {
1800 daemon_ready("winbindd");
1803 /* Loop waiting for requests */
1804 while (1) {
1805 frame = talloc_stackframe();
1807 if (tevent_loop_once(winbind_event_context()) == -1) {
1808 DEBUG(1, ("tevent_loop_once() failed: %s\n",
1809 strerror(errno)));
1810 return 1;
1813 TALLOC_FREE(frame);
1816 return 0;