selftest: fix domain name of nt4_dc_smb1 environment
[Samba.git] / source3 / winbindd / winbindd.c
blob29a24a981c37b6146c3de3861cf2272f54cadd09
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 "lib/cmdline/cmdline.h"
27 #include "winbindd.h"
28 #include "nsswitch/winbind_client.h"
29 #include "nsswitch/wb_reqtrans.h"
30 #include "ntdomain.h"
31 #include "librpc/rpc/dcesrv_core.h"
32 #include "librpc/gen_ndr/ndr_lsa_scompat.h"
33 #include "librpc/gen_ndr/ndr_samr_scompat.h"
34 #include "librpc/gen_ndr/ndr_winbind_scompat.h"
35 #include "secrets.h"
36 #include "rpc_client/cli_netlogon.h"
37 #include "idmap.h"
38 #include "lib/addrchange.h"
39 #include "auth.h"
40 #include "messages.h"
41 #include "../lib/util/pidfile.h"
42 #include "util_cluster.h"
43 #include "source4/lib/messaging/irpc.h"
44 #include "source4/lib/messaging/messaging.h"
45 #include "lib/param/param.h"
46 #include "lib/async_req/async_sock.h"
47 #include "libsmb/samlogon_cache.h"
48 #include "libcli/auth/netlogon_creds_cli.h"
49 #include "passdb.h"
50 #include "lib/util/tevent_req_profile.h"
51 #include "lib/gencache.h"
52 #include "rpc_server/rpc_config.h"
53 #include "lib/global_contexts.h"
54 #include "source3/lib/substitute.h"
55 #include "winbindd_traceid.h"
56 #include "lib/util/util_process.h"
58 #undef DBGC_CLASS
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,
97 uint16_t flags,
98 void *private_data)
100 char c;
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",
107 (int)*is_parent));
108 winbindd_terminate(*is_parent);
112 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
114 bool *is_parent;
116 if (foreground) {
117 struct stat st;
119 is_parent = talloc(global_event_context(), bool);
120 if (!is_parent) {
121 return false;
124 *is_parent = parent;
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) {
132 return false;
134 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
135 tevent_add_fd(global_event_context(),
136 is_parent,
138 TEVENT_FD_READ,
139 winbindd_stdin_handler,
140 is_parent);
144 return true;
147 static void winbindd_sig_chld_handler(struct tevent_context *ev,
148 struct tevent_signal *se,
149 int signum,
150 int count,
151 void *siginfo,
152 void *private_data)
154 pid_t pid;
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(),
167 SIGCHLD, 0,
168 winbindd_sig_chld_handler,
169 NULL);
170 if (!se) {
171 return false;
174 return true;
177 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
178 struct tevent_signal *se,
179 int signum,
180 int count,
181 void *siginfo,
182 void *private_data)
184 winbindd_status();
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(),
193 SIGUSR2, 0,
194 winbindd_sig_usr2_handler,
195 NULL);
196 if (!se) {
197 return false;
200 return true;
203 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
204 static void msg_shutdown(struct messaging_context *msg,
205 void *private_data,
206 uint32_t msg_type,
207 struct server_id server_id,
208 DATA_BLOB *data)
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,
217 void *private_data,
218 uint32_t msg_type,
219 struct server_id server_id,
220 DATA_BLOB *data)
222 uint8_t ret;
223 pid_t child_pid;
224 NTSTATUS status;
226 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
227 "message.\n"));
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...
234 child_pid = fork();
236 if (child_pid == -1) {
237 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
238 strerror(errno)));
239 return;
242 if (child_pid != 0) {
243 /* parent */
244 DEBUG(5, ("winbind_msg_validate_cache: child created with "
245 "pid %d.\n", (int)child_pid));
246 return;
249 /* child */
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",
254 nt_errstr(status)));
255 _exit(0);
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,
266 (size_t)1);
267 _exit(0);
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" },
278 { WINBINDD_INFO,
279 winbindd_info,
280 "INFO" },
281 { WINBINDD_PING,
282 winbindd_ping,
283 "PING" },
284 { WINBINDD_DOMAIN_NAME,
285 winbindd_domain_name,
286 "DOMAIN_NAME" },
287 { WINBINDD_NETBIOS_NAME,
288 winbindd_netbios_name,
289 "NETBIOS_NAME" },
290 { WINBINDD_DC_INFO,
291 winbindd_dc_info,
292 "DC_INFO" },
293 { WINBINDD_CCACHE_NTLMAUTH,
294 winbindd_ccache_ntlm_auth,
295 "NTLMAUTH" },
296 { WINBINDD_CCACHE_SAVE,
297 winbindd_ccache_save,
298 "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,
304 "LIST_TRUSTDOM" },
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(
416 TALLOC_CTX *mem_ctx,
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;
424 size_t i;
425 bool ok;
426 static uint64_t request_index = 1;
429 * debug traceid values:
430 * 0 .. inactive
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);
440 if (req == NULL) {
441 return NULL;
443 state->cli_state = cli_state;
444 state->ev = ev;
446 ok = tevent_req_set_profile(req);
447 if (!ok) {
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(
458 cli_state->mem_ctx,
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) {
480 break;
484 if ((atable->send_req == NULL) && cli_state->privileged) {
485 for (atable = async_priv_table; atable->send_req;
486 atable += 1) {
487 if (cmd == atable->cmd) {
488 break;
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,
499 (int)cli_state->pid,
500 cli_state->cmd_name);
502 subreq = atable->send_req(
503 state,
504 state->ev,
505 cli_state,
506 cli_state->request);
507 if (tevent_req_nomem(subreq, req)) {
508 return tevent_req_post(req, ev);
510 tevent_req_set_callback(subreq, process_request_done, req);
511 return req;
514 for (i=0; i<ARRAY_SIZE(bool_dispatch_table); i++) {
515 if (cmd == bool_dispatch_table[i].cmd) {
516 break;
520 ok = false;
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(
536 state,
537 state->ev,
538 cli_state->out_queue,
539 cli_state->sock,
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;
548 return req;
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;
558 NTSTATUS status;
559 bool ok;
561 status = cli_state->recv_fn(subreq, cli_state->response);
562 TALLOC_FREE(subreq);
564 DBG_NOTICE("[%s(%d):%s]: %s\n",
565 cli_state->client_name,
566 (int)cli_state->pid,
567 cli_state->cmd_name,
568 nt_errstr(status));
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(
577 state,
578 state->ev,
579 cli_state->out_queue,
580 cli_state->sock,
581 cli_state->response);
582 if (tevent_req_nomem(subreq, req)) {
583 return;
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;
597 ssize_t ret;
598 int err;
600 cli_state->io_req = NULL;
602 ret = wb_resp_write_recv(subreq, &err);
603 TALLOC_FREE(subreq);
604 if (ret == -1) {
605 tevent_req_nterror(req, map_nt_error_from_unix(err));
606 return;
609 DBG_DEBUG("[%s(%d):%s]: delivered response to client\n",
610 cli_state->client_name,
611 (int)cli_state->pid,
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,
624 TALLOC_CTX *mem_ctx,
625 struct tevent_req_profile **profile)
627 NTSTATUS status;
629 if (tevent_req_is_nterror(req, &status)) {
630 tevent_req_received(req);
631 return status;
634 *profile = tevent_req_move_profile(req, mem_ctx);
635 tevent_req_received(req);
636 return NT_STATUS_OK;
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;
660 socklen_t len;
661 int sock;
663 /* Accept connection */
665 len = sizeof(sunaddr);
667 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
669 if (sock == -1) {
670 if (errno != EINTR) {
671 D_ERR("Failed to accept socket: %s\n", strerror(errno));
673 return;
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) {
682 close(sock);
683 return;
686 state->sock = sock;
688 state->out_queue = tevent_queue_create(state, "winbind client reply");
689 if (state->out_queue == NULL) {
690 close(sock);
691 TALLOC_FREE(state);
692 return;
695 state->privileged = privileged;
697 req = wb_req_read_send(state, global_event_context(), state->sock,
698 WINBINDD_MAX_EXTRA_DATA);
699 if (req == NULL) {
700 TALLOC_FREE(state);
701 close(sock);
702 return;
704 tevent_req_set_callback(req, winbind_client_request_read, state);
705 state->io_req = req;
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);
716 ssize_t ret;
717 int err;
719 state->io_req = NULL;
721 ret = wb_req_read_recv(req, state, &state->request, &err);
722 TALLOC_FREE(req);
723 if (ret == -1) {
724 if (err == EPIPE) {
725 DEBUG(6, ("closing socket %d, client exited\n",
726 state->sock));
727 } else {
728 DEBUG(2, ("Could not read client request from fd %d: "
729 "%s\n", state->sock, strerror(err)));
731 close(state->sock);
732 state->sock = -1;
733 remove_client(state);
734 return;
737 req = wait_for_read_send(state, global_event_context(), state->sock,
738 true);
739 if (req == NULL) {
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);
744 return;
746 tevent_req_set_callback(req, winbind_client_activity, state);
747 state->io_req = req;
749 req = process_request_send(state, global_event_context(), state);
750 if (req == NULL) {
751 DBG_ERR("process_request_send failed\n");
752 remove_client(state);
753 return;
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);
762 int err;
763 bool has_data;
765 has_data = wait_for_read_recv(req, &err);
767 if (has_data) {
768 DEBUG(0, ("winbind_client_activity[%d:%s]:"
769 "unexpected data from client - removing client\n",
770 (int)state->pid, state->cmd_name));
771 } else {
772 if (err == EPIPE) {
773 DEBUG(6, ("winbind_client_activity[%d:%s]: "
774 "client has closed connection - removing "
775 "client\n",
776 (int)state->pid, state->cmd_name));
777 } else {
778 DEBUG(2, ("winbind_client_activity[%d:%s]: "
779 "client socket error (%s) - removing "
780 "client\n",
781 (int)state->pid, state->cmd_name,
782 strerror(err)));
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;
795 int threshold;
796 NTSTATUS status;
798 status = process_request_recv(req, cli_state, &profile);
799 TALLOC_FREE(req);
800 if (!NT_STATUS_IS_OK(status)) {
801 DBG_DEBUG("process_request failed: %s\n", nt_errstr(status));
802 remove_client(cli_state);
803 return;
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) {
813 int depth;
814 char *str;
816 depth = lp_parm_int(
818 "winbind",
819 "request profile depth",
820 INT_MAX);
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);
827 if (str != NULL) {
828 /* No "\n", already contained in "str" */
829 DEBUGADD(0, ("%s", str));
831 TALLOC_FREE(str);
834 TALLOC_FREE(profile);
836 req = wb_req_read_send(
837 cli_state,
838 global_event_context(),
839 cli_state->sock,
840 WINBINDD_MAX_EXTRA_DATA);
841 if (req == NULL) {
842 remove_client(cli_state);
843 return;
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 */
855 if (state == NULL) {
856 return;
860 * We need to remove a pending wb_req_read_*
861 * or wb_resp_write_* request before closing the
862 * socket.
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.
874 * See bug #11141.
876 TALLOC_FREE(state->io_req);
878 if (state->sock != -1) {
879 char c = 0;
880 int nwritten;
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",
886 strerror(errno)));
889 /* Close socket */
891 close(state->sock);
892 state->sock = -1;
895 TALLOC_FREE(state->mem_ctx);
897 /* Remove from list and free */
899 winbindd_remove_client(state);
900 TALLOC_FREE(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;
916 int nidle = 0;
918 for (state = winbindd_client_list(); state; state = state->next) {
919 if (client_is_idle(state)) {
920 nidle++;
921 /* list is sorted by access time */
922 remove_state = state;
926 if (remove_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);
930 return True;
933 return False;
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) {
949 time_t expiry_time;
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
956 list are newer */
957 break;
960 if (client_is_idle(state)) {
961 DEBUG(5,("Idle client timed out, "
962 "shutting down sock %d, pid %u\n",
963 state->sock,
964 (unsigned int)state->pid));
965 } else {
966 DEBUG(5,("Client request timed out, "
967 "shutting down sock %d, pid %u\n",
968 state->sock,
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,
979 void *private_data)
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"));
986 exit(1);
990 struct winbindd_listen_state {
991 bool privileged;
992 int fd;
995 static void winbindd_listen_fde_handler(struct tevent_context *ev,
996 struct tevent_fd *fde,
997 uint16_t flags,
998 void *private_data)
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()));
1012 break;
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;
1028 int rc;
1029 char *socket_path;
1031 pub_state = talloc(global_event_context(),
1032 struct winbindd_listen_state);
1033 if (!pub_state) {
1034 goto failed;
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) {
1041 goto failed;
1043 rc = listen(pub_state->fd, 5);
1044 if (rc < 0) {
1045 goto failed;
1048 fde = tevent_add_fd(global_event_context(), pub_state, pub_state->fd,
1049 TEVENT_FD_READ, winbindd_listen_fde_handler,
1050 pub_state);
1051 if (fde == NULL) {
1052 close(pub_state->fd);
1053 goto failed;
1055 tevent_fd_set_auto_close(fde);
1057 priv_state = talloc(global_event_context(),
1058 struct winbindd_listen_state);
1059 if (!priv_state) {
1060 goto failed;
1063 socket_path = get_winbind_priv_pipe_dir();
1064 if (socket_path == NULL) {
1065 goto failed;
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) {
1073 goto failed;
1075 rc = listen(priv_state->fd, 5);
1076 if (rc < 0) {
1077 goto failed;
1080 fde = tevent_add_fd(global_event_context(), priv_state,
1081 priv_state->fd, TEVENT_FD_READ,
1082 winbindd_listen_fde_handler, priv_state);
1083 if (fde == NULL) {
1084 close(priv_state->fd);
1085 goto failed;
1087 tevent_fd_set_auto_close(fde);
1089 winbindd_scrub_clients_handler(global_event_context(), NULL,
1090 timeval_current(), NULL);
1091 return true;
1092 failed:
1093 TALLOC_FREE(pub_state);
1094 TALLOC_FREE(priv_state);
1095 return false;
1098 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1099 bool foreground)
1101 bool scan_trusts = true;
1102 NTSTATUS status;
1103 struct tevent_timer *te = NULL;
1105 /* Setup signal handlers */
1107 if (!winbindd_setup_sig_term_handler(true))
1108 exit(1);
1109 if (!winbindd_setup_stdin_handler(true, foreground))
1110 exit(1);
1111 if (!winbindd_setup_sig_hup_handler(NULL))
1112 exit(1);
1113 if (!winbindd_setup_sig_chld_handler())
1114 exit(1);
1115 if (!winbindd_setup_sig_usr2_handler())
1116 exit(1);
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()) {
1125 exit(1);
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,
1164 MSG_DEBUG,
1165 winbind_msg_debug);
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 */
1175 wcache_tdc_clear();
1177 if (!init_domain_list()) {
1178 DEBUG(0,("unable to initialize domain list\n"));
1179 exit(1);
1182 status = init_idmap_child(global_event_context());
1183 if (NT_STATUS_IS_ERR(status)) {
1184 DBG_ERR("Unable to start idmap child: %s\n", nt_errstr(status));
1185 exit(1);
1188 status = init_locator_child(global_event_context());
1189 if (NT_STATUS_IS_ERR(status)) {
1190 DBG_ERR("Unable to start locator child: %s\n", nt_errstr(status));
1191 exit(1);
1194 smb_nscd_flush_user_cache();
1195 smb_nscd_flush_group_cache();
1197 if (!lp_winbind_scan_trusted_domains()) {
1198 scan_trusts = false;
1201 if (!lp_allow_trusted_domains()) {
1202 scan_trusts = false;
1205 if (IS_DC) {
1206 scan_trusts = false;
1209 if (scan_trusts) {
1210 if (tevent_add_timer(global_event_context(), NULL, timeval_zero(),
1211 rescan_trusted_domains, NULL) == NULL) {
1212 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1213 exit(1);
1217 te = tevent_add_timer(global_event_context(),
1218 NULL,
1219 timeval_zero(),
1220 winbindd_ping_offline_domains,
1221 NULL);
1222 if (te == NULL) {
1223 DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
1224 exit(1);
1227 status = wb_irpc_register();
1229 if (!NT_STATUS_IS_OK(status)) {
1230 DEBUG(0, ("Could not register IRPC handlers\n"));
1231 exit(1);
1235 struct winbindd_addrchanged_state {
1236 struct addrchange_context *ctx;
1237 struct tevent_context *ev;
1238 struct messaging_context *msg_ctx;
1241 static void winbindd_addr_changed(struct tevent_req *req);
1243 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1244 struct tevent_context *ev,
1245 struct messaging_context *msg_ctx)
1247 struct winbindd_addrchanged_state *state;
1248 struct tevent_req *req;
1249 NTSTATUS status;
1251 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1252 if (state == NULL) {
1253 DEBUG(10, ("talloc failed\n"));
1254 return;
1256 state->ev = ev;
1257 state->msg_ctx = msg_ctx;
1259 status = addrchange_context_create(state, &state->ctx);
1260 if (!NT_STATUS_IS_OK(status)) {
1261 DEBUG(10, ("addrchange_context_create failed: %s\n",
1262 nt_errstr(status)));
1263 TALLOC_FREE(state);
1264 return;
1266 req = addrchange_send(state, ev, state->ctx);
1267 if (req == NULL) {
1268 DEBUG(0, ("addrchange_send failed\n"));
1269 TALLOC_FREE(state);
1270 return;
1272 tevent_req_set_callback(req, winbindd_addr_changed, state);
1275 static void winbindd_addr_changed(struct tevent_req *req)
1277 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1278 req, struct winbindd_addrchanged_state);
1279 enum addrchange_type type;
1280 struct sockaddr_storage addr;
1281 NTSTATUS status;
1283 status = addrchange_recv(req, &type, &addr);
1284 TALLOC_FREE(req);
1285 if (!NT_STATUS_IS_OK(status)) {
1286 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1287 nt_errstr(status)));
1288 TALLOC_FREE(state);
1289 return;
1291 if (type == ADDRCHANGE_DEL) {
1292 char addrstr[INET6_ADDRSTRLEN];
1293 DATA_BLOB blob;
1295 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1297 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1298 addrstr));
1300 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1302 status = messaging_send(state->msg_ctx,
1303 messaging_server_id(state->msg_ctx),
1304 MSG_WINBIND_IP_DROPPED, &blob);
1305 if (!NT_STATUS_IS_OK(status)) {
1306 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1307 nt_errstr(status)));
1310 req = addrchange_send(state, state->ev, state->ctx);
1311 if (req == NULL) {
1312 DEBUG(0, ("addrchange_send failed\n"));
1313 TALLOC_FREE(state);
1314 return;
1316 tevent_req_set_callback(req, winbindd_addr_changed, state);
1319 /* Main function */
1321 int main(int argc, const char **argv)
1323 static bool log_stdout = False;
1324 struct samba_cmdline_daemon_cfg *cmdline_daemon_cfg = NULL;
1325 struct poptOption long_options[] = {
1326 POPT_AUTOHELP
1328 .longName = "no-caching",
1329 .shortName = 'n',
1330 .argInfo = POPT_ARG_NONE,
1331 .arg = NULL,
1332 .val = 'n',
1333 .descrip = "Disable caching",
1335 POPT_COMMON_SAMBA
1336 POPT_COMMON_DAEMON
1337 POPT_COMMON_VERSION
1338 POPT_TABLEEND
1340 const struct loadparm_substitution *lp_sub =
1341 loadparm_s3_global_substitution();
1342 poptContext pc;
1343 int opt;
1344 TALLOC_CTX *frame;
1345 NTSTATUS status;
1346 bool ok;
1347 const struct dcesrv_endpoint_server *ep_server = NULL;
1348 struct dcesrv_context *dce_ctx = NULL;
1349 size_t winbindd_socket_dir_len = 0;
1350 char *winbindd_priv_socket_dir = NULL;
1351 size_t winbindd_priv_socket_dir_len = 0;
1353 setproctitle_init(argc, discard_const(argv), environ);
1356 * Do this before any other talloc operation
1358 talloc_enable_null_tracking();
1359 frame = talloc_stackframe();
1362 * We want total control over the permissions on created files,
1363 * so set our umask to 0.
1365 umask(0);
1367 smb_init_locale();
1369 /* glibc (?) likes to print "User defined signal 1" and exit if a
1370 SIGUSR[12] is received before a handler is installed */
1372 CatchSignal(SIGUSR1, SIG_IGN);
1373 CatchSignal(SIGUSR2, SIG_IGN);
1375 ok = samba_cmdline_init(frame,
1376 SAMBA_CMDLINE_CONFIG_SERVER,
1377 true /* require_smbconf */);
1378 if (!ok) {
1379 DBG_ERR("Failed to setup cmdline parser\n");
1380 TALLOC_FREE(frame);
1381 exit(1);
1384 cmdline_daemon_cfg = samba_cmdline_get_daemon_cfg();
1386 pc = samba_popt_get_context(getprogname(), argc, argv, long_options, 0);
1387 if (pc == NULL) {
1388 DBG_ERR("Failed to setup popt parser!\n");
1389 TALLOC_FREE(frame);
1390 exit(1);
1393 while ((opt = poptGetNextOpt(pc)) != -1) {
1394 switch (opt) {
1395 case 'n':
1396 winbindd_set_use_cache(false);
1397 break;
1398 default:
1399 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1400 poptBadOption(pc, 0), poptStrerror(opt));
1401 poptPrintUsage(pc, stderr, 0);
1402 exit(1);
1406 /* Set environment variable so we don't recursively call ourselves.
1407 This may also be useful interactively. */
1408 if ( !winbind_off() ) {
1409 DEBUG(0,("Failed to disable recursive winbindd calls. Exiting.\n"));
1410 exit(1);
1413 /* Initialise for running in non-root mode */
1414 sec_init();
1416 set_remote_machine_name("winbindd", False);
1418 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1419 if (cmdline_daemon_cfg->daemon && cmdline_daemon_cfg->interactive) {
1420 d_fprintf(stderr,"\nERROR: "
1421 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1422 poptPrintUsage(pc, stderr, 0);
1423 exit(1);
1426 log_stdout = (debug_get_log_type() == DEBUG_STDOUT);
1427 if (cmdline_daemon_cfg->interactive) {
1429 * libcmdline POPT_DAEMON callback sets "fork" to false if "-i"
1430 * for interactive is passed on the commandline. Set it back to
1431 * true. TODO: check if this is correct, smbd and nmbd don't do
1432 * this.
1434 cmdline_daemon_cfg->fork = true;
1435 log_stdout = true;
1438 if (log_stdout && cmdline_daemon_cfg->fork) {
1439 d_fprintf(stderr, "\nERROR: "
1440 "Can't log to stdout (-S) unless daemon is in "
1441 "foreground (-F) or interactive (-i)\n\n");
1442 poptPrintUsage(pc, stderr, 0);
1443 exit(1);
1446 poptFreeContext(pc);
1448 reopen_logs();
1450 DBG_STARTUP_NOTICE("winbindd version %s started.\n%s\n",
1451 samba_version_string(),
1452 samba_copyright_string());
1454 /* After parsing the configuration file we setup the core path one more time
1455 * as the log file might have been set in the configuration and cores's
1456 * path is by default basename(lp_logfile()).
1458 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1460 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1461 if (!lp_parm_bool(-1, "server role check", "inhibit", false)) {
1462 DBG_ERR("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n");
1463 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"));
1464 exit(1);
1466 /* Main 'samba' daemon will notify */
1467 daemon_sd_notifications(false);
1470 if (lp_security() == SEC_ADS) {
1471 const char *realm = lp_realm();
1472 const char *workgroup = lp_workgroup();
1474 if (workgroup == NULL || strlen(workgroup) == 0) {
1475 DBG_ERR("For 'secuirity = ADS' mode, the 'workgroup' "
1476 "parameter is required to be set!\n");
1477 exit(1);
1480 if (realm == NULL || strlen(realm) == 0) {
1481 DBG_ERR("For 'secuirity = ADS' mode, the 'realm' "
1482 "parameter is required to be set!\n");
1483 exit(1);
1487 winbindd_socket_dir_len = strlen(lp_winbindd_socket_directory());
1488 if (winbindd_socket_dir_len > 0) {
1489 size_t winbindd_socket_len =
1490 winbindd_socket_dir_len + 1 +
1491 strlen(WINBINDD_SOCKET_NAME);
1492 struct sockaddr_un un = {
1493 .sun_family = AF_UNIX,
1495 size_t sun_path_len = sizeof(un.sun_path);
1497 if (winbindd_socket_len >= sun_path_len) {
1498 DBG_ERR("The winbind socket path [%s/%s] is too long "
1499 "(%zu >= %zu)\n",
1500 lp_winbindd_socket_directory(),
1501 WINBINDD_SOCKET_NAME,
1502 winbindd_socket_len,
1503 sun_path_len);
1504 exit(1);
1506 } else {
1507 DBG_ERR("'winbindd_socket_directory' parameter is empty\n");
1508 exit(1);
1511 winbindd_priv_socket_dir = get_winbind_priv_pipe_dir();
1512 winbindd_priv_socket_dir_len = strlen(winbindd_priv_socket_dir);
1513 if (winbindd_priv_socket_dir_len > 0) {
1514 size_t winbindd_priv_socket_len =
1515 winbindd_priv_socket_dir_len + 1 +
1516 strlen(WINBINDD_SOCKET_NAME);
1517 struct sockaddr_un un = {
1518 .sun_family = AF_UNIX,
1520 size_t sun_path_len = sizeof(un.sun_path);
1522 if (winbindd_priv_socket_len >= sun_path_len) {
1523 DBG_ERR("The winbind privileged socket path [%s/%s] is too long "
1524 "(%zu >= %zu)\n",
1525 winbindd_priv_socket_dir,
1526 WINBINDD_SOCKET_NAME,
1527 winbindd_priv_socket_len,
1528 sun_path_len);
1529 exit(1);
1531 } else {
1532 DBG_ERR("'winbindd_priv_socket_directory' parameter is empty\n");
1533 exit(1);
1535 TALLOC_FREE(winbindd_priv_socket_dir);
1537 if (!cluster_probe_ok()) {
1538 exit(1);
1541 /* Initialise messaging system */
1543 if (global_messaging_context() == NULL) {
1544 exit(1);
1547 if (!winbindd_reload_services_file(NULL)) {
1548 DEBUG(0, ("error opening config file\n"));
1549 exit(1);
1553 size_t i;
1554 const char *idmap_backend;
1555 const char *invalid_backends[] = {
1556 "ad", "rfc2307", "rid",
1559 idmap_backend = lp_idmap_default_backend();
1560 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1561 ok = strequal(idmap_backend, invalid_backends[i]);
1562 if (ok) {
1563 DBG_ERR("FATAL: Invalid idmap backend %s "
1564 "configured as the default backend!\n",
1565 idmap_backend);
1566 exit(1);
1571 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1572 if (!ok) {
1573 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1574 lp_lock_directory(), strerror(errno)));
1575 exit(1);
1578 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1579 if (!ok) {
1580 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1581 lp_pid_directory(), strerror(errno)));
1582 exit(1);
1585 load_interfaces();
1587 if (!secrets_init()) {
1589 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1590 return False;
1593 status = rpccli_pre_open_netlogon_creds();
1594 if (!NT_STATUS_IS_OK(status)) {
1595 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1596 nt_errstr(status)));
1597 exit(1);
1600 /* Unblock all signals we are interested in as they may have been
1601 blocked by the parent process. */
1603 BlockSignals(False, SIGINT);
1604 BlockSignals(False, SIGQUIT);
1605 BlockSignals(False, SIGTERM);
1606 BlockSignals(False, SIGUSR1);
1607 BlockSignals(False, SIGUSR2);
1608 BlockSignals(False, SIGHUP);
1609 BlockSignals(False, SIGCHLD);
1611 if (!interactive) {
1612 become_daemon(cmdline_daemon_cfg->fork,
1613 cmdline_daemon_cfg->no_process_group,
1614 log_stdout);
1615 } else {
1616 daemon_status("winbindd", "Starting process ...");
1619 pidfile_create(lp_pid_directory(), "winbindd");
1621 #ifdef HAVE_SETPGID
1623 * If we're interactive we want to set our own process group for
1624 * signal management.
1626 if (cmdline_daemon_cfg->interactive &&
1627 !cmdline_daemon_cfg->no_process_group)
1629 setpgid( (pid_t)0, (pid_t)0);
1631 #endif
1633 TimeInit();
1635 /* Don't use winbindd_reinit_after_fork here as
1636 * we're just starting up and haven't created any
1637 * winbindd-specific resources we must free yet. JRA.
1640 status = reinit_after_fork(global_messaging_context(),
1641 global_event_context(),
1642 false);
1643 if (!NT_STATUS_IS_OK(status)) {
1644 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1647 if (lp_winbind_debug_traceid()) {
1648 winbind_debug_traceid_setup(global_event_context());
1649 winbind_debug_call_depth_setup(debug_call_depth_addr());
1650 tevent_thread_call_depth_set_callback(
1651 debuglevel_get() > 1 ? winbind_call_flow : NULL,
1652 NULL);
1654 ok = initialize_password_db(true, global_event_context());
1655 if (!ok) {
1656 exit_daemon("Failed to initialize passdb backend! "
1657 "Check the 'passdb backend' variable in your "
1658 "smb.conf file.", EINVAL);
1662 * Do not initialize the parent-child-pipe before becoming
1663 * a daemon: this is used to detect a died parent in the child
1664 * process.
1666 status = init_before_fork();
1667 if (!NT_STATUS_IS_OK(status)) {
1668 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1671 winbindd_register_handlers(global_messaging_context(),
1672 !cmdline_daemon_cfg->fork);
1674 if (!messaging_parent_dgm_cleanup_init(global_messaging_context())) {
1675 exit(1);
1678 status = init_system_session_info(NULL);
1679 if (!NT_STATUS_IS_OK(status)) {
1680 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1683 DBG_INFO("Registering DCE/RPC endpoint servers\n");
1685 ep_server = winbind_get_ep_server();
1686 if (ep_server == NULL) {
1687 DBG_ERR("Failed to get 'winbind' endpoint server\n");
1688 exit(1);
1690 status = dcerpc_register_ep_server(ep_server);
1691 if (!NT_STATUS_IS_OK(status)) {
1692 DBG_ERR("Failed to register 'winbind' endpoint "
1693 "server: %s\n", nt_errstr(status));
1694 exit(1);
1697 dce_ctx = global_dcesrv_context();
1699 DBG_INFO("Initializing DCE/RPC registered endpoint servers\n");
1701 /* Init all registered ep servers */
1702 status = dcesrv_init_registered_ep_servers(dce_ctx);
1703 if (!NT_STATUS_IS_OK(status)) {
1704 DBG_ERR("Failed to init DCE/RPC endpoint servers: %s\n",
1705 nt_errstr(status));
1706 exit(1);
1709 winbindd_init_addrchange(NULL, global_event_context(),
1710 global_messaging_context());
1712 /* setup listen sockets */
1714 if (!winbindd_setup_listeners()) {
1715 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1718 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1720 TALLOC_FREE(frame);
1722 if (!interactive) {
1723 daemon_ready("winbindd");
1726 gpupdate_init();
1728 /* Loop waiting for requests */
1729 while (1) {
1730 frame = talloc_stackframe();
1732 if (tevent_loop_once(global_event_context()) == -1) {
1733 DEBUG(1, ("tevent_loop_once() failed: %s\n",
1734 strerror(errno)));
1735 return 1;
1738 TALLOC_FREE(frame);
1741 return 0;