winbindd: winbindd_ccache_ntlm_auth() -> bool_dispatch_table
[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_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
538         { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
539           "WINBINDD_PRIV_PIPE_DIR" },
540
541         /* Credential cache access */
542         { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
543
544         /* End of list */
545
546         { WINBINDD_NUM_CMDS, NULL, "NONE" }
547 };
548
549 static struct winbindd_bool_dispatch_table {
550         enum winbindd_cmd cmd;
551         bool (*fn)(struct winbindd_cli_state *state);
552         const char *cmd_name;
553 } bool_dispatch_table[] = {
554         { WINBINDD_INTERFACE_VERSION,
555           winbindd_interface_version,
556           "INTERFACE_VERSION" },
557         { WINBINDD_INFO,
558           winbindd_info,
559           "INFO" },
560         { WINBINDD_PING,
561           winbindd_ping,
562           "PING" },
563         { WINBINDD_DOMAIN_NAME,
564           winbindd_domain_name,
565           "DOMAIN_NAME" },
566         { WINBINDD_NETBIOS_NAME,
567           winbindd_netbios_name,
568           "NETBIOS_NAME" },
569         { WINBINDD_DC_INFO,
570           winbindd_dc_info,
571           "DC_INFO" },
572         { WINBINDD_CCACHE_NTLMAUTH,
573           winbindd_ccache_ntlm_auth,
574           "NTLMAUTH" },
575 };
576
577 struct winbindd_async_dispatch_table {
578         enum winbindd_cmd cmd;
579         const char *cmd_name;
580         struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
581                                        struct tevent_context *ev,
582                                        struct winbindd_cli_state *cli,
583                                        struct winbindd_request *request);
584         NTSTATUS (*recv_req)(struct tevent_req *req,
585                              struct winbindd_response *presp);
586 };
587
588 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
589         { WINBINDD_LOOKUPSID, "LOOKUPSID",
590           winbindd_lookupsid_send, winbindd_lookupsid_recv },
591         { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
592           winbindd_lookupsids_send, winbindd_lookupsids_recv },
593         { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
594           winbindd_lookupname_send, winbindd_lookupname_recv },
595         { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
596           winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
597         { WINBINDD_XIDS_TO_SIDS, "XIDS_TO_SIDS",
598           winbindd_xids_to_sids_send, winbindd_xids_to_sids_recv },
599         { WINBINDD_GETPWSID, "GETPWSID",
600           winbindd_getpwsid_send, winbindd_getpwsid_recv },
601         { WINBINDD_GETPWNAM, "GETPWNAM",
602           winbindd_getpwnam_send, winbindd_getpwnam_recv },
603         { WINBINDD_GETPWUID, "GETPWUID",
604           winbindd_getpwuid_send, winbindd_getpwuid_recv },
605         { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
606           winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
607         { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
608           winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
609         { WINBINDD_GETGROUPS, "GETGROUPS",
610           winbindd_getgroups_send, winbindd_getgroups_recv },
611         { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
612           winbindd_show_sequence_send, winbindd_show_sequence_recv },
613         { WINBINDD_GETGRGID, "GETGRGID",
614           winbindd_getgrgid_send, winbindd_getgrgid_recv },
615         { WINBINDD_GETGRNAM, "GETGRNAM",
616           winbindd_getgrnam_send, winbindd_getgrnam_recv },
617         { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
618           winbindd_getusersids_send, winbindd_getusersids_recv },
619         { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
620           winbindd_lookuprids_send, winbindd_lookuprids_recv },
621         { WINBINDD_SETPWENT, "SETPWENT",
622           winbindd_setpwent_send, winbindd_setpwent_recv },
623         { WINBINDD_GETPWENT, "GETPWENT",
624           winbindd_getpwent_send, winbindd_getpwent_recv },
625         { WINBINDD_ENDPWENT, "ENDPWENT",
626           winbindd_endpwent_send, winbindd_endpwent_recv },
627         { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
628           winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
629         { WINBINDD_GETDCNAME, "GETDCNAME",
630           winbindd_getdcname_send, winbindd_getdcname_recv },
631         { WINBINDD_SETGRENT, "SETGRENT",
632           winbindd_setgrent_send, winbindd_setgrent_recv },
633         { WINBINDD_GETGRENT, "GETGRENT",
634           winbindd_getgrent_send, winbindd_getgrent_recv },
635         { WINBINDD_ENDGRENT, "ENDGRENT",
636           winbindd_endgrent_send, winbindd_endgrent_recv },
637         { WINBINDD_LIST_USERS, "LIST_USERS",
638           winbindd_list_users_send, winbindd_list_users_recv },
639         { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
640           winbindd_list_groups_send, winbindd_list_groups_recv },
641         { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
642           winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
643         { WINBINDD_PING_DC, "PING_DC",
644           winbindd_ping_dc_send, winbindd_ping_dc_recv },
645         { WINBINDD_PAM_AUTH, "PAM_AUTH",
646           winbindd_pam_auth_send, winbindd_pam_auth_recv },
647         { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
648           winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
649         { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
650           winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
651         { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
652           winbindd_pam_chng_pswd_auth_crap_send,
653           winbindd_pam_chng_pswd_auth_crap_recv },
654         { WINBINDD_WINS_BYIP, "WINS_BYIP",
655           winbindd_wins_byip_send, winbindd_wins_byip_recv },
656         { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
657           winbindd_wins_byname_send, winbindd_wins_byname_recv },
658
659         { 0, NULL, NULL, NULL }
660 };
661
662 static struct winbindd_async_dispatch_table async_priv_table[] = {
663         { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
664           winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
665         { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
666           winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
667         { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
668           winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
669         { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
670           winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
671
672         { 0, NULL, NULL, NULL }
673 };
674
675 static void wb_request_done(struct tevent_req *req);
676
677 static void process_request(struct winbindd_cli_state *state)
678 {
679         struct winbindd_dispatch_table *table = dispatch_table;
680         struct winbindd_async_dispatch_table *atable;
681         size_t i;
682         bool ok;
683
684         state->mem_ctx = talloc_named(state, 0, "winbind request");
685         if (state->mem_ctx == NULL)
686                 return;
687
688         /* Remember who asked us. */
689         state->pid = state->request->pid;
690
691         state->cmd_name = "unknown request";
692         state->recv_fn = NULL;
693         /* client is newest */
694         winbindd_promote_client(state);
695
696         /* Process command */
697
698         for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
699                 if (state->request->cmd == atable->cmd) {
700                         break;
701                 }
702         }
703
704         if ((atable->send_req == NULL) && state->privileged) {
705                 for (atable = async_priv_table; atable->send_req;
706                      atable += 1) {
707                         if (state->request->cmd == atable->cmd) {
708                                 break;
709                         }
710                 }
711         }
712
713         if (atable->send_req != NULL) {
714                 struct tevent_req *req;
715
716                 state->cmd_name = atable->cmd_name;
717                 state->recv_fn = atable->recv_req;
718
719                 DEBUG(10, ("process_request: Handling async request %d:%s\n",
720                            (int)state->pid, state->cmd_name));
721
722                 req = atable->send_req(state->mem_ctx, server_event_context(),
723                                        state, state->request);
724                 if (req == NULL) {
725                         DEBUG(0, ("process_request: atable->send failed for "
726                                   "%s\n", atable->cmd_name));
727                         request_error(state);
728                         return;
729                 }
730                 tevent_req_set_callback(req, wb_request_done, state);
731                 return;
732         }
733
734         state->response = talloc_zero(state->mem_ctx,
735                                       struct winbindd_response);
736         if (state->response == NULL) {
737                 DEBUG(10, ("talloc failed\n"));
738                 remove_client(state);
739                 return;
740         }
741         state->response->result = WINBINDD_PENDING;
742         state->response->length = sizeof(struct winbindd_response);
743
744         for (table = dispatch_table; table->fn; table++) {
745                 if (state->request->cmd == table->cmd) {
746                         DEBUG(10,("process_request: request fn %s\n",
747                                   table->winbindd_cmd_name ));
748                         state->cmd_name = table->winbindd_cmd_name;
749                         table->fn(state);
750                         return;
751                 }
752         }
753
754         for (i=0; i<ARRAY_SIZE(bool_dispatch_table); i++) {
755                 if (bool_dispatch_table[i].cmd == state->request->cmd) {
756                         break;
757                 }
758         }
759
760         if (i == ARRAY_SIZE(bool_dispatch_table)) {
761                 DEBUG(10,("process_request: unknown request fn number %d\n",
762                           (int)state->request->cmd ));
763                 request_error(state);
764                 return;
765         }
766
767         DBG_DEBUG("process_request: request fn %s\n",
768                   bool_dispatch_table[i].cmd_name);
769
770         ok = bool_dispatch_table[i].fn(state);
771
772         if (ok) {
773                 request_ok(state);
774         } else {
775                 request_error(state);
776         }
777 }
778
779 static void wb_request_done(struct tevent_req *req)
780 {
781         struct winbindd_cli_state *state = tevent_req_callback_data(
782                 req, struct winbindd_cli_state);
783         NTSTATUS status;
784
785         state->response = talloc_zero(state->mem_ctx,
786                                       struct winbindd_response);
787         if (state->response == NULL) {
788                 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
789                           (int)state->pid, state->cmd_name));
790                 remove_client(state);
791                 return;
792         }
793         state->response->result = WINBINDD_PENDING;
794         state->response->length = sizeof(struct winbindd_response);
795
796         status = state->recv_fn(req, state->response);
797         TALLOC_FREE(req);
798
799         DEBUG(10,("wb_request_done[%d:%s]: %s\n",
800                   (int)state->pid, state->cmd_name, nt_errstr(status)));
801
802         if (!NT_STATUS_IS_OK(status)) {
803                 request_error(state);
804                 return;
805         }
806         request_ok(state);
807 }
808
809 /*
810  * This is the main event loop of winbind requests. It goes through a
811  * state-machine of 3 read/write requests, 4 if you have extra data to send.
812  *
813  * An idle winbind client has a read request of 4 bytes outstanding,
814  * finalizing function is request_len_recv, checking the length. request_recv
815  * then processes the packet. The processing function then at some point has
816  * to call request_finished which schedules sending the response.
817  */
818
819 static void request_finished(struct winbindd_cli_state *state);
820
821 static void winbind_client_request_read(struct tevent_req *req);
822 static void winbind_client_response_written(struct tevent_req *req);
823 static void winbind_client_activity(struct tevent_req *req);
824
825 static void request_finished(struct winbindd_cli_state *state)
826 {
827         struct tevent_req *req;
828
829         /* free client socket monitoring request */
830         TALLOC_FREE(state->io_req);
831
832         TALLOC_FREE(state->request);
833
834         req = wb_resp_write_send(state, server_event_context(),
835                                  state->out_queue, state->sock,
836                                  state->response);
837         if (req == NULL) {
838                 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
839                           (int)state->pid, state->cmd_name));
840                 remove_client(state);
841                 return;
842         }
843         tevent_req_set_callback(req, winbind_client_response_written, state);
844         state->io_req = req;
845 }
846
847 static void winbind_client_response_written(struct tevent_req *req)
848 {
849         struct winbindd_cli_state *state = tevent_req_callback_data(
850                 req, struct winbindd_cli_state);
851         ssize_t ret;
852         int err;
853
854         state->io_req = NULL;
855
856         ret = wb_resp_write_recv(req, &err);
857         TALLOC_FREE(req);
858         if (ret == -1) {
859                 close(state->sock);
860                 state->sock = -1;
861                 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
862                           (int)state->pid, state->cmd_name, strerror(err)));
863                 remove_client(state);
864                 return;
865         }
866
867         DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
868                   "to client\n", (int)state->pid, state->cmd_name));
869
870         TALLOC_FREE(state->mem_ctx);
871         state->response = NULL;
872         state->cmd_name = "no request";
873         state->recv_fn = NULL;
874
875         req = wb_req_read_send(state, server_event_context(), state->sock,
876                                WINBINDD_MAX_EXTRA_DATA);
877         if (req == NULL) {
878                 remove_client(state);
879                 return;
880         }
881         tevent_req_set_callback(req, winbind_client_request_read, state);
882         state->io_req = req;
883 }
884
885 void request_error(struct winbindd_cli_state *state)
886 {
887         SMB_ASSERT(state->response->result == WINBINDD_PENDING);
888         state->response->result = WINBINDD_ERROR;
889         request_finished(state);
890 }
891
892 void request_ok(struct winbindd_cli_state *state)
893 {
894         SMB_ASSERT(state->response->result == WINBINDD_PENDING);
895         state->response->result = WINBINDD_OK;
896         request_finished(state);
897 }
898
899 /* Process a new connection by adding it to the client connection list */
900
901 static void new_connection(int listen_sock, bool privileged)
902 {
903         struct sockaddr_un sunaddr;
904         struct winbindd_cli_state *state;
905         struct tevent_req *req;
906         socklen_t len;
907         int sock;
908
909         /* Accept connection */
910
911         len = sizeof(sunaddr);
912
913         sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
914
915         if (sock == -1) {
916                 if (errno != EINTR) {
917                         DEBUG(0, ("Failed to accept socket - %s\n",
918                                   strerror(errno)));
919                 }
920                 return;
921         }
922         smb_set_close_on_exec(sock);
923
924         DEBUG(6,("accepted socket %d\n", sock));
925
926         /* Create new connection structure */
927
928         if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
929                 close(sock);
930                 return;
931         }
932
933         state->sock = sock;
934
935         state->out_queue = tevent_queue_create(state, "winbind client reply");
936         if (state->out_queue == NULL) {
937                 close(sock);
938                 TALLOC_FREE(state);
939                 return;
940         }
941
942         state->privileged = privileged;
943
944         req = wb_req_read_send(state, server_event_context(), state->sock,
945                                WINBINDD_MAX_EXTRA_DATA);
946         if (req == NULL) {
947                 TALLOC_FREE(state);
948                 close(sock);
949                 return;
950         }
951         tevent_req_set_callback(req, winbind_client_request_read, state);
952         state->io_req = req;
953
954         /* Add to connection list */
955
956         winbindd_add_client(state);
957 }
958
959 static void winbind_client_request_read(struct tevent_req *req)
960 {
961         struct winbindd_cli_state *state = tevent_req_callback_data(
962                 req, struct winbindd_cli_state);
963         ssize_t ret;
964         int err;
965
966         state->io_req = NULL;
967
968         ret = wb_req_read_recv(req, state, &state->request, &err);
969         TALLOC_FREE(req);
970         if (ret == -1) {
971                 if (err == EPIPE) {
972                         DEBUG(6, ("closing socket %d, client exited\n",
973                                   state->sock));
974                 } else {
975                         DEBUG(2, ("Could not read client request from fd %d: "
976                                   "%s\n", state->sock, strerror(err)));
977                 }
978                 close(state->sock);
979                 state->sock = -1;
980                 remove_client(state);
981                 return;
982         }
983
984         req = wait_for_read_send(state, server_event_context(), state->sock,
985                                  true);
986         if (req == NULL) {
987                 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
988                           " wait_for_read_send failed - removing client\n",
989                           (int)state->pid, state->cmd_name));
990                 remove_client(state);
991                 return;
992         }
993         tevent_req_set_callback(req, winbind_client_activity, state);
994         state->io_req = req;
995
996         process_request(state);
997 }
998
999 static void winbind_client_activity(struct tevent_req *req)
1000 {
1001         struct winbindd_cli_state *state =
1002             tevent_req_callback_data(req, struct winbindd_cli_state);
1003         int err;
1004         bool has_data;
1005
1006         has_data = wait_for_read_recv(req, &err);
1007
1008         if (has_data) {
1009                 DEBUG(0, ("winbind_client_activity[%d:%s]:"
1010                           "unexpected data from client - removing client\n",
1011                           (int)state->pid, state->cmd_name));
1012         } else {
1013                 if (err == EPIPE) {
1014                         DEBUG(6, ("winbind_client_activity[%d:%s]: "
1015                                   "client has closed connection - removing "
1016                                   "client\n",
1017                                   (int)state->pid, state->cmd_name));
1018                 } else {
1019                         DEBUG(2, ("winbind_client_activity[%d:%s]: "
1020                                   "client socket error (%s) - removing "
1021                                   "client\n",
1022                                   (int)state->pid, state->cmd_name,
1023                                   strerror(err)));
1024                 }
1025         }
1026
1027         remove_client(state);
1028 }
1029
1030 /* Remove a client connection from client connection list */
1031
1032 static void remove_client(struct winbindd_cli_state *state)
1033 {
1034         char c = 0;
1035         int nwritten;
1036
1037         /* It's a dead client - hold a funeral */
1038
1039         if (state == NULL) {
1040                 return;
1041         }
1042
1043         /*
1044          * We need to remove a pending wb_req_read_*
1045          * or wb_resp_write_* request before closing the
1046          * socket.
1047          *
1048          * This is important as they might have used tevent_add_fd() and we
1049          * use the epoll * backend on linux. So we must remove the tevent_fd
1050          * before closing the fd.
1051          *
1052          * Otherwise we might hit a race with close_conns_after_fork() (via
1053          * winbindd_reinit_after_fork()) where a file description
1054          * is still open in a child, which means it's still active in
1055          * the parents epoll queue, but the related tevent_fd is already
1056          * already gone in the parent.
1057          *
1058          * See bug #11141.
1059          */
1060         TALLOC_FREE(state->io_req);
1061
1062         if (state->sock != -1) {
1063                 /* tell client, we are closing ... */
1064                 nwritten = write(state->sock, &c, sizeof(c));
1065                 if (nwritten == -1) {
1066                         DEBUG(2, ("final write to client failed: %s\n",
1067                                 strerror(errno)));
1068                 }
1069
1070                 /* Close socket */
1071
1072                 close(state->sock);
1073                 state->sock = -1;
1074         }
1075
1076         TALLOC_FREE(state->mem_ctx);
1077
1078         /* Remove from list and free */
1079
1080         winbindd_remove_client(state);
1081         TALLOC_FREE(state);
1082 }
1083
1084 /* Is a client idle? */
1085
1086 static bool client_is_idle(struct winbindd_cli_state *state) {
1087   return (state->request == NULL &&
1088           state->response == NULL &&
1089           !state->pwent_state && !state->grent_state);
1090 }
1091
1092 /* Shutdown client connection which has been idle for the longest time */
1093
1094 static bool remove_idle_client(void)
1095 {
1096         struct winbindd_cli_state *state, *remove_state = NULL;
1097         int nidle = 0;
1098
1099         for (state = winbindd_client_list(); state; state = state->next) {
1100                 if (client_is_idle(state)) {
1101                         nidle++;
1102                         /* list is sorted by access time */
1103                         remove_state = state;
1104                 }
1105         }
1106
1107         if (remove_state) {
1108                 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1109                         nidle, remove_state->sock, (unsigned int)remove_state->pid));
1110                 remove_client(remove_state);
1111                 return True;
1112         }
1113
1114         return False;
1115 }
1116
1117 /*
1118  * Terminate all clients whose requests have taken longer than
1119  * "winbind request timeout" seconds to process, or have been
1120  * idle for more than "winbind request timeout" seconds.
1121  */
1122
1123 static void remove_timed_out_clients(void)
1124 {
1125         struct winbindd_cli_state *state, *prev = NULL;
1126         time_t curr_time = time(NULL);
1127         int timeout_val = lp_winbind_request_timeout();
1128
1129         for (state = winbindd_client_list_tail(); state; state = prev) {
1130                 time_t expiry_time;
1131
1132                 prev = winbindd_client_list_prev(state);
1133                 expiry_time = state->last_access + timeout_val;
1134
1135                 if (curr_time <= expiry_time) {
1136                         /* list is sorted, previous clients in
1137                            list are newer */
1138                         break;
1139                 }
1140
1141                 if (client_is_idle(state)) {
1142                         DEBUG(5,("Idle client timed out, "
1143                                  "shutting down sock %d, pid %u\n",
1144                                  state->sock,
1145                                  (unsigned int)state->pid));
1146                 } else {
1147                         DEBUG(5,("Client request timed out, "
1148                                  "shutting down sock %d, pid %u\n",
1149                                  state->sock,
1150                                  (unsigned int)state->pid));
1151                 }
1152
1153                 remove_client(state);
1154         }
1155 }
1156
1157 static 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
1171 struct winbindd_listen_state {
1172         bool privileged;
1173         int fd;
1174 };
1175
1176 static 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
1204 char *get_winbind_priv_pipe_dir(void)
1205 {
1206         return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1207 }
1208
1209 static 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
1238 static 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(server_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(server_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(server_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(server_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(server_event_context(), NULL,
1305                                        timeval_current(), NULL);
1306         return true;
1307 failed:
1308         TALLOC_FREE(pub_state);
1309         TALLOC_FREE(priv_state);
1310         return false;
1311 }
1312
1313 bool winbindd_use_idmap_cache(void)
1314 {
1315         return !opt_nocache;
1316 }
1317
1318 bool winbindd_use_cache(void)
1319 {
1320         return !opt_nocache;
1321 }
1322
1323 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1324                                        bool foreground)
1325 {
1326         bool scan_trusts = true;
1327         NTSTATUS status;
1328         /* Setup signal handlers */
1329
1330         if (!winbindd_setup_sig_term_handler(true))
1331                 exit(1);
1332         if (!winbindd_setup_stdin_handler(true, foreground))
1333                 exit(1);
1334         if (!winbindd_setup_sig_hup_handler(NULL))
1335                 exit(1);
1336         if (!winbindd_setup_sig_chld_handler())
1337                 exit(1);
1338         if (!winbindd_setup_sig_usr2_handler())
1339                 exit(1);
1340
1341         CatchSignal(SIGPIPE, SIG_IGN);                 /* Ignore sigpipe */
1342
1343         /*
1344          * Ensure all cache and idmap caches are consistent
1345          * and initialized before we startup.
1346          */
1347         if (!winbindd_cache_validate_and_initialize()) {
1348                 exit(1);
1349         }
1350
1351         /* React on 'smbcontrol winbindd reload-config' in the same way
1352            as to SIGHUP signal */
1353         messaging_register(msg_ctx, NULL,
1354                            MSG_SMB_CONF_UPDATED, msg_reload_services);
1355         messaging_register(msg_ctx, NULL,
1356                            MSG_SHUTDOWN, msg_shutdown);
1357
1358         /* Handle online/offline messages. */
1359         messaging_register(msg_ctx, NULL,
1360                            MSG_WINBIND_OFFLINE, winbind_msg_offline);
1361         messaging_register(msg_ctx, NULL,
1362                            MSG_WINBIND_ONLINE, winbind_msg_online);
1363         messaging_register(msg_ctx, NULL,
1364                            MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1365
1366         /* Handle domain online/offline messages for domains */
1367         messaging_register(server_messaging_context(), NULL,
1368                            MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1369         messaging_register(server_messaging_context(), NULL,
1370                            MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1371
1372         messaging_register(msg_ctx, NULL,
1373                            MSG_WINBIND_VALIDATE_CACHE,
1374                            winbind_msg_validate_cache);
1375
1376         messaging_register(msg_ctx, NULL,
1377                            MSG_WINBIND_DUMP_DOMAIN_LIST,
1378                            winbind_msg_dump_domain_list);
1379
1380         messaging_register(msg_ctx, NULL,
1381                            MSG_WINBIND_IP_DROPPED,
1382                            winbind_msg_ip_dropped_parent);
1383
1384         /* Register handler for MSG_DEBUG. */
1385         messaging_register(msg_ctx, NULL,
1386                            MSG_DEBUG,
1387                            winbind_msg_debug);
1388
1389         messaging_register(msg_ctx, NULL,
1390                            MSG_WINBIND_DISCONNECT_DC,
1391                            winbind_disconnect_dc_parent);
1392
1393         netsamlogon_cache_init(); /* Non-critical */
1394
1395         /* clear the cached list of trusted domains */
1396
1397         wcache_tdc_clear();
1398
1399         if (!init_domain_list()) {
1400                 DEBUG(0,("unable to initialize domain list\n"));
1401                 exit(1);
1402         }
1403
1404         init_idmap_child();
1405         init_locator_child();
1406
1407         smb_nscd_flush_user_cache();
1408         smb_nscd_flush_group_cache();
1409
1410         if (!lp_winbind_scan_trusted_domains()) {
1411                 scan_trusts = false;
1412         }
1413
1414         if (!lp_allow_trusted_domains()) {
1415                 scan_trusts = false;
1416         }
1417
1418         if (IS_DC) {
1419                 scan_trusts = false;
1420         }
1421
1422         if (scan_trusts) {
1423                 if (tevent_add_timer(server_event_context(), NULL, timeval_zero(),
1424                               rescan_trusted_domains, NULL) == NULL) {
1425                         DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1426                         exit(1);
1427                 }
1428         }
1429
1430         status = wb_irpc_register();
1431
1432         if (!NT_STATUS_IS_OK(status)) {
1433                 DEBUG(0, ("Could not register IRPC handlers\n"));
1434                 exit(1);
1435         }
1436 }
1437
1438 struct winbindd_addrchanged_state {
1439         struct addrchange_context *ctx;
1440         struct tevent_context *ev;
1441         struct messaging_context *msg_ctx;
1442 };
1443
1444 static void winbindd_addr_changed(struct tevent_req *req);
1445
1446 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1447                                      struct tevent_context *ev,
1448                                      struct messaging_context *msg_ctx)
1449 {
1450         struct winbindd_addrchanged_state *state;
1451         struct tevent_req *req;
1452         NTSTATUS status;
1453
1454         state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1455         if (state == NULL) {
1456                 DEBUG(10, ("talloc failed\n"));
1457                 return;
1458         }
1459         state->ev = ev;
1460         state->msg_ctx = msg_ctx;
1461
1462         status = addrchange_context_create(state, &state->ctx);
1463         if (!NT_STATUS_IS_OK(status)) {
1464                 DEBUG(10, ("addrchange_context_create failed: %s\n",
1465                            nt_errstr(status)));
1466                 TALLOC_FREE(state);
1467                 return;
1468         }
1469         req = addrchange_send(state, ev, state->ctx);
1470         if (req == NULL) {
1471                 DEBUG(0, ("addrchange_send failed\n"));
1472                 TALLOC_FREE(state);
1473                 return;
1474         }
1475         tevent_req_set_callback(req, winbindd_addr_changed, state);
1476 }
1477
1478 static void winbindd_addr_changed(struct tevent_req *req)
1479 {
1480         struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1481                 req, struct winbindd_addrchanged_state);
1482         enum addrchange_type type;
1483         struct sockaddr_storage addr;
1484         NTSTATUS status;
1485
1486         status = addrchange_recv(req, &type, &addr);
1487         TALLOC_FREE(req);
1488         if (!NT_STATUS_IS_OK(status)) {
1489                 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1490                            nt_errstr(status)));
1491                 TALLOC_FREE(state);
1492                 return;
1493         }
1494         if (type == ADDRCHANGE_DEL) {
1495                 char addrstr[INET6_ADDRSTRLEN];
1496                 DATA_BLOB blob;
1497
1498                 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1499
1500                 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1501                           addrstr));
1502
1503                 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1504
1505                 status = messaging_send(state->msg_ctx,
1506                                         messaging_server_id(state->msg_ctx),
1507                                         MSG_WINBIND_IP_DROPPED, &blob);
1508                 if (!NT_STATUS_IS_OK(status)) {
1509                         DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1510                                    nt_errstr(status)));
1511                 }
1512         }
1513         req = addrchange_send(state, state->ev, state->ctx);
1514         if (req == NULL) {
1515                 DEBUG(0, ("addrchange_send failed\n"));
1516                 TALLOC_FREE(state);
1517                 return;
1518         }
1519         tevent_req_set_callback(req, winbindd_addr_changed, state);
1520 }
1521
1522 /* Main function */
1523
1524 int main(int argc, const char **argv)
1525 {
1526         static bool is_daemon = False;
1527         static bool Fork = True;
1528         static bool log_stdout = False;
1529         static bool no_process_group = False;
1530         enum {
1531                 OPT_DAEMON = 1000,
1532                 OPT_FORK,
1533                 OPT_NO_PROCESS_GROUP,
1534                 OPT_LOG_STDOUT
1535         };
1536         struct poptOption long_options[] = {
1537                 POPT_AUTOHELP
1538                 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1539                 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1540                 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1541                 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1542                 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1543                 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1544                 POPT_COMMON_SAMBA
1545                 POPT_TABLEEND
1546         };
1547         poptContext pc;
1548         int opt;
1549         TALLOC_CTX *frame;
1550         NTSTATUS status;
1551         bool ok;
1552
1553         setproctitle_init(argc, discard_const(argv), environ);
1554
1555         /*
1556          * Do this before any other talloc operation
1557          */
1558         talloc_enable_null_tracking();
1559         frame = talloc_stackframe();
1560
1561         /*
1562          * We want total control over the permissions on created files,
1563          * so set our umask to 0.
1564          */
1565         umask(0);
1566
1567         setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1568
1569         /* glibc (?) likes to print "User defined signal 1" and exit if a
1570            SIGUSR[12] is received before a handler is installed */
1571
1572         CatchSignal(SIGUSR1, SIG_IGN);
1573         CatchSignal(SIGUSR2, SIG_IGN);
1574
1575         fault_setup();
1576         dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1577
1578         smb_init_locale();
1579
1580         /* Initialise for running in non-root mode */
1581
1582         sec_init();
1583
1584         set_remote_machine_name("winbindd", False);
1585
1586         /* Set environment variable so we don't recursively call ourselves.
1587            This may also be useful interactively. */
1588
1589         if ( !winbind_off() ) {
1590                 DEBUG(0,("Failed to disable recusive winbindd calls.  Exiting.\n"));
1591                 exit(1);
1592         }
1593
1594         /* Initialise samba/rpc client stuff */
1595
1596         pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1597
1598         while ((opt = poptGetNextOpt(pc)) != -1) {
1599                 switch (opt) {
1600                         /* Don't become a daemon */
1601                 case OPT_DAEMON:
1602                         is_daemon = True;
1603                         break;
1604                 case 'i':
1605                         interactive = True;
1606                         log_stdout = True;
1607                         Fork = False;
1608                         break;
1609                 case OPT_FORK:
1610                         Fork = false;
1611                         break;
1612                 case OPT_NO_PROCESS_GROUP:
1613                         no_process_group = true;
1614                         break;
1615                 case OPT_LOG_STDOUT:
1616                         log_stdout = true;
1617                         break;
1618                 case 'n':
1619                         opt_nocache = true;
1620                         break;
1621                 default:
1622                         d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1623                                   poptBadOption(pc, 0), poptStrerror(opt));
1624                         poptPrintUsage(pc, stderr, 0);
1625                         exit(1);
1626                 }
1627         }
1628
1629         /* We call dump_core_setup one more time because the command line can
1630          * set the log file or the log-basename and this will influence where
1631          * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1632          * the default value derived from build's prefix. For EOM this value
1633          * is often not related to the path where winbindd is actually run
1634          * in production.
1635          */
1636         dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1637         if (is_daemon && interactive) {
1638                 d_fprintf(stderr,"\nERROR: "
1639                           "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1640                 poptPrintUsage(pc, stderr, 0);
1641                 exit(1);
1642         }
1643
1644         if (log_stdout && Fork) {
1645                 d_fprintf(stderr, "\nERROR: "
1646                           "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1647                 poptPrintUsage(pc, stderr, 0);
1648                 exit(1);
1649         }
1650
1651         poptFreeContext(pc);
1652
1653         if (!override_logfile) {
1654                 char *lfile = NULL;
1655                 if (asprintf(&lfile,"%s/log.winbindd",
1656                                 get_dyn_LOGFILEBASE()) > 0) {
1657                         lp_set_logfile(lfile);
1658                         SAFE_FREE(lfile);
1659                 }
1660         }
1661
1662         if (log_stdout) {
1663                 setup_logging("winbindd", DEBUG_STDOUT);
1664         } else {
1665                 setup_logging("winbindd", DEBUG_FILE);
1666         }
1667         reopen_logs();
1668
1669         DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1670         DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1671
1672         if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1673                 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1674                 exit(1);
1675         }
1676         /* After parsing the configuration file we setup the core path one more time
1677          * as the log file might have been set in the configuration and cores's
1678          * path is by default basename(lp_logfile()).
1679          */
1680         dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1681
1682         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1683             && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1684                 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1685                 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"));
1686                 exit(1);
1687         }
1688
1689         if (!cluster_probe_ok()) {
1690                 exit(1);
1691         }
1692
1693         /* Initialise messaging system */
1694
1695         if (server_messaging_context() == NULL) {
1696                 exit(1);
1697         }
1698
1699         if (!reload_services_file(NULL)) {
1700                 DEBUG(0, ("error opening config file\n"));
1701                 exit(1);
1702         }
1703
1704         {
1705                 size_t i;
1706                 const char *idmap_backend;
1707                 const char *invalid_backends[] = {
1708                         "ad", "rfc2307", "rid",
1709                 };
1710
1711                 idmap_backend = lp_idmap_default_backend();
1712                 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1713                         ok = strequal(idmap_backend, invalid_backends[i]);
1714                         if (ok) {
1715                                 DBG_ERR("FATAL: Invalid idmap backend %s "
1716                                         "configured as the default backend!\n",
1717                                         idmap_backend);
1718                                 exit(1);
1719                         }
1720                 }
1721         }
1722
1723         ok = directory_create_or_exist(lp_lock_directory(), 0755);
1724         if (!ok) {
1725                 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1726                           lp_lock_directory(), strerror(errno)));
1727                 exit(1);
1728         }
1729
1730         ok = directory_create_or_exist(lp_pid_directory(), 0755);
1731         if (!ok) {
1732                 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1733                           lp_pid_directory(), strerror(errno)));
1734                 exit(1);
1735         }
1736
1737         /* Setup names. */
1738
1739         if (!init_names())
1740                 exit(1);
1741
1742         load_interfaces();
1743
1744         if (!secrets_init()) {
1745
1746                 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1747                 return False;
1748         }
1749
1750         status = rpccli_pre_open_netlogon_creds();
1751         if (!NT_STATUS_IS_OK(status)) {
1752                 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1753                           nt_errstr(status)));
1754                 exit(1);
1755         }
1756
1757         /* Unblock all signals we are interested in as they may have been
1758            blocked by the parent process. */
1759
1760         BlockSignals(False, SIGINT);
1761         BlockSignals(False, SIGQUIT);
1762         BlockSignals(False, SIGTERM);
1763         BlockSignals(False, SIGUSR1);
1764         BlockSignals(False, SIGUSR2);
1765         BlockSignals(False, SIGHUP);
1766         BlockSignals(False, SIGCHLD);
1767
1768         if (!interactive)
1769                 become_daemon(Fork, no_process_group, log_stdout);
1770
1771         pidfile_create(lp_pid_directory(), "winbindd");
1772
1773 #if HAVE_SETPGID
1774         /*
1775          * If we're interactive we want to set our own process group for
1776          * signal management.
1777          */
1778         if (interactive && !no_process_group)
1779                 setpgid( (pid_t)0, (pid_t)0);
1780 #endif
1781
1782         TimeInit();
1783
1784         /* Don't use winbindd_reinit_after_fork here as
1785          * we're just starting up and haven't created any
1786          * winbindd-specific resources we must free yet. JRA.
1787          */
1788
1789         status = reinit_after_fork(server_messaging_context(),
1790                                    server_event_context(),
1791                                    false, NULL);
1792         if (!NT_STATUS_IS_OK(status)) {
1793                 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1794         }
1795         initialize_password_db(true, server_event_context());
1796
1797         /*
1798          * Do not initialize the parent-child-pipe before becoming
1799          * a daemon: this is used to detect a died parent in the child
1800          * process.
1801          */
1802         status = init_before_fork();
1803         if (!NT_STATUS_IS_OK(status)) {
1804                 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1805         }
1806
1807         winbindd_register_handlers(server_messaging_context(), !Fork);
1808
1809         if (!messaging_parent_dgm_cleanup_init(server_messaging_context())) {
1810                 exit(1);
1811         }
1812
1813         status = init_system_session_info(NULL);
1814         if (!NT_STATUS_IS_OK(status)) {
1815                 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1816         }
1817
1818         rpc_lsarpc_init(NULL);
1819         rpc_samr_init(NULL);
1820
1821         winbindd_init_addrchange(NULL, server_event_context(),
1822                                  server_messaging_context());
1823
1824         /* setup listen sockets */
1825
1826         if (!winbindd_setup_listeners()) {
1827                 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1828         }
1829
1830         irpc_add_name(winbind_imessaging_context(), "winbind_server");
1831
1832         TALLOC_FREE(frame);
1833
1834         if (!interactive) {
1835                 daemon_ready("winbindd");
1836         }
1837
1838         gpupdate_init();
1839
1840         /* Loop waiting for requests */
1841         while (1) {
1842                 frame = talloc_stackframe();
1843
1844                 if (tevent_loop_once(server_event_context()) == -1) {
1845                         DEBUG(1, ("tevent_loop_once() failed: %s\n",
1846                                   strerror(errno)));
1847                         return 1;
1848                 }
1849
1850                 TALLOC_FREE(frame);
1851         }
1852
1853         return 0;
1854 }