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