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