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/>.
26 #include "lib/cmdline/cmdline.h"
28 #include "nsswitch/winbind_client.h"
29 #include "nsswitch/wb_reqtrans.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"
36 #include "rpc_client/cli_netlogon.h"
38 #include "lib/addrchange.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"
50 #include "lib/util/tevent_req_profile.h"
51 #include "lib/gencache.h"
52 #include "rpc_server/rpc_config.h"
53 #include "lib/global_contexts.h"
54 #include "source3/lib/substitute.h"
55 #include "winbindd_traceid.h"
56 #include "lib/util/util_process.h"
59 #define DBGC_CLASS DBGC_WINBIND
61 #define SCRUB_CLIENTS_INTERVAL 5
63 static bool client_is_idle(struct winbindd_cli_state
*state
);
64 static void remove_client(struct winbindd_cli_state
*state
);
66 static bool interactive
= False
;
68 /* Reload configuration */
72 static void winbindd_status(void)
74 struct winbindd_cli_state
*tmp
;
76 DEBUG(0, ("winbindd status:\n"));
78 /* Print client state information */
80 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
82 if (DEBUGLEVEL
>= 2 && winbindd_num_clients()) {
83 DEBUG(2, ("\tclient list:\n"));
84 for(tmp
= winbindd_client_list(); tmp
; tmp
= tmp
->next
) {
85 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
86 (unsigned long)tmp
->pid
, tmp
->sock
,
87 client_is_idle(tmp
) ? "idle" : "active"));
93 handle stdin becoming readable when we are in --foreground mode
95 static void winbindd_stdin_handler(struct tevent_context
*ev
,
96 struct tevent_fd
*fde
,
101 if (read(0, &c
, 1) != 1) {
102 bool *is_parent
= talloc_get_type_abort(private_data
, bool);
104 /* we have reached EOF on stdin, which means the
105 parent has exited. Shutdown the server */
106 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
108 winbindd_terminate(*is_parent
);
112 bool winbindd_setup_stdin_handler(bool parent
, bool foreground
)
119 is_parent
= talloc(global_event_context(), bool);
126 /* if we are running in the foreground then look for
127 EOF on stdin, and exit if it happens. This allows
128 us to die if the parent process dies
129 Only do this on a pipe or socket, no other device.
131 if (fstat(0, &st
) != 0) {
134 if (S_ISFIFO(st
.st_mode
) || S_ISSOCK(st
.st_mode
)) {
135 tevent_add_fd(global_event_context(),
139 winbindd_stdin_handler
,
147 static void winbindd_sig_chld_handler(struct tevent_context
*ev
,
148 struct tevent_signal
*se
,
156 while ((pid
= waitpid(-1, NULL
, WNOHANG
)) > 0) {
157 winbind_child_died(pid
);
161 static bool winbindd_setup_sig_chld_handler(void)
163 struct tevent_signal
*se
;
165 se
= tevent_add_signal(global_event_context(),
166 global_event_context(),
168 winbindd_sig_chld_handler
,
177 static void winbindd_sig_usr2_handler(struct tevent_context
*ev
,
178 struct tevent_signal
*se
,
187 static bool winbindd_setup_sig_usr2_handler(void)
189 struct tevent_signal
*se
;
191 se
= tevent_add_signal(global_event_context(),
192 global_event_context(),
194 winbindd_sig_usr2_handler
,
203 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
204 static void msg_shutdown(struct messaging_context
*msg
,
207 struct server_id server_id
,
210 /* only the parent waits for this message */
211 DEBUG(0,("Got shutdown message\n"));
212 winbindd_terminate(true);
216 static void winbind_msg_validate_cache(struct messaging_context
*msg_ctx
,
219 struct server_id server_id
,
226 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
230 * call the validation code from a child:
231 * so we don't block the main winbindd and the validation
232 * code can safely use fork/waitpid...
236 if (child_pid
== -1) {
237 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
242 if (child_pid
!= 0) {
244 DEBUG(5, ("winbind_msg_validate_cache: child created with "
245 "pid %d.\n", (int)child_pid
));
251 status
= winbindd_reinit_after_fork(NULL
, NULL
);
252 if (!NT_STATUS_IS_OK(status
)) {
253 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
258 /* install default SIGCHLD handler: validation code uses fork/waitpid */
259 CatchSignal(SIGCHLD
, SIG_DFL
);
261 process_set_title("wb: check cache", "validate cache child");
263 ret
= (uint8_t)winbindd_validate_cache_nobackup();
264 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret
));
265 messaging_send_buf(msg_ctx
, server_id
, MSG_WINBIND_VALIDATE_CACHE
, &ret
,
270 static struct winbindd_bool_dispatch_table
{
271 enum winbindd_cmd cmd
;
272 bool (*fn
)(struct winbindd_cli_state
*state
);
273 const char *cmd_name
;
274 } bool_dispatch_table
[] = {
275 { WINBINDD_INTERFACE_VERSION
,
276 winbindd_interface_version
,
277 "INTERFACE_VERSION" },
284 { WINBINDD_DOMAIN_NAME
,
285 winbindd_domain_name
,
287 { WINBINDD_NETBIOS_NAME
,
288 winbindd_netbios_name
,
293 { WINBINDD_CCACHE_NTLMAUTH
,
294 winbindd_ccache_ntlm_auth
,
296 { WINBINDD_CCACHE_SAVE
,
297 winbindd_ccache_save
,
299 { WINBINDD_PRIV_PIPE_DIR
,
300 winbindd_priv_pipe_dir
,
301 "WINBINDD_PRIV_PIPE_DIR" },
302 { WINBINDD_LIST_TRUSTDOM
,
303 winbindd_list_trusted_domains
,
307 struct winbindd_async_dispatch_table
{
308 enum winbindd_cmd cmd
;
309 const char *cmd_name
;
310 struct tevent_req
*(*send_req
)(TALLOC_CTX
*mem_ctx
,
311 struct tevent_context
*ev
,
312 struct winbindd_cli_state
*cli
,
313 struct winbindd_request
*request
);
314 NTSTATUS (*recv_req
)(struct tevent_req
*req
,
315 struct winbindd_response
*presp
);
318 static struct winbindd_async_dispatch_table async_nonpriv_table
[] = {
319 { WINBINDD_LOOKUPSID
, "LOOKUPSID",
320 winbindd_lookupsid_send
, winbindd_lookupsid_recv
},
321 { WINBINDD_LOOKUPSIDS
, "LOOKUPSIDS",
322 winbindd_lookupsids_send
, winbindd_lookupsids_recv
},
323 { WINBINDD_LOOKUPNAME
, "LOOKUPNAME",
324 winbindd_lookupname_send
, winbindd_lookupname_recv
},
325 { WINBINDD_SIDS_TO_XIDS
, "SIDS_TO_XIDS",
326 winbindd_sids_to_xids_send
, winbindd_sids_to_xids_recv
},
327 { WINBINDD_XIDS_TO_SIDS
, "XIDS_TO_SIDS",
328 winbindd_xids_to_sids_send
, winbindd_xids_to_sids_recv
},
329 { WINBINDD_GETPWSID
, "GETPWSID",
330 winbindd_getpwsid_send
, winbindd_getpwsid_recv
},
331 { WINBINDD_GETPWNAM
, "GETPWNAM",
332 winbindd_getpwnam_send
, winbindd_getpwnam_recv
},
333 { WINBINDD_GETPWUID
, "GETPWUID",
334 winbindd_getpwuid_send
, winbindd_getpwuid_recv
},
335 { WINBINDD_GETSIDALIASES
, "GETSIDALIASES",
336 winbindd_getsidaliases_send
, winbindd_getsidaliases_recv
},
337 { WINBINDD_GETUSERDOMGROUPS
, "GETUSERDOMGROUPS",
338 winbindd_getuserdomgroups_send
, winbindd_getuserdomgroups_recv
},
339 { WINBINDD_GETGROUPS
, "GETGROUPS",
340 winbindd_getgroups_send
, winbindd_getgroups_recv
},
341 { WINBINDD_GETGRGID
, "GETGRGID",
342 winbindd_getgrgid_send
, winbindd_getgrgid_recv
},
343 { WINBINDD_GETGRNAM
, "GETGRNAM",
344 winbindd_getgrnam_send
, winbindd_getgrnam_recv
},
345 { WINBINDD_GETUSERSIDS
, "GETUSERSIDS",
346 winbindd_getusersids_send
, winbindd_getusersids_recv
},
347 { WINBINDD_LOOKUPRIDS
, "LOOKUPRIDS",
348 winbindd_lookuprids_send
, winbindd_lookuprids_recv
},
349 { WINBINDD_SETPWENT
, "SETPWENT",
350 winbindd_setpwent_send
, winbindd_setpwent_recv
},
351 { WINBINDD_GETPWENT
, "GETPWENT",
352 winbindd_getpwent_send
, winbindd_getpwent_recv
},
353 { WINBINDD_ENDPWENT
, "ENDPWENT",
354 winbindd_endpwent_send
, winbindd_endpwent_recv
},
355 { WINBINDD_DSGETDCNAME
, "DSGETDCNAME",
356 winbindd_dsgetdcname_send
, winbindd_dsgetdcname_recv
},
357 { WINBINDD_GETDCNAME
, "GETDCNAME",
358 winbindd_getdcname_send
, winbindd_getdcname_recv
},
359 { WINBINDD_SETGRENT
, "SETGRENT",
360 winbindd_setgrent_send
, winbindd_setgrent_recv
},
361 { WINBINDD_GETGRENT
, "GETGRENT",
362 winbindd_getgrent_send
, winbindd_getgrent_recv
},
363 { WINBINDD_ENDGRENT
, "ENDGRENT",
364 winbindd_endgrent_send
, winbindd_endgrent_recv
},
365 { WINBINDD_LIST_USERS
, "LIST_USERS",
366 winbindd_list_users_send
, winbindd_list_users_recv
},
367 { WINBINDD_LIST_GROUPS
, "LIST_GROUPS",
368 winbindd_list_groups_send
, winbindd_list_groups_recv
},
369 { WINBINDD_CHECK_MACHACC
, "CHECK_MACHACC",
370 winbindd_check_machine_acct_send
, winbindd_check_machine_acct_recv
},
371 { WINBINDD_PING_DC
, "PING_DC",
372 winbindd_ping_dc_send
, winbindd_ping_dc_recv
},
373 { WINBINDD_PAM_AUTH
, "PAM_AUTH",
374 winbindd_pam_auth_send
, winbindd_pam_auth_recv
},
375 { WINBINDD_PAM_LOGOFF
, "PAM_LOGOFF",
376 winbindd_pam_logoff_send
, winbindd_pam_logoff_recv
},
377 { WINBINDD_PAM_CHAUTHTOK
, "PAM_CHAUTHTOK",
378 winbindd_pam_chauthtok_send
, winbindd_pam_chauthtok_recv
},
379 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP
, "PAM_CHNG_PSWD_AUTH_CRAP",
380 winbindd_pam_chng_pswd_auth_crap_send
,
381 winbindd_pam_chng_pswd_auth_crap_recv
},
382 { WINBINDD_WINS_BYIP
, "WINS_BYIP",
383 winbindd_wins_byip_send
, winbindd_wins_byip_recv
},
384 { WINBINDD_WINS_BYNAME
, "WINS_BYNAME",
385 winbindd_wins_byname_send
, winbindd_wins_byname_recv
},
386 { WINBINDD_DOMAIN_INFO
, "DOMAIN_INFO",
387 winbindd_domain_info_send
, winbindd_domain_info_recv
},
389 { 0, NULL
, NULL
, NULL
}
392 static struct winbindd_async_dispatch_table async_priv_table
[] = {
393 { WINBINDD_ALLOCATE_UID
, "ALLOCATE_UID",
394 winbindd_allocate_uid_send
, winbindd_allocate_uid_recv
},
395 { WINBINDD_ALLOCATE_GID
, "ALLOCATE_GID",
396 winbindd_allocate_gid_send
, winbindd_allocate_gid_recv
},
397 { WINBINDD_CHANGE_MACHACC
, "CHANGE_MACHACC",
398 winbindd_change_machine_acct_send
, winbindd_change_machine_acct_recv
},
399 { WINBINDD_PAM_AUTH_CRAP
, "PAM_AUTH_CRAP",
400 winbindd_pam_auth_crap_send
, winbindd_pam_auth_crap_recv
},
402 { 0, NULL
, NULL
, NULL
}
405 struct process_request_state
{
406 struct winbindd_cli_state
*cli_state
;
407 struct tevent_context
*ev
;
410 static void process_request_done(struct tevent_req
*subreq
);
411 static void process_request_written(struct tevent_req
*subreq
);
413 static struct tevent_req
*process_request_send(
415 struct tevent_context
*ev
,
416 struct winbindd_cli_state
*cli_state
)
418 struct tevent_req
*req
, *subreq
;
419 struct process_request_state
*state
;
420 struct winbindd_async_dispatch_table
*atable
;
421 enum winbindd_cmd cmd
= cli_state
->request
->cmd
;
424 static uint64_t request_index
= 1;
427 * debug traceid values:
429 * 1 .. not processing a winbind request, but in other code (timers)
430 * >=2 .. winbind request processing
432 if (debug_traceid_get() != 0) {
433 request_index
= ++request_index
== 0 ? 2 : request_index
;
434 debug_traceid_set(request_index
);
436 req
= tevent_req_create(mem_ctx
, &state
,
437 struct process_request_state
);
441 state
->cli_state
= cli_state
;
444 ok
= tevent_req_set_profile(req
);
446 return tevent_req_post(req
, ev
);
449 SMB_ASSERT(cli_state
->mem_ctx
== NULL
);
450 cli_state
->mem_ctx
= talloc_named(cli_state
, 0, "winbind request");
451 if (tevent_req_nomem(cli_state
->mem_ctx
, req
)) {
452 return tevent_req_post(req
, ev
);
455 cli_state
->response
= talloc_zero(
457 struct winbindd_response
);
458 if (tevent_req_nomem(cli_state
->response
, req
)) {
459 return tevent_req_post(req
, ev
);
461 cli_state
->response
->result
= WINBINDD_PENDING
;
462 cli_state
->response
->length
= sizeof(struct winbindd_response
);
464 /* Remember who asked us. */
465 cli_state
->pid
= cli_state
->request
->pid
;
466 memcpy(cli_state
->client_name
,
467 cli_state
->request
->client_name
,
468 sizeof(cli_state
->client_name
));
470 cli_state
->cmd_name
= "unknown request";
471 cli_state
->recv_fn
= NULL
;
473 /* client is newest */
474 winbindd_promote_client(cli_state
);
476 for (atable
= async_nonpriv_table
; atable
->send_req
; atable
+= 1) {
477 if (cmd
== atable
->cmd
) {
482 if ((atable
->send_req
== NULL
) && cli_state
->privileged
) {
483 for (atable
= async_priv_table
; atable
->send_req
;
485 if (cmd
== atable
->cmd
) {
491 if (atable
->send_req
!= NULL
) {
492 cli_state
->cmd_name
= atable
->cmd_name
;
493 cli_state
->recv_fn
= atable
->recv_req
;
495 DBG_NOTICE("[%s (%d)] Handling async request: %s\n",
496 cli_state
->client_name
,
498 cli_state
->cmd_name
);
500 subreq
= atable
->send_req(
505 if (tevent_req_nomem(subreq
, req
)) {
506 return tevent_req_post(req
, ev
);
508 tevent_req_set_callback(subreq
, process_request_done
, req
);
512 for (i
=0; i
<ARRAY_SIZE(bool_dispatch_table
); i
++) {
513 if (cmd
== bool_dispatch_table
[i
].cmd
) {
520 if (i
< ARRAY_SIZE(bool_dispatch_table
)) {
521 cli_state
->cmd_name
= bool_dispatch_table
[i
].cmd_name
;
523 DBG_DEBUG("process_request: request fn %s\n",
524 bool_dispatch_table
[i
].cmd_name
);
525 ok
= bool_dispatch_table
[i
].fn(cli_state
);
528 cli_state
->response
->result
= ok
? WINBINDD_OK
: WINBINDD_ERROR
;
530 TALLOC_FREE(cli_state
->io_req
);
531 TALLOC_FREE(cli_state
->request
);
533 subreq
= wb_resp_write_send(
536 cli_state
->out_queue
,
538 cli_state
->response
);
539 if (tevent_req_nomem(subreq
, req
)) {
540 return tevent_req_post(req
, ev
);
542 tevent_req_set_callback(subreq
, process_request_written
, req
);
544 cli_state
->io_req
= subreq
;
549 static void process_request_done(struct tevent_req
*subreq
)
551 struct tevent_req
*req
= tevent_req_callback_data(
552 subreq
, struct tevent_req
);
553 struct process_request_state
*state
= tevent_req_data(
554 req
, struct process_request_state
);
555 struct winbindd_cli_state
*cli_state
= state
->cli_state
;
559 status
= cli_state
->recv_fn(subreq
, cli_state
->response
);
562 DBG_NOTICE("[%s(%d):%s]: %s\n",
563 cli_state
->client_name
,
568 ok
= NT_STATUS_IS_OK(status
);
569 cli_state
->response
->result
= ok
? WINBINDD_OK
: WINBINDD_ERROR
;
571 TALLOC_FREE(cli_state
->io_req
);
572 TALLOC_FREE(cli_state
->request
);
574 subreq
= wb_resp_write_send(
577 cli_state
->out_queue
,
579 cli_state
->response
);
580 if (tevent_req_nomem(subreq
, req
)) {
583 tevent_req_set_callback(subreq
, process_request_written
, req
);
585 cli_state
->io_req
= subreq
;
588 static void process_request_written(struct tevent_req
*subreq
)
590 struct tevent_req
*req
= tevent_req_callback_data(
591 subreq
, struct tevent_req
);
592 struct process_request_state
*state
= tevent_req_data(
593 req
, struct process_request_state
);
594 struct winbindd_cli_state
*cli_state
= state
->cli_state
;
598 cli_state
->io_req
= NULL
;
600 ret
= wb_resp_write_recv(subreq
, &err
);
603 tevent_req_nterror(req
, map_nt_error_from_unix(err
));
607 DBG_DEBUG("[%s(%d):%s]: delivered response to client\n",
608 cli_state
->client_name
,
610 cli_state
->cmd_name
);
612 TALLOC_FREE(cli_state
->mem_ctx
);
613 cli_state
->response
= NULL
;
614 cli_state
->cmd_name
= "no request";
615 cli_state
->recv_fn
= NULL
;
617 tevent_req_done(req
);
620 static NTSTATUS
process_request_recv(
621 struct tevent_req
*req
,
623 struct tevent_req_profile
**profile
)
627 if (tevent_req_is_nterror(req
, &status
)) {
628 tevent_req_received(req
);
632 *profile
= tevent_req_move_profile(req
, mem_ctx
);
633 tevent_req_received(req
);
638 * This is the main event loop of winbind requests. It goes through a
639 * state-machine of 3 read/write requests, 4 if you have extra data to send.
641 * An idle winbind client has a read request of 4 bytes outstanding,
642 * finalizing function is request_len_recv, checking the length. request_recv
643 * then processes the packet. The processing function then at some point has
644 * to call request_finished which schedules sending the response.
647 static void winbind_client_request_read(struct tevent_req
*req
);
648 static void winbind_client_activity(struct tevent_req
*req
);
649 static void winbind_client_processed(struct tevent_req
*req
);
651 /* Process a new connection by adding it to the client connection list */
653 static void new_connection(int listen_sock
, bool privileged
)
655 struct samba_sockaddr saddr
= { .sa_socklen
= 0, };
656 struct winbindd_cli_state
*state
;
657 struct tevent_req
*req
;
660 /* Accept connection */
662 saddr
.sa_socklen
= sizeof(saddr
.u
.un
);
663 sock
= accept(listen_sock
, &saddr
.u
.sa
, &saddr
.sa_socklen
);
665 if (errno
!= EINTR
) {
666 D_ERR("Failed to accept socket: %s\n", strerror(errno
));
670 smb_set_close_on_exec(sock
);
672 D_INFO("Accepted client socket %d\n", sock
);
674 /* Create new connection structure */
676 if ((state
= talloc_zero(NULL
, struct winbindd_cli_state
)) == NULL
) {
683 state
->out_queue
= tevent_queue_create(state
, "winbind client reply");
684 if (state
->out_queue
== NULL
) {
690 state
->privileged
= privileged
;
692 req
= wb_req_read_send(state
, global_event_context(), state
->sock
,
693 WINBINDD_MAX_EXTRA_DATA
);
699 tevent_req_set_callback(req
, winbind_client_request_read
, state
);
702 /* Add to connection list */
704 winbindd_add_client(state
);
707 static void winbind_client_request_read(struct tevent_req
*req
)
709 struct winbindd_cli_state
*state
= tevent_req_callback_data(
710 req
, struct winbindd_cli_state
);
714 state
->io_req
= NULL
;
716 ret
= wb_req_read_recv(req
, state
, &state
->request
, &err
);
720 DEBUG(6, ("closing socket %d, client exited\n",
723 DEBUG(2, ("Could not read client request from fd %d: "
724 "%s\n", state
->sock
, strerror(err
)));
728 remove_client(state
);
732 req
= wait_for_read_send(state
, global_event_context(), state
->sock
,
735 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
736 " wait_for_read_send failed - removing client\n",
737 (int)state
->pid
, state
->cmd_name
));
738 remove_client(state
);
741 tevent_req_set_callback(req
, winbind_client_activity
, state
);
744 req
= process_request_send(state
, global_event_context(), state
);
746 DBG_ERR("process_request_send failed\n");
747 remove_client(state
);
750 tevent_req_set_callback(req
, winbind_client_processed
, state
);
753 static void winbind_client_activity(struct tevent_req
*req
)
755 struct winbindd_cli_state
*state
=
756 tevent_req_callback_data(req
, struct winbindd_cli_state
);
760 has_data
= wait_for_read_recv(req
, &err
);
763 DEBUG(0, ("winbind_client_activity[%d:%s]:"
764 "unexpected data from client - removing client\n",
765 (int)state
->pid
, state
->cmd_name
));
768 DEBUG(6, ("winbind_client_activity[%d:%s]: "
769 "client has closed connection - removing "
771 (int)state
->pid
, state
->cmd_name
));
773 DEBUG(2, ("winbind_client_activity[%d:%s]: "
774 "client socket error (%s) - removing "
776 (int)state
->pid
, state
->cmd_name
,
781 remove_client(state
);
784 static void winbind_client_processed(struct tevent_req
*req
)
786 struct winbindd_cli_state
*cli_state
= tevent_req_callback_data(
787 req
, struct winbindd_cli_state
);
788 struct tevent_req_profile
*profile
= NULL
;
789 struct timeval start
, stop
, diff
;
793 status
= process_request_recv(req
, cli_state
, &profile
);
795 if (!NT_STATUS_IS_OK(status
)) {
796 DBG_DEBUG("process_request failed: %s\n", nt_errstr(status
));
797 remove_client(cli_state
);
801 tevent_req_profile_get_start(profile
, NULL
, &start
);
802 tevent_req_profile_get_stop(profile
, NULL
, &stop
);
803 diff
= tevent_timeval_until(&start
, &stop
);
805 threshold
= lp_parm_int(-1, "winbind", "request profile threshold", 60);
807 if (diff
.tv_sec
>= threshold
) {
814 "request profile depth",
817 DBG_ERR("request took %u.%.6u seconds\n",
818 (unsigned)diff
.tv_sec
, (unsigned)diff
.tv_usec
);
820 str
= tevent_req_profile_string(
821 talloc_tos(), profile
, 0, depth
);
823 /* No "\n", already contained in "str" */
824 DEBUGADD(0, ("%s", str
));
829 TALLOC_FREE(profile
);
831 req
= wb_req_read_send(
833 global_event_context(),
835 WINBINDD_MAX_EXTRA_DATA
);
837 remove_client(cli_state
);
840 tevent_req_set_callback(req
, winbind_client_request_read
, cli_state
);
841 cli_state
->io_req
= req
;
844 /* Remove a client connection from client connection list */
846 static void remove_client(struct winbindd_cli_state
*state
)
848 /* It's a dead client - hold a funeral */
855 * We need to remove a pending wb_req_read_*
856 * or wb_resp_write_* request before closing the
859 * This is important as they might have used tevent_add_fd() and we
860 * use the epoll * backend on linux. So we must remove the tevent_fd
861 * before closing the fd.
863 * Otherwise we might hit a race with close_conns_after_fork() (via
864 * winbindd_reinit_after_fork()) where a file descriptor
865 * is still open in a child, which means it's still active in
866 * the parents epoll queue, but the related tevent_fd is already
867 * already gone in the parent.
871 TALLOC_FREE(state
->io_req
);
873 if (state
->sock
!= -1) {
877 /* tell client, we are closing ... */
878 nwritten
= write(state
->sock
, &c
, sizeof(c
));
879 if (nwritten
== -1) {
880 DEBUG(2, ("final write to client failed: %s\n",
890 TALLOC_FREE(state
->mem_ctx
);
892 /* Remove from list and free */
894 winbindd_remove_client(state
);
898 /* Is a client idle? */
900 static bool client_is_idle(struct winbindd_cli_state
*state
) {
901 return (state
->request
== NULL
&&
902 state
->response
== NULL
&&
903 !state
->pwent_state
&& !state
->grent_state
);
906 /* Shutdown client connection which has been idle for the longest time */
908 static bool remove_idle_client(void)
910 struct winbindd_cli_state
*state
, *remove_state
= NULL
;
913 for (state
= winbindd_client_list(); state
; state
= state
->next
) {
914 if (client_is_idle(state
)) {
916 /* list is sorted by access time */
917 remove_state
= state
;
922 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
923 nidle
, remove_state
->sock
, (unsigned int)remove_state
->pid
));
924 remove_client(remove_state
);
932 * Terminate all clients whose requests have taken longer than
933 * "winbind request timeout" seconds to process, or have been
934 * idle for more than "winbind request timeout" seconds.
937 static void remove_timed_out_clients(void)
939 struct winbindd_cli_state
*state
, *prev
= NULL
;
940 time_t curr_time
= time(NULL
);
941 int timeout_val
= lp_winbind_request_timeout();
943 for (state
= winbindd_client_list_tail(); state
; state
= prev
) {
946 prev
= winbindd_client_list_prev(state
);
947 expiry_time
= state
->last_access
+ timeout_val
;
949 if (curr_time
<= expiry_time
) {
950 /* list is sorted, previous clients in
955 if (client_is_idle(state
)) {
956 DEBUG(5,("Idle client timed out, "
957 "shutting down sock %d, pid %u\n",
959 (unsigned int)state
->pid
));
961 DEBUG(5,("Client request timed out, "
962 "shutting down sock %d, pid %u\n",
964 (unsigned int)state
->pid
));
967 remove_client(state
);
971 static void winbindd_scrub_clients_handler(struct tevent_context
*ev
,
972 struct tevent_timer
*te
,
973 struct timeval current_time
,
976 remove_timed_out_clients();
977 if (tevent_add_timer(ev
, ev
,
978 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL
, 0),
979 winbindd_scrub_clients_handler
, NULL
) == NULL
) {
980 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
985 struct winbindd_listen_state
{
990 static void winbindd_listen_fde_handler(struct tevent_context
*ev
,
991 struct tevent_fd
*fde
,
995 struct winbindd_listen_state
*s
= talloc_get_type_abort(private_data
,
996 struct winbindd_listen_state
);
998 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
999 DEBUG(5,("winbindd: Exceeding %d client "
1000 "connections, removing idle "
1001 "connection.\n", lp_winbind_max_clients()));
1002 if (!remove_idle_client()) {
1003 DEBUG(0,("winbindd: Exceeding %d "
1004 "client connections, no idle "
1005 "connection found\n",
1006 lp_winbind_max_clients()));
1010 remove_timed_out_clients();
1011 new_connection(s
->fd
, s
->privileged
);
1015 * Winbindd socket accessor functions
1018 static bool winbindd_setup_listeners(void)
1020 struct winbindd_listen_state
*pub_state
= NULL
;
1021 struct winbindd_listen_state
*priv_state
= NULL
;
1022 struct tevent_fd
*fde
;
1026 pub_state
= talloc(global_event_context(),
1027 struct winbindd_listen_state
);
1032 pub_state
->privileged
= false;
1033 pub_state
->fd
= create_pipe_sock(
1034 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME
, 0755);
1035 if (pub_state
->fd
== -1) {
1038 rc
= listen(pub_state
->fd
, 5);
1043 fde
= tevent_add_fd(global_event_context(), pub_state
, pub_state
->fd
,
1044 TEVENT_FD_READ
, winbindd_listen_fde_handler
,
1047 close(pub_state
->fd
);
1050 tevent_fd_set_auto_close(fde
);
1052 priv_state
= talloc(global_event_context(),
1053 struct winbindd_listen_state
);
1058 socket_path
= get_winbind_priv_pipe_dir();
1059 if (socket_path
== NULL
) {
1063 priv_state
->privileged
= true;
1064 priv_state
->fd
= create_pipe_sock(
1065 socket_path
, WINBINDD_SOCKET_NAME
, 0750);
1066 TALLOC_FREE(socket_path
);
1067 if (priv_state
->fd
== -1) {
1070 rc
= listen(priv_state
->fd
, 5);
1075 fde
= tevent_add_fd(global_event_context(), priv_state
,
1076 priv_state
->fd
, TEVENT_FD_READ
,
1077 winbindd_listen_fde_handler
, priv_state
);
1079 close(priv_state
->fd
);
1082 tevent_fd_set_auto_close(fde
);
1084 winbindd_scrub_clients_handler(global_event_context(), NULL
,
1085 timeval_current(), NULL
);
1088 TALLOC_FREE(pub_state
);
1089 TALLOC_FREE(priv_state
);
1093 static void winbindd_register_handlers(struct messaging_context
*msg_ctx
,
1096 bool scan_trusts
= true;
1098 struct tevent_timer
*te
= NULL
;
1100 /* Setup signal handlers */
1102 if (!winbindd_setup_sig_term_handler(true))
1104 if (!winbindd_setup_stdin_handler(true, foreground
))
1106 if (!winbindd_setup_sig_hup_handler(NULL
))
1108 if (!winbindd_setup_sig_chld_handler())
1110 if (!winbindd_setup_sig_usr2_handler())
1113 CatchSignal(SIGPIPE
, SIG_IGN
); /* Ignore sigpipe */
1116 * Ensure all cache and idmap caches are consistent
1117 * and initialized before we startup.
1119 if (!winbindd_cache_validate_and_initialize()) {
1123 /* React on 'smbcontrol winbindd reload-config' in the same way
1124 as to SIGHUP signal */
1125 messaging_register(msg_ctx
, NULL
,
1126 MSG_SMB_CONF_UPDATED
,
1127 winbindd_msg_reload_services_parent
);
1128 messaging_register(msg_ctx
, NULL
,
1129 MSG_SHUTDOWN
, msg_shutdown
);
1131 /* Handle online/offline messages. */
1132 messaging_register(msg_ctx
, NULL
,
1133 MSG_WINBIND_OFFLINE
, winbind_msg_offline
);
1134 messaging_register(msg_ctx
, NULL
,
1135 MSG_WINBIND_ONLINE
, winbind_msg_online
);
1136 messaging_register(msg_ctx
, NULL
,
1137 MSG_WINBIND_ONLINESTATUS
, winbind_msg_onlinestatus
);
1139 /* Handle domain online/offline messages for domains */
1140 messaging_register(global_messaging_context(), NULL
,
1141 MSG_WINBIND_DOMAIN_OFFLINE
, winbind_msg_domain_offline
);
1142 messaging_register(global_messaging_context(), NULL
,
1143 MSG_WINBIND_DOMAIN_ONLINE
, winbind_msg_domain_online
);
1145 messaging_register(msg_ctx
, NULL
,
1146 MSG_WINBIND_VALIDATE_CACHE
,
1147 winbind_msg_validate_cache
);
1149 messaging_register(msg_ctx
, NULL
,
1150 MSG_WINBIND_DUMP_DOMAIN_LIST
,
1151 winbind_msg_dump_domain_list
);
1153 messaging_register(msg_ctx
, NULL
,
1154 MSG_WINBIND_IP_DROPPED
,
1155 winbind_msg_ip_dropped_parent
);
1157 /* Register handler for MSG_DEBUG. */
1158 messaging_register(msg_ctx
, NULL
,
1162 messaging_register(msg_ctx
, NULL
,
1163 MSG_WINBIND_DISCONNECT_DC
,
1164 winbind_disconnect_dc_parent
);
1166 netsamlogon_cache_init(); /* Non-critical */
1168 /* clear the cached list of trusted domains */
1172 if (!init_domain_list()) {
1173 DEBUG(0,("unable to initialize domain list\n"));
1177 status
= init_idmap_child(global_event_context());
1178 if (NT_STATUS_IS_ERR(status
)) {
1179 DBG_ERR("Unable to start idmap child: %s\n", nt_errstr(status
));
1183 status
= init_locator_child(global_event_context());
1184 if (NT_STATUS_IS_ERR(status
)) {
1185 DBG_ERR("Unable to start locator child: %s\n", nt_errstr(status
));
1189 smb_nscd_flush_user_cache();
1190 smb_nscd_flush_group_cache();
1192 if (!lp_winbind_scan_trusted_domains()) {
1193 scan_trusts
= false;
1196 if (!lp_allow_trusted_domains()) {
1197 scan_trusts
= false;
1201 scan_trusts
= false;
1205 if (tevent_add_timer(global_event_context(), NULL
, timeval_zero(),
1206 rescan_trusted_domains
, NULL
) == NULL
) {
1207 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1212 te
= tevent_add_timer(global_event_context(),
1215 winbindd_ping_offline_domains
,
1218 DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
1222 status
= wb_irpc_register();
1224 if (!NT_STATUS_IS_OK(status
)) {
1225 DEBUG(0, ("Could not register IRPC handlers\n"));
1230 struct winbindd_addrchanged_state
{
1231 struct addrchange_context
*ctx
;
1232 struct tevent_context
*ev
;
1233 struct messaging_context
*msg_ctx
;
1236 static void winbindd_addr_changed(struct tevent_req
*req
);
1238 static void winbindd_init_addrchange(TALLOC_CTX
*mem_ctx
,
1239 struct tevent_context
*ev
,
1240 struct messaging_context
*msg_ctx
)
1242 struct winbindd_addrchanged_state
*state
;
1243 struct tevent_req
*req
;
1246 state
= talloc(mem_ctx
, struct winbindd_addrchanged_state
);
1247 if (state
== NULL
) {
1248 DEBUG(10, ("talloc failed\n"));
1252 state
->msg_ctx
= msg_ctx
;
1254 status
= addrchange_context_create(state
, &state
->ctx
);
1255 if (!NT_STATUS_IS_OK(status
)) {
1256 DEBUG(10, ("addrchange_context_create failed: %s\n",
1257 nt_errstr(status
)));
1261 req
= addrchange_send(state
, ev
, state
->ctx
);
1263 DEBUG(0, ("addrchange_send failed\n"));
1267 tevent_req_set_callback(req
, winbindd_addr_changed
, state
);
1270 static void winbindd_addr_changed(struct tevent_req
*req
)
1272 struct winbindd_addrchanged_state
*state
= tevent_req_callback_data(
1273 req
, struct winbindd_addrchanged_state
);
1274 enum addrchange_type type
;
1275 struct sockaddr_storage addr
;
1278 status
= addrchange_recv(req
, &type
, &addr
, NULL
);
1280 if (!NT_STATUS_IS_OK(status
)) {
1281 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1282 nt_errstr(status
)));
1286 if (type
== ADDRCHANGE_DEL
) {
1287 char addrstr
[INET6_ADDRSTRLEN
];
1290 print_sockaddr(addrstr
, sizeof(addrstr
), &addr
);
1292 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1295 blob
= data_blob_const(addrstr
, strlen(addrstr
)+1);
1297 status
= messaging_send(state
->msg_ctx
,
1298 messaging_server_id(state
->msg_ctx
),
1299 MSG_WINBIND_IP_DROPPED
, &blob
);
1300 if (!NT_STATUS_IS_OK(status
)) {
1301 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1302 nt_errstr(status
)));
1305 req
= addrchange_send(state
, state
->ev
, state
->ctx
);
1307 DEBUG(0, ("addrchange_send failed\n"));
1311 tevent_req_set_callback(req
, winbindd_addr_changed
, state
);
1316 int main(int argc
, const char **argv
)
1318 static bool log_stdout
= False
;
1319 struct samba_cmdline_daemon_cfg
*cmdline_daemon_cfg
= NULL
;
1320 struct poptOption long_options
[] = {
1323 .longName
= "no-caching",
1325 .argInfo
= POPT_ARG_NONE
,
1328 .descrip
= "Disable caching",
1335 const struct loadparm_substitution
*lp_sub
=
1336 loadparm_s3_global_substitution();
1342 const struct dcesrv_endpoint_server
*ep_server
= NULL
;
1343 struct dcesrv_context
*dce_ctx
= NULL
;
1344 size_t winbindd_socket_dir_len
= 0;
1345 char *winbindd_priv_socket_dir
= NULL
;
1346 size_t winbindd_priv_socket_dir_len
= 0;
1348 setproctitle_init(argc
, discard_const(argv
), environ
);
1351 * Do this before any other talloc operation
1353 talloc_enable_null_tracking();
1354 frame
= talloc_stackframe();
1357 * We want total control over the permissions on created files,
1358 * so set our umask to 0.
1364 /* glibc (?) likes to print "User defined signal 1" and exit if a
1365 SIGUSR[12] is received before a handler is installed */
1367 CatchSignal(SIGUSR1
, SIG_IGN
);
1368 CatchSignal(SIGUSR2
, SIG_IGN
);
1370 ok
= samba_cmdline_init(frame
,
1371 SAMBA_CMDLINE_CONFIG_SERVER
,
1372 true /* require_smbconf */);
1374 DBG_ERR("Failed to setup cmdline parser\n");
1379 cmdline_daemon_cfg
= samba_cmdline_get_daemon_cfg();
1381 pc
= samba_popt_get_context(getprogname(), argc
, argv
, long_options
, 0);
1383 DBG_ERR("Failed to setup popt parser!\n");
1388 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1391 winbindd_set_use_cache(false);
1394 d_fprintf(stderr
, "\nInvalid option %s: %s\n\n",
1395 poptBadOption(pc
, 0), poptStrerror(opt
));
1396 poptPrintUsage(pc
, stderr
, 0);
1401 /* Set environment variable so we don't recursively call ourselves.
1402 This may also be useful interactively. */
1403 if ( !winbind_off() ) {
1404 DEBUG(0,("Failed to disable recursive winbindd calls. Exiting.\n"));
1408 /* Initialise for running in non-root mode */
1411 set_remote_machine_name("winbindd", False
);
1413 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub
));
1414 if (cmdline_daemon_cfg
->daemon
&& cmdline_daemon_cfg
->interactive
) {
1415 d_fprintf(stderr
,"\nERROR: "
1416 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1417 poptPrintUsage(pc
, stderr
, 0);
1421 log_stdout
= (debug_get_log_type() == DEBUG_STDOUT
);
1422 if (cmdline_daemon_cfg
->interactive
) {
1424 * libcmdline POPT_DAEMON callback sets "fork" to false if "-i"
1425 * for interactive is passed on the commandline. Set it back to
1426 * true. TODO: check if this is correct, smbd and nmbd don't do
1429 cmdline_daemon_cfg
->fork
= true;
1433 if (log_stdout
&& cmdline_daemon_cfg
->fork
) {
1434 d_fprintf(stderr
, "\nERROR: "
1435 "Can't log to stdout (-S) unless daemon is in "
1436 "foreground (-F) or interactive (-i)\n\n");
1437 poptPrintUsage(pc
, stderr
, 0);
1441 poptFreeContext(pc
);
1445 DBG_STARTUP_NOTICE("winbindd version %s started.\n%s\n",
1446 samba_version_string(),
1447 samba_copyright_string());
1449 /* After parsing the configuration file we setup the core path one more time
1450 * as the log file might have been set in the configuration and cores's
1451 * path is by default basename(lp_logfile()).
1453 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub
));
1455 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
) {
1456 if (!lp_parm_bool(-1, "server role check", "inhibit", false)) {
1457 DBG_ERR("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n");
1458 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"));
1461 /* Main 'samba' daemon will notify */
1462 daemon_sd_notifications(false);
1465 if (lp_security() == SEC_ADS
) {
1466 const char *realm
= lp_realm();
1467 const char *workgroup
= lp_workgroup();
1469 if (workgroup
== NULL
|| strlen(workgroup
) == 0) {
1470 DBG_ERR("For 'secuirity = ADS' mode, the 'workgroup' "
1471 "parameter is required to be set!\n");
1475 if (realm
== NULL
|| strlen(realm
) == 0) {
1476 DBG_ERR("For 'secuirity = ADS' mode, the 'realm' "
1477 "parameter is required to be set!\n");
1482 winbindd_socket_dir_len
= strlen(lp_winbindd_socket_directory());
1483 if (winbindd_socket_dir_len
> 0) {
1484 size_t winbindd_socket_len
=
1485 winbindd_socket_dir_len
+ 1 +
1486 strlen(WINBINDD_SOCKET_NAME
);
1487 struct sockaddr_un un
= {
1488 .sun_family
= AF_UNIX
,
1490 size_t sun_path_len
= sizeof(un
.sun_path
);
1492 if (winbindd_socket_len
>= sun_path_len
) {
1493 DBG_ERR("The winbind socket path [%s/%s] is too long "
1495 lp_winbindd_socket_directory(),
1496 WINBINDD_SOCKET_NAME
,
1497 winbindd_socket_len
,
1502 DBG_ERR("'winbindd_socket_directory' parameter is empty\n");
1506 winbindd_priv_socket_dir
= get_winbind_priv_pipe_dir();
1507 winbindd_priv_socket_dir_len
= strlen(winbindd_priv_socket_dir
);
1508 if (winbindd_priv_socket_dir_len
> 0) {
1509 size_t winbindd_priv_socket_len
=
1510 winbindd_priv_socket_dir_len
+ 1 +
1511 strlen(WINBINDD_SOCKET_NAME
);
1512 struct sockaddr_un un
= {
1513 .sun_family
= AF_UNIX
,
1515 size_t sun_path_len
= sizeof(un
.sun_path
);
1517 if (winbindd_priv_socket_len
>= sun_path_len
) {
1518 DBG_ERR("The winbind privileged socket path [%s/%s] is too long "
1520 winbindd_priv_socket_dir
,
1521 WINBINDD_SOCKET_NAME
,
1522 winbindd_priv_socket_len
,
1527 DBG_ERR("'winbindd_priv_socket_directory' parameter is empty\n");
1530 TALLOC_FREE(winbindd_priv_socket_dir
);
1532 if (!cluster_probe_ok()) {
1536 /* Initialise messaging system */
1538 if (global_messaging_context() == NULL
) {
1542 if (!winbindd_reload_services_file(NULL
)) {
1543 DEBUG(0, ("error opening config file\n"));
1549 const char *idmap_backend
;
1550 const char *invalid_backends
[] = {
1551 "ad", "rfc2307", "rid",
1554 idmap_backend
= lp_idmap_default_backend();
1555 for (i
= 0; i
< ARRAY_SIZE(invalid_backends
); i
++) {
1556 ok
= strequal(idmap_backend
, invalid_backends
[i
]);
1558 DBG_ERR("FATAL: Invalid idmap backend %s "
1559 "configured as the default backend!\n",
1566 ok
= directory_create_or_exist(lp_lock_directory(), 0755);
1568 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1569 lp_lock_directory(), strerror(errno
)));
1573 ok
= directory_create_or_exist(lp_pid_directory(), 0755);
1575 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1576 lp_pid_directory(), strerror(errno
)));
1582 if (!secrets_init()) {
1584 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1588 status
= rpccli_pre_open_netlogon_creds();
1589 if (!NT_STATUS_IS_OK(status
)) {
1590 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1591 nt_errstr(status
)));
1595 /* Unblock all signals we are interested in as they may have been
1596 blocked by the parent process. */
1598 BlockSignals(False
, SIGINT
);
1599 BlockSignals(False
, SIGQUIT
);
1600 BlockSignals(False
, SIGTERM
);
1601 BlockSignals(False
, SIGUSR1
);
1602 BlockSignals(False
, SIGUSR2
);
1603 BlockSignals(False
, SIGHUP
);
1604 BlockSignals(False
, SIGCHLD
);
1607 become_daemon(cmdline_daemon_cfg
->fork
,
1608 cmdline_daemon_cfg
->no_process_group
,
1611 daemon_status("winbindd", "Starting process ...");
1614 pidfile_create(lp_pid_directory(), "winbindd");
1618 * If we're interactive we want to set our own process group for
1619 * signal management.
1621 if (cmdline_daemon_cfg
->interactive
&&
1622 !cmdline_daemon_cfg
->no_process_group
)
1624 setpgid( (pid_t
)0, (pid_t
)0);
1630 /* Don't use winbindd_reinit_after_fork here as
1631 * we're just starting up and haven't created any
1632 * winbindd-specific resources we must free yet. JRA.
1635 status
= reinit_after_fork(global_messaging_context(),
1636 global_event_context(),
1638 if (!NT_STATUS_IS_OK(status
)) {
1639 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status
));
1642 if (lp_winbind_debug_traceid()) {
1643 winbind_debug_traceid_setup(global_event_context());
1644 winbind_debug_call_depth_setup(debug_call_depth_addr());
1645 tevent_thread_call_depth_set_callback(
1646 debuglevel_get() > 1 ? winbind_call_flow
: NULL
,
1649 ok
= initialize_password_db(true, global_event_context());
1651 exit_daemon("Failed to initialize passdb backend! "
1652 "Check the 'passdb backend' variable in your "
1653 "smb.conf file.", EINVAL
);
1657 * Do not initialize the parent-child-pipe before becoming
1658 * a daemon: this is used to detect a died parent in the child
1661 status
= init_before_fork();
1662 if (!NT_STATUS_IS_OK(status
)) {
1663 exit_daemon(nt_errstr(status
), map_errno_from_nt_status(status
));
1666 winbindd_register_handlers(global_messaging_context(),
1667 !cmdline_daemon_cfg
->fork
);
1669 if (!messaging_parent_dgm_cleanup_init(global_messaging_context())) {
1673 status
= init_system_session_info(NULL
);
1674 if (!NT_STATUS_IS_OK(status
)) {
1675 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status
));
1678 DBG_INFO("Registering DCE/RPC endpoint servers\n");
1680 ep_server
= winbind_get_ep_server();
1681 if (ep_server
== NULL
) {
1682 DBG_ERR("Failed to get 'winbind' endpoint server\n");
1685 status
= dcerpc_register_ep_server(ep_server
);
1686 if (!NT_STATUS_IS_OK(status
)) {
1687 DBG_ERR("Failed to register 'winbind' endpoint "
1688 "server: %s\n", nt_errstr(status
));
1692 dce_ctx
= global_dcesrv_context();
1694 DBG_INFO("Initializing DCE/RPC registered endpoint servers\n");
1696 /* Init all registered ep servers */
1697 status
= dcesrv_init_registered_ep_servers(dce_ctx
);
1698 if (!NT_STATUS_IS_OK(status
)) {
1699 DBG_ERR("Failed to init DCE/RPC endpoint servers: %s\n",
1704 winbindd_init_addrchange(NULL
, global_event_context(),
1705 global_messaging_context());
1707 /* setup listen sockets */
1709 if (!winbindd_setup_listeners()) {
1710 exit_daemon("Winbindd failed to setup listeners", EPIPE
);
1713 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1718 daemon_ready("winbindd");
1723 /* Loop waiting for requests */
1725 frame
= talloc_stackframe();
1727 if (tevent_loop_once(global_event_context()) == -1) {
1728 DEBUG(1, ("tevent_loop_once() failed: %s\n",