source: vendor/current/source3/winbindd/winbindd.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

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