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