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_SHOW_SEQUENCE
, "SHOW_SEQUENCE",
342 winbindd_show_sequence_send
, winbindd_show_sequence_recv
},
343 { WINBINDD_GETGRGID
, "GETGRGID",
344 winbindd_getgrgid_send
, winbindd_getgrgid_recv
},
345 { WINBINDD_GETGRNAM
, "GETGRNAM",
346 winbindd_getgrnam_send
, winbindd_getgrnam_recv
},
347 { WINBINDD_GETUSERSIDS
, "GETUSERSIDS",
348 winbindd_getusersids_send
, winbindd_getusersids_recv
},
349 { WINBINDD_LOOKUPRIDS
, "LOOKUPRIDS",
350 winbindd_lookuprids_send
, winbindd_lookuprids_recv
},
351 { WINBINDD_SETPWENT
, "SETPWENT",
352 winbindd_setpwent_send
, winbindd_setpwent_recv
},
353 { WINBINDD_GETPWENT
, "GETPWENT",
354 winbindd_getpwent_send
, winbindd_getpwent_recv
},
355 { WINBINDD_ENDPWENT
, "ENDPWENT",
356 winbindd_endpwent_send
, winbindd_endpwent_recv
},
357 { WINBINDD_DSGETDCNAME
, "DSGETDCNAME",
358 winbindd_dsgetdcname_send
, winbindd_dsgetdcname_recv
},
359 { WINBINDD_GETDCNAME
, "GETDCNAME",
360 winbindd_getdcname_send
, winbindd_getdcname_recv
},
361 { WINBINDD_SETGRENT
, "SETGRENT",
362 winbindd_setgrent_send
, winbindd_setgrent_recv
},
363 { WINBINDD_GETGRENT
, "GETGRENT",
364 winbindd_getgrent_send
, winbindd_getgrent_recv
},
365 { WINBINDD_ENDGRENT
, "ENDGRENT",
366 winbindd_endgrent_send
, winbindd_endgrent_recv
},
367 { WINBINDD_LIST_USERS
, "LIST_USERS",
368 winbindd_list_users_send
, winbindd_list_users_recv
},
369 { WINBINDD_LIST_GROUPS
, "LIST_GROUPS",
370 winbindd_list_groups_send
, winbindd_list_groups_recv
},
371 { WINBINDD_CHECK_MACHACC
, "CHECK_MACHACC",
372 winbindd_check_machine_acct_send
, winbindd_check_machine_acct_recv
},
373 { WINBINDD_PING_DC
, "PING_DC",
374 winbindd_ping_dc_send
, winbindd_ping_dc_recv
},
375 { WINBINDD_PAM_AUTH
, "PAM_AUTH",
376 winbindd_pam_auth_send
, winbindd_pam_auth_recv
},
377 { WINBINDD_PAM_LOGOFF
, "PAM_LOGOFF",
378 winbindd_pam_logoff_send
, winbindd_pam_logoff_recv
},
379 { WINBINDD_PAM_CHAUTHTOK
, "PAM_CHAUTHTOK",
380 winbindd_pam_chauthtok_send
, winbindd_pam_chauthtok_recv
},
381 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP
, "PAM_CHNG_PSWD_AUTH_CRAP",
382 winbindd_pam_chng_pswd_auth_crap_send
,
383 winbindd_pam_chng_pswd_auth_crap_recv
},
384 { WINBINDD_WINS_BYIP
, "WINS_BYIP",
385 winbindd_wins_byip_send
, winbindd_wins_byip_recv
},
386 { WINBINDD_WINS_BYNAME
, "WINS_BYNAME",
387 winbindd_wins_byname_send
, winbindd_wins_byname_recv
},
388 { WINBINDD_DOMAIN_INFO
, "DOMAIN_INFO",
389 winbindd_domain_info_send
, winbindd_domain_info_recv
},
391 { 0, NULL
, NULL
, NULL
}
394 static struct winbindd_async_dispatch_table async_priv_table
[] = {
395 { WINBINDD_ALLOCATE_UID
, "ALLOCATE_UID",
396 winbindd_allocate_uid_send
, winbindd_allocate_uid_recv
},
397 { WINBINDD_ALLOCATE_GID
, "ALLOCATE_GID",
398 winbindd_allocate_gid_send
, winbindd_allocate_gid_recv
},
399 { WINBINDD_CHANGE_MACHACC
, "CHANGE_MACHACC",
400 winbindd_change_machine_acct_send
, winbindd_change_machine_acct_recv
},
401 { WINBINDD_PAM_AUTH_CRAP
, "PAM_AUTH_CRAP",
402 winbindd_pam_auth_crap_send
, winbindd_pam_auth_crap_recv
},
404 { 0, NULL
, NULL
, NULL
}
407 struct process_request_state
{
408 struct winbindd_cli_state
*cli_state
;
409 struct tevent_context
*ev
;
412 static void process_request_done(struct tevent_req
*subreq
);
413 static void process_request_written(struct tevent_req
*subreq
);
415 static struct tevent_req
*process_request_send(
417 struct tevent_context
*ev
,
418 struct winbindd_cli_state
*cli_state
)
420 struct tevent_req
*req
, *subreq
;
421 struct process_request_state
*state
;
422 struct winbindd_async_dispatch_table
*atable
;
423 enum winbindd_cmd cmd
= cli_state
->request
->cmd
;
426 static uint64_t request_index
= 1;
429 * debug traceid values:
431 * 1 .. not processing a winbind request, but in other code (timers)
432 * >=2 .. winbind request processing
434 if (debug_traceid_get() != 0) {
435 request_index
= ++request_index
== 0 ? 2 : request_index
;
436 debug_traceid_set(request_index
);
438 req
= tevent_req_create(mem_ctx
, &state
,
439 struct process_request_state
);
443 state
->cli_state
= cli_state
;
446 ok
= tevent_req_set_profile(req
);
448 return tevent_req_post(req
, ev
);
451 SMB_ASSERT(cli_state
->mem_ctx
== NULL
);
452 cli_state
->mem_ctx
= talloc_named(cli_state
, 0, "winbind request");
453 if (tevent_req_nomem(cli_state
->mem_ctx
, req
)) {
454 return tevent_req_post(req
, ev
);
457 cli_state
->response
= talloc_zero(
459 struct winbindd_response
);
460 if (tevent_req_nomem(cli_state
->response
, req
)) {
461 return tevent_req_post(req
, ev
);
463 cli_state
->response
->result
= WINBINDD_PENDING
;
464 cli_state
->response
->length
= sizeof(struct winbindd_response
);
466 /* Remember who asked us. */
467 cli_state
->pid
= cli_state
->request
->pid
;
468 memcpy(cli_state
->client_name
,
469 cli_state
->request
->client_name
,
470 sizeof(cli_state
->client_name
));
472 cli_state
->cmd_name
= "unknown request";
473 cli_state
->recv_fn
= NULL
;
475 /* client is newest */
476 winbindd_promote_client(cli_state
);
478 for (atable
= async_nonpriv_table
; atable
->send_req
; atable
+= 1) {
479 if (cmd
== atable
->cmd
) {
484 if ((atable
->send_req
== NULL
) && cli_state
->privileged
) {
485 for (atable
= async_priv_table
; atable
->send_req
;
487 if (cmd
== atable
->cmd
) {
493 if (atable
->send_req
!= NULL
) {
494 cli_state
->cmd_name
= atable
->cmd_name
;
495 cli_state
->recv_fn
= atable
->recv_req
;
497 DBG_NOTICE("[%s (%d)] Handling async request: %s\n",
498 cli_state
->client_name
,
500 cli_state
->cmd_name
);
502 subreq
= atable
->send_req(
507 if (tevent_req_nomem(subreq
, req
)) {
508 return tevent_req_post(req
, ev
);
510 tevent_req_set_callback(subreq
, process_request_done
, req
);
514 for (i
=0; i
<ARRAY_SIZE(bool_dispatch_table
); i
++) {
515 if (cmd
== bool_dispatch_table
[i
].cmd
) {
522 if (i
< ARRAY_SIZE(bool_dispatch_table
)) {
523 cli_state
->cmd_name
= bool_dispatch_table
[i
].cmd_name
;
525 DBG_DEBUG("process_request: request fn %s\n",
526 bool_dispatch_table
[i
].cmd_name
);
527 ok
= bool_dispatch_table
[i
].fn(cli_state
);
530 cli_state
->response
->result
= ok
? WINBINDD_OK
: WINBINDD_ERROR
;
532 TALLOC_FREE(cli_state
->io_req
);
533 TALLOC_FREE(cli_state
->request
);
535 subreq
= wb_resp_write_send(
538 cli_state
->out_queue
,
540 cli_state
->response
);
541 if (tevent_req_nomem(subreq
, req
)) {
542 return tevent_req_post(req
, ev
);
544 tevent_req_set_callback(subreq
, process_request_written
, req
);
546 cli_state
->io_req
= subreq
;
551 static void process_request_done(struct tevent_req
*subreq
)
553 struct tevent_req
*req
= tevent_req_callback_data(
554 subreq
, struct tevent_req
);
555 struct process_request_state
*state
= tevent_req_data(
556 req
, struct process_request_state
);
557 struct winbindd_cli_state
*cli_state
= state
->cli_state
;
561 status
= cli_state
->recv_fn(subreq
, cli_state
->response
);
564 DBG_NOTICE("[%s(%d):%s]: %s\n",
565 cli_state
->client_name
,
570 ok
= NT_STATUS_IS_OK(status
);
571 cli_state
->response
->result
= ok
? WINBINDD_OK
: WINBINDD_ERROR
;
573 TALLOC_FREE(cli_state
->io_req
);
574 TALLOC_FREE(cli_state
->request
);
576 subreq
= wb_resp_write_send(
579 cli_state
->out_queue
,
581 cli_state
->response
);
582 if (tevent_req_nomem(subreq
, req
)) {
585 tevent_req_set_callback(subreq
, process_request_written
, req
);
587 cli_state
->io_req
= subreq
;
590 static void process_request_written(struct tevent_req
*subreq
)
592 struct tevent_req
*req
= tevent_req_callback_data(
593 subreq
, struct tevent_req
);
594 struct process_request_state
*state
= tevent_req_data(
595 req
, struct process_request_state
);
596 struct winbindd_cli_state
*cli_state
= state
->cli_state
;
600 cli_state
->io_req
= NULL
;
602 ret
= wb_resp_write_recv(subreq
, &err
);
605 tevent_req_nterror(req
, map_nt_error_from_unix(err
));
609 DBG_DEBUG("[%s(%d):%s]: delivered response to client\n",
610 cli_state
->client_name
,
612 cli_state
->cmd_name
);
614 TALLOC_FREE(cli_state
->mem_ctx
);
615 cli_state
->response
= NULL
;
616 cli_state
->cmd_name
= "no request";
617 cli_state
->recv_fn
= NULL
;
619 tevent_req_done(req
);
622 static NTSTATUS
process_request_recv(
623 struct tevent_req
*req
,
625 struct tevent_req_profile
**profile
)
629 if (tevent_req_is_nterror(req
, &status
)) {
630 tevent_req_received(req
);
634 *profile
= tevent_req_move_profile(req
, mem_ctx
);
635 tevent_req_received(req
);
640 * This is the main event loop of winbind requests. It goes through a
641 * state-machine of 3 read/write requests, 4 if you have extra data to send.
643 * An idle winbind client has a read request of 4 bytes outstanding,
644 * finalizing function is request_len_recv, checking the length. request_recv
645 * then processes the packet. The processing function then at some point has
646 * to call request_finished which schedules sending the response.
649 static void winbind_client_request_read(struct tevent_req
*req
);
650 static void winbind_client_activity(struct tevent_req
*req
);
651 static void winbind_client_processed(struct tevent_req
*req
);
653 /* Process a new connection by adding it to the client connection list */
655 static void new_connection(int listen_sock
, bool privileged
)
657 struct sockaddr_un sunaddr
;
658 struct winbindd_cli_state
*state
;
659 struct tevent_req
*req
;
663 /* Accept connection */
665 len
= sizeof(sunaddr
);
667 sock
= accept(listen_sock
, (struct sockaddr
*)(void *)&sunaddr
, &len
);
670 if (errno
!= EINTR
) {
671 D_ERR("Failed to accept socket: %s\n", strerror(errno
));
675 smb_set_close_on_exec(sock
);
677 D_INFO("Accepted client socket %d\n", sock
);
679 /* Create new connection structure */
681 if ((state
= talloc_zero(NULL
, struct winbindd_cli_state
)) == NULL
) {
688 state
->out_queue
= tevent_queue_create(state
, "winbind client reply");
689 if (state
->out_queue
== NULL
) {
695 state
->privileged
= privileged
;
697 req
= wb_req_read_send(state
, global_event_context(), state
->sock
,
698 WINBINDD_MAX_EXTRA_DATA
);
704 tevent_req_set_callback(req
, winbind_client_request_read
, state
);
707 /* Add to connection list */
709 winbindd_add_client(state
);
712 static void winbind_client_request_read(struct tevent_req
*req
)
714 struct winbindd_cli_state
*state
= tevent_req_callback_data(
715 req
, struct winbindd_cli_state
);
719 state
->io_req
= NULL
;
721 ret
= wb_req_read_recv(req
, state
, &state
->request
, &err
);
725 DEBUG(6, ("closing socket %d, client exited\n",
728 DEBUG(2, ("Could not read client request from fd %d: "
729 "%s\n", state
->sock
, strerror(err
)));
733 remove_client(state
);
737 req
= wait_for_read_send(state
, global_event_context(), state
->sock
,
740 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
741 " wait_for_read_send failed - removing client\n",
742 (int)state
->pid
, state
->cmd_name
));
743 remove_client(state
);
746 tevent_req_set_callback(req
, winbind_client_activity
, state
);
749 req
= process_request_send(state
, global_event_context(), state
);
751 DBG_ERR("process_request_send failed\n");
752 remove_client(state
);
755 tevent_req_set_callback(req
, winbind_client_processed
, state
);
758 static void winbind_client_activity(struct tevent_req
*req
)
760 struct winbindd_cli_state
*state
=
761 tevent_req_callback_data(req
, struct winbindd_cli_state
);
765 has_data
= wait_for_read_recv(req
, &err
);
768 DEBUG(0, ("winbind_client_activity[%d:%s]:"
769 "unexpected data from client - removing client\n",
770 (int)state
->pid
, state
->cmd_name
));
773 DEBUG(6, ("winbind_client_activity[%d:%s]: "
774 "client has closed connection - removing "
776 (int)state
->pid
, state
->cmd_name
));
778 DEBUG(2, ("winbind_client_activity[%d:%s]: "
779 "client socket error (%s) - removing "
781 (int)state
->pid
, state
->cmd_name
,
786 remove_client(state
);
789 static void winbind_client_processed(struct tevent_req
*req
)
791 struct winbindd_cli_state
*cli_state
= tevent_req_callback_data(
792 req
, struct winbindd_cli_state
);
793 struct tevent_req_profile
*profile
= NULL
;
794 struct timeval start
, stop
, diff
;
798 status
= process_request_recv(req
, cli_state
, &profile
);
800 if (!NT_STATUS_IS_OK(status
)) {
801 DBG_DEBUG("process_request failed: %s\n", nt_errstr(status
));
802 remove_client(cli_state
);
806 tevent_req_profile_get_start(profile
, NULL
, &start
);
807 tevent_req_profile_get_stop(profile
, NULL
, &stop
);
808 diff
= tevent_timeval_until(&start
, &stop
);
810 threshold
= lp_parm_int(-1, "winbind", "request profile threshold", 60);
812 if (diff
.tv_sec
>= threshold
) {
819 "request profile depth",
822 DBG_ERR("request took %u.%.6u seconds\n",
823 (unsigned)diff
.tv_sec
, (unsigned)diff
.tv_usec
);
825 str
= tevent_req_profile_string(
826 talloc_tos(), profile
, 0, depth
);
828 /* No "\n", already contained in "str" */
829 DEBUGADD(0, ("%s", str
));
834 TALLOC_FREE(profile
);
836 req
= wb_req_read_send(
838 global_event_context(),
840 WINBINDD_MAX_EXTRA_DATA
);
842 remove_client(cli_state
);
845 tevent_req_set_callback(req
, winbind_client_request_read
, cli_state
);
846 cli_state
->io_req
= req
;
849 /* Remove a client connection from client connection list */
851 static void remove_client(struct winbindd_cli_state
*state
)
853 /* It's a dead client - hold a funeral */
860 * We need to remove a pending wb_req_read_*
861 * or wb_resp_write_* request before closing the
864 * This is important as they might have used tevent_add_fd() and we
865 * use the epoll * backend on linux. So we must remove the tevent_fd
866 * before closing the fd.
868 * Otherwise we might hit a race with close_conns_after_fork() (via
869 * winbindd_reinit_after_fork()) where a file descriptor
870 * is still open in a child, which means it's still active in
871 * the parents epoll queue, but the related tevent_fd is already
872 * already gone in the parent.
876 TALLOC_FREE(state
->io_req
);
878 if (state
->sock
!= -1) {
882 /* tell client, we are closing ... */
883 nwritten
= write(state
->sock
, &c
, sizeof(c
));
884 if (nwritten
== -1) {
885 DEBUG(2, ("final write to client failed: %s\n",
895 TALLOC_FREE(state
->mem_ctx
);
897 /* Remove from list and free */
899 winbindd_remove_client(state
);
903 /* Is a client idle? */
905 static bool client_is_idle(struct winbindd_cli_state
*state
) {
906 return (state
->request
== NULL
&&
907 state
->response
== NULL
&&
908 !state
->pwent_state
&& !state
->grent_state
);
911 /* Shutdown client connection which has been idle for the longest time */
913 static bool remove_idle_client(void)
915 struct winbindd_cli_state
*state
, *remove_state
= NULL
;
918 for (state
= winbindd_client_list(); state
; state
= state
->next
) {
919 if (client_is_idle(state
)) {
921 /* list is sorted by access time */
922 remove_state
= state
;
927 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
928 nidle
, remove_state
->sock
, (unsigned int)remove_state
->pid
));
929 remove_client(remove_state
);
937 * Terminate all clients whose requests have taken longer than
938 * "winbind request timeout" seconds to process, or have been
939 * idle for more than "winbind request timeout" seconds.
942 static void remove_timed_out_clients(void)
944 struct winbindd_cli_state
*state
, *prev
= NULL
;
945 time_t curr_time
= time(NULL
);
946 int timeout_val
= lp_winbind_request_timeout();
948 for (state
= winbindd_client_list_tail(); state
; state
= prev
) {
951 prev
= winbindd_client_list_prev(state
);
952 expiry_time
= state
->last_access
+ timeout_val
;
954 if (curr_time
<= expiry_time
) {
955 /* list is sorted, previous clients in
960 if (client_is_idle(state
)) {
961 DEBUG(5,("Idle client timed out, "
962 "shutting down sock %d, pid %u\n",
964 (unsigned int)state
->pid
));
966 DEBUG(5,("Client request timed out, "
967 "shutting down sock %d, pid %u\n",
969 (unsigned int)state
->pid
));
972 remove_client(state
);
976 static void winbindd_scrub_clients_handler(struct tevent_context
*ev
,
977 struct tevent_timer
*te
,
978 struct timeval current_time
,
981 remove_timed_out_clients();
982 if (tevent_add_timer(ev
, ev
,
983 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL
, 0),
984 winbindd_scrub_clients_handler
, NULL
) == NULL
) {
985 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
990 struct winbindd_listen_state
{
995 static void winbindd_listen_fde_handler(struct tevent_context
*ev
,
996 struct tevent_fd
*fde
,
1000 struct winbindd_listen_state
*s
= talloc_get_type_abort(private_data
,
1001 struct winbindd_listen_state
);
1003 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1004 DEBUG(5,("winbindd: Exceeding %d client "
1005 "connections, removing idle "
1006 "connection.\n", lp_winbind_max_clients()));
1007 if (!remove_idle_client()) {
1008 DEBUG(0,("winbindd: Exceeding %d "
1009 "client connections, no idle "
1010 "connection found\n",
1011 lp_winbind_max_clients()));
1015 remove_timed_out_clients();
1016 new_connection(s
->fd
, s
->privileged
);
1020 * Winbindd socket accessor functions
1023 static bool winbindd_setup_listeners(void)
1025 struct winbindd_listen_state
*pub_state
= NULL
;
1026 struct winbindd_listen_state
*priv_state
= NULL
;
1027 struct tevent_fd
*fde
;
1031 pub_state
= talloc(global_event_context(),
1032 struct winbindd_listen_state
);
1037 pub_state
->privileged
= false;
1038 pub_state
->fd
= create_pipe_sock(
1039 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME
, 0755);
1040 if (pub_state
->fd
== -1) {
1043 rc
= listen(pub_state
->fd
, 5);
1048 fde
= tevent_add_fd(global_event_context(), pub_state
, pub_state
->fd
,
1049 TEVENT_FD_READ
, winbindd_listen_fde_handler
,
1052 close(pub_state
->fd
);
1055 tevent_fd_set_auto_close(fde
);
1057 priv_state
= talloc(global_event_context(),
1058 struct winbindd_listen_state
);
1063 socket_path
= get_winbind_priv_pipe_dir();
1064 if (socket_path
== NULL
) {
1068 priv_state
->privileged
= true;
1069 priv_state
->fd
= create_pipe_sock(
1070 socket_path
, WINBINDD_SOCKET_NAME
, 0750);
1071 TALLOC_FREE(socket_path
);
1072 if (priv_state
->fd
== -1) {
1075 rc
= listen(priv_state
->fd
, 5);
1080 fde
= tevent_add_fd(global_event_context(), priv_state
,
1081 priv_state
->fd
, TEVENT_FD_READ
,
1082 winbindd_listen_fde_handler
, priv_state
);
1084 close(priv_state
->fd
);
1087 tevent_fd_set_auto_close(fde
);
1089 winbindd_scrub_clients_handler(global_event_context(), NULL
,
1090 timeval_current(), NULL
);
1093 TALLOC_FREE(pub_state
);
1094 TALLOC_FREE(priv_state
);
1098 static void winbindd_register_handlers(struct messaging_context
*msg_ctx
,
1101 bool scan_trusts
= true;
1103 struct tevent_timer
*te
= NULL
;
1105 /* Setup signal handlers */
1107 if (!winbindd_setup_sig_term_handler(true))
1109 if (!winbindd_setup_stdin_handler(true, foreground
))
1111 if (!winbindd_setup_sig_hup_handler(NULL
))
1113 if (!winbindd_setup_sig_chld_handler())
1115 if (!winbindd_setup_sig_usr2_handler())
1118 CatchSignal(SIGPIPE
, SIG_IGN
); /* Ignore sigpipe */
1121 * Ensure all cache and idmap caches are consistent
1122 * and initialized before we startup.
1124 if (!winbindd_cache_validate_and_initialize()) {
1128 /* React on 'smbcontrol winbindd reload-config' in the same way
1129 as to SIGHUP signal */
1130 messaging_register(msg_ctx
, NULL
,
1131 MSG_SMB_CONF_UPDATED
,
1132 winbindd_msg_reload_services_parent
);
1133 messaging_register(msg_ctx
, NULL
,
1134 MSG_SHUTDOWN
, msg_shutdown
);
1136 /* Handle online/offline messages. */
1137 messaging_register(msg_ctx
, NULL
,
1138 MSG_WINBIND_OFFLINE
, winbind_msg_offline
);
1139 messaging_register(msg_ctx
, NULL
,
1140 MSG_WINBIND_ONLINE
, winbind_msg_online
);
1141 messaging_register(msg_ctx
, NULL
,
1142 MSG_WINBIND_ONLINESTATUS
, winbind_msg_onlinestatus
);
1144 /* Handle domain online/offline messages for domains */
1145 messaging_register(global_messaging_context(), NULL
,
1146 MSG_WINBIND_DOMAIN_OFFLINE
, winbind_msg_domain_offline
);
1147 messaging_register(global_messaging_context(), NULL
,
1148 MSG_WINBIND_DOMAIN_ONLINE
, winbind_msg_domain_online
);
1150 messaging_register(msg_ctx
, NULL
,
1151 MSG_WINBIND_VALIDATE_CACHE
,
1152 winbind_msg_validate_cache
);
1154 messaging_register(msg_ctx
, NULL
,
1155 MSG_WINBIND_DUMP_DOMAIN_LIST
,
1156 winbind_msg_dump_domain_list
);
1158 messaging_register(msg_ctx
, NULL
,
1159 MSG_WINBIND_IP_DROPPED
,
1160 winbind_msg_ip_dropped_parent
);
1162 /* Register handler for MSG_DEBUG. */
1163 messaging_register(msg_ctx
, NULL
,
1167 messaging_register(msg_ctx
, NULL
,
1168 MSG_WINBIND_DISCONNECT_DC
,
1169 winbind_disconnect_dc_parent
);
1171 netsamlogon_cache_init(); /* Non-critical */
1173 /* clear the cached list of trusted domains */
1177 if (!init_domain_list()) {
1178 DEBUG(0,("unable to initialize domain list\n"));
1183 init_locator_child();
1185 smb_nscd_flush_user_cache();
1186 smb_nscd_flush_group_cache();
1188 if (!lp_winbind_scan_trusted_domains()) {
1189 scan_trusts
= false;
1192 if (!lp_allow_trusted_domains()) {
1193 scan_trusts
= false;
1197 scan_trusts
= false;
1201 if (tevent_add_timer(global_event_context(), NULL
, timeval_zero(),
1202 rescan_trusted_domains
, NULL
) == NULL
) {
1203 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1208 te
= tevent_add_timer(global_event_context(),
1211 winbindd_ping_offline_domains
,
1214 DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
1218 status
= wb_irpc_register();
1220 if (!NT_STATUS_IS_OK(status
)) {
1221 DEBUG(0, ("Could not register IRPC handlers\n"));
1226 struct winbindd_addrchanged_state
{
1227 struct addrchange_context
*ctx
;
1228 struct tevent_context
*ev
;
1229 struct messaging_context
*msg_ctx
;
1232 static void winbindd_addr_changed(struct tevent_req
*req
);
1234 static void winbindd_init_addrchange(TALLOC_CTX
*mem_ctx
,
1235 struct tevent_context
*ev
,
1236 struct messaging_context
*msg_ctx
)
1238 struct winbindd_addrchanged_state
*state
;
1239 struct tevent_req
*req
;
1242 state
= talloc(mem_ctx
, struct winbindd_addrchanged_state
);
1243 if (state
== NULL
) {
1244 DEBUG(10, ("talloc failed\n"));
1248 state
->msg_ctx
= msg_ctx
;
1250 status
= addrchange_context_create(state
, &state
->ctx
);
1251 if (!NT_STATUS_IS_OK(status
)) {
1252 DEBUG(10, ("addrchange_context_create failed: %s\n",
1253 nt_errstr(status
)));
1257 req
= addrchange_send(state
, ev
, state
->ctx
);
1259 DEBUG(0, ("addrchange_send failed\n"));
1263 tevent_req_set_callback(req
, winbindd_addr_changed
, state
);
1266 static void winbindd_addr_changed(struct tevent_req
*req
)
1268 struct winbindd_addrchanged_state
*state
= tevent_req_callback_data(
1269 req
, struct winbindd_addrchanged_state
);
1270 enum addrchange_type type
;
1271 struct sockaddr_storage addr
;
1274 status
= addrchange_recv(req
, &type
, &addr
);
1276 if (!NT_STATUS_IS_OK(status
)) {
1277 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1278 nt_errstr(status
)));
1282 if (type
== ADDRCHANGE_DEL
) {
1283 char addrstr
[INET6_ADDRSTRLEN
];
1286 print_sockaddr(addrstr
, sizeof(addrstr
), &addr
);
1288 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1291 blob
= data_blob_const(addrstr
, strlen(addrstr
)+1);
1293 status
= messaging_send(state
->msg_ctx
,
1294 messaging_server_id(state
->msg_ctx
),
1295 MSG_WINBIND_IP_DROPPED
, &blob
);
1296 if (!NT_STATUS_IS_OK(status
)) {
1297 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1298 nt_errstr(status
)));
1301 req
= addrchange_send(state
, state
->ev
, state
->ctx
);
1303 DEBUG(0, ("addrchange_send failed\n"));
1307 tevent_req_set_callback(req
, winbindd_addr_changed
, state
);
1312 int main(int argc
, const char **argv
)
1314 static bool log_stdout
= False
;
1315 struct samba_cmdline_daemon_cfg
*cmdline_daemon_cfg
= NULL
;
1316 struct poptOption long_options
[] = {
1319 .longName
= "no-caching",
1321 .argInfo
= POPT_ARG_NONE
,
1324 .descrip
= "Disable caching",
1331 const struct loadparm_substitution
*lp_sub
=
1332 loadparm_s3_global_substitution();
1338 const struct dcesrv_endpoint_server
*ep_server
= NULL
;
1339 struct dcesrv_context
*dce_ctx
= NULL
;
1340 size_t winbindd_socket_dir_len
= 0;
1341 char *winbindd_priv_socket_dir
= NULL
;
1342 size_t winbindd_priv_socket_dir_len
= 0;
1344 setproctitle_init(argc
, discard_const(argv
), environ
);
1347 * Do this before any other talloc operation
1349 talloc_enable_null_tracking();
1350 frame
= talloc_stackframe();
1353 * We want total control over the permissions on created files,
1354 * so set our umask to 0.
1360 /* glibc (?) likes to print "User defined signal 1" and exit if a
1361 SIGUSR[12] is received before a handler is installed */
1363 CatchSignal(SIGUSR1
, SIG_IGN
);
1364 CatchSignal(SIGUSR2
, SIG_IGN
);
1366 ok
= samba_cmdline_init(frame
,
1367 SAMBA_CMDLINE_CONFIG_SERVER
,
1368 true /* require_smbconf */);
1370 DBG_ERR("Failed to setup cmdline parser\n");
1375 cmdline_daemon_cfg
= samba_cmdline_get_daemon_cfg();
1377 pc
= samba_popt_get_context(getprogname(), argc
, argv
, long_options
, 0);
1379 DBG_ERR("Failed to setup popt parser!\n");
1384 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1387 winbindd_set_use_cache(false);
1390 d_fprintf(stderr
, "\nInvalid option %s: %s\n\n",
1391 poptBadOption(pc
, 0), poptStrerror(opt
));
1392 poptPrintUsage(pc
, stderr
, 0);
1397 /* Set environment variable so we don't recursively call ourselves.
1398 This may also be useful interactively. */
1399 if ( !winbind_off() ) {
1400 DEBUG(0,("Failed to disable recursive winbindd calls. Exiting.\n"));
1404 /* Initialise for running in non-root mode */
1407 set_remote_machine_name("winbindd", False
);
1409 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub
));
1410 if (cmdline_daemon_cfg
->daemon
&& cmdline_daemon_cfg
->interactive
) {
1411 d_fprintf(stderr
,"\nERROR: "
1412 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1413 poptPrintUsage(pc
, stderr
, 0);
1417 log_stdout
= (debug_get_log_type() == DEBUG_STDOUT
);
1418 if (cmdline_daemon_cfg
->interactive
) {
1420 * libcmdline POPT_DAEMON callback sets "fork" to false if "-i"
1421 * for interactive is passed on the commandline. Set it back to
1422 * true. TODO: check if this is correct, smbd and nmbd don't do
1425 cmdline_daemon_cfg
->fork
= true;
1429 if (log_stdout
&& cmdline_daemon_cfg
->fork
) {
1430 d_fprintf(stderr
, "\nERROR: "
1431 "Can't log to stdout (-S) unless daemon is in "
1432 "foreground (-F) or interactive (-i)\n\n");
1433 poptPrintUsage(pc
, stderr
, 0);
1437 poptFreeContext(pc
);
1441 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1442 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE
));
1444 /* After parsing the configuration file we setup the core path one more time
1445 * as the log file might have been set in the configuration and cores's
1446 * path is by default basename(lp_logfile()).
1448 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub
));
1450 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
) {
1451 if (!lp_parm_bool(-1, "server role check", "inhibit", false)) {
1452 DBG_ERR("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n");
1453 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"));
1456 /* Main 'samba' daemon will notify */
1457 daemon_sd_notifications(false);
1460 if (lp_security() == SEC_ADS
) {
1461 const char *realm
= lp_realm();
1462 const char *workgroup
= lp_workgroup();
1464 if (workgroup
== NULL
|| strlen(workgroup
) == 0) {
1465 DBG_ERR("For 'secuirity = ADS' mode, the 'workgroup' "
1466 "parameter is required to be set!\n");
1470 if (realm
== NULL
|| strlen(realm
) == 0) {
1471 DBG_ERR("For 'secuirity = ADS' mode, the 'realm' "
1472 "parameter is required to be set!\n");
1477 winbindd_socket_dir_len
= strlen(lp_winbindd_socket_directory());
1478 if (winbindd_socket_dir_len
> 0) {
1479 size_t winbindd_socket_len
=
1480 winbindd_socket_dir_len
+ 1 +
1481 strlen(WINBINDD_SOCKET_NAME
);
1482 struct sockaddr_un un
= {
1483 .sun_family
= AF_UNIX
,
1485 size_t sun_path_len
= sizeof(un
.sun_path
);
1487 if (winbindd_socket_len
>= sun_path_len
) {
1488 DBG_ERR("The winbind socket path [%s/%s] is too long "
1490 lp_winbindd_socket_directory(),
1491 WINBINDD_SOCKET_NAME
,
1492 winbindd_socket_len
,
1497 DBG_ERR("'winbindd_socket_directory' parameter is empty\n");
1501 winbindd_priv_socket_dir
= get_winbind_priv_pipe_dir();
1502 winbindd_priv_socket_dir_len
= strlen(winbindd_priv_socket_dir
);
1503 if (winbindd_priv_socket_dir_len
> 0) {
1504 size_t winbindd_priv_socket_len
=
1505 winbindd_priv_socket_dir_len
+ 1 +
1506 strlen(WINBINDD_SOCKET_NAME
);
1507 struct sockaddr_un un
= {
1508 .sun_family
= AF_UNIX
,
1510 size_t sun_path_len
= sizeof(un
.sun_path
);
1512 if (winbindd_priv_socket_len
>= sun_path_len
) {
1513 DBG_ERR("The winbind privileged socket path [%s/%s] is too long "
1515 winbindd_priv_socket_dir
,
1516 WINBINDD_SOCKET_NAME
,
1517 winbindd_priv_socket_len
,
1522 DBG_ERR("'winbindd_priv_socket_directory' parameter is empty\n");
1525 TALLOC_FREE(winbindd_priv_socket_dir
);
1527 if (!cluster_probe_ok()) {
1531 /* Initialise messaging system */
1533 if (global_messaging_context() == NULL
) {
1537 if (!winbindd_reload_services_file(NULL
)) {
1538 DEBUG(0, ("error opening config file\n"));
1544 const char *idmap_backend
;
1545 const char *invalid_backends
[] = {
1546 "ad", "rfc2307", "rid",
1549 idmap_backend
= lp_idmap_default_backend();
1550 for (i
= 0; i
< ARRAY_SIZE(invalid_backends
); i
++) {
1551 ok
= strequal(idmap_backend
, invalid_backends
[i
]);
1553 DBG_ERR("FATAL: Invalid idmap backend %s "
1554 "configured as the default backend!\n",
1561 ok
= directory_create_or_exist(lp_lock_directory(), 0755);
1563 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1564 lp_lock_directory(), strerror(errno
)));
1568 ok
= directory_create_or_exist(lp_pid_directory(), 0755);
1570 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1571 lp_pid_directory(), strerror(errno
)));
1577 if (!secrets_init()) {
1579 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1583 status
= rpccli_pre_open_netlogon_creds();
1584 if (!NT_STATUS_IS_OK(status
)) {
1585 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1586 nt_errstr(status
)));
1590 /* Unblock all signals we are interested in as they may have been
1591 blocked by the parent process. */
1593 BlockSignals(False
, SIGINT
);
1594 BlockSignals(False
, SIGQUIT
);
1595 BlockSignals(False
, SIGTERM
);
1596 BlockSignals(False
, SIGUSR1
);
1597 BlockSignals(False
, SIGUSR2
);
1598 BlockSignals(False
, SIGHUP
);
1599 BlockSignals(False
, SIGCHLD
);
1602 become_daemon(cmdline_daemon_cfg
->fork
,
1603 cmdline_daemon_cfg
->no_process_group
,
1606 daemon_status("winbindd", "Starting process ...");
1609 pidfile_create(lp_pid_directory(), "winbindd");
1613 * If we're interactive we want to set our own process group for
1614 * signal management.
1616 if (cmdline_daemon_cfg
->interactive
&&
1617 !cmdline_daemon_cfg
->no_process_group
)
1619 setpgid( (pid_t
)0, (pid_t
)0);
1625 /* Don't use winbindd_reinit_after_fork here as
1626 * we're just starting up and haven't created any
1627 * winbindd-specific resources we must free yet. JRA.
1630 status
= reinit_after_fork(global_messaging_context(),
1631 global_event_context(),
1633 if (!NT_STATUS_IS_OK(status
)) {
1634 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status
));
1637 if (lp_winbind_debug_traceid()) {
1638 winbind_debug_traceid_setup(global_event_context());
1639 winbind_debug_call_depth_setup(debug_call_depth_addr());
1640 tevent_thread_call_depth_set_callback(
1641 debuglevel_get() > 1 ? winbind_call_flow
: NULL
,
1644 ok
= initialize_password_db(true, global_event_context());
1646 exit_daemon("Failed to initialize passdb backend! "
1647 "Check the 'passdb backend' variable in your "
1648 "smb.conf file.", EINVAL
);
1652 * Do not initialize the parent-child-pipe before becoming
1653 * a daemon: this is used to detect a died parent in the child
1656 status
= init_before_fork();
1657 if (!NT_STATUS_IS_OK(status
)) {
1658 exit_daemon(nt_errstr(status
), map_errno_from_nt_status(status
));
1661 winbindd_register_handlers(global_messaging_context(),
1662 !cmdline_daemon_cfg
->fork
);
1664 if (!messaging_parent_dgm_cleanup_init(global_messaging_context())) {
1668 status
= init_system_session_info(NULL
);
1669 if (!NT_STATUS_IS_OK(status
)) {
1670 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status
));
1673 DBG_INFO("Registering DCE/RPC endpoint servers\n");
1675 ep_server
= winbind_get_ep_server();
1676 if (ep_server
== NULL
) {
1677 DBG_ERR("Failed to get 'winbind' endpoint server\n");
1680 status
= dcerpc_register_ep_server(ep_server
);
1681 if (!NT_STATUS_IS_OK(status
)) {
1682 DBG_ERR("Failed to register 'winbind' endpoint "
1683 "server: %s\n", nt_errstr(status
));
1687 dce_ctx
= global_dcesrv_context();
1689 DBG_INFO("Initializing DCE/RPC registered endpoint servers\n");
1691 /* Init all registered ep servers */
1692 status
= dcesrv_init_registered_ep_servers(dce_ctx
);
1693 if (!NT_STATUS_IS_OK(status
)) {
1694 DBG_ERR("Failed to init DCE/RPC endpoint servers: %s\n",
1699 winbindd_init_addrchange(NULL
, global_event_context(),
1700 global_messaging_context());
1702 /* setup listen sockets */
1704 if (!winbindd_setup_listeners()) {
1705 exit_daemon("Winbindd failed to setup listeners", EPIPE
);
1708 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1713 daemon_ready("winbindd");
1718 /* Loop waiting for requests */
1720 frame
= talloc_stackframe();
1722 if (tevent_loop_once(global_event_context()) == -1) {
1723 DEBUG(1, ("tevent_loop_once() failed: %s\n",