s3: winbindd: On new client connect, prune idle or hung connections older than "winbi...
[samba.git] / source3 / winbindd / winbindd.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Winbind daemon for ntdom nss module
5
6    Copyright (C) by Tim Potter 2000-2002
7    Copyright (C) Andrew Tridgell 2002
8    Copyright (C) Jelmer Vernooij 2003
9    Copyright (C) Volker Lendecke 2004
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26 #include "popt_common.h"
27 #include "winbindd.h"
28 #include "nsswitch/winbind_client.h"
29 #include "nsswitch/wb_reqtrans.h"
30 #include "ntdomain.h"
31 #include "../librpc/gen_ndr/srv_lsa.h"
32 #include "../librpc/gen_ndr/srv_samr.h"
33 #include "secrets.h"
34 #include "rpc_client/cli_netlogon.h"
35 #include "idmap.h"
36 #include "lib/addrchange.h"
37 #include "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 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)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 }
828
829 static void winbind_client_response_written(struct tevent_req *req)
830 {
831         struct winbindd_cli_state *state = tevent_req_callback_data(
832                 req, struct winbindd_cli_state);
833         ssize_t ret;
834         int err;
835
836         ret = wb_resp_write_recv(req, &err);
837         TALLOC_FREE(req);
838         if (ret == -1) {
839                 close(state->sock);
840                 state->sock = -1;
841                 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
842                           (int)state->pid, state->cmd_name, strerror(err)));
843                 remove_client(state);
844                 return;
845         }
846
847         DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
848                   "to client\n", (int)state->pid, state->cmd_name));
849
850         TALLOC_FREE(state->mem_ctx);
851         state->response = NULL;
852         state->cmd_name = "no request";
853         state->recv_fn = NULL;
854
855         req = wb_req_read_send(state, winbind_event_context(), state->sock,
856                                WINBINDD_MAX_EXTRA_DATA);
857         if (req == NULL) {
858                 remove_client(state);
859                 return;
860         }
861         tevent_req_set_callback(req, winbind_client_request_read, state);
862 }
863
864 void request_error(struct winbindd_cli_state *state)
865 {
866         SMB_ASSERT(state->response->result == WINBINDD_PENDING);
867         state->response->result = WINBINDD_ERROR;
868         request_finished(state);
869 }
870
871 void request_ok(struct winbindd_cli_state *state)
872 {
873         SMB_ASSERT(state->response->result == WINBINDD_PENDING);
874         state->response->result = WINBINDD_OK;
875         request_finished(state);
876 }
877
878 /* Process a new connection by adding it to the client connection list */
879
880 static void new_connection(int listen_sock, bool privileged)
881 {
882         struct sockaddr_un sunaddr;
883         struct winbindd_cli_state *state;
884         struct tevent_req *req;
885         socklen_t len;
886         int sock;
887
888         /* Accept connection */
889
890         len = sizeof(sunaddr);
891
892         sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
893
894         if (sock == -1) {
895                 if (errno != EINTR) {
896                         DEBUG(0, ("Failed to accept socket - %s\n",
897                                   strerror(errno)));
898                 }
899                 return;
900         }
901
902         DEBUG(6,("accepted socket %d\n", sock));
903
904         /* Create new connection structure */
905
906         if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
907                 close(sock);
908                 return;
909         }
910
911         state->sock = sock;
912
913         state->out_queue = tevent_queue_create(state, "winbind client reply");
914         if (state->out_queue == NULL) {
915                 close(sock);
916                 TALLOC_FREE(state);
917                 return;
918         }
919
920         state->last_access = time(NULL);        
921
922         state->privileged = privileged;
923
924         req = wb_req_read_send(state, winbind_event_context(), state->sock,
925                                WINBINDD_MAX_EXTRA_DATA);
926         if (req == NULL) {
927                 TALLOC_FREE(state);
928                 close(sock);
929                 return;
930         }
931         tevent_req_set_callback(req, winbind_client_request_read, state);
932
933         /* Add to connection list */
934
935         winbindd_add_client(state);
936 }
937
938 static void winbind_client_request_read(struct tevent_req *req)
939 {
940         struct winbindd_cli_state *state = tevent_req_callback_data(
941                 req, struct winbindd_cli_state);
942         ssize_t ret;
943         int err;
944
945         ret = wb_req_read_recv(req, state, &state->request, &err);
946         TALLOC_FREE(req);
947         if (ret == -1) {
948                 if (err == EPIPE) {
949                         DEBUG(6, ("closing socket %d, client exited\n",
950                                   state->sock));
951                 } else {
952                         DEBUG(2, ("Could not read client request from fd %d: "
953                                   "%s\n", state->sock, strerror(err)));
954                 }
955                 close(state->sock);
956                 state->sock = -1;
957                 remove_client(state);
958                 return;
959         }
960         process_request(state);
961 }
962
963 /* Remove a client connection from client connection list */
964
965 static void remove_client(struct winbindd_cli_state *state)
966 {
967         char c = 0;
968         int nwritten;
969
970         /* It's a dead client - hold a funeral */
971
972         if (state == NULL) {
973                 return;
974         }
975
976         if (state->sock != -1) {
977                 /* tell client, we are closing ... */
978                 nwritten = write(state->sock, &c, sizeof(c));
979                 if (nwritten == -1) {
980                         DEBUG(2, ("final write to client failed: %s\n",
981                                 strerror(errno)));
982                 }
983
984                 /* Close socket */
985
986                 close(state->sock);
987                 state->sock = -1;
988         }
989
990         TALLOC_FREE(state->mem_ctx);
991
992         /* Remove from list and free */
993
994         winbindd_remove_client(state);
995         TALLOC_FREE(state);
996 }
997
998 /* Is a client idle? */
999
1000 static bool client_is_idle(struct winbindd_cli_state *state) {
1001   return (state->request == NULL &&
1002           state->response == NULL &&
1003           !state->pwent_state && !state->grent_state);
1004 }
1005
1006 /* Shutdown client connection which has been idle for the longest time */
1007
1008 static bool remove_idle_client(void)
1009 {
1010         struct winbindd_cli_state *state, *remove_state = NULL;
1011         time_t last_access = 0;
1012         int nidle = 0;
1013
1014         for (state = winbindd_client_list(); state; state = state->next) {
1015                 if (client_is_idle(state)) {
1016                         nidle++;
1017                         if (!last_access || state->last_access < last_access) {
1018                                 last_access = state->last_access;
1019                                 remove_state = state;
1020                         }
1021                 }
1022         }
1023
1024         if (remove_state) {
1025                 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
1026                         nidle, remove_state->sock, (unsigned int)remove_state->pid));
1027                 remove_client(remove_state);
1028                 return True;
1029         }
1030
1031         return False;
1032 }
1033
1034 /*
1035  * Terminate all clients whose requests have taken longer than
1036  * "winbind request timeout" seconds to process, or have been
1037  * idle for more than "winbind request timeout" seconds.
1038  */
1039
1040 static void remove_timed_out_clients(void)
1041 {
1042         struct winbindd_cli_state *state, *next = NULL;
1043         time_t curr_time = time(NULL);
1044         int timeout_val = lp_winbind_request_timeout();
1045
1046         for (state = winbindd_client_list(); state; state = next) {
1047                 time_t expiry_time;
1048
1049                 next = state->next;
1050                 expiry_time = state->last_access + timeout_val;
1051
1052                 if (curr_time > expiry_time) {
1053                         if (client_is_idle(state)) {
1054                                 DEBUG(5,("Idle client timed out, "
1055                                         "shutting down sock %d, pid %u\n",
1056                                         state->sock,
1057                                         (unsigned int)state->pid));
1058                         } else {
1059                                 DEBUG(5,("Client request timed out, "
1060                                         "shutting down sock %d, pid %u\n",
1061                                         state->sock,
1062                                         (unsigned int)state->pid));
1063                         }
1064                         remove_client(state);
1065                 }
1066         }
1067 }
1068
1069 struct winbindd_listen_state {
1070         bool privileged;
1071         int fd;
1072 };
1073
1074 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1075                                         struct tevent_fd *fde,
1076                                         uint16_t flags,
1077                                         void *private_data)
1078 {
1079         struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1080                                           struct winbindd_listen_state);
1081
1082         while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1083                 DEBUG(5,("winbindd: Exceeding %d client "
1084                          "connections, removing idle "
1085                          "connection.\n", lp_winbind_max_clients()));
1086                 if (!remove_idle_client()) {
1087                         DEBUG(0,("winbindd: Exceeding %d "
1088                                  "client connections, no idle "
1089                                  "connection found\n",
1090                                  lp_winbind_max_clients()));
1091                         break;
1092                 }
1093         }
1094         remove_timed_out_clients();
1095         new_connection(s->fd, s->privileged);
1096 }
1097
1098 /*
1099  * Winbindd socket accessor functions
1100  */
1101
1102 char *get_winbind_priv_pipe_dir(void)
1103 {
1104         return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1105 }
1106
1107 static bool winbindd_setup_listeners(void)
1108 {
1109         struct winbindd_listen_state *pub_state = NULL;
1110         struct winbindd_listen_state *priv_state = NULL;
1111         struct tevent_fd *fde;
1112         int rc;
1113
1114         pub_state = talloc(winbind_event_context(),
1115                            struct winbindd_listen_state);
1116         if (!pub_state) {
1117                 goto failed;
1118         }
1119
1120         pub_state->privileged = false;
1121         pub_state->fd = create_pipe_sock(
1122                 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1123         if (pub_state->fd == -1) {
1124                 goto failed;
1125         }
1126         rc = listen(pub_state->fd, 5);
1127         if (rc < 0) {
1128                 goto failed;
1129         }
1130
1131         fde = tevent_add_fd(winbind_event_context(), pub_state, pub_state->fd,
1132                             TEVENT_FD_READ, winbindd_listen_fde_handler,
1133                             pub_state);
1134         if (fde == NULL) {
1135                 close(pub_state->fd);
1136                 goto failed;
1137         }
1138         tevent_fd_set_auto_close(fde);
1139
1140         priv_state = talloc(winbind_event_context(),
1141                             struct winbindd_listen_state);
1142         if (!priv_state) {
1143                 goto failed;
1144         }
1145
1146         priv_state->privileged = true;
1147         priv_state->fd = create_pipe_sock(
1148                 get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750);
1149         if (priv_state->fd == -1) {
1150                 goto failed;
1151         }
1152         rc = listen(priv_state->fd, 5);
1153         if (rc < 0) {
1154                 goto failed;
1155         }
1156
1157         fde = tevent_add_fd(winbind_event_context(), priv_state,
1158                             priv_state->fd, TEVENT_FD_READ,
1159                             winbindd_listen_fde_handler, priv_state);
1160         if (fde == NULL) {
1161                 close(priv_state->fd);
1162                 goto failed;
1163         }
1164         tevent_fd_set_auto_close(fde);
1165
1166         return true;
1167 failed:
1168         TALLOC_FREE(pub_state);
1169         TALLOC_FREE(priv_state);
1170         return false;
1171 }
1172
1173 bool winbindd_use_idmap_cache(void)
1174 {
1175         return !opt_nocache;
1176 }
1177
1178 bool winbindd_use_cache(void)
1179 {
1180         return !opt_nocache;
1181 }
1182
1183 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1184                                        bool foreground)
1185 {
1186         NTSTATUS status;
1187         /* Setup signal handlers */
1188
1189         if (!winbindd_setup_sig_term_handler(true))
1190                 exit(1);
1191         if (!winbindd_setup_stdin_handler(true, foreground))
1192                 exit(1);
1193         if (!winbindd_setup_sig_hup_handler(NULL))
1194                 exit(1);
1195         if (!winbindd_setup_sig_chld_handler())
1196                 exit(1);
1197         if (!winbindd_setup_sig_usr2_handler())
1198                 exit(1);
1199
1200         CatchSignal(SIGPIPE, SIG_IGN);                 /* Ignore sigpipe */
1201
1202         /*
1203          * Ensure all cache and idmap caches are consistent
1204          * and initialized before we startup.
1205          */
1206         if (!winbindd_cache_validate_and_initialize()) {
1207                 exit(1);
1208         }
1209
1210         /* get broadcast messages */
1211
1212         if (!serverid_register(messaging_server_id(msg_ctx),
1213                                FLAG_MSG_GENERAL |
1214                                FLAG_MSG_WINBIND |
1215                                FLAG_MSG_DBWRAP)) {
1216                 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
1217                 exit(1);
1218         }
1219
1220         /* React on 'smbcontrol winbindd reload-config' in the same way
1221            as to SIGHUP signal */
1222         messaging_register(msg_ctx, NULL,
1223                            MSG_SMB_CONF_UPDATED, msg_reload_services);
1224         messaging_register(msg_ctx, NULL,
1225                            MSG_SHUTDOWN, msg_shutdown);
1226
1227         /* Handle online/offline messages. */
1228         messaging_register(msg_ctx, NULL,
1229                            MSG_WINBIND_OFFLINE, winbind_msg_offline);
1230         messaging_register(msg_ctx, NULL,
1231                            MSG_WINBIND_ONLINE, winbind_msg_online);
1232         messaging_register(msg_ctx, NULL,
1233                            MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1234
1235         /* Handle domain online/offline messages for domains */
1236         messaging_register(winbind_messaging_context(), NULL,
1237                            MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1238         messaging_register(winbind_messaging_context(), NULL,
1239                            MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1240
1241         messaging_register(msg_ctx, NULL,
1242                            MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
1243
1244         messaging_register(msg_ctx, NULL,
1245                            MSG_WINBIND_VALIDATE_CACHE,
1246                            winbind_msg_validate_cache);
1247
1248         messaging_register(msg_ctx, NULL,
1249                            MSG_WINBIND_DUMP_DOMAIN_LIST,
1250                            winbind_msg_dump_domain_list);
1251
1252         messaging_register(msg_ctx, NULL,
1253                            MSG_WINBIND_IP_DROPPED,
1254                            winbind_msg_ip_dropped_parent);
1255
1256         /* Register handler for MSG_DEBUG. */
1257         messaging_register(msg_ctx, NULL,
1258                            MSG_DEBUG,
1259                            winbind_msg_debug);
1260
1261         netsamlogon_cache_init(); /* Non-critical */
1262
1263         /* clear the cached list of trusted domains */
1264
1265         wcache_tdc_clear();
1266
1267         if (!init_domain_list()) {
1268                 DEBUG(0,("unable to initialize domain list\n"));
1269                 exit(1);
1270         }
1271
1272         init_idmap_child();
1273         init_locator_child();
1274
1275         smb_nscd_flush_user_cache();
1276         smb_nscd_flush_group_cache();
1277
1278         if (lp_allow_trusted_domains()) {
1279                 if (tevent_add_timer(winbind_event_context(), NULL, timeval_zero(),
1280                               rescan_trusted_domains, NULL) == NULL) {
1281                         DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1282                         exit(1);
1283                 }
1284         }
1285
1286         status = wb_irpc_register();
1287
1288         if (!NT_STATUS_IS_OK(status)) {
1289                 DEBUG(0, ("Could not register IRPC handlers\n"));
1290                 exit(1);
1291         }
1292 }
1293
1294 struct winbindd_addrchanged_state {
1295         struct addrchange_context *ctx;
1296         struct tevent_context *ev;
1297         struct messaging_context *msg_ctx;
1298 };
1299
1300 static void winbindd_addr_changed(struct tevent_req *req);
1301
1302 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1303                                      struct tevent_context *ev,
1304                                      struct messaging_context *msg_ctx)
1305 {
1306         struct winbindd_addrchanged_state *state;
1307         struct tevent_req *req;
1308         NTSTATUS status;
1309
1310         state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1311         if (state == NULL) {
1312                 DEBUG(10, ("talloc failed\n"));
1313                 return;
1314         }
1315         state->ev = ev;
1316         state->msg_ctx = msg_ctx;
1317
1318         status = addrchange_context_create(state, &state->ctx);
1319         if (!NT_STATUS_IS_OK(status)) {
1320                 DEBUG(10, ("addrchange_context_create failed: %s\n",
1321                            nt_errstr(status)));
1322                 TALLOC_FREE(state);
1323                 return;
1324         }
1325         req = addrchange_send(state, ev, state->ctx);
1326         if (req == NULL) {
1327                 DEBUG(0, ("addrchange_send failed\n"));
1328                 TALLOC_FREE(state);
1329                 return;
1330         }
1331         tevent_req_set_callback(req, winbindd_addr_changed, state);
1332 }
1333
1334 static void winbindd_addr_changed(struct tevent_req *req)
1335 {
1336         struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1337                 req, struct winbindd_addrchanged_state);
1338         enum addrchange_type type;
1339         struct sockaddr_storage addr;
1340         NTSTATUS status;
1341
1342         status = addrchange_recv(req, &type, &addr);
1343         TALLOC_FREE(req);
1344         if (!NT_STATUS_IS_OK(status)) {
1345                 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1346                            nt_errstr(status)));
1347                 TALLOC_FREE(state);
1348                 return;
1349         }
1350         if (type == ADDRCHANGE_DEL) {
1351                 char addrstr[INET6_ADDRSTRLEN];
1352                 DATA_BLOB blob;
1353
1354                 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1355
1356                 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1357                           addrstr));
1358
1359                 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1360
1361                 status = messaging_send(state->msg_ctx,
1362                                         messaging_server_id(state->msg_ctx),
1363                                         MSG_WINBIND_IP_DROPPED, &blob);
1364                 if (!NT_STATUS_IS_OK(status)) {
1365                         DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1366                                    nt_errstr(status)));
1367                 }
1368         }
1369         req = addrchange_send(state, state->ev, state->ctx);
1370         if (req == NULL) {
1371                 DEBUG(0, ("addrchange_send failed\n"));
1372                 TALLOC_FREE(state);
1373                 return;
1374         }
1375         tevent_req_set_callback(req, winbindd_addr_changed, state);
1376 }
1377
1378 /* Main function */
1379
1380 int main(int argc, const char **argv)
1381 {
1382         static bool is_daemon = False;
1383         static bool Fork = True;
1384         static bool log_stdout = False;
1385         static bool no_process_group = False;
1386         enum {
1387                 OPT_DAEMON = 1000,
1388                 OPT_FORK,
1389                 OPT_NO_PROCESS_GROUP,
1390                 OPT_LOG_STDOUT
1391         };
1392         struct poptOption long_options[] = {
1393                 POPT_AUTOHELP
1394                 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1395                 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1396                 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1397                 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1398                 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1399                 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1400                 POPT_COMMON_SAMBA
1401                 POPT_TABLEEND
1402         };
1403         poptContext pc;
1404         int opt;
1405         TALLOC_CTX *frame;
1406         NTSTATUS status;
1407         bool ok;
1408
1409         /*
1410          * Do this before any other talloc operation
1411          */
1412         talloc_enable_null_tracking();
1413         frame = talloc_stackframe();
1414
1415         /*
1416          * We want total control over the permissions on created files,
1417          * so set our umask to 0.
1418          */
1419         umask(0);
1420
1421         setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1422
1423         /* glibc (?) likes to print "User defined signal 1" and exit if a
1424            SIGUSR[12] is received before a handler is installed */
1425
1426         CatchSignal(SIGUSR1, SIG_IGN);
1427         CatchSignal(SIGUSR2, SIG_IGN);
1428
1429         fault_setup();
1430         dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1431
1432         load_case_tables();
1433
1434         /* Initialise for running in non-root mode */
1435
1436         sec_init();
1437
1438         set_remote_machine_name("winbindd", False);
1439
1440         /* Set environment variable so we don't recursively call ourselves.
1441            This may also be useful interactively. */
1442
1443         if ( !winbind_off() ) {
1444                 DEBUG(0,("Failed to disable recusive winbindd calls.  Exiting.\n"));
1445                 exit(1);
1446         }
1447
1448         /* Initialise samba/rpc client stuff */
1449
1450         pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1451
1452         while ((opt = poptGetNextOpt(pc)) != -1) {
1453                 switch (opt) {
1454                         /* Don't become a daemon */
1455                 case OPT_DAEMON:
1456                         is_daemon = True;
1457                         break;
1458                 case 'i':
1459                         interactive = True;
1460                         log_stdout = True;
1461                         Fork = False;
1462                         break;
1463                 case OPT_FORK:
1464                         Fork = false;
1465                         break;
1466                 case OPT_NO_PROCESS_GROUP:
1467                         no_process_group = true;
1468                         break;
1469                 case OPT_LOG_STDOUT:
1470                         log_stdout = true;
1471                         break;
1472                 case 'n':
1473                         opt_nocache = true;
1474                         break;
1475                 default:
1476                         d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1477                                   poptBadOption(pc, 0), poptStrerror(opt));
1478                         poptPrintUsage(pc, stderr, 0);
1479                         exit(1);
1480                 }
1481         }
1482
1483         /* We call dump_core_setup one more time because the command line can
1484          * set the log file or the log-basename and this will influence where
1485          * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1486          * the default value derived from build's prefix. For EOM this value
1487          * is often not related to the path where winbindd is actually run
1488          * in production.
1489          */
1490         dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1491         if (is_daemon && interactive) {
1492                 d_fprintf(stderr,"\nERROR: "
1493                           "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1494                 poptPrintUsage(pc, stderr, 0);
1495                 exit(1);
1496         }
1497
1498         if (log_stdout && Fork) {
1499                 d_fprintf(stderr, "\nERROR: "
1500                           "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1501                 poptPrintUsage(pc, stderr, 0);
1502                 exit(1);
1503         }
1504
1505         poptFreeContext(pc);
1506
1507         if (!override_logfile) {
1508                 char *lfile = NULL;
1509                 if (asprintf(&lfile,"%s/log.winbindd",
1510                                 get_dyn_LOGFILEBASE()) > 0) {
1511                         lp_set_logfile(lfile);
1512                         SAFE_FREE(lfile);
1513                 }
1514         }
1515
1516         if (log_stdout) {
1517                 setup_logging("winbindd", DEBUG_STDOUT);
1518         } else {
1519                 setup_logging("winbindd", DEBUG_FILE);
1520         }
1521         reopen_logs();
1522
1523         DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1524         DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1525
1526         if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1527                 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1528                 exit(1);
1529         }
1530         /* After parsing the configuration file we setup the core path one more time
1531          * as the log file might have been set in the configuration and cores's
1532          * path is by default basename(lp_logfile()).
1533          */
1534         dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1535
1536         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1537             && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1538                 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1539                 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"));
1540                 exit(1);
1541         }
1542
1543         if (!cluster_probe_ok()) {
1544                 exit(1);
1545         }
1546
1547         /* Initialise messaging system */
1548
1549         if (winbind_messaging_context() == NULL) {
1550                 exit(1);
1551         }
1552
1553         if (!reload_services_file(NULL)) {
1554                 DEBUG(0, ("error opening config file\n"));
1555                 exit(1);
1556         }
1557
1558         ok = directory_create_or_exist(lp_lock_directory(), 0755);
1559         if (!ok) {
1560                 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1561                           lp_lock_directory(), strerror(errno)));
1562                 exit(1);
1563         }
1564
1565         ok = directory_create_or_exist(lp_pid_directory(), 0755);
1566         if (!ok) {
1567                 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1568                           lp_pid_directory(), strerror(errno)));
1569                 exit(1);
1570         }
1571
1572         /* Setup names. */
1573
1574         if (!init_names())
1575                 exit(1);
1576
1577         load_interfaces();
1578
1579         if (!secrets_init()) {
1580
1581                 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1582                 return False;
1583         }
1584
1585         status = rpccli_pre_open_netlogon_creds();
1586         if (!NT_STATUS_IS_OK(status)) {
1587                 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1588                           nt_errstr(status)));
1589                 exit(1);
1590         }
1591
1592         /* Unblock all signals we are interested in as they may have been
1593            blocked by the parent process. */
1594
1595         BlockSignals(False, SIGINT);
1596         BlockSignals(False, SIGQUIT);
1597         BlockSignals(False, SIGTERM);
1598         BlockSignals(False, SIGUSR1);
1599         BlockSignals(False, SIGUSR2);
1600         BlockSignals(False, SIGHUP);
1601         BlockSignals(False, SIGCHLD);
1602
1603         if (!interactive)
1604                 become_daemon(Fork, no_process_group, log_stdout);
1605
1606         pidfile_create(lp_pid_directory(), "winbindd");
1607
1608 #if HAVE_SETPGID
1609         /*
1610          * If we're interactive we want to set our own process group for
1611          * signal management.
1612          */
1613         if (interactive && !no_process_group)
1614                 setpgid( (pid_t)0, (pid_t)0);
1615 #endif
1616
1617         TimeInit();
1618
1619         /* Don't use winbindd_reinit_after_fork here as
1620          * we're just starting up and haven't created any
1621          * winbindd-specific resources we must free yet. JRA.
1622          */
1623
1624         status = reinit_after_fork(winbind_messaging_context(),
1625                                    winbind_event_context(),
1626                                    false);
1627         if (!NT_STATUS_IS_OK(status)) {
1628                 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1629         }
1630
1631         /*
1632          * Do not initialize the parent-child-pipe before becoming
1633          * a daemon: this is used to detect a died parent in the child
1634          * process.
1635          */
1636         status = init_before_fork();
1637         if (!NT_STATUS_IS_OK(status)) {
1638                 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1639         }
1640
1641         winbindd_register_handlers(winbind_messaging_context(), !Fork);
1642
1643         if (!messaging_parent_dgm_cleanup_init(winbind_messaging_context())) {
1644                 exit(1);
1645         }
1646
1647         status = init_system_session_info();
1648         if (!NT_STATUS_IS_OK(status)) {
1649                 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1650         }
1651
1652         rpc_lsarpc_init(NULL);
1653         rpc_samr_init(NULL);
1654
1655         winbindd_init_addrchange(NULL, winbind_event_context(),
1656                                  winbind_messaging_context());
1657
1658         /* setup listen sockets */
1659
1660         if (!winbindd_setup_listeners()) {
1661                 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1662         }
1663
1664         irpc_add_name(winbind_imessaging_context(), "winbind_server");
1665
1666         TALLOC_FREE(frame);
1667
1668         if (!interactive) {
1669                 daemon_ready("winbindd");
1670         }
1671
1672         /* Loop waiting for requests */
1673         while (1) {
1674                 frame = talloc_stackframe();
1675
1676                 if (tevent_loop_once(winbind_event_context()) == -1) {
1677                         DEBUG(1, ("tevent_loop_once() failed: %s\n",
1678                                   strerror(errno)));
1679                         return 1;
1680                 }
1681
1682                 TALLOC_FREE(frame);
1683         }
1684
1685         return 0;
1686 }