s3:winbindd: make use of samba_sockaddr to avoid compiler warnings
[Samba.git] / source3 / winbindd / winbindd.c
blobdf0c7d08cf0fda5c85a26eb061c6611453f425f8
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 samba_sockaddr saddr = { .sa_socklen = 0, };
658 struct winbindd_cli_state *state;
659 struct tevent_req *req;
660 int sock;
662 /* Accept connection */
664 saddr.sa_socklen = sizeof(saddr.u.un);
665 sock = accept(listen_sock, &saddr.u.sa, &saddr.sa_socklen);
666 if (sock == -1) {
667 if (errno != EINTR) {
668 D_ERR("Failed to accept socket: %s\n", strerror(errno));
670 return;
672 smb_set_close_on_exec(sock);
674 D_INFO("Accepted client socket %d\n", sock);
676 /* Create new connection structure */
678 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
679 close(sock);
680 return;
683 state->sock = sock;
685 state->out_queue = tevent_queue_create(state, "winbind client reply");
686 if (state->out_queue == NULL) {
687 close(sock);
688 TALLOC_FREE(state);
689 return;
692 state->privileged = privileged;
694 req = wb_req_read_send(state, global_event_context(), state->sock,
695 WINBINDD_MAX_EXTRA_DATA);
696 if (req == NULL) {
697 TALLOC_FREE(state);
698 close(sock);
699 return;
701 tevent_req_set_callback(req, winbind_client_request_read, state);
702 state->io_req = req;
704 /* Add to connection list */
706 winbindd_add_client(state);
709 static void winbind_client_request_read(struct tevent_req *req)
711 struct winbindd_cli_state *state = tevent_req_callback_data(
712 req, struct winbindd_cli_state);
713 ssize_t ret;
714 int err;
716 state->io_req = NULL;
718 ret = wb_req_read_recv(req, state, &state->request, &err);
719 TALLOC_FREE(req);
720 if (ret == -1) {
721 if (err == EPIPE) {
722 DEBUG(6, ("closing socket %d, client exited\n",
723 state->sock));
724 } else {
725 DEBUG(2, ("Could not read client request from fd %d: "
726 "%s\n", state->sock, strerror(err)));
728 close(state->sock);
729 state->sock = -1;
730 remove_client(state);
731 return;
734 req = wait_for_read_send(state, global_event_context(), state->sock,
735 true);
736 if (req == NULL) {
737 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
738 " wait_for_read_send failed - removing client\n",
739 (int)state->pid, state->cmd_name));
740 remove_client(state);
741 return;
743 tevent_req_set_callback(req, winbind_client_activity, state);
744 state->io_req = req;
746 req = process_request_send(state, global_event_context(), state);
747 if (req == NULL) {
748 DBG_ERR("process_request_send failed\n");
749 remove_client(state);
750 return;
752 tevent_req_set_callback(req, winbind_client_processed, state);
755 static void winbind_client_activity(struct tevent_req *req)
757 struct winbindd_cli_state *state =
758 tevent_req_callback_data(req, struct winbindd_cli_state);
759 int err;
760 bool has_data;
762 has_data = wait_for_read_recv(req, &err);
764 if (has_data) {
765 DEBUG(0, ("winbind_client_activity[%d:%s]:"
766 "unexpected data from client - removing client\n",
767 (int)state->pid, state->cmd_name));
768 } else {
769 if (err == EPIPE) {
770 DEBUG(6, ("winbind_client_activity[%d:%s]: "
771 "client has closed connection - removing "
772 "client\n",
773 (int)state->pid, state->cmd_name));
774 } else {
775 DEBUG(2, ("winbind_client_activity[%d:%s]: "
776 "client socket error (%s) - removing "
777 "client\n",
778 (int)state->pid, state->cmd_name,
779 strerror(err)));
783 remove_client(state);
786 static void winbind_client_processed(struct tevent_req *req)
788 struct winbindd_cli_state *cli_state = tevent_req_callback_data(
789 req, struct winbindd_cli_state);
790 struct tevent_req_profile *profile = NULL;
791 struct timeval start, stop, diff;
792 int threshold;
793 NTSTATUS status;
795 status = process_request_recv(req, cli_state, &profile);
796 TALLOC_FREE(req);
797 if (!NT_STATUS_IS_OK(status)) {
798 DBG_DEBUG("process_request failed: %s\n", nt_errstr(status));
799 remove_client(cli_state);
800 return;
803 tevent_req_profile_get_start(profile, NULL, &start);
804 tevent_req_profile_get_stop(profile, NULL, &stop);
805 diff = tevent_timeval_until(&start, &stop);
807 threshold = lp_parm_int(-1, "winbind", "request profile threshold", 60);
809 if (diff.tv_sec >= threshold) {
810 int depth;
811 char *str;
813 depth = lp_parm_int(
815 "winbind",
816 "request profile depth",
817 INT_MAX);
819 DBG_ERR("request took %u.%.6u seconds\n",
820 (unsigned)diff.tv_sec, (unsigned)diff.tv_usec);
822 str = tevent_req_profile_string(
823 talloc_tos(), profile, 0, depth);
824 if (str != NULL) {
825 /* No "\n", already contained in "str" */
826 DEBUGADD(0, ("%s", str));
828 TALLOC_FREE(str);
831 TALLOC_FREE(profile);
833 req = wb_req_read_send(
834 cli_state,
835 global_event_context(),
836 cli_state->sock,
837 WINBINDD_MAX_EXTRA_DATA);
838 if (req == NULL) {
839 remove_client(cli_state);
840 return;
842 tevent_req_set_callback(req, winbind_client_request_read, cli_state);
843 cli_state->io_req = req;
846 /* Remove a client connection from client connection list */
848 static void remove_client(struct winbindd_cli_state *state)
850 /* It's a dead client - hold a funeral */
852 if (state == NULL) {
853 return;
857 * We need to remove a pending wb_req_read_*
858 * or wb_resp_write_* request before closing the
859 * socket.
861 * This is important as they might have used tevent_add_fd() and we
862 * use the epoll * backend on linux. So we must remove the tevent_fd
863 * before closing the fd.
865 * Otherwise we might hit a race with close_conns_after_fork() (via
866 * winbindd_reinit_after_fork()) where a file descriptor
867 * is still open in a child, which means it's still active in
868 * the parents epoll queue, but the related tevent_fd is already
869 * already gone in the parent.
871 * See bug #11141.
873 TALLOC_FREE(state->io_req);
875 if (state->sock != -1) {
876 char c = 0;
877 int nwritten;
879 /* tell client, we are closing ... */
880 nwritten = write(state->sock, &c, sizeof(c));
881 if (nwritten == -1) {
882 DEBUG(2, ("final write to client failed: %s\n",
883 strerror(errno)));
886 /* Close socket */
888 close(state->sock);
889 state->sock = -1;
892 TALLOC_FREE(state->mem_ctx);
894 /* Remove from list and free */
896 winbindd_remove_client(state);
897 TALLOC_FREE(state);
900 /* Is a client idle? */
902 static bool client_is_idle(struct winbindd_cli_state *state) {
903 return (state->request == NULL &&
904 state->response == NULL &&
905 !state->pwent_state && !state->grent_state);
908 /* Shutdown client connection which has been idle for the longest time */
910 static bool remove_idle_client(void)
912 struct winbindd_cli_state *state, *remove_state = NULL;
913 int nidle = 0;
915 for (state = winbindd_client_list(); state; state = state->next) {
916 if (client_is_idle(state)) {
917 nidle++;
918 /* list is sorted by access time */
919 remove_state = state;
923 if (remove_state) {
924 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
925 nidle, remove_state->sock, (unsigned int)remove_state->pid));
926 remove_client(remove_state);
927 return True;
930 return False;
934 * Terminate all clients whose requests have taken longer than
935 * "winbind request timeout" seconds to process, or have been
936 * idle for more than "winbind request timeout" seconds.
939 static void remove_timed_out_clients(void)
941 struct winbindd_cli_state *state, *prev = NULL;
942 time_t curr_time = time(NULL);
943 int timeout_val = lp_winbind_request_timeout();
945 for (state = winbindd_client_list_tail(); state; state = prev) {
946 time_t expiry_time;
948 prev = winbindd_client_list_prev(state);
949 expiry_time = state->last_access + timeout_val;
951 if (curr_time <= expiry_time) {
952 /* list is sorted, previous clients in
953 list are newer */
954 break;
957 if (client_is_idle(state)) {
958 DEBUG(5,("Idle client timed out, "
959 "shutting down sock %d, pid %u\n",
960 state->sock,
961 (unsigned int)state->pid));
962 } else {
963 DEBUG(5,("Client request timed out, "
964 "shutting down sock %d, pid %u\n",
965 state->sock,
966 (unsigned int)state->pid));
969 remove_client(state);
973 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
974 struct tevent_timer *te,
975 struct timeval current_time,
976 void *private_data)
978 remove_timed_out_clients();
979 if (tevent_add_timer(ev, ev,
980 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
981 winbindd_scrub_clients_handler, NULL) == NULL) {
982 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
983 exit(1);
987 struct winbindd_listen_state {
988 bool privileged;
989 int fd;
992 static void winbindd_listen_fde_handler(struct tevent_context *ev,
993 struct tevent_fd *fde,
994 uint16_t flags,
995 void *private_data)
997 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
998 struct winbindd_listen_state);
1000 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1001 DEBUG(5,("winbindd: Exceeding %d client "
1002 "connections, removing idle "
1003 "connection.\n", lp_winbind_max_clients()));
1004 if (!remove_idle_client()) {
1005 DEBUG(0,("winbindd: Exceeding %d "
1006 "client connections, no idle "
1007 "connection found\n",
1008 lp_winbind_max_clients()));
1009 break;
1012 remove_timed_out_clients();
1013 new_connection(s->fd, s->privileged);
1017 * Winbindd socket accessor functions
1020 static bool winbindd_setup_listeners(void)
1022 struct winbindd_listen_state *pub_state = NULL;
1023 struct winbindd_listen_state *priv_state = NULL;
1024 struct tevent_fd *fde;
1025 int rc;
1026 char *socket_path;
1028 pub_state = talloc(global_event_context(),
1029 struct winbindd_listen_state);
1030 if (!pub_state) {
1031 goto failed;
1034 pub_state->privileged = false;
1035 pub_state->fd = create_pipe_sock(
1036 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1037 if (pub_state->fd == -1) {
1038 goto failed;
1040 rc = listen(pub_state->fd, 5);
1041 if (rc < 0) {
1042 goto failed;
1045 fde = tevent_add_fd(global_event_context(), pub_state, pub_state->fd,
1046 TEVENT_FD_READ, winbindd_listen_fde_handler,
1047 pub_state);
1048 if (fde == NULL) {
1049 close(pub_state->fd);
1050 goto failed;
1052 tevent_fd_set_auto_close(fde);
1054 priv_state = talloc(global_event_context(),
1055 struct winbindd_listen_state);
1056 if (!priv_state) {
1057 goto failed;
1060 socket_path = get_winbind_priv_pipe_dir();
1061 if (socket_path == NULL) {
1062 goto failed;
1065 priv_state->privileged = true;
1066 priv_state->fd = create_pipe_sock(
1067 socket_path, WINBINDD_SOCKET_NAME, 0750);
1068 TALLOC_FREE(socket_path);
1069 if (priv_state->fd == -1) {
1070 goto failed;
1072 rc = listen(priv_state->fd, 5);
1073 if (rc < 0) {
1074 goto failed;
1077 fde = tevent_add_fd(global_event_context(), priv_state,
1078 priv_state->fd, TEVENT_FD_READ,
1079 winbindd_listen_fde_handler, priv_state);
1080 if (fde == NULL) {
1081 close(priv_state->fd);
1082 goto failed;
1084 tevent_fd_set_auto_close(fde);
1086 winbindd_scrub_clients_handler(global_event_context(), NULL,
1087 timeval_current(), NULL);
1088 return true;
1089 failed:
1090 TALLOC_FREE(pub_state);
1091 TALLOC_FREE(priv_state);
1092 return false;
1095 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1096 bool foreground)
1098 bool scan_trusts = true;
1099 NTSTATUS status;
1100 struct tevent_timer *te = NULL;
1102 /* Setup signal handlers */
1104 if (!winbindd_setup_sig_term_handler(true))
1105 exit(1);
1106 if (!winbindd_setup_stdin_handler(true, foreground))
1107 exit(1);
1108 if (!winbindd_setup_sig_hup_handler(NULL))
1109 exit(1);
1110 if (!winbindd_setup_sig_chld_handler())
1111 exit(1);
1112 if (!winbindd_setup_sig_usr2_handler())
1113 exit(1);
1115 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1118 * Ensure all cache and idmap caches are consistent
1119 * and initialized before we startup.
1121 if (!winbindd_cache_validate_and_initialize()) {
1122 exit(1);
1125 /* React on 'smbcontrol winbindd reload-config' in the same way
1126 as to SIGHUP signal */
1127 messaging_register(msg_ctx, NULL,
1128 MSG_SMB_CONF_UPDATED,
1129 winbindd_msg_reload_services_parent);
1130 messaging_register(msg_ctx, NULL,
1131 MSG_SHUTDOWN, msg_shutdown);
1133 /* Handle online/offline messages. */
1134 messaging_register(msg_ctx, NULL,
1135 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1136 messaging_register(msg_ctx, NULL,
1137 MSG_WINBIND_ONLINE, winbind_msg_online);
1138 messaging_register(msg_ctx, NULL,
1139 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1141 /* Handle domain online/offline messages for domains */
1142 messaging_register(global_messaging_context(), NULL,
1143 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1144 messaging_register(global_messaging_context(), NULL,
1145 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1147 messaging_register(msg_ctx, NULL,
1148 MSG_WINBIND_VALIDATE_CACHE,
1149 winbind_msg_validate_cache);
1151 messaging_register(msg_ctx, NULL,
1152 MSG_WINBIND_DUMP_DOMAIN_LIST,
1153 winbind_msg_dump_domain_list);
1155 messaging_register(msg_ctx, NULL,
1156 MSG_WINBIND_IP_DROPPED,
1157 winbind_msg_ip_dropped_parent);
1159 /* Register handler for MSG_DEBUG. */
1160 messaging_register(msg_ctx, NULL,
1161 MSG_DEBUG,
1162 winbind_msg_debug);
1164 messaging_register(msg_ctx, NULL,
1165 MSG_WINBIND_DISCONNECT_DC,
1166 winbind_disconnect_dc_parent);
1168 netsamlogon_cache_init(); /* Non-critical */
1170 /* clear the cached list of trusted domains */
1172 wcache_tdc_clear();
1174 if (!init_domain_list()) {
1175 DEBUG(0,("unable to initialize domain list\n"));
1176 exit(1);
1179 status = init_idmap_child(global_event_context());
1180 if (NT_STATUS_IS_ERR(status)) {
1181 DBG_ERR("Unable to start idmap child: %s\n", nt_errstr(status));
1182 exit(1);
1185 status = init_locator_child(global_event_context());
1186 if (NT_STATUS_IS_ERR(status)) {
1187 DBG_ERR("Unable to start locator child: %s\n", nt_errstr(status));
1188 exit(1);
1191 smb_nscd_flush_user_cache();
1192 smb_nscd_flush_group_cache();
1194 if (!lp_winbind_scan_trusted_domains()) {
1195 scan_trusts = false;
1198 if (!lp_allow_trusted_domains()) {
1199 scan_trusts = false;
1202 if (IS_DC) {
1203 scan_trusts = false;
1206 if (scan_trusts) {
1207 if (tevent_add_timer(global_event_context(), NULL, timeval_zero(),
1208 rescan_trusted_domains, NULL) == NULL) {
1209 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1210 exit(1);
1214 te = tevent_add_timer(global_event_context(),
1215 NULL,
1216 timeval_zero(),
1217 winbindd_ping_offline_domains,
1218 NULL);
1219 if (te == NULL) {
1220 DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
1221 exit(1);
1224 status = wb_irpc_register();
1226 if (!NT_STATUS_IS_OK(status)) {
1227 DEBUG(0, ("Could not register IRPC handlers\n"));
1228 exit(1);
1232 struct winbindd_addrchanged_state {
1233 struct addrchange_context *ctx;
1234 struct tevent_context *ev;
1235 struct messaging_context *msg_ctx;
1238 static void winbindd_addr_changed(struct tevent_req *req);
1240 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1241 struct tevent_context *ev,
1242 struct messaging_context *msg_ctx)
1244 struct winbindd_addrchanged_state *state;
1245 struct tevent_req *req;
1246 NTSTATUS status;
1248 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1249 if (state == NULL) {
1250 DEBUG(10, ("talloc failed\n"));
1251 return;
1253 state->ev = ev;
1254 state->msg_ctx = msg_ctx;
1256 status = addrchange_context_create(state, &state->ctx);
1257 if (!NT_STATUS_IS_OK(status)) {
1258 DEBUG(10, ("addrchange_context_create failed: %s\n",
1259 nt_errstr(status)));
1260 TALLOC_FREE(state);
1261 return;
1263 req = addrchange_send(state, ev, state->ctx);
1264 if (req == NULL) {
1265 DEBUG(0, ("addrchange_send failed\n"));
1266 TALLOC_FREE(state);
1267 return;
1269 tevent_req_set_callback(req, winbindd_addr_changed, state);
1272 static void winbindd_addr_changed(struct tevent_req *req)
1274 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1275 req, struct winbindd_addrchanged_state);
1276 enum addrchange_type type;
1277 struct sockaddr_storage addr;
1278 NTSTATUS status;
1280 status = addrchange_recv(req, &type, &addr, NULL);
1281 TALLOC_FREE(req);
1282 if (!NT_STATUS_IS_OK(status)) {
1283 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1284 nt_errstr(status)));
1285 TALLOC_FREE(state);
1286 return;
1288 if (type == ADDRCHANGE_DEL) {
1289 char addrstr[INET6_ADDRSTRLEN];
1290 DATA_BLOB blob;
1292 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1294 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1295 addrstr));
1297 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1299 status = messaging_send(state->msg_ctx,
1300 messaging_server_id(state->msg_ctx),
1301 MSG_WINBIND_IP_DROPPED, &blob);
1302 if (!NT_STATUS_IS_OK(status)) {
1303 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1304 nt_errstr(status)));
1307 req = addrchange_send(state, state->ev, state->ctx);
1308 if (req == NULL) {
1309 DEBUG(0, ("addrchange_send failed\n"));
1310 TALLOC_FREE(state);
1311 return;
1313 tevent_req_set_callback(req, winbindd_addr_changed, state);
1316 /* Main function */
1318 int main(int argc, const char **argv)
1320 static bool log_stdout = False;
1321 struct samba_cmdline_daemon_cfg *cmdline_daemon_cfg = NULL;
1322 struct poptOption long_options[] = {
1323 POPT_AUTOHELP
1325 .longName = "no-caching",
1326 .shortName = 'n',
1327 .argInfo = POPT_ARG_NONE,
1328 .arg = NULL,
1329 .val = 'n',
1330 .descrip = "Disable caching",
1332 POPT_COMMON_SAMBA
1333 POPT_COMMON_DAEMON
1334 POPT_COMMON_VERSION
1335 POPT_TABLEEND
1337 const struct loadparm_substitution *lp_sub =
1338 loadparm_s3_global_substitution();
1339 poptContext pc;
1340 int opt;
1341 TALLOC_CTX *frame;
1342 NTSTATUS status;
1343 bool ok;
1344 const struct dcesrv_endpoint_server *ep_server = NULL;
1345 struct dcesrv_context *dce_ctx = NULL;
1346 size_t winbindd_socket_dir_len = 0;
1347 char *winbindd_priv_socket_dir = NULL;
1348 size_t winbindd_priv_socket_dir_len = 0;
1350 setproctitle_init(argc, discard_const(argv), environ);
1353 * Do this before any other talloc operation
1355 talloc_enable_null_tracking();
1356 frame = talloc_stackframe();
1359 * We want total control over the permissions on created files,
1360 * so set our umask to 0.
1362 umask(0);
1364 smb_init_locale();
1366 /* glibc (?) likes to print "User defined signal 1" and exit if a
1367 SIGUSR[12] is received before a handler is installed */
1369 CatchSignal(SIGUSR1, SIG_IGN);
1370 CatchSignal(SIGUSR2, SIG_IGN);
1372 ok = samba_cmdline_init(frame,
1373 SAMBA_CMDLINE_CONFIG_SERVER,
1374 true /* require_smbconf */);
1375 if (!ok) {
1376 DBG_ERR("Failed to setup cmdline parser\n");
1377 TALLOC_FREE(frame);
1378 exit(1);
1381 cmdline_daemon_cfg = samba_cmdline_get_daemon_cfg();
1383 pc = samba_popt_get_context(getprogname(), argc, argv, long_options, 0);
1384 if (pc == NULL) {
1385 DBG_ERR("Failed to setup popt parser!\n");
1386 TALLOC_FREE(frame);
1387 exit(1);
1390 while ((opt = poptGetNextOpt(pc)) != -1) {
1391 switch (opt) {
1392 case 'n':
1393 winbindd_set_use_cache(false);
1394 break;
1395 default:
1396 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1397 poptBadOption(pc, 0), poptStrerror(opt));
1398 poptPrintUsage(pc, stderr, 0);
1399 exit(1);
1403 /* Set environment variable so we don't recursively call ourselves.
1404 This may also be useful interactively. */
1405 if ( !winbind_off() ) {
1406 DEBUG(0,("Failed to disable recursive winbindd calls. Exiting.\n"));
1407 exit(1);
1410 /* Initialise for running in non-root mode */
1411 sec_init();
1413 set_remote_machine_name("winbindd", False);
1415 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1416 if (cmdline_daemon_cfg->daemon && cmdline_daemon_cfg->interactive) {
1417 d_fprintf(stderr,"\nERROR: "
1418 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1419 poptPrintUsage(pc, stderr, 0);
1420 exit(1);
1423 log_stdout = (debug_get_log_type() == DEBUG_STDOUT);
1424 if (cmdline_daemon_cfg->interactive) {
1426 * libcmdline POPT_DAEMON callback sets "fork" to false if "-i"
1427 * for interactive is passed on the commandline. Set it back to
1428 * true. TODO: check if this is correct, smbd and nmbd don't do
1429 * this.
1431 cmdline_daemon_cfg->fork = true;
1432 log_stdout = true;
1435 if (log_stdout && cmdline_daemon_cfg->fork) {
1436 d_fprintf(stderr, "\nERROR: "
1437 "Can't log to stdout (-S) unless daemon is in "
1438 "foreground (-F) or interactive (-i)\n\n");
1439 poptPrintUsage(pc, stderr, 0);
1440 exit(1);
1443 poptFreeContext(pc);
1445 reopen_logs();
1447 DBG_STARTUP_NOTICE("winbindd version %s started.\n%s\n",
1448 samba_version_string(),
1449 samba_copyright_string());
1451 /* After parsing the configuration file we setup the core path one more time
1452 * as the log file might have been set in the configuration and cores's
1453 * path is by default basename(lp_logfile()).
1455 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1457 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1458 if (!lp_parm_bool(-1, "server role check", "inhibit", false)) {
1459 DBG_ERR("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n");
1460 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 exit(1);
1463 /* Main 'samba' daemon will notify */
1464 daemon_sd_notifications(false);
1467 if (lp_security() == SEC_ADS) {
1468 const char *realm = lp_realm();
1469 const char *workgroup = lp_workgroup();
1471 if (workgroup == NULL || strlen(workgroup) == 0) {
1472 DBG_ERR("For 'secuirity = ADS' mode, the 'workgroup' "
1473 "parameter is required to be set!\n");
1474 exit(1);
1477 if (realm == NULL || strlen(realm) == 0) {
1478 DBG_ERR("For 'secuirity = ADS' mode, the 'realm' "
1479 "parameter is required to be set!\n");
1480 exit(1);
1484 winbindd_socket_dir_len = strlen(lp_winbindd_socket_directory());
1485 if (winbindd_socket_dir_len > 0) {
1486 size_t winbindd_socket_len =
1487 winbindd_socket_dir_len + 1 +
1488 strlen(WINBINDD_SOCKET_NAME);
1489 struct sockaddr_un un = {
1490 .sun_family = AF_UNIX,
1492 size_t sun_path_len = sizeof(un.sun_path);
1494 if (winbindd_socket_len >= sun_path_len) {
1495 DBG_ERR("The winbind socket path [%s/%s] is too long "
1496 "(%zu >= %zu)\n",
1497 lp_winbindd_socket_directory(),
1498 WINBINDD_SOCKET_NAME,
1499 winbindd_socket_len,
1500 sun_path_len);
1501 exit(1);
1503 } else {
1504 DBG_ERR("'winbindd_socket_directory' parameter is empty\n");
1505 exit(1);
1508 winbindd_priv_socket_dir = get_winbind_priv_pipe_dir();
1509 winbindd_priv_socket_dir_len = strlen(winbindd_priv_socket_dir);
1510 if (winbindd_priv_socket_dir_len > 0) {
1511 size_t winbindd_priv_socket_len =
1512 winbindd_priv_socket_dir_len + 1 +
1513 strlen(WINBINDD_SOCKET_NAME);
1514 struct sockaddr_un un = {
1515 .sun_family = AF_UNIX,
1517 size_t sun_path_len = sizeof(un.sun_path);
1519 if (winbindd_priv_socket_len >= sun_path_len) {
1520 DBG_ERR("The winbind privileged socket path [%s/%s] is too long "
1521 "(%zu >= %zu)\n",
1522 winbindd_priv_socket_dir,
1523 WINBINDD_SOCKET_NAME,
1524 winbindd_priv_socket_len,
1525 sun_path_len);
1526 exit(1);
1528 } else {
1529 DBG_ERR("'winbindd_priv_socket_directory' parameter is empty\n");
1530 exit(1);
1532 TALLOC_FREE(winbindd_priv_socket_dir);
1534 if (!cluster_probe_ok()) {
1535 exit(1);
1538 /* Initialise messaging system */
1540 if (global_messaging_context() == NULL) {
1541 exit(1);
1544 if (!winbindd_reload_services_file(NULL)) {
1545 DEBUG(0, ("error opening config file\n"));
1546 exit(1);
1550 size_t i;
1551 const char *idmap_backend;
1552 const char *invalid_backends[] = {
1553 "ad", "rfc2307", "rid",
1556 idmap_backend = lp_idmap_default_backend();
1557 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1558 ok = strequal(idmap_backend, invalid_backends[i]);
1559 if (ok) {
1560 DBG_ERR("FATAL: Invalid idmap backend %s "
1561 "configured as the default backend!\n",
1562 idmap_backend);
1563 exit(1);
1568 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1569 if (!ok) {
1570 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1571 lp_lock_directory(), strerror(errno)));
1572 exit(1);
1575 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1576 if (!ok) {
1577 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1578 lp_pid_directory(), strerror(errno)));
1579 exit(1);
1582 load_interfaces();
1584 if (!secrets_init()) {
1586 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1587 return False;
1590 status = rpccli_pre_open_netlogon_creds();
1591 if (!NT_STATUS_IS_OK(status)) {
1592 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1593 nt_errstr(status)));
1594 exit(1);
1597 /* Unblock all signals we are interested in as they may have been
1598 blocked by the parent process. */
1600 BlockSignals(False, SIGINT);
1601 BlockSignals(False, SIGQUIT);
1602 BlockSignals(False, SIGTERM);
1603 BlockSignals(False, SIGUSR1);
1604 BlockSignals(False, SIGUSR2);
1605 BlockSignals(False, SIGHUP);
1606 BlockSignals(False, SIGCHLD);
1608 if (!interactive) {
1609 become_daemon(cmdline_daemon_cfg->fork,
1610 cmdline_daemon_cfg->no_process_group,
1611 log_stdout);
1612 } else {
1613 daemon_status("winbindd", "Starting process ...");
1616 pidfile_create(lp_pid_directory(), "winbindd");
1618 #ifdef HAVE_SETPGID
1620 * If we're interactive we want to set our own process group for
1621 * signal management.
1623 if (cmdline_daemon_cfg->interactive &&
1624 !cmdline_daemon_cfg->no_process_group)
1626 setpgid( (pid_t)0, (pid_t)0);
1628 #endif
1630 TimeInit();
1632 /* Don't use winbindd_reinit_after_fork here as
1633 * we're just starting up and haven't created any
1634 * winbindd-specific resources we must free yet. JRA.
1637 status = reinit_after_fork(global_messaging_context(),
1638 global_event_context(),
1639 false);
1640 if (!NT_STATUS_IS_OK(status)) {
1641 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1644 if (lp_winbind_debug_traceid()) {
1645 winbind_debug_traceid_setup(global_event_context());
1646 winbind_debug_call_depth_setup(debug_call_depth_addr());
1647 tevent_thread_call_depth_set_callback(
1648 debuglevel_get() > 1 ? winbind_call_flow : NULL,
1649 NULL);
1651 ok = initialize_password_db(true, global_event_context());
1652 if (!ok) {
1653 exit_daemon("Failed to initialize passdb backend! "
1654 "Check the 'passdb backend' variable in your "
1655 "smb.conf file.", EINVAL);
1659 * Do not initialize the parent-child-pipe before becoming
1660 * a daemon: this is used to detect a died parent in the child
1661 * process.
1663 status = init_before_fork();
1664 if (!NT_STATUS_IS_OK(status)) {
1665 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1668 winbindd_register_handlers(global_messaging_context(),
1669 !cmdline_daemon_cfg->fork);
1671 if (!messaging_parent_dgm_cleanup_init(global_messaging_context())) {
1672 exit(1);
1675 status = init_system_session_info(NULL);
1676 if (!NT_STATUS_IS_OK(status)) {
1677 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1680 DBG_INFO("Registering DCE/RPC endpoint servers\n");
1682 ep_server = winbind_get_ep_server();
1683 if (ep_server == NULL) {
1684 DBG_ERR("Failed to get 'winbind' endpoint server\n");
1685 exit(1);
1687 status = dcerpc_register_ep_server(ep_server);
1688 if (!NT_STATUS_IS_OK(status)) {
1689 DBG_ERR("Failed to register 'winbind' endpoint "
1690 "server: %s\n", nt_errstr(status));
1691 exit(1);
1694 dce_ctx = global_dcesrv_context();
1696 DBG_INFO("Initializing DCE/RPC registered endpoint servers\n");
1698 /* Init all registered ep servers */
1699 status = dcesrv_init_registered_ep_servers(dce_ctx);
1700 if (!NT_STATUS_IS_OK(status)) {
1701 DBG_ERR("Failed to init DCE/RPC endpoint servers: %s\n",
1702 nt_errstr(status));
1703 exit(1);
1706 winbindd_init_addrchange(NULL, global_event_context(),
1707 global_messaging_context());
1709 /* setup listen sockets */
1711 if (!winbindd_setup_listeners()) {
1712 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1715 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1717 TALLOC_FREE(frame);
1719 if (!interactive) {
1720 daemon_ready("winbindd");
1723 gpupdate_init();
1725 /* Loop waiting for requests */
1726 while (1) {
1727 frame = talloc_stackframe();
1729 if (tevent_loop_once(global_event_context()) == -1) {
1730 DEBUG(1, ("tevent_loop_once() failed: %s\n",
1731 strerror(errno)));
1732 return 1;
1735 TALLOC_FREE(frame);
1738 return 0;