s3:rpc_client: implement bind time feature negotiation
[metze/samba-autobuild/.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         memcpy(cli_state->client_name,
712                cli_state->request->client_name,
713                sizeof(cli_state->client_name));
714
715         cli_state->cmd_name = "unknown request";
716         cli_state->recv_fn = NULL;
717
718         /* client is newest */
719         winbindd_promote_client(cli_state);
720
721         for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
722                 if (cmd == atable->cmd) {
723                         break;
724                 }
725         }
726
727         if ((atable->send_req == NULL) && cli_state->privileged) {
728                 for (atable = async_priv_table; atable->send_req;
729                      atable += 1) {
730                         if (cmd == atable->cmd) {
731                                 break;
732                         }
733                 }
734         }
735
736         if (atable->send_req != NULL) {
737                 cli_state->cmd_name = atable->cmd_name;
738                 cli_state->recv_fn = atable->recv_req;
739
740                 DBG_DEBUG("process_request: "
741                           "Handling async request %s(%d):%s\n",
742                           cli_state->client_name,
743                           (int)cli_state->pid,
744                           cli_state->cmd_name);
745
746                 subreq = atable->send_req(
747                         state,
748                         state->ev,
749                         cli_state,
750                         cli_state->request);
751                 if (tevent_req_nomem(subreq, req)) {
752                         return tevent_req_post(req, ev);
753                 }
754                 tevent_req_set_callback(subreq, process_request_done, req);
755                 return req;
756         }
757
758         for (i=0; i<ARRAY_SIZE(bool_dispatch_table); i++) {
759                 if (cmd == bool_dispatch_table[i].cmd) {
760                         break;
761                 }
762         }
763
764         ok = false;
765
766         if (i < ARRAY_SIZE(bool_dispatch_table)) {
767                 DBG_DEBUG("process_request: request fn %s\n",
768                           bool_dispatch_table[i].cmd_name);
769                 ok = bool_dispatch_table[i].fn(cli_state);
770         }
771
772         cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
773
774         TALLOC_FREE(cli_state->io_req);
775         TALLOC_FREE(cli_state->request);
776
777         subreq = wb_resp_write_send(
778                 state,
779                 state->ev,
780                 cli_state->out_queue,
781                 cli_state->sock,
782                 cli_state->response);
783         if (tevent_req_nomem(subreq, req)) {
784                 return tevent_req_post(req, ev);
785         }
786         tevent_req_set_callback(subreq, process_request_written, req);
787
788         cli_state->io_req = subreq;
789
790         return req;
791 }
792
793 static void process_request_done(struct tevent_req *subreq)
794 {
795         struct tevent_req *req = tevent_req_callback_data(
796                 subreq, struct tevent_req);
797         struct process_request_state *state = tevent_req_data(
798                 req, struct process_request_state);
799         struct winbindd_cli_state *cli_state = state->cli_state;
800         NTSTATUS status;
801         bool ok;
802
803         status = cli_state->recv_fn(subreq, cli_state->response);
804         TALLOC_FREE(subreq);
805
806         DBG_DEBUG("[%s(%d):%s]: %s\n",
807                   cli_state->client_name,
808                   (int)cli_state->pid,
809                   cli_state->cmd_name,
810                   nt_errstr(status));
811
812         ok = NT_STATUS_IS_OK(status);
813         cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
814
815         TALLOC_FREE(cli_state->io_req);
816         TALLOC_FREE(cli_state->request);
817
818         subreq = wb_resp_write_send(
819                 state,
820                 state->ev,
821                 cli_state->out_queue,
822                 cli_state->sock,
823                 cli_state->response);
824         if (tevent_req_nomem(subreq, req)) {
825                 return;
826         }
827         tevent_req_set_callback(subreq, process_request_written, req);
828
829         cli_state->io_req = subreq;
830 }
831
832 static void process_request_written(struct tevent_req *subreq)
833 {
834         struct tevent_req *req = tevent_req_callback_data(
835                 subreq, struct tevent_req);
836         struct process_request_state *state = tevent_req_data(
837                 req, struct process_request_state);
838         struct winbindd_cli_state *cli_state = state->cli_state;
839         ssize_t ret;
840         int err;
841
842         cli_state->io_req = NULL;
843
844         ret = wb_resp_write_recv(subreq, &err);
845         TALLOC_FREE(subreq);
846         if (ret == -1) {
847                 tevent_req_nterror(req, map_nt_error_from_unix(err));
848                 return;
849         }
850
851         DBG_DEBUG("[%s(%d):%s]: delivered response to client\n",
852                   cli_state->client_name,
853                   (int)cli_state->pid,
854                   cli_state->cmd_name);
855
856         TALLOC_FREE(cli_state->mem_ctx);
857         cli_state->response = NULL;
858         cli_state->cmd_name = "no request";
859         cli_state->recv_fn = NULL;
860
861         tevent_req_done(req);
862 }
863
864 static NTSTATUS process_request_recv(
865         struct tevent_req *req,
866         TALLOC_CTX *mem_ctx,
867         struct tevent_req_profile **profile)
868 {
869         NTSTATUS status;
870
871         if (tevent_req_is_nterror(req, &status)) {
872                 tevent_req_received(req);
873                 return status;
874         }
875
876         *profile = tevent_req_move_profile(req, mem_ctx);
877         tevent_req_received(req);
878         return NT_STATUS_OK;
879 }
880
881 /*
882  * This is the main event loop of winbind requests. It goes through a
883  * state-machine of 3 read/write requests, 4 if you have extra data to send.
884  *
885  * An idle winbind client has a read request of 4 bytes outstanding,
886  * finalizing function is request_len_recv, checking the length. request_recv
887  * then processes the packet. The processing function then at some point has
888  * to call request_finished which schedules sending the response.
889  */
890
891 static void winbind_client_request_read(struct tevent_req *req);
892 static void winbind_client_activity(struct tevent_req *req);
893 static void winbind_client_processed(struct tevent_req *req);
894
895 /* Process a new connection by adding it to the client connection list */
896
897 static void new_connection(int listen_sock, bool privileged)
898 {
899         struct sockaddr_un sunaddr;
900         struct winbindd_cli_state *state;
901         struct tevent_req *req;
902         socklen_t len;
903         int sock;
904
905         /* Accept connection */
906
907         len = sizeof(sunaddr);
908
909         sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
910
911         if (sock == -1) {
912                 if (errno != EINTR) {
913                         DEBUG(0, ("Failed to accept socket - %s\n",
914                                   strerror(errno)));
915                 }
916                 return;
917         }
918         smb_set_close_on_exec(sock);
919
920         DEBUG(6,("accepted socket %d\n", sock));
921
922         /* Create new connection structure */
923
924         if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
925                 close(sock);
926                 return;
927         }
928
929         state->sock = sock;
930
931         state->out_queue = tevent_queue_create(state, "winbind client reply");
932         if (state->out_queue == NULL) {
933                 close(sock);
934                 TALLOC_FREE(state);
935                 return;
936         }
937
938         state->privileged = privileged;
939
940         req = wb_req_read_send(state, global_event_context(), state->sock,
941                                WINBINDD_MAX_EXTRA_DATA);
942         if (req == NULL) {
943                 TALLOC_FREE(state);
944                 close(sock);
945                 return;
946         }
947         tevent_req_set_callback(req, winbind_client_request_read, state);
948         state->io_req = req;
949
950         /* Add to connection list */
951
952         winbindd_add_client(state);
953 }
954
955 static void winbind_client_request_read(struct tevent_req *req)
956 {
957         struct winbindd_cli_state *state = tevent_req_callback_data(
958                 req, struct winbindd_cli_state);
959         ssize_t ret;
960         int err;
961
962         state->io_req = NULL;
963
964         ret = wb_req_read_recv(req, state, &state->request, &err);
965         TALLOC_FREE(req);
966         if (ret == -1) {
967                 if (err == EPIPE) {
968                         DEBUG(6, ("closing socket %d, client exited\n",
969                                   state->sock));
970                 } else {
971                         DEBUG(2, ("Could not read client request from fd %d: "
972                                   "%s\n", state->sock, strerror(err)));
973                 }
974                 close(state->sock);
975                 state->sock = -1;
976                 remove_client(state);
977                 return;
978         }
979
980         req = wait_for_read_send(state, global_event_context(), state->sock,
981                                  true);
982         if (req == NULL) {
983                 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
984                           " wait_for_read_send failed - removing client\n",
985                           (int)state->pid, state->cmd_name));
986                 remove_client(state);
987                 return;
988         }
989         tevent_req_set_callback(req, winbind_client_activity, state);
990         state->io_req = req;
991
992         req = process_request_send(state, global_event_context(), state);
993         if (req == NULL) {
994                 DBG_ERR("process_request_send failed\n");
995                 remove_client(state);
996                 return;
997         }
998         tevent_req_set_callback(req, winbind_client_processed, state);
999 }
1000
1001 static void winbind_client_activity(struct tevent_req *req)
1002 {
1003         struct winbindd_cli_state *state =
1004             tevent_req_callback_data(req, struct winbindd_cli_state);
1005         int err;
1006         bool has_data;
1007
1008         has_data = wait_for_read_recv(req, &err);
1009
1010         if (has_data) {
1011                 DEBUG(0, ("winbind_client_activity[%d:%s]:"
1012                           "unexpected data from client - removing client\n",
1013                           (int)state->pid, state->cmd_name));
1014         } else {
1015                 if (err == EPIPE) {
1016                         DEBUG(6, ("winbind_client_activity[%d:%s]: "
1017                                   "client has closed connection - removing "
1018                                   "client\n",
1019                                   (int)state->pid, state->cmd_name));
1020                 } else {
1021                         DEBUG(2, ("winbind_client_activity[%d:%s]: "
1022                                   "client socket error (%s) - removing "
1023                                   "client\n",
1024                                   (int)state->pid, state->cmd_name,
1025                                   strerror(err)));
1026                 }
1027         }
1028
1029         remove_client(state);
1030 }
1031
1032 static void winbind_client_processed(struct tevent_req *req)
1033 {
1034         struct winbindd_cli_state *cli_state = tevent_req_callback_data(
1035                 req, struct winbindd_cli_state);
1036         struct tevent_req_profile *profile = NULL;
1037         struct timeval start, stop, diff;
1038         int threshold;
1039         NTSTATUS status;
1040
1041         status = process_request_recv(req, cli_state, &profile);
1042         TALLOC_FREE(req);
1043         if (!NT_STATUS_IS_OK(status)) {
1044                 DBG_DEBUG("process_request failed: %s\n", nt_errstr(status));
1045                 remove_client(cli_state);
1046                 return;
1047         }
1048
1049         tevent_req_profile_get_start(profile, NULL, &start);
1050         tevent_req_profile_get_stop(profile, NULL, &stop);
1051         diff = tevent_timeval_until(&start, &stop);
1052
1053         threshold = lp_parm_int(-1, "winbind", "request profile threshold", 60);
1054
1055         if (diff.tv_sec >= threshold) {
1056                 int depth;
1057                 char *str;
1058
1059                 depth = lp_parm_int(
1060                         -1,
1061                         "winbind",
1062                         "request profile depth",
1063                         INT_MAX);
1064
1065                 DBG_ERR("request took %u.%.6u seconds\n",
1066                         (unsigned)diff.tv_sec, (unsigned)diff.tv_usec);
1067
1068                 str = tevent_req_profile_string(
1069                         talloc_tos(), profile, 0, depth);
1070                 if (str != NULL) {
1071                         /* No "\n", already contained in "str" */
1072                         DEBUGADD(0, ("%s", str));
1073                 }
1074                 TALLOC_FREE(str);
1075         }
1076
1077         TALLOC_FREE(profile);
1078
1079         req = wb_req_read_send(
1080                 cli_state,
1081                 global_event_context(),
1082                 cli_state->sock,
1083                 WINBINDD_MAX_EXTRA_DATA);
1084         if (req == NULL) {
1085                 remove_client(cli_state);
1086                 return;
1087         }
1088         tevent_req_set_callback(req, winbind_client_request_read, cli_state);
1089         cli_state->io_req = req;
1090 }
1091
1092 /* Remove a client connection from client connection list */
1093
1094 static void remove_client(struct winbindd_cli_state *state)
1095 {
1096         /* It's a dead client - hold a funeral */
1097
1098         if (state == NULL) {
1099                 return;
1100         }
1101
1102         /*
1103          * We need to remove a pending wb_req_read_*
1104          * or wb_resp_write_* request before closing the
1105          * socket.
1106          *
1107          * This is important as they might have used tevent_add_fd() and we
1108          * use the epoll * backend on linux. So we must remove the tevent_fd
1109          * before closing the fd.
1110          *
1111          * Otherwise we might hit a race with close_conns_after_fork() (via
1112          * winbindd_reinit_after_fork()) where a file descriptor
1113          * is still open in a child, which means it's still active in
1114          * the parents epoll queue, but the related tevent_fd is already
1115          * already gone in the parent.
1116          *
1117          * See bug #11141.
1118          */
1119         TALLOC_FREE(state->io_req);
1120
1121         if (state->sock != -1) {
1122                 char c = 0;
1123                 int nwritten;
1124
1125                 /* tell client, we are closing ... */
1126                 nwritten = write(state->sock, &c, sizeof(c));
1127                 if (nwritten == -1) {
1128                         DEBUG(2, ("final write to client failed: %s\n",
1129                                 strerror(errno)));
1130                 }
1131
1132                 /* Close socket */
1133
1134                 close(state->sock);
1135                 state->sock = -1;
1136         }
1137
1138         TALLOC_FREE(state->mem_ctx);
1139
1140         /* Remove from list and free */
1141
1142         winbindd_remove_client(state);
1143         TALLOC_FREE(state);
1144 }
1145
1146 /* Is a client idle? */
1147
1148 static bool client_is_idle(struct winbindd_cli_state *state) {
1149   return (state->request == NULL &&
1150           state->response == NULL &&
1151           !state->pwent_state && !state->grent_state);
1152 }
1153
1154 /* Shutdown client connection which has been idle for the longest time */
1155
1156 static bool remove_idle_client(void)
1157 {
1158         struct winbindd_cli_state *state, *remove_state = NULL;
1159         int nidle = 0;
1160
1161         for (state = winbindd_client_list(); state; state = state->next) {
1162                 if (client_is_idle(state)) {
1163                         nidle++;
1164                         /* list is sorted by access time */
1165                         remove_state = state;
1166                 }
1167         }
1168
1169         if (remove_state) {
1170                 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1171                         nidle, remove_state->sock, (unsigned int)remove_state->pid));
1172                 remove_client(remove_state);
1173                 return True;
1174         }
1175
1176         return False;
1177 }
1178
1179 /*
1180  * Terminate all clients whose requests have taken longer than
1181  * "winbind request timeout" seconds to process, or have been
1182  * idle for more than "winbind request timeout" seconds.
1183  */
1184
1185 static void remove_timed_out_clients(void)
1186 {
1187         struct winbindd_cli_state *state, *prev = NULL;
1188         time_t curr_time = time(NULL);
1189         int timeout_val = lp_winbind_request_timeout();
1190
1191         for (state = winbindd_client_list_tail(); state; state = prev) {
1192                 time_t expiry_time;
1193
1194                 prev = winbindd_client_list_prev(state);
1195                 expiry_time = state->last_access + timeout_val;
1196
1197                 if (curr_time <= expiry_time) {
1198                         /* list is sorted, previous clients in
1199                            list are newer */
1200                         break;
1201                 }
1202
1203                 if (client_is_idle(state)) {
1204                         DEBUG(5,("Idle client timed out, "
1205                                  "shutting down sock %d, pid %u\n",
1206                                  state->sock,
1207                                  (unsigned int)state->pid));
1208                 } else {
1209                         DEBUG(5,("Client request timed out, "
1210                                  "shutting down sock %d, pid %u\n",
1211                                  state->sock,
1212                                  (unsigned int)state->pid));
1213                 }
1214
1215                 remove_client(state);
1216         }
1217 }
1218
1219 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
1220                                            struct tevent_timer *te,
1221                                            struct timeval current_time,
1222                                            void *private_data)
1223 {
1224         remove_timed_out_clients();
1225         if (tevent_add_timer(ev, ev,
1226                              timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
1227                              winbindd_scrub_clients_handler, NULL) == NULL) {
1228                 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
1229                 exit(1);
1230         }
1231 }
1232
1233 struct winbindd_listen_state {
1234         bool privileged;
1235         int fd;
1236 };
1237
1238 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1239                                         struct tevent_fd *fde,
1240                                         uint16_t flags,
1241                                         void *private_data)
1242 {
1243         struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1244                                           struct winbindd_listen_state);
1245
1246         while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1247                 DEBUG(5,("winbindd: Exceeding %d client "
1248                          "connections, removing idle "
1249                          "connection.\n", lp_winbind_max_clients()));
1250                 if (!remove_idle_client()) {
1251                         DEBUG(0,("winbindd: Exceeding %d "
1252                                  "client connections, no idle "
1253                                  "connection found\n",
1254                                  lp_winbind_max_clients()));
1255                         break;
1256                 }
1257         }
1258         remove_timed_out_clients();
1259         new_connection(s->fd, s->privileged);
1260 }
1261
1262 /*
1263  * Winbindd socket accessor functions
1264  */
1265
1266 char *get_winbind_priv_pipe_dir(void)
1267 {
1268         return state_path(talloc_tos(), WINBINDD_PRIV_SOCKET_SUBDIR);
1269 }
1270
1271 static void winbindd_setup_max_fds(void)
1272 {
1273         int num_fds = MAX_OPEN_FUDGEFACTOR;
1274         int actual_fds;
1275
1276         num_fds += lp_winbind_max_clients();
1277         /* Add some more to account for 2 sockets open
1278            when the client transitions from unprivileged
1279            to privileged socket
1280         */
1281         num_fds += lp_winbind_max_clients() / 10;
1282
1283         /* Add one socket per child process
1284            (yeah there are child processes other than the
1285            domain children but only domain children can vary
1286            with configuration
1287         */
1288         num_fds += lp_winbind_max_domain_connections() *
1289                    (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
1290
1291         actual_fds = set_maxfiles(num_fds);
1292
1293         if (actual_fds < num_fds) {
1294                 DEBUG(1, ("winbindd_setup_max_fds: Information only: "
1295                           "requested %d open files, %d are available.\n",
1296                           num_fds, actual_fds));
1297         }
1298 }
1299
1300 static bool winbindd_setup_listeners(void)
1301 {
1302         struct winbindd_listen_state *pub_state = NULL;
1303         struct winbindd_listen_state *priv_state = NULL;
1304         struct tevent_fd *fde;
1305         int rc;
1306         char *socket_path;
1307
1308         pub_state = talloc(global_event_context(),
1309                            struct winbindd_listen_state);
1310         if (!pub_state) {
1311                 goto failed;
1312         }
1313
1314         pub_state->privileged = false;
1315         pub_state->fd = create_pipe_sock(
1316                 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1317         if (pub_state->fd == -1) {
1318                 goto failed;
1319         }
1320         rc = listen(pub_state->fd, 5);
1321         if (rc < 0) {
1322                 goto failed;
1323         }
1324
1325         fde = tevent_add_fd(global_event_context(), pub_state, pub_state->fd,
1326                             TEVENT_FD_READ, winbindd_listen_fde_handler,
1327                             pub_state);
1328         if (fde == NULL) {
1329                 close(pub_state->fd);
1330                 goto failed;
1331         }
1332         tevent_fd_set_auto_close(fde);
1333
1334         priv_state = talloc(global_event_context(),
1335                             struct winbindd_listen_state);
1336         if (!priv_state) {
1337                 goto failed;
1338         }
1339
1340         socket_path = get_winbind_priv_pipe_dir();
1341         if (socket_path == NULL) {
1342                 goto failed;
1343         }
1344
1345         priv_state->privileged = true;
1346         priv_state->fd = create_pipe_sock(
1347                 socket_path, WINBINDD_SOCKET_NAME, 0750);
1348         TALLOC_FREE(socket_path);
1349         if (priv_state->fd == -1) {
1350                 goto failed;
1351         }
1352         rc = listen(priv_state->fd, 5);
1353         if (rc < 0) {
1354                 goto failed;
1355         }
1356
1357         fde = tevent_add_fd(global_event_context(), priv_state,
1358                             priv_state->fd, TEVENT_FD_READ,
1359                             winbindd_listen_fde_handler, priv_state);
1360         if (fde == NULL) {
1361                 close(priv_state->fd);
1362                 goto failed;
1363         }
1364         tevent_fd_set_auto_close(fde);
1365
1366         winbindd_scrub_clients_handler(global_event_context(), NULL,
1367                                        timeval_current(), NULL);
1368         return true;
1369 failed:
1370         TALLOC_FREE(pub_state);
1371         TALLOC_FREE(priv_state);
1372         return false;
1373 }
1374
1375 bool winbindd_use_idmap_cache(void)
1376 {
1377         return !opt_nocache;
1378 }
1379
1380 bool winbindd_use_cache(void)
1381 {
1382         return !opt_nocache;
1383 }
1384
1385 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1386                                        bool foreground)
1387 {
1388         bool scan_trusts = true;
1389         NTSTATUS status;
1390         /* Setup signal handlers */
1391
1392         if (!winbindd_setup_sig_term_handler(true))
1393                 exit(1);
1394         if (!winbindd_setup_stdin_handler(true, foreground))
1395                 exit(1);
1396         if (!winbindd_setup_sig_hup_handler(NULL))
1397                 exit(1);
1398         if (!winbindd_setup_sig_chld_handler())
1399                 exit(1);
1400         if (!winbindd_setup_sig_usr2_handler())
1401                 exit(1);
1402
1403         CatchSignal(SIGPIPE, SIG_IGN);                 /* Ignore sigpipe */
1404
1405         /*
1406          * Ensure all cache and idmap caches are consistent
1407          * and initialized before we startup.
1408          */
1409         if (!winbindd_cache_validate_and_initialize()) {
1410                 exit(1);
1411         }
1412
1413         /* React on 'smbcontrol winbindd reload-config' in the same way
1414            as to SIGHUP signal */
1415         messaging_register(msg_ctx, NULL,
1416                            MSG_SMB_CONF_UPDATED, msg_reload_services);
1417         messaging_register(msg_ctx, NULL,
1418                            MSG_SHUTDOWN, msg_shutdown);
1419
1420         /* Handle online/offline messages. */
1421         messaging_register(msg_ctx, NULL,
1422                            MSG_WINBIND_OFFLINE, winbind_msg_offline);
1423         messaging_register(msg_ctx, NULL,
1424                            MSG_WINBIND_ONLINE, winbind_msg_online);
1425         messaging_register(msg_ctx, NULL,
1426                            MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1427
1428         /* Handle domain online/offline messages for domains */
1429         messaging_register(global_messaging_context(), NULL,
1430                            MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1431         messaging_register(global_messaging_context(), NULL,
1432                            MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1433
1434         messaging_register(msg_ctx, NULL,
1435                            MSG_WINBIND_VALIDATE_CACHE,
1436                            winbind_msg_validate_cache);
1437
1438         messaging_register(msg_ctx, NULL,
1439                            MSG_WINBIND_DUMP_DOMAIN_LIST,
1440                            winbind_msg_dump_domain_list);
1441
1442         messaging_register(msg_ctx, NULL,
1443                            MSG_WINBIND_IP_DROPPED,
1444                            winbind_msg_ip_dropped_parent);
1445
1446         /* Register handler for MSG_DEBUG. */
1447         messaging_register(msg_ctx, NULL,
1448                            MSG_DEBUG,
1449                            winbind_msg_debug);
1450
1451         messaging_register(msg_ctx, NULL,
1452                            MSG_WINBIND_DISCONNECT_DC,
1453                            winbind_disconnect_dc_parent);
1454
1455         netsamlogon_cache_init(); /* Non-critical */
1456
1457         /* clear the cached list of trusted domains */
1458
1459         wcache_tdc_clear();
1460
1461         if (!init_domain_list()) {
1462                 DEBUG(0,("unable to initialize domain list\n"));
1463                 exit(1);
1464         }
1465
1466         init_idmap_child();
1467         init_locator_child();
1468
1469         smb_nscd_flush_user_cache();
1470         smb_nscd_flush_group_cache();
1471
1472         if (!lp_winbind_scan_trusted_domains()) {
1473                 scan_trusts = false;
1474         }
1475
1476         if (!lp_allow_trusted_domains()) {
1477                 scan_trusts = false;
1478         }
1479
1480         if (IS_DC) {
1481                 scan_trusts = false;
1482         }
1483
1484         if (scan_trusts) {
1485                 if (tevent_add_timer(global_event_context(), NULL, timeval_zero(),
1486                               rescan_trusted_domains, NULL) == NULL) {
1487                         DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1488                         exit(1);
1489                 }
1490         }
1491
1492         status = wb_irpc_register();
1493
1494         if (!NT_STATUS_IS_OK(status)) {
1495                 DEBUG(0, ("Could not register IRPC handlers\n"));
1496                 exit(1);
1497         }
1498 }
1499
1500 struct winbindd_addrchanged_state {
1501         struct addrchange_context *ctx;
1502         struct tevent_context *ev;
1503         struct messaging_context *msg_ctx;
1504 };
1505
1506 static void winbindd_addr_changed(struct tevent_req *req);
1507
1508 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1509                                      struct tevent_context *ev,
1510                                      struct messaging_context *msg_ctx)
1511 {
1512         struct winbindd_addrchanged_state *state;
1513         struct tevent_req *req;
1514         NTSTATUS status;
1515
1516         state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1517         if (state == NULL) {
1518                 DEBUG(10, ("talloc failed\n"));
1519                 return;
1520         }
1521         state->ev = ev;
1522         state->msg_ctx = msg_ctx;
1523
1524         status = addrchange_context_create(state, &state->ctx);
1525         if (!NT_STATUS_IS_OK(status)) {
1526                 DEBUG(10, ("addrchange_context_create failed: %s\n",
1527                            nt_errstr(status)));
1528                 TALLOC_FREE(state);
1529                 return;
1530         }
1531         req = addrchange_send(state, ev, state->ctx);
1532         if (req == NULL) {
1533                 DEBUG(0, ("addrchange_send failed\n"));
1534                 TALLOC_FREE(state);
1535                 return;
1536         }
1537         tevent_req_set_callback(req, winbindd_addr_changed, state);
1538 }
1539
1540 static void winbindd_addr_changed(struct tevent_req *req)
1541 {
1542         struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1543                 req, struct winbindd_addrchanged_state);
1544         enum addrchange_type type;
1545         struct sockaddr_storage addr;
1546         NTSTATUS status;
1547
1548         status = addrchange_recv(req, &type, &addr);
1549         TALLOC_FREE(req);
1550         if (!NT_STATUS_IS_OK(status)) {
1551                 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1552                            nt_errstr(status)));
1553                 TALLOC_FREE(state);
1554                 return;
1555         }
1556         if (type == ADDRCHANGE_DEL) {
1557                 char addrstr[INET6_ADDRSTRLEN];
1558                 DATA_BLOB blob;
1559
1560                 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1561
1562                 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1563                           addrstr));
1564
1565                 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1566
1567                 status = messaging_send(state->msg_ctx,
1568                                         messaging_server_id(state->msg_ctx),
1569                                         MSG_WINBIND_IP_DROPPED, &blob);
1570                 if (!NT_STATUS_IS_OK(status)) {
1571                         DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1572                                    nt_errstr(status)));
1573                 }
1574         }
1575         req = addrchange_send(state, state->ev, state->ctx);
1576         if (req == NULL) {
1577                 DEBUG(0, ("addrchange_send failed\n"));
1578                 TALLOC_FREE(state);
1579                 return;
1580         }
1581         tevent_req_set_callback(req, winbindd_addr_changed, state);
1582 }
1583
1584 /* Main function */
1585
1586 int main(int argc, const char **argv)
1587 {
1588         static bool is_daemon = False;
1589         static bool Fork = True;
1590         static bool log_stdout = False;
1591         static bool no_process_group = False;
1592         enum {
1593                 OPT_DAEMON = 1000,
1594                 OPT_FORK,
1595                 OPT_NO_PROCESS_GROUP,
1596                 OPT_LOG_STDOUT
1597         };
1598         struct poptOption long_options[] = {
1599                 POPT_AUTOHELP
1600                 {
1601                         .longName   = "stdout",
1602                         .shortName  = 'S',
1603                         .argInfo    = POPT_ARG_NONE,
1604                         .arg        = NULL,
1605                         .val        = OPT_LOG_STDOUT,
1606                         .descrip    = "Log to stdout",
1607                 },
1608                 {
1609                         .longName   = "foreground",
1610                         .shortName  = 'F',
1611                         .argInfo    = POPT_ARG_NONE,
1612                         .arg        = NULL,
1613                         .val        = OPT_FORK,
1614                         .descrip    = "Daemon in foreground mode",
1615                 },
1616                 {
1617                         .longName   = "no-process-group",
1618                         .shortName  = 0,
1619                         .argInfo    = POPT_ARG_NONE,
1620                         .arg        = NULL,
1621                         .val        = OPT_NO_PROCESS_GROUP,
1622                         .descrip    = "Don't create a new process group",
1623                 },
1624                 {
1625                         .longName   = "daemon",
1626                         .shortName  = 'D',
1627                         .argInfo    = POPT_ARG_NONE,
1628                         .arg        = NULL,
1629                         .val        = OPT_DAEMON,
1630                         .descrip    = "Become a daemon (default)",
1631                 },
1632                 {
1633                         .longName   = "interactive",
1634                         .shortName  = 'i',
1635                         .argInfo    = POPT_ARG_NONE,
1636                         .arg        = NULL,
1637                         .val        = 'i',
1638                         .descrip    = "Interactive mode",
1639                 },
1640                 {
1641                         .longName   = "no-caching",
1642                         .shortName  = 'n',
1643                         .argInfo    = POPT_ARG_NONE,
1644                         .arg        = NULL,
1645                         .val        = 'n',
1646                         .descrip    = "Disable caching",
1647                 },
1648                 POPT_COMMON_SAMBA
1649                 POPT_TABLEEND
1650         };
1651         poptContext pc;
1652         int opt;
1653         TALLOC_CTX *frame;
1654         NTSTATUS status;
1655         bool ok;
1656
1657         setproctitle_init(argc, discard_const(argv), environ);
1658
1659         /*
1660          * Do this before any other talloc operation
1661          */
1662         talloc_enable_null_tracking();
1663         frame = talloc_stackframe();
1664
1665         /*
1666          * We want total control over the permissions on created files,
1667          * so set our umask to 0.
1668          */
1669         umask(0);
1670
1671         setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1672
1673         /* glibc (?) likes to print "User defined signal 1" and exit if a
1674            SIGUSR[12] is received before a handler is installed */
1675
1676         CatchSignal(SIGUSR1, SIG_IGN);
1677         CatchSignal(SIGUSR2, SIG_IGN);
1678
1679         fault_setup();
1680         dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1681
1682         smb_init_locale();
1683
1684         /* Initialise for running in non-root mode */
1685
1686         sec_init();
1687
1688         set_remote_machine_name("winbindd", False);
1689
1690         /* Set environment variable so we don't recursively call ourselves.
1691            This may also be useful interactively. */
1692
1693         if ( !winbind_off() ) {
1694                 DEBUG(0,("Failed to disable recusive winbindd calls.  Exiting.\n"));
1695                 exit(1);
1696         }
1697
1698         /* Initialise samba/rpc client stuff */
1699
1700         pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1701
1702         while ((opt = poptGetNextOpt(pc)) != -1) {
1703                 switch (opt) {
1704                         /* Don't become a daemon */
1705                 case OPT_DAEMON:
1706                         is_daemon = True;
1707                         break;
1708                 case 'i':
1709                         interactive = True;
1710                         log_stdout = True;
1711                         Fork = False;
1712                         break;
1713                 case OPT_FORK:
1714                         Fork = false;
1715                         break;
1716                 case OPT_NO_PROCESS_GROUP:
1717                         no_process_group = true;
1718                         break;
1719                 case OPT_LOG_STDOUT:
1720                         log_stdout = true;
1721                         break;
1722                 case 'n':
1723                         opt_nocache = true;
1724                         break;
1725                 default:
1726                         d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1727                                   poptBadOption(pc, 0), poptStrerror(opt));
1728                         poptPrintUsage(pc, stderr, 0);
1729                         exit(1);
1730                 }
1731         }
1732
1733         /* We call dump_core_setup one more time because the command line can
1734          * set the log file or the log-basename and this will influence where
1735          * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1736          * the default value derived from build's prefix. For EOM this value
1737          * is often not related to the path where winbindd is actually run
1738          * in production.
1739          */
1740         dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1741         if (is_daemon && interactive) {
1742                 d_fprintf(stderr,"\nERROR: "
1743                           "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1744                 poptPrintUsage(pc, stderr, 0);
1745                 exit(1);
1746         }
1747
1748         if (log_stdout && Fork) {
1749                 d_fprintf(stderr, "\nERROR: "
1750                           "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1751                 poptPrintUsage(pc, stderr, 0);
1752                 exit(1);
1753         }
1754
1755         poptFreeContext(pc);
1756
1757         if (!override_logfile) {
1758                 char *lfile = NULL;
1759                 if (asprintf(&lfile,"%s/log.winbindd",
1760                                 get_dyn_LOGFILEBASE()) > 0) {
1761                         lp_set_logfile(lfile);
1762                         SAFE_FREE(lfile);
1763                 }
1764         }
1765
1766         if (log_stdout) {
1767                 setup_logging("winbindd", DEBUG_STDOUT);
1768         } else {
1769                 setup_logging("winbindd", DEBUG_FILE);
1770         }
1771         reopen_logs();
1772
1773         DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1774         DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1775
1776         if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1777                 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1778                 exit(1);
1779         }
1780         /* After parsing the configuration file we setup the core path one more time
1781          * as the log file might have been set in the configuration and cores's
1782          * path is by default basename(lp_logfile()).
1783          */
1784         dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1785
1786         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1787             && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1788                 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1789                 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"));
1790                 exit(1);
1791         }
1792
1793         if (!cluster_probe_ok()) {
1794                 exit(1);
1795         }
1796
1797         /* Initialise messaging system */
1798
1799         if (global_messaging_context() == NULL) {
1800                 exit(1);
1801         }
1802
1803         if (!reload_services_file(NULL)) {
1804                 DEBUG(0, ("error opening config file\n"));
1805                 exit(1);
1806         }
1807
1808         {
1809                 size_t i;
1810                 const char *idmap_backend;
1811                 const char *invalid_backends[] = {
1812                         "ad", "rfc2307", "rid",
1813                 };
1814
1815                 idmap_backend = lp_idmap_default_backend();
1816                 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1817                         ok = strequal(idmap_backend, invalid_backends[i]);
1818                         if (ok) {
1819                                 DBG_ERR("FATAL: Invalid idmap backend %s "
1820                                         "configured as the default backend!\n",
1821                                         idmap_backend);
1822                                 exit(1);
1823                         }
1824                 }
1825         }
1826
1827         ok = directory_create_or_exist(lp_lock_directory(), 0755);
1828         if (!ok) {
1829                 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1830                           lp_lock_directory(), strerror(errno)));
1831                 exit(1);
1832         }
1833
1834         ok = directory_create_or_exist(lp_pid_directory(), 0755);
1835         if (!ok) {
1836                 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1837                           lp_pid_directory(), strerror(errno)));
1838                 exit(1);
1839         }
1840
1841         /* Setup names. */
1842
1843         if (!init_names())
1844                 exit(1);
1845
1846         load_interfaces();
1847
1848         if (!secrets_init()) {
1849
1850                 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1851                 return False;
1852         }
1853
1854         status = rpccli_pre_open_netlogon_creds();
1855         if (!NT_STATUS_IS_OK(status)) {
1856                 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1857                           nt_errstr(status)));
1858                 exit(1);
1859         }
1860
1861         /* Unblock all signals we are interested in as they may have been
1862            blocked by the parent process. */
1863
1864         BlockSignals(False, SIGINT);
1865         BlockSignals(False, SIGQUIT);
1866         BlockSignals(False, SIGTERM);
1867         BlockSignals(False, SIGUSR1);
1868         BlockSignals(False, SIGUSR2);
1869         BlockSignals(False, SIGHUP);
1870         BlockSignals(False, SIGCHLD);
1871
1872         if (!interactive)
1873                 become_daemon(Fork, no_process_group, log_stdout);
1874
1875         pidfile_create(lp_pid_directory(), "winbindd");
1876
1877 #ifdef HAVE_SETPGID
1878         /*
1879          * If we're interactive we want to set our own process group for
1880          * signal management.
1881          */
1882         if (interactive && !no_process_group)
1883                 setpgid( (pid_t)0, (pid_t)0);
1884 #endif
1885
1886         TimeInit();
1887
1888         /* Don't use winbindd_reinit_after_fork here as
1889          * we're just starting up and haven't created any
1890          * winbindd-specific resources we must free yet. JRA.
1891          */
1892
1893         status = reinit_after_fork(global_messaging_context(),
1894                                    global_event_context(),
1895                                    false, NULL);
1896         if (!NT_STATUS_IS_OK(status)) {
1897                 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1898         }
1899
1900         ok = initialize_password_db(true, global_event_context());
1901         if (!ok) {
1902                 exit_daemon("Failed to initialize passdb backend! "
1903                             "Check the 'passdb backend' variable in your "
1904                             "smb.conf file.", EINVAL);
1905         }
1906
1907         /*
1908          * Do not initialize the parent-child-pipe before becoming
1909          * a daemon: this is used to detect a died parent in the child
1910          * process.
1911          */
1912         status = init_before_fork();
1913         if (!NT_STATUS_IS_OK(status)) {
1914                 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1915         }
1916
1917         winbindd_register_handlers(global_messaging_context(), !Fork);
1918
1919         if (!messaging_parent_dgm_cleanup_init(global_messaging_context())) {
1920                 exit(1);
1921         }
1922
1923         status = init_system_session_info(NULL);
1924         if (!NT_STATUS_IS_OK(status)) {
1925                 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1926         }
1927
1928         rpc_lsarpc_init(NULL);
1929         rpc_samr_init(NULL);
1930
1931         winbindd_init_addrchange(NULL, global_event_context(),
1932                                  global_messaging_context());
1933
1934         /* setup listen sockets */
1935
1936         if (!winbindd_setup_listeners()) {
1937                 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1938         }
1939
1940         irpc_add_name(winbind_imessaging_context(), "winbind_server");
1941
1942         TALLOC_FREE(frame);
1943
1944         if (!interactive) {
1945                 daemon_ready("winbindd");
1946         }
1947
1948         gpupdate_init();
1949
1950         /* Loop waiting for requests */
1951         while (1) {
1952                 frame = talloc_stackframe();
1953
1954                 if (tevent_loop_once(global_event_context()) == -1) {
1955                         DEBUG(1, ("tevent_loop_once() failed: %s\n",
1956                                   strerror(errno)));
1957                         return 1;
1958                 }
1959
1960                 TALLOC_FREE(frame);
1961         }
1962
1963         return 0;
1964 }