1 /*
2 Unix SMB/CIFS implementation.
3
4 Winbind daemon for ntdom nss module
5
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
10
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.
15
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.
20
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/>.
23 */
24
25 #include "includes.h"
26 #include "popt_common.h"
27 #include "winbindd.h"
28 #include "nsswitch/winbind_client.h"
29 #include "nsswitch/wb_reqtrans.h"
30 #include "ntdomain.h"
31 #include "../librpc/gen_ndr/srv_lsa.h"
32 #include "../librpc/gen_ndr/srv_samr.h"
33 #include "secrets.h"
34 #include "rpc_client/cli_netlogon.h"
35 #include "idmap.h"
36 #include "lib/addrchange.h"
37 #include "auth.h"
38 #include "messages.h"
39 #include "../lib/util/pidfile.h"
40 #include "util_cluster.h"
41 #include "source4/lib/messaging/irpc.h"
42 #include "source4/lib/messaging/messaging.h"
43 #include "lib/param/param.h"
44 #include "lib/async_req/async_sock.h"
45 #include "libsmb/samlogon_cache.h"
46 #include "libcli/auth/netlogon_creds_cli.h"
47 #include "passdb.h"
48 #include "lib/util/tevent_req_profile.h"
49 #include "lib/gencache.h"
50
51 #undef DBGC_CLASS
52 #define DBGC_CLASS DBGC_WINBIND
53
54 #define SCRUB_CLIENTS_INTERVAL 5
55
56 static bool client_is_idle(struct winbindd_cli_state *state);
57 static void remove_client(struct winbindd_cli_state *state);
58 static void winbindd_setup_max_fds(void);
59
60 static bool opt_nocache = False;
61 static bool interactive = False;
62
63 extern bool override_logfile;
64
winbind_imessaging_context(void)65 struct imessaging_context *winbind_imessaging_context(void)
66 {
67 static struct imessaging_context *msg = NULL;
68 struct messaging_context *msg_ctx;
69 struct server_id myself;
70 struct loadparm_context *lp_ctx;
71
72 if (msg != NULL) {
73 return msg;
74 }
75
76 msg_ctx = global_messaging_context();
77 if (msg_ctx == NULL) {
78 smb_panic("global_messaging_context failed\n");
79 }
80 myself = messaging_server_id(msg_ctx);
81
82 lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
83 if (lp_ctx == NULL) {
84 smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
85 }
86
87 /*
88 * Note we MUST use the NULL context here, not the autofree context,
89 * to avoid side effects in forked children exiting.
90 */
91 msg = imessaging_init(NULL, lp_ctx, myself, global_event_context());
92 talloc_unlink(NULL, lp_ctx);
93
94 if (msg == NULL) {
95 smb_panic("Could not init winbindd's messaging context.\n");
96 }
97 return msg;
98 }
99
100 /* Reload configuration */
101
winbindd_reload_services_file(const char * lfile)102 bool winbindd_reload_services_file(const char *lfile)
103 {
104 const struct loadparm_substitution *lp_sub =
105 loadparm_s3_global_substitution();
106 bool ret;
107
108 if (lp_loaded()) {
109 char *fname = lp_next_configfile(talloc_tos(), lp_sub);
110
111 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
112 set_dyn_CONFIGFILE(fname);
113 }
114 TALLOC_FREE(fname);
115 }
116
117 reopen_logs();
118 ret = lp_load_global(get_dyn_CONFIGFILE());
119
120 /* if this is a child, restore the logfile to the special
121 name - <domain>, idmap, etc. */
122 if (lfile && *lfile) {
123 lp_set_logfile(lfile);
124 }
125
126 reopen_logs();
127 load_interfaces();
128 winbindd_setup_max_fds();
129
130 return(ret);
131 }
132
133
winbindd_status(void)134 static void winbindd_status(void)
135 {
136 struct winbindd_cli_state *tmp;
137
138 DEBUG(0, ("winbindd status:\n"));
139
140 /* Print client state information */
141
142 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
143
144 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
145 DEBUG(2, ("\tclient list:\n"));
146 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
147 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
148 (unsigned long)tmp->pid, tmp->sock,
149 client_is_idle(tmp) ? "idle" : "active"));
150 }
151 }
152 }
153
154 /* Flush client cache */
155
winbindd_flush_caches(void)156 void winbindd_flush_caches(void)
157 {
158 /* We need to invalidate cached user list entries on a SIGHUP
159 otherwise cached access denied errors due to restrict anonymous
160 hang around until the sequence number changes. */
161
162 if (!wcache_invalidate_cache()) {
163 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
164 if (!winbindd_cache_validate_and_initialize()) {
165 exit(1);
166 }
167 }
168 }
169
flush_caches_noinit(void)170 static void flush_caches_noinit(void)
171 {
172 /*
173 * We need to invalidate cached user list entries on a SIGHUP
174 * otherwise cached access denied errors due to restrict anonymous
175 * hang around until the sequence number changes.
176 * NB
177 * Skip uninitialized domains when flush cache.
178 * If domain is not initialized, it means it is never
179 * used or never become online. look, wcache_invalidate_cache()
180 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
181 * for unused domains and large traffic for primay domain's DC if there
182 * are many domains..
183 */
184
185 if (!wcache_invalidate_cache_noinit()) {
186 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
187 if (!winbindd_cache_validate_and_initialize()) {
188 exit(1);
189 }
190 }
191 }
192
193 /* Handle the signal by unlinking socket and exiting */
194
terminate(bool is_parent)195 static void terminate(bool is_parent)
196 {
197 if (is_parent) {
198 /* When parent goes away we should
199 * remove the socket file. Not so
200 * when children terminate.
201 */
202 char *path = NULL;
203
204 if (asprintf(&path, "%s/%s",
205 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) {
206 unlink(path);
207 SAFE_FREE(path);
208 }
209 }
210
211 idmap_close();
212
213 netlogon_creds_cli_close_global_db();
214
215 #if 0
216 if (interactive) {
217 TALLOC_CTX *mem_ctx = talloc_init("end_description");
218 char *description = talloc_describe_all(mem_ctx);
219
220 DEBUG(3, ("tallocs left:\n%s\n", description));
221 talloc_destroy(mem_ctx);
222 }
223 #endif
224
225 if (is_parent) {
226 pidfile_unlink(lp_pid_directory(), "winbindd");
227 }
228
229 exit(0);
230 }
231
winbindd_sig_term_handler(struct tevent_context * ev,struct tevent_signal * se,int signum,int count,void * siginfo,void * private_data)232 static void winbindd_sig_term_handler(struct tevent_context *ev,
233 struct tevent_signal *se,
234 int signum,
235 int count,
236 void *siginfo,
237 void *private_data)
238 {
239 bool *p = talloc_get_type_abort(private_data, bool);
240 bool is_parent = *p;
241
242 TALLOC_FREE(p);
243
244 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
245 signum, is_parent));
246 terminate(is_parent);
247 }
248
249 /*
250 handle stdin becoming readable when we are in --foreground mode
251 */
winbindd_stdin_handler(struct tevent_context * ev,struct tevent_fd * fde,uint16_t flags,void * private_data)252 static void winbindd_stdin_handler(struct tevent_context *ev,
253 struct tevent_fd *fde,
254 uint16_t flags,
255 void *private_data)
256 {
257 char c;
258 if (read(0, &c, 1) != 1) {
259 bool *is_parent = talloc_get_type_abort(private_data, bool);
260
261 /* we have reached EOF on stdin, which means the
262 parent has exited. Shutdown the server */
263 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
264 (int)*is_parent));
265 terminate(*is_parent);
266 }
267 }
268
winbindd_setup_sig_term_handler(bool parent)269 bool winbindd_setup_sig_term_handler(bool parent)
270 {
271 struct tevent_signal *se;
272 bool *is_parent;
273
274 is_parent = talloc(global_event_context(), bool);
275 if (!is_parent) {
276 return false;
277 }
278
279 *is_parent = parent;
280
281 se = tevent_add_signal(global_event_context(),
282 is_parent,
283 SIGTERM, 0,
284 winbindd_sig_term_handler,
285 is_parent);
286 if (!se) {
287 DEBUG(0,("failed to setup SIGTERM handler"));
288 talloc_free(is_parent);
289 return false;
290 }
291
292 se = tevent_add_signal(global_event_context(),
293 is_parent,
294 SIGINT, 0,
295 winbindd_sig_term_handler,
296 is_parent);
297 if (!se) {
298 DEBUG(0,("failed to setup SIGINT handler"));
299 talloc_free(is_parent);
300 return false;
301 }
302
303 se = tevent_add_signal(global_event_context(),
304 is_parent,
305 SIGQUIT, 0,
306 winbindd_sig_term_handler,
307 is_parent);
308 if (!se) {
309 DEBUG(0,("failed to setup SIGINT handler"));
310 talloc_free(is_parent);
311 return false;
312 }
313
314 return true;
315 }
316
winbindd_setup_stdin_handler(bool parent,bool foreground)317 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
318 {
319 bool *is_parent;
320
321 if (foreground) {
322 struct stat st;
323
324 is_parent = talloc(global_event_context(), bool);
325 if (!is_parent) {
326 return false;
327 }
328
329 *is_parent = parent;
330
331 /* if we are running in the foreground then look for
332 EOF on stdin, and exit if it happens. This allows
333 us to die if the parent process dies
334 Only do this on a pipe or socket, no other device.
335 */
336 if (fstat(0, &st) != 0) {
337 return false;
338 }
339 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
340 tevent_add_fd(global_event_context(),
341 is_parent,
342 0,
343 TEVENT_FD_READ,
344 winbindd_stdin_handler,
345 is_parent);
346 }
347 }
348
349 return true;
350 }
351
winbindd_sig_hup_handler(struct tevent_context * ev,struct tevent_signal * se,int signum,int count,void * siginfo,void * private_data)352 static void winbindd_sig_hup_handler(struct tevent_context *ev,
353 struct tevent_signal *se,
354 int signum,
355 int count,
356 void *siginfo,
357 void *private_data)
358 {
359 const char *file = (const char *)private_data;
360
361 DEBUG(1,("Reloading services after SIGHUP\n"));
362 flush_caches_noinit();
363 winbindd_reload_services_file(file);
364 }
365
winbindd_setup_sig_hup_handler(const char * lfile)366 bool winbindd_setup_sig_hup_handler(const char *lfile)
367 {
368 struct tevent_signal *se;
369 char *file = NULL;
370
371 if (lfile) {
372 file = talloc_strdup(global_event_context(),
373 lfile);
374 if (!file) {
375 return false;
376 }
377 }
378
379 se = tevent_add_signal(global_event_context(),
380 global_event_context(),
381 SIGHUP, 0,
382 winbindd_sig_hup_handler,
383 file);
384 if (!se) {
385 return false;
386 }
387
388 return true;
389 }
390
winbindd_sig_chld_handler(struct tevent_context * ev,struct tevent_signal * se,int signum,int count,void * siginfo,void * private_data)391 static void winbindd_sig_chld_handler(struct tevent_context *ev,
392 struct tevent_signal *se,
393 int signum,
394 int count,
395 void *siginfo,
396 void *private_data)
397 {
398 pid_t pid;
399
400 while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
401 winbind_child_died(pid);
402 }
403 }
404
winbindd_setup_sig_chld_handler(void)405 static bool winbindd_setup_sig_chld_handler(void)
406 {
407 struct tevent_signal *se;
408
409 se = tevent_add_signal(global_event_context(),
410 global_event_context(),
411 SIGCHLD, 0,
412 winbindd_sig_chld_handler,
413 NULL);
414 if (!se) {
415 return false;
416 }
417
418 return true;
419 }
420
winbindd_sig_usr2_handler(struct tevent_context * ev,struct tevent_signal * se,int signum,int count,void * siginfo,void * private_data)421 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
422 struct tevent_signal *se,
423 int signum,
424 int count,
425 void *siginfo,
426 void *private_data)
427 {
428 winbindd_status();
429 }
430
winbindd_setup_sig_usr2_handler(void)431 static bool winbindd_setup_sig_usr2_handler(void)
432 {
433 struct tevent_signal *se;
434
435 se = tevent_add_signal(global_event_context(),
436 global_event_context(),
437 SIGUSR2, 0,
438 winbindd_sig_usr2_handler,
439 NULL);
440 if (!se) {
441 return false;
442 }
443
444 return true;
445 }
446
447 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
msg_shutdown(struct messaging_context * msg,void * private_data,uint32_t msg_type,struct server_id server_id,DATA_BLOB * data)448 static void msg_shutdown(struct messaging_context *msg,
449 void *private_data,
450 uint32_t msg_type,
451 struct server_id server_id,
452 DATA_BLOB *data)
453 {
454 /* only the parent waits for this message */
455 DEBUG(0,("Got shutdown message\n"));
456 terminate(true);
457 }
458
459
winbind_msg_validate_cache(struct messaging_context * msg_ctx,void * private_data,uint32_t msg_type,struct server_id server_id,DATA_BLOB * data)460 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
461 void *private_data,
462 uint32_t msg_type,
463 struct server_id server_id,
464 DATA_BLOB *data)
465 {
466 uint8_t ret;
467 pid_t child_pid;
468 NTSTATUS status;
469
470 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
471 "message.\n"));
472
473 /*
474 * call the validation code from a child:
475 * so we don't block the main winbindd and the validation
476 * code can safely use fork/waitpid...
477 */
478 child_pid = fork();
479
480 if (child_pid == -1) {
481 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
482 strerror(errno)));
483 return;
484 }
485
486 if (child_pid != 0) {
487 /* parent */
488 DEBUG(5, ("winbind_msg_validate_cache: child created with "
489 "pid %d.\n", (int)child_pid));
490 return;
491 }
492
493 /* child */
494
495 status = winbindd_reinit_after_fork(NULL, NULL);
496 if (!NT_STATUS_IS_OK(status)) {
497 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
498 nt_errstr(status)));
499 _exit(0);
500 }
501
502 /* install default SIGCHLD handler: validation code uses fork/waitpid */
503 CatchSignal(SIGCHLD, SIG_DFL);
504
505 setproctitle("validate cache child");
506
507 ret = (uint8_t)winbindd_validate_cache_nobackup();
508 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
509 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
510 (size_t)1);
511 _exit(0);
512 }
513
514 static struct winbindd_bool_dispatch_table {
515 enum winbindd_cmd cmd;
516 bool (*fn)(struct winbindd_cli_state *state);
517 const char *cmd_name;
518 } bool_dispatch_table[] = {
519 { WINBINDD_INTERFACE_VERSION,
520 winbindd_interface_version,
521 "INTERFACE_VERSION" },
522 { WINBINDD_INFO,
523 winbindd_info,
524 "INFO" },
525 { WINBINDD_PING,
526 winbindd_ping,
527 "PING" },
528 { WINBINDD_DOMAIN_NAME,
529 winbindd_domain_name,
530 "DOMAIN_NAME" },
531 { WINBINDD_NETBIOS_NAME,
532 winbindd_netbios_name,
533 "NETBIOS_NAME" },
534 { WINBINDD_DC_INFO,
535 winbindd_dc_info,
536 "DC_INFO" },
537 { WINBINDD_CCACHE_NTLMAUTH,
538 winbindd_ccache_ntlm_auth,
539 "NTLMAUTH" },
540 { WINBINDD_CCACHE_SAVE,
541 winbindd_ccache_save,
542 "CCACHE_SAVE" },
543 { WINBINDD_PRIV_PIPE_DIR,
544 winbindd_priv_pipe_dir,
545 "WINBINDD_PRIV_PIPE_DIR" },
546 { WINBINDD_LIST_TRUSTDOM,
547 winbindd_list_trusted_domains,
548 "LIST_TRUSTDOM" },
549 };
550
551 struct winbindd_async_dispatch_table {
552 enum winbindd_cmd cmd;
553 const char *cmd_name;
554 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
555 struct tevent_context *ev,
556 struct winbindd_cli_state *cli,
557 struct winbindd_request *request);
558 NTSTATUS (*recv_req)(struct tevent_req *req,
559 struct winbindd_response *presp);
560 };
561
562 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
563 { WINBINDD_LOOKUPSID, "LOOKUPSID",
564 winbindd_lookupsid_send, winbindd_lookupsid_recv },
565 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
566 winbindd_lookupsids_send, winbindd_lookupsids_recv },
567 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
568 winbindd_lookupname_send, winbindd_lookupname_recv },
569 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
570 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
571 { WINBINDD_XIDS_TO_SIDS, "XIDS_TO_SIDS",
572 winbindd_xids_to_sids_send, winbindd_xids_to_sids_recv },
573 { WINBINDD_GETPWSID, "GETPWSID",
574 winbindd_getpwsid_send, winbindd_getpwsid_recv },
575 { WINBINDD_GETPWNAM, "GETPWNAM",
576 winbindd_getpwnam_send, winbindd_getpwnam_recv },
577 { WINBINDD_GETPWUID, "GETPWUID",
578 winbindd_getpwuid_send, winbindd_getpwuid_recv },
579 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
580 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
581 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
582 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
583 { WINBINDD_GETGROUPS, "GETGROUPS",
584 winbindd_getgroups_send, winbindd_getgroups_recv },
585 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
586 winbindd_show_sequence_send, winbindd_show_sequence_recv },
587 { WINBINDD_GETGRGID, "GETGRGID",
588 winbindd_getgrgid_send, winbindd_getgrgid_recv },
589 { WINBINDD_GETGRNAM, "GETGRNAM",
590 winbindd_getgrnam_send, winbindd_getgrnam_recv },
591 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
592 winbindd_getusersids_send, winbindd_getusersids_recv },
593 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
594 winbindd_lookuprids_send, winbindd_lookuprids_recv },
595 { WINBINDD_SETPWENT, "SETPWENT",
596 winbindd_setpwent_send, winbindd_setpwent_recv },
597 { WINBINDD_GETPWENT, "GETPWENT",
598 winbindd_getpwent_send, winbindd_getpwent_recv },
599 { WINBINDD_ENDPWENT, "ENDPWENT",
600 winbindd_endpwent_send, winbindd_endpwent_recv },
601 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
602 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
603 { WINBINDD_GETDCNAME, "GETDCNAME",
604 winbindd_getdcname_send, winbindd_getdcname_recv },
605 { WINBINDD_SETGRENT, "SETGRENT",
606 winbindd_setgrent_send, winbindd_setgrent_recv },
607 { WINBINDD_GETGRENT, "GETGRENT",
608 winbindd_getgrent_send, winbindd_getgrent_recv },
609 { WINBINDD_ENDGRENT, "ENDGRENT",
610 winbindd_endgrent_send, winbindd_endgrent_recv },
611 { WINBINDD_LIST_USERS, "LIST_USERS",
612 winbindd_list_users_send, winbindd_list_users_recv },
613 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
614 winbindd_list_groups_send, winbindd_list_groups_recv },
615 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
616 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
617 { WINBINDD_PING_DC, "PING_DC",
618 winbindd_ping_dc_send, winbindd_ping_dc_recv },
619 { WINBINDD_PAM_AUTH, "PAM_AUTH",
620 winbindd_pam_auth_send, winbindd_pam_auth_recv },
621 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
622 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
623 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
624 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
625 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
626 winbindd_pam_chng_pswd_auth_crap_send,
627 winbindd_pam_chng_pswd_auth_crap_recv },
628 { WINBINDD_WINS_BYIP, "WINS_BYIP",
629 winbindd_wins_byip_send, winbindd_wins_byip_recv },
630 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
631 winbindd_wins_byname_send, winbindd_wins_byname_recv },
632 { WINBINDD_DOMAIN_INFO, "DOMAIN_INFO",
633 winbindd_domain_info_send, winbindd_domain_info_recv },
634
635 { 0, NULL, NULL, NULL }
636 };
637
638 static struct winbindd_async_dispatch_table async_priv_table[] = {
639 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
640 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
641 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
642 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
643 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
644 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
645 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
646 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
647
648 { 0, NULL, NULL, NULL }
649 };
650
651 struct process_request_state {
652 struct winbindd_cli_state *cli_state;
653 struct tevent_context *ev;
654 };
655
656 static void process_request_done(struct tevent_req *subreq);
657 static void process_request_written(struct tevent_req *subreq);
658
process_request_send(TALLOC_CTX * mem_ctx,struct tevent_context * ev,struct winbindd_cli_state * cli_state)659 static struct tevent_req *process_request_send(
660 TALLOC_CTX *mem_ctx,
661 struct tevent_context *ev,
662 struct winbindd_cli_state *cli_state)
663 {
664 struct tevent_req *req, *subreq;
665 struct process_request_state *state;
666 struct winbindd_async_dispatch_table *atable;
667 enum winbindd_cmd cmd = cli_state->request->cmd;
668 size_t i;
669 bool ok;
670
671 req = tevent_req_create(mem_ctx, &state,
672 struct process_request_state);
673 if (req == NULL) {
674 return NULL;
675 }
676 state->cli_state = cli_state;
677 state->ev = ev;
678
679 ok = tevent_req_set_profile(req);
680 if (!ok) {
681 return tevent_req_post(req, ev);
682 }
683
684 SMB_ASSERT(cli_state->mem_ctx == NULL);
685 cli_state->mem_ctx = talloc_named(cli_state, 0, "winbind request");
686 if (tevent_req_nomem(cli_state->mem_ctx, req)) {
687 return tevent_req_post(req, ev);
688 }
689
690 cli_state->response = talloc_zero(
691 cli_state->mem_ctx,
692 struct winbindd_response);
693 if (tevent_req_nomem(cli_state->response, req)) {
694 return tevent_req_post(req, ev);
695 }
696 cli_state->response->result = WINBINDD_PENDING;
697 cli_state->response->length = sizeof(struct winbindd_response);
698
699 /* Remember who asked us. */
700 cli_state->pid = cli_state->request->pid;
701 memcpy(cli_state->client_name,
702 cli_state->request->client_name,
703 sizeof(cli_state->client_name));
704
705 cli_state->cmd_name = "unknown request";
706 cli_state->recv_fn = NULL;
707
708 /* client is newest */
709 winbindd_promote_client(cli_state);
710
711 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
712 if (cmd == atable->cmd) {
713 break;
714 }
715 }
716
717 if ((atable->send_req == NULL) && cli_state->privileged) {
718 for (atable = async_priv_table; atable->send_req;
719 atable += 1) {
720 if (cmd == atable->cmd) {
721 break;
722 }
723 }
724 }
725
726 if (atable->send_req != NULL) {
727 cli_state->cmd_name = atable->cmd_name;
728 cli_state->recv_fn = atable->recv_req;
729
730 DBG_DEBUG("process_request: "
731 "Handling async request %s(%d):%s\n",
732 cli_state->client_name,
733 (int)cli_state->pid,
734 cli_state->cmd_name);
735
736 subreq = atable->send_req(
737 state,
738 state->ev,
739 cli_state,
740 cli_state->request);
741 if (tevent_req_nomem(subreq, req)) {
742 return tevent_req_post(req, ev);
743 }
744 tevent_req_set_callback(subreq, process_request_done, req);
745 return req;
746 }
747
748 for (i=0; i<ARRAY_SIZE(bool_dispatch_table); i++) {
749 if (cmd == bool_dispatch_table[i].cmd) {
750 break;
751 }
752 }
753
754 ok = false;
755
756 if (i < ARRAY_SIZE(bool_dispatch_table)) {
757 cli_state->cmd_name = bool_dispatch_table[i].cmd_name;
758
759 DBG_DEBUG("process_request: request fn %s\n",
760 bool_dispatch_table[i].cmd_name);
761 ok = bool_dispatch_table[i].fn(cli_state);
762 }
763
764 cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
765
766 TALLOC_FREE(cli_state->io_req);
767 TALLOC_FREE(cli_state->request);
768
769 subreq = wb_resp_write_send(
770 state,
771 state->ev,
772 cli_state->out_queue,
773 cli_state->sock,
774 cli_state->response);
775 if (tevent_req_nomem(subreq, req)) {
776 return tevent_req_post(req, ev);
777 }
778 tevent_req_set_callback(subreq, process_request_written, req);
779
780 cli_state->io_req = subreq;
781
782 return req;
783 }
784
process_request_done(struct tevent_req * subreq)785 static void process_request_done(struct tevent_req *subreq)
786 {
787 struct tevent_req *req = tevent_req_callback_data(
788 subreq, struct tevent_req);
789 struct process_request_state *state = tevent_req_data(
790 req, struct process_request_state);
791 struct winbindd_cli_state *cli_state = state->cli_state;
792 NTSTATUS status;
793 bool ok;
794
795 status = cli_state->recv_fn(subreq, cli_state->response);
796 TALLOC_FREE(subreq);
797
798 DBG_DEBUG("[%s(%d):%s]: %s\n",
799 cli_state->client_name,
800 (int)cli_state->pid,
801 cli_state->cmd_name,
802 nt_errstr(status));
803
804 ok = NT_STATUS_IS_OK(status);
805 cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
806
807 TALLOC_FREE(cli_state->io_req);
808 TALLOC_FREE(cli_state->request);
809
810 subreq = wb_resp_write_send(
811 state,
812 state->ev,
813 cli_state->out_queue,
814 cli_state->sock,
815 cli_state->response);
816 if (tevent_req_nomem(subreq, req)) {
817 return;
818 }
819 tevent_req_set_callback(subreq, process_request_written, req);
820
821 cli_state->io_req = subreq;
822 }
823
process_request_written(struct tevent_req * subreq)824 static void process_request_written(struct tevent_req *subreq)
825 {
826 struct tevent_req *req = tevent_req_callback_data(
827 subreq, struct tevent_req);
828 struct process_request_state *state = tevent_req_data(
829 req, struct process_request_state);
830 struct winbindd_cli_state *cli_state = state->cli_state;
831 ssize_t ret;
832 int err;
833
834 cli_state->io_req = NULL;
835
836 ret = wb_resp_write_recv(subreq, &err);
837 TALLOC_FREE(subreq);
838 if (ret == -1) {
839 tevent_req_nterror(req, map_nt_error_from_unix(err));
840 return;
841 }
842
843 DBG_DEBUG("[%s(%d):%s]: delivered response to client\n",
844 cli_state->client_name,
845 (int)cli_state->pid,
846 cli_state->cmd_name);
847
848 TALLOC_FREE(cli_state->mem_ctx);
849 cli_state->response = NULL;
850 cli_state->cmd_name = "no request";
851 cli_state->recv_fn = NULL;
852
853 tevent_req_done(req);
854 }
855
process_request_recv(struct tevent_req * req,TALLOC_CTX * mem_ctx,struct tevent_req_profile ** profile)856 static NTSTATUS process_request_recv(
857 struct tevent_req *req,
858 TALLOC_CTX *mem_ctx,
859 struct tevent_req_profile **profile)
860 {
861 NTSTATUS status;
862
863 if (tevent_req_is_nterror(req, &status)) {
864 tevent_req_received(req);
865 return status;
866 }
867
868 *profile = tevent_req_move_profile(req, mem_ctx);
869 tevent_req_received(req);
870 return NT_STATUS_OK;
871 }
872
873 /*
874 * This is the main event loop of winbind requests. It goes through a
875 * state-machine of 3 read/write requests, 4 if you have extra data to send.
876 *
877 * An idle winbind client has a read request of 4 bytes outstanding,
878 * finalizing function is request_len_recv, checking the length. request_recv
879 * then processes the packet. The processing function then at some point has
880 * to call request_finished which schedules sending the response.
881 */
882
883 static void winbind_client_request_read(struct tevent_req *req);
884 static void winbind_client_activity(struct tevent_req *req);
885 static void winbind_client_processed(struct tevent_req *req);
886
887 /* Process a new connection by adding it to the client connection list */
888
new_connection(int listen_sock,bool privileged)889 static void new_connection(int listen_sock, bool privileged)
890 {
891 struct sockaddr_un sunaddr;
892 struct winbindd_cli_state *state;
893 struct tevent_req *req;
894 socklen_t len;
895 int sock;
896
897 /* Accept connection */
898
899 len = sizeof(sunaddr);
900
901 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
902
903 if (sock == -1) {
904 if (errno != EINTR) {
905 DEBUG(0, ("Failed to accept socket - %s\n",
906 strerror(errno)));
907 }
908 return;
909 }
910 smb_set_close_on_exec(sock);
911
912 DEBUG(6,("accepted socket %d\n", sock));
913
914 /* Create new connection structure */
915
916 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
917 close(sock);
918 return;
919 }
920
921 state->sock = sock;
922
923 state->out_queue = tevent_queue_create(state, "winbind client reply");
924 if (state->out_queue == NULL) {
925 close(sock);
926 TALLOC_FREE(state);
927 return;
928 }
929
930 state->privileged = privileged;
931
932 req = wb_req_read_send(state, global_event_context(), state->sock,
933 WINBINDD_MAX_EXTRA_DATA);
934 if (req == NULL) {
935 TALLOC_FREE(state);
936 close(sock);
937 return;
938 }
939 tevent_req_set_callback(req, winbind_client_request_read, state);
940 state->io_req = req;
941
942 /* Add to connection list */
943
944 winbindd_add_client(state);
945 }
946
winbind_client_request_read(struct tevent_req * req)947 static void winbind_client_request_read(struct tevent_req *req)
948 {
949 struct winbindd_cli_state *state = tevent_req_callback_data(
950 req, struct winbindd_cli_state);
951 ssize_t ret;
952 int err;
953
954 state->io_req = NULL;
955
956 ret = wb_req_read_recv(req, state, &state->request, &err);
957 TALLOC_FREE(req);
958 if (ret == -1) {
959 if (err == EPIPE) {
960 DEBUG(6, ("closing socket %d, client exited\n",
961 state->sock));
962 } else {
963 DEBUG(2, ("Could not read client request from fd %d: "
964 "%s\n", state->sock, strerror(err)));
965 }
966 close(state->sock);
967 state->sock = -1;
968 remove_client(state);
969 return;
970 }
971
972 req = wait_for_read_send(state, global_event_context(), state->sock,
973 true);
974 if (req == NULL) {
975 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
976 " wait_for_read_send failed - removing client\n",
977 (int)state->pid, state->cmd_name));
978 remove_client(state);
979 return;
980 }
981 tevent_req_set_callback(req, winbind_client_activity, state);
982 state->io_req = req;
983
984 req = process_request_send(state, global_event_context(), state);
985 if (req == NULL) {
986 DBG_ERR("process_request_send failed\n");
987 remove_client(state);
988 return;
989 }
990 tevent_req_set_callback(req, winbind_client_processed, state);
991 }
992
winbind_client_activity(struct tevent_req * req)993 static void winbind_client_activity(struct tevent_req *req)
994 {
995 struct winbindd_cli_state *state =
996 tevent_req_callback_data(req, struct winbindd_cli_state);
997 int err;
998 bool has_data;
999
1000 has_data = wait_for_read_recv(req, &err);
1001
1002 if (has_data) {
1003 DEBUG(0, ("winbind_client_activity[%d:%s]:"
1004 "unexpected data from client - removing client\n",
1005 (int)state->pid, state->cmd_name));
1006 } else {
1007 if (err == EPIPE) {
1008 DEBUG(6, ("winbind_client_activity[%d:%s]: "
1009 "client has closed connection - removing "
1010 "client\n",
1011 (int)state->pid, state->cmd_name));
1012 } else {
1013 DEBUG(2, ("winbind_client_activity[%d:%s]: "
1014 "client socket error (%s) - removing "
1015 "client\n",
1016 (int)state->pid, state->cmd_name,
1017 strerror(err)));
1018 }
1019 }
1020
1021 remove_client(state);
1022 }
1023
winbind_client_processed(struct tevent_req * req)1024 static void winbind_client_processed(struct tevent_req *req)
1025 {
1026 struct winbindd_cli_state *cli_state = tevent_req_callback_data(
1027 req, struct winbindd_cli_state);
1028 struct tevent_req_profile *profile = NULL;
1029 struct timeval start, stop, diff;
1030 int threshold;
1031 NTSTATUS status;
1032
1033 status = process_request_recv(req, cli_state, &profile);
1034 TALLOC_FREE(req);
1035 if (!NT_STATUS_IS_OK(status)) {
1036 DBG_DEBUG("process_request failed: %s\n", nt_errstr(status));
1037 remove_client(cli_state);
1038 return;
1039 }
1040
1041 tevent_req_profile_get_start(profile, NULL, &start);
1042 tevent_req_profile_get_stop(profile, NULL, &stop);
1043 diff = tevent_timeval_until(&start, &stop);
1044
1045 threshold = lp_parm_int(-1, "winbind", "request profile threshold", 60);
1046
1047 if (diff.tv_sec >= threshold) {
1048 int depth;
1049 char *str;
1050
1051 depth = lp_parm_int(
1052 -1,
1053 "winbind",
1054 "request profile depth",
1055 INT_MAX);
1056
1057 DBG_ERR("request took %u.%.6u seconds\n",
1058 (unsigned)diff.tv_sec, (unsigned)diff.tv_usec);
1059
1060 str = tevent_req_profile_string(
1061 talloc_tos(), profile, 0, depth);
1062 if (str != NULL) {
1063 /* No "\n", already contained in "str" */
1064 DEBUGADD(0, ("%s", str));
1065 }
1066 TALLOC_FREE(str);
1067 }
1068
1069 TALLOC_FREE(profile);
1070
1071 req = wb_req_read_send(
1072 cli_state,
1073 global_event_context(),
1074 cli_state->sock,
1075 WINBINDD_MAX_EXTRA_DATA);
1076 if (req == NULL) {
1077 remove_client(cli_state);
1078 return;
1079 }
1080 tevent_req_set_callback(req, winbind_client_request_read, cli_state);
1081 cli_state->io_req = req;
1082 }
1083
1084 /* Remove a client connection from client connection list */
1085
remove_client(struct winbindd_cli_state * state)1086 static void remove_client(struct winbindd_cli_state *state)
1087 {
1088 /* It's a dead client - hold a funeral */
1089
1090 if (state == NULL) {
1091 return;
1092 }
1093
1094 /*
1095 * We need to remove a pending wb_req_read_*
1096 * or wb_resp_write_* request before closing the
1097 * socket.
1098 *
1099 * This is important as they might have used tevent_add_fd() and we
1100 * use the epoll * backend on linux. So we must remove the tevent_fd
1101 * before closing the fd.
1102 *
1103 * Otherwise we might hit a race with close_conns_after_fork() (via
1104 * winbindd_reinit_after_fork()) where a file descriptor
1105 * is still open in a child, which means it's still active in
1106 * the parents epoll queue, but the related tevent_fd is already
1107 * already gone in the parent.
1108 *
1109 * See bug #11141.
1110 */
1111 TALLOC_FREE(state->io_req);
1112
1113 if (state->sock != -1) {
1114 char c = 0;
1115 int nwritten;
1116
1117 /* tell client, we are closing ... */
1118 nwritten = write(state->sock, &c, sizeof(c));
1119 if (nwritten == -1) {
1120 DEBUG(2, ("final write to client failed: %s\n",
1121 strerror(errno)));
1122 }
1123
1124 /* Close socket */
1125
1126 close(state->sock);
1127 state->sock = -1;
1128 }
1129
1130 TALLOC_FREE(state->mem_ctx);
1131
1132 /* Remove from list and free */
1133
1134 winbindd_remove_client(state);
1135 TALLOC_FREE(state);
1136 }
1137
1138 /* Is a client idle? */
1139
client_is_idle(struct winbindd_cli_state * state)1140 static bool client_is_idle(struct winbindd_cli_state *state) {
1141 return (state->request == NULL &&
1142 state->response == NULL &&
1143 !state->pwent_state && !state->grent_state);
1144 }
1145
1146 /* Shutdown client connection which has been idle for the longest time */
1147
remove_idle_client(void)1148 static bool remove_idle_client(void)
1149 {
1150 struct winbindd_cli_state *state, *remove_state = NULL;
1151 int nidle = 0;
1152
1153 for (state = winbindd_client_list(); state; state = state->next) {
1154 if (client_is_idle(state)) {
1155 nidle++;
1156 /* list is sorted by access time */
1157 remove_state = state;
1158 }
1159 }
1160
1161 if (remove_state) {
1162 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1163 nidle, remove_state->sock, (unsigned int)remove_state->pid));
1164 remove_client(remove_state);
1165 return True;
1166 }
1167
1168 return False;
1169 }
1170
1171 /*
1172 * Terminate all clients whose requests have taken longer than
1173 * "winbind request timeout" seconds to process, or have been
1174 * idle for more than "winbind request timeout" seconds.
1175 */
1176
remove_timed_out_clients(void)1177 static void remove_timed_out_clients(void)
1178 {
1179 struct winbindd_cli_state *state, *prev = NULL;
1180 time_t curr_time = time(NULL);
1181 int timeout_val = lp_winbind_request_timeout();
1182
1183 for (state = winbindd_client_list_tail(); state; state = prev) {
1184 time_t expiry_time;
1185
1186 prev = winbindd_client_list_prev(state);
1187 expiry_time = state->last_access + timeout_val;
1188
1189 if (curr_time <= expiry_time) {
1190 /* list is sorted, previous clients in
1191 list are newer */
1192 break;
1193 }
1194
1195 if (client_is_idle(state)) {
1196 DEBUG(5,("Idle client timed out, "
1197 "shutting down sock %d, pid %u\n",
1198 state->sock,
1199 (unsigned int)state->pid));
1200 } else {
1201 DEBUG(5,("Client request timed out, "
1202 "shutting down sock %d, pid %u\n",
1203 state->sock,
1204 (unsigned int)state->pid));
1205 }
1206
1207 remove_client(state);
1208 }
1209 }
1210
winbindd_scrub_clients_handler(struct tevent_context * ev,struct tevent_timer * te,struct timeval current_time,void * private_data)1211 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
1212 struct tevent_timer *te,
1213 struct timeval current_time,
1214 void *private_data)
1215 {
1216 remove_timed_out_clients();
1217 if (tevent_add_timer(ev, ev,
1218 timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
1219 winbindd_scrub_clients_handler, NULL) == NULL) {
1220 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
1221 exit(1);
1222 }
1223 }
1224
1225 struct winbindd_listen_state {
1226 bool privileged;
1227 int fd;
1228 };
1229
winbindd_listen_fde_handler(struct tevent_context * ev,struct tevent_fd * fde,uint16_t flags,void * private_data)1230 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1231 struct tevent_fd *fde,
1232 uint16_t flags,
1233 void *private_data)
1234 {
1235 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1236 struct winbindd_listen_state);
1237
1238 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1239 DEBUG(5,("winbindd: Exceeding %d client "
1240 "connections, removing idle "
1241 "connection.\n", lp_winbind_max_clients()));
1242 if (!remove_idle_client()) {
1243 DEBUG(0,("winbindd: Exceeding %d "
1244 "client connections, no idle "
1245 "connection found\n",
1246 lp_winbind_max_clients()));
1247 break;
1248 }
1249 }
1250 remove_timed_out_clients();
1251 new_connection(s->fd, s->privileged);
1252 }
1253
1254 /*
1255 * Winbindd socket accessor functions
1256 */
1257
get_winbind_priv_pipe_dir(void)1258 char *get_winbind_priv_pipe_dir(void)
1259 {
1260 return state_path(talloc_tos(), WINBINDD_PRIV_SOCKET_SUBDIR);
1261 }
1262
winbindd_setup_max_fds(void)1263 static void winbindd_setup_max_fds(void)
1264 {
1265 int num_fds = MAX_OPEN_FUDGEFACTOR;
1266 int actual_fds;
1267
1268 num_fds += lp_winbind_max_clients();
1269 /* Add some more to account for 2 sockets open
1270 when the client transitions from unprivileged
1271 to privileged socket
1272 */
1273 num_fds += lp_winbind_max_clients() / 10;
1274
1275 /* Add one socket per child process
1276 (yeah there are child processes other than the
1277 domain children but only domain children can vary
1278 with configuration
1279 */
1280 num_fds += lp_winbind_max_domain_connections() *
1281 (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
1282
1283 actual_fds = set_maxfiles(num_fds);
1284
1285 if (actual_fds < num_fds) {
1286 DEBUG(1, ("winbindd_setup_max_fds: Information only: "
1287 "requested %d open files, %d are available.\n",
1288 num_fds, actual_fds));
1289 }
1290 }
1291
winbindd_setup_listeners(void)1292 static bool winbindd_setup_listeners(void)
1293 {
1294 struct winbindd_listen_state *pub_state = NULL;
1295 struct winbindd_listen_state *priv_state = NULL;
1296 struct tevent_fd *fde;
1297 int rc;
1298 char *socket_path;
1299
1300 pub_state = talloc(global_event_context(),
1301 struct winbindd_listen_state);
1302 if (!pub_state) {
1303 goto failed;
1304 }
1305
1306 pub_state->privileged = false;
1307 pub_state->fd = create_pipe_sock(
1308 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1309 if (pub_state->fd == -1) {
1310 goto failed;
1311 }
1312 rc = listen(pub_state->fd, DEFAULT_LISTEN_BACKLOG);
1313 if (rc < 0) {
1314 goto failed;
1315 }
1316
1317 fde = tevent_add_fd(global_event_context(), pub_state, pub_state->fd,
1318 TEVENT_FD_READ, winbindd_listen_fde_handler,
1319 pub_state);
1320 if (fde == NULL) {
1321 close(pub_state->fd);
1322 goto failed;
1323 }
1324 tevent_fd_set_auto_close(fde);
1325
1326 priv_state = talloc(global_event_context(),
1327 struct winbindd_listen_state);
1328 if (!priv_state) {
1329 goto failed;
1330 }
1331
1332 socket_path = get_winbind_priv_pipe_dir();
1333 if (socket_path == NULL) {
1334 goto failed;
1335 }
1336
1337 priv_state->privileged = true;
1338 priv_state->fd = create_pipe_sock(
1339 socket_path, WINBINDD_SOCKET_NAME, 0750);
1340 TALLOC_FREE(socket_path);
1341 if (priv_state->fd == -1) {
1342 goto failed;
1343 }
1344 rc = listen(priv_state->fd, DEFAULT_LISTEN_BACKLOG);
1345 if (rc < 0) {
1346 goto failed;
1347 }
1348
1349 fde = tevent_add_fd(global_event_context(), priv_state,
1350 priv_state->fd, TEVENT_FD_READ,
1351 winbindd_listen_fde_handler, priv_state);
1352 if (fde == NULL) {
1353 close(priv_state->fd);
1354 goto failed;
1355 }
1356 tevent_fd_set_auto_close(fde);
1357
1358 winbindd_scrub_clients_handler(global_event_context(), NULL,
1359 timeval_current(), NULL);
1360 return true;
1361 failed:
1362 TALLOC_FREE(pub_state);
1363 TALLOC_FREE(priv_state);
1364 return false;
1365 }
1366
winbindd_use_idmap_cache(void)1367 bool winbindd_use_idmap_cache(void)
1368 {
1369 return !opt_nocache;
1370 }
1371
winbindd_use_cache(void)1372 bool winbindd_use_cache(void)
1373 {
1374 return !opt_nocache;
1375 }
1376
winbindd_register_handlers(struct messaging_context * msg_ctx,bool foreground)1377 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1378 bool foreground)
1379 {
1380 bool scan_trusts = true;
1381 NTSTATUS status;
1382 /* Setup signal handlers */
1383
1384 if (!winbindd_setup_sig_term_handler(true))
1385 exit(1);
1386 if (!winbindd_setup_stdin_handler(true, foreground))
1387 exit(1);
1388 if (!winbindd_setup_sig_hup_handler(NULL))
1389 exit(1);
1390 if (!winbindd_setup_sig_chld_handler())
1391 exit(1);
1392 if (!winbindd_setup_sig_usr2_handler())
1393 exit(1);
1394
1395 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1396
1397 /*
1398 * Ensure all cache and idmap caches are consistent
1399 * and initialized before we startup.
1400 */
1401 if (!winbindd_cache_validate_and_initialize()) {
1402 exit(1);
1403 }
1404
1405 /* React on 'smbcontrol winbindd reload-config' in the same way
1406 as to SIGHUP signal */
1407 messaging_register(msg_ctx, NULL,
1408 MSG_SMB_CONF_UPDATED,
1409 winbindd_msg_reload_services_parent);
1410 messaging_register(msg_ctx, NULL,
1411 MSG_SHUTDOWN, msg_shutdown);
1412
1413 /* Handle online/offline messages. */
1414 messaging_register(msg_ctx, NULL,
1415 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1416 messaging_register(msg_ctx, NULL,
1417 MSG_WINBIND_ONLINE, winbind_msg_online);
1418 messaging_register(msg_ctx, NULL,
1419 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1420
1421 /* Handle domain online/offline messages for domains */
1422 messaging_register(global_messaging_context(), NULL,
1423 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1424 messaging_register(global_messaging_context(), NULL,
1425 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1426
1427 messaging_register(msg_ctx, NULL,
1428 MSG_WINBIND_VALIDATE_CACHE,
1429 winbind_msg_validate_cache);
1430
1431 messaging_register(msg_ctx, NULL,
1432 MSG_WINBIND_DUMP_DOMAIN_LIST,
1433 winbind_msg_dump_domain_list);
1434
1435 messaging_register(msg_ctx, NULL,
1436 MSG_WINBIND_IP_DROPPED,
1437 winbind_msg_ip_dropped_parent);
1438
1439 /* Register handler for MSG_DEBUG. */
1440 messaging_register(msg_ctx, NULL,
1441 MSG_DEBUG,
1442 winbind_msg_debug);
1443
1444 messaging_register(msg_ctx, NULL,
1445 MSG_WINBIND_DISCONNECT_DC,
1446 winbind_disconnect_dc_parent);
1447
1448 netsamlogon_cache_init(); /* Non-critical */
1449
1450 /* clear the cached list of trusted domains */
1451
1452 wcache_tdc_clear();
1453
1454 if (!init_domain_list()) {
1455 DEBUG(0,("unable to initialize domain list\n"));
1456 exit(1);
1457 }
1458
1459 init_idmap_child();
1460 init_locator_child();
1461
1462 smb_nscd_flush_user_cache();
1463 smb_nscd_flush_group_cache();
1464
1465 if (!lp_winbind_scan_trusted_domains()) {
1466 scan_trusts = false;
1467 }
1468
1469 if (!lp_allow_trusted_domains()) {
1470 scan_trusts = false;
1471 }
1472
1473 if (IS_DC) {
1474 scan_trusts = false;
1475 }
1476
1477 if (scan_trusts) {
1478 if (tevent_add_timer(global_event_context(), NULL, timeval_zero(),
1479 rescan_trusted_domains, NULL) == NULL) {
1480 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1481 exit(1);
1482 }
1483 }
1484
1485 status = wb_irpc_register();
1486
1487 if (!NT_STATUS_IS_OK(status)) {
1488 DEBUG(0, ("Could not register IRPC handlers\n"));
1489 exit(1);
1490 }
1491 }
1492
1493 struct winbindd_addrchanged_state {
1494 struct addrchange_context *ctx;
1495 struct tevent_context *ev;
1496 struct messaging_context *msg_ctx;
1497 };
1498
1499 static void winbindd_addr_changed(struct tevent_req *req);
1500
winbindd_init_addrchange(TALLOC_CTX * mem_ctx,struct tevent_context * ev,struct messaging_context * msg_ctx)1501 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1502 struct tevent_context *ev,
1503 struct messaging_context *msg_ctx)
1504 {
1505 struct winbindd_addrchanged_state *state;
1506 struct tevent_req *req;
1507 NTSTATUS status;
1508
1509 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1510 if (state == NULL) {
1511 DEBUG(10, ("talloc failed\n"));
1512 return;
1513 }
1514 state->ev = ev;
1515 state->msg_ctx = msg_ctx;
1516
1517 status = addrchange_context_create(state, &state->ctx);
1518 if (!NT_STATUS_IS_OK(status)) {
1519 DEBUG(10, ("addrchange_context_create failed: %s\n",
1520 nt_errstr(status)));
1521 TALLOC_FREE(state);
1522 return;
1523 }
1524 req = addrchange_send(state, ev, state->ctx);
1525 if (req == NULL) {
1526 DEBUG(0, ("addrchange_send failed\n"));
1527 TALLOC_FREE(state);
1528 return;
1529 }
1530 tevent_req_set_callback(req, winbindd_addr_changed, state);
1531 }
1532
winbindd_addr_changed(struct tevent_req * req)1533 static void winbindd_addr_changed(struct tevent_req *req)
1534 {
1535 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1536 req, struct winbindd_addrchanged_state);
1537 enum addrchange_type type;
1538 struct sockaddr_storage addr;
1539 NTSTATUS status;
1540
1541 status = addrchange_recv(req, &type, &addr);
1542 TALLOC_FREE(req);
1543 if (!NT_STATUS_IS_OK(status)) {
1544 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1545 nt_errstr(status)));
1546 TALLOC_FREE(state);
1547 return;
1548 }
1549 if (type == ADDRCHANGE_DEL) {
1550 char addrstr[INET6_ADDRSTRLEN];
1551 DATA_BLOB blob;
1552
1553 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1554
1555 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1556 addrstr));
1557
1558 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1559
1560 status = messaging_send(state->msg_ctx,
1561 messaging_server_id(state->msg_ctx),
1562 MSG_WINBIND_IP_DROPPED, &blob);
1563 if (!NT_STATUS_IS_OK(status)) {
1564 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1565 nt_errstr(status)));
1566 }
1567 }
1568 req = addrchange_send(state, state->ev, state->ctx);
1569 if (req == NULL) {
1570 DEBUG(0, ("addrchange_send failed\n"));
1571 TALLOC_FREE(state);
1572 return;
1573 }
1574 tevent_req_set_callback(req, winbindd_addr_changed, state);
1575 }
1576
1577 /* Main function */
1578
main(int argc,const char ** argv)1579 int main(int argc, const char **argv)
1580 {
1581 static bool is_daemon = False;
1582 static bool Fork = True;
1583 static bool log_stdout = False;
1584 static bool no_process_group = False;
1585 enum {
1586 OPT_DAEMON = 1000,
1587 OPT_FORK,
1588 OPT_NO_PROCESS_GROUP,
1589 OPT_LOG_STDOUT
1590 };
1591 struct poptOption long_options[] = {
1592 POPT_AUTOHELP
1593 {
1594 .longName = "stdout",
1595 .shortName = 'S',
1596 .argInfo = POPT_ARG_NONE,
1597 .arg = NULL,
1598 .val = OPT_LOG_STDOUT,
1599 .descrip = "Log to stdout",
1600 },
1601 {
1602 .longName = "foreground",
1603 .shortName = 'F',
1604 .argInfo = POPT_ARG_NONE,
1605 .arg = NULL,
1606 .val = OPT_FORK,
1607 .descrip = "Daemon in foreground mode",
1608 },
1609 {
1610 .longName = "no-process-group",
1611 .shortName = 0,
1612 .argInfo = POPT_ARG_NONE,
1613 .arg = NULL,
1614 .val = OPT_NO_PROCESS_GROUP,
1615 .descrip = "Don't create a new process group",
1616 },
1617 {
1618 .longName = "daemon",
1619 .shortName = 'D',
1620 .argInfo = POPT_ARG_NONE,
1621 .arg = NULL,
1622 .val = OPT_DAEMON,
1623 .descrip = "Become a daemon (default)",
1624 },
1625 {
1626 .longName = "interactive",
1627 .shortName = 'i',
1628 .argInfo = POPT_ARG_NONE,
1629 .arg = NULL,
1630 .val = 'i',
1631 .descrip = "Interactive mode",
1632 },
1633 {
1634 .longName = "no-caching",
1635 .shortName = 'n',
1636 .argInfo = POPT_ARG_NONE,
1637 .arg = NULL,
1638 .val = 'n',
1639 .descrip = "Disable caching",
1640 },
1641 POPT_COMMON_SAMBA
1642 POPT_TABLEEND
1643 };
1644 const struct loadparm_substitution *lp_sub =
1645 loadparm_s3_global_substitution();
1646 poptContext pc;
1647 int opt;
1648 TALLOC_CTX *frame;
1649 NTSTATUS status;
1650 bool ok;
1651
1652 setproctitle_init(argc, discard_const(argv), environ);
1653
1654 /*
1655 * Do this before any other talloc operation
1656 */
1657 talloc_enable_null_tracking();
1658 frame = talloc_stackframe();
1659
1660 /*
1661 * We want total control over the permissions on created files,
1662 * so set our umask to 0.
1663 */
1664 umask(0);
1665
1666 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1667
1668 /* glibc (?) likes to print "User defined signal 1" and exit if a
1669 SIGUSR[12] is received before a handler is installed */
1670
1671 CatchSignal(SIGUSR1, SIG_IGN);
1672 CatchSignal(SIGUSR2, SIG_IGN);
1673
1674 fault_setup();
1675 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1676
1677 smb_init_locale();
1678
1679 /* Initialise for running in non-root mode */
1680
1681 sec_init();
1682
1683 set_remote_machine_name("winbindd", False);
1684
1685 /* Set environment variable so we don't recursively call ourselves.
1686 This may also be useful interactively. */
1687
1688 if ( !winbind_off() ) {
1689 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1690 exit(1);
1691 }
1692
1693 /* Initialise samba/rpc client stuff */
1694
1695 pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1696
1697 while ((opt = poptGetNextOpt(pc)) != -1) {
1698 switch (opt) {
1699 /* Don't become a daemon */
1700 case OPT_DAEMON:
1701 is_daemon = True;
1702 break;
1703 case 'i':
1704 interactive = True;
1705 log_stdout = True;
1706 Fork = False;
1707 break;
1708 case OPT_FORK:
1709 Fork = false;
1710 break;
1711 case OPT_NO_PROCESS_GROUP:
1712 no_process_group = true;
1713 break;
1714 case OPT_LOG_STDOUT:
1715 log_stdout = true;
1716 break;
1717 case 'n':
1718 opt_nocache = true;
1719 break;
1720 default:
1721 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1722 poptBadOption(pc, 0), poptStrerror(opt));
1723 poptPrintUsage(pc, stderr, 0);
1724 exit(1);
1725 }
1726 }
1727
1728 /* We call dump_core_setup one more time because the command line can
1729 * set the log file or the log-basename and this will influence where
1730 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1731 * the default value derived from build's prefix. For EOM this value
1732 * is often not related to the path where winbindd is actually run
1733 * in production.
1734 */
1735 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1736 if (is_daemon && interactive) {
1737 d_fprintf(stderr,"\nERROR: "
1738 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1739 poptPrintUsage(pc, stderr, 0);
1740 exit(1);
1741 }
1742
1743 if (log_stdout && Fork) {
1744 d_fprintf(stderr, "\nERROR: "
1745 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1746 poptPrintUsage(pc, stderr, 0);
1747 exit(1);
1748 }
1749
1750 poptFreeContext(pc);
1751
1752 if (!override_logfile) {
1753 char *lfile = NULL;
1754 if (asprintf(&lfile,"%s/log.winbindd",
1755 get_dyn_LOGFILEBASE()) > 0) {
1756 lp_set_logfile(lfile);
1757 SAFE_FREE(lfile);
1758 }
1759 }
1760
1761 if (log_stdout) {
1762 setup_logging("winbindd", DEBUG_STDOUT);
1763 } else {
1764 setup_logging("winbindd", DEBUG_FILE);
1765 }
1766 reopen_logs();
1767
1768 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1769 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1770
1771 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1772 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1773 exit(1);
1774 }
1775 /* After parsing the configuration file we setup the core path one more time
1776 * as the log file might have been set in the configuration and cores's
1777 * path is by default basename(lp_logfile()).
1778 */
1779 dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1780
1781 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1782 && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1783 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1784 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"));
1785 exit(1);
1786 }
1787
1788 if (!cluster_probe_ok()) {
1789 exit(1);
1790 }
1791
1792 /* Initialise messaging system */
1793
1794 if (global_messaging_context() == NULL) {
1795 exit(1);
1796 }
1797
1798 if (!winbindd_reload_services_file(NULL)) {
1799 DEBUG(0, ("error opening config file\n"));
1800 exit(1);
1801 }
1802
1803 {
1804 size_t i;
1805 const char *idmap_backend;
1806 const char *invalid_backends[] = {
1807 "ad", "rfc2307", "rid",
1808 };
1809
1810 idmap_backend = lp_idmap_default_backend();
1811 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1812 ok = strequal(idmap_backend, invalid_backends[i]);
1813 if (ok) {
1814 DBG_ERR("FATAL: Invalid idmap backend %s "
1815 "configured as the default backend!\n",
1816 idmap_backend);
1817 exit(1);
1818 }
1819 }
1820 }
1821
1822 ok = directory_create_or_exist(lp_lock_directory(), 0755);
1823 if (!ok) {
1824 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1825 lp_lock_directory(), strerror(errno)));
1826 exit(1);
1827 }
1828
1829 ok = directory_create_or_exist(lp_pid_directory(), 0755);
1830 if (!ok) {
1831 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1832 lp_pid_directory(), strerror(errno)));
1833 exit(1);
1834 }
1835
1836 /* Setup names. */
1837
1838 if (!init_names())
1839 exit(1);
1840
1841 load_interfaces();
1842
1843 if (!secrets_init()) {
1844
1845 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1846 return False;
1847 }
1848
1849 status = rpccli_pre_open_netlogon_creds();
1850 if (!NT_STATUS_IS_OK(status)) {
1851 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1852 nt_errstr(status)));
1853 exit(1);
1854 }
1855
1856 /* Unblock all signals we are interested in as they may have been
1857 blocked by the parent process. */
1858
1859 BlockSignals(False, SIGINT);
1860 BlockSignals(False, SIGQUIT);
1861 BlockSignals(False, SIGTERM);
1862 BlockSignals(False, SIGUSR1);
1863 BlockSignals(False, SIGUSR2);
1864 BlockSignals(False, SIGHUP);
1865 BlockSignals(False, SIGCHLD);
1866
1867 if (!interactive)
1868 become_daemon(Fork, no_process_group, log_stdout);
1869
1870 pidfile_create(lp_pid_directory(), "winbindd");
1871
1872 #ifdef HAVE_SETPGID
1873 /*
1874 * If we're interactive we want to set our own process group for
1875 * signal management.
1876 */
1877 if (interactive && !no_process_group)
1878 setpgid( (pid_t)0, (pid_t)0);
1879 #endif
1880
1881 TimeInit();
1882
1883 /* Don't use winbindd_reinit_after_fork here as
1884 * we're just starting up and haven't created any
1885 * winbindd-specific resources we must free yet. JRA.
1886 */
1887
1888 status = reinit_after_fork(global_messaging_context(),
1889 global_event_context(),
1890 false, NULL);
1891 if (!NT_STATUS_IS_OK(status)) {
1892 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1893 }
1894
1895 ok = initialize_password_db(true, global_event_context());
1896 if (!ok) {
1897 exit_daemon("Failed to initialize passdb backend! "
1898 "Check the 'passdb backend' variable in your "
1899 "smb.conf file.", EINVAL);
1900 }
1901
1902 /*
1903 * Do not initialize the parent-child-pipe before becoming
1904 * a daemon: this is used to detect a died parent in the child
1905 * process.
1906 */
1907 status = init_before_fork();
1908 if (!NT_STATUS_IS_OK(status)) {
1909 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1910 }
1911
1912 winbindd_register_handlers(global_messaging_context(), !Fork);
1913
1914 if (!messaging_parent_dgm_cleanup_init(global_messaging_context())) {
1915 exit(1);
1916 }
1917
1918 status = init_system_session_info(NULL);
1919 if (!NT_STATUS_IS_OK(status)) {
1920 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1921 }
1922
1923 rpc_lsarpc_init(NULL);
1924 rpc_samr_init(NULL);
1925
1926 winbindd_init_addrchange(NULL, global_event_context(),
1927 global_messaging_context());
1928
1929 /* setup listen sockets */
1930
1931 if (!winbindd_setup_listeners()) {
1932 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1933 }
1934
1935 irpc_add_name(winbind_imessaging_context(), "winbind_server");
1936
1937 TALLOC_FREE(frame);
1938
1939 if (!interactive) {
1940 daemon_ready("winbindd");
1941 }
1942
1943 gpupdate_init();
1944
1945 /* Loop waiting for requests */
1946 while (1) {
1947 frame = talloc_stackframe();
1948
1949 if (tevent_loop_once(global_event_context()) == -1) {
1950 DEBUG(1, ("tevent_loop_once() failed: %s\n",
1951 strerror(errno)));
1952 return 1;
1953 }
1954
1955 TALLOC_FREE(frame);
1956 }
1957
1958 return 0;
1959 }
1960