87bc5324272dc743668d949fc9c3672b376aa465
[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_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 }
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         char *socket_path;
1114
1115         pub_state = talloc(winbind_event_context(),
1116                            struct winbindd_listen_state);
1117         if (!pub_state) {
1118                 goto failed;
1119         }
1120
1121         pub_state->privileged = false;
1122         pub_state->fd = create_pipe_sock(
1123                 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1124         if (pub_state->fd == -1) {
1125                 goto failed;
1126         }
1127         rc = listen(pub_state->fd, 5);
1128         if (rc < 0) {
1129                 goto failed;
1130         }
1131
1132         fde = tevent_add_fd(winbind_event_context(), pub_state, pub_state->fd,
1133                             TEVENT_FD_READ, winbindd_listen_fde_handler,
1134                             pub_state);
1135         if (fde == NULL) {
1136                 close(pub_state->fd);
1137                 goto failed;
1138         }
1139         tevent_fd_set_auto_close(fde);
1140
1141         priv_state = talloc(winbind_event_context(),
1142                             struct winbindd_listen_state);
1143         if (!priv_state) {
1144                 goto failed;
1145         }
1146
1147         socket_path = get_winbind_priv_pipe_dir();
1148         if (socket_path == NULL) {
1149                 goto failed;
1150         }
1151
1152         priv_state->privileged = true;
1153         priv_state->fd = create_pipe_sock(
1154                 socket_path, WINBINDD_SOCKET_NAME, 0750);
1155         TALLOC_FREE(socket_path);
1156         if (priv_state->fd == -1) {
1157                 goto failed;
1158         }
1159         rc = listen(priv_state->fd, 5);
1160         if (rc < 0) {
1161                 goto failed;
1162         }
1163
1164         fde = tevent_add_fd(winbind_event_context(), priv_state,
1165                             priv_state->fd, TEVENT_FD_READ,
1166                             winbindd_listen_fde_handler, priv_state);
1167         if (fde == NULL) {
1168                 close(priv_state->fd);
1169                 goto failed;
1170         }
1171         tevent_fd_set_auto_close(fde);
1172
1173         return true;
1174 failed:
1175         TALLOC_FREE(pub_state);
1176         TALLOC_FREE(priv_state);
1177         return false;
1178 }
1179
1180 bool winbindd_use_idmap_cache(void)
1181 {
1182         return !opt_nocache;
1183 }
1184
1185 bool winbindd_use_cache(void)
1186 {
1187         return !opt_nocache;
1188 }
1189
1190 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1191                                        bool foreground)
1192 {
1193         NTSTATUS status;
1194         /* Setup signal handlers */
1195
1196         if (!winbindd_setup_sig_term_handler(true))
1197                 exit(1);
1198         if (!winbindd_setup_stdin_handler(true, foreground))
1199                 exit(1);
1200         if (!winbindd_setup_sig_hup_handler(NULL))
1201                 exit(1);
1202         if (!winbindd_setup_sig_chld_handler())
1203                 exit(1);
1204         if (!winbindd_setup_sig_usr2_handler())
1205                 exit(1);
1206
1207         CatchSignal(SIGPIPE, SIG_IGN);                 /* Ignore sigpipe */
1208
1209         /*
1210          * Ensure all cache and idmap caches are consistent
1211          * and initialized before we startup.
1212          */
1213         if (!winbindd_cache_validate_and_initialize()) {
1214                 exit(1);
1215         }
1216
1217         /* get broadcast messages */
1218
1219         if (!serverid_register(messaging_server_id(msg_ctx),
1220                                FLAG_MSG_GENERAL |
1221                                FLAG_MSG_WINBIND |
1222                                FLAG_MSG_DBWRAP)) {
1223                 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
1224                 exit(1);
1225         }
1226
1227         /* React on 'smbcontrol winbindd reload-config' in the same way
1228            as to SIGHUP signal */
1229         messaging_register(msg_ctx, NULL,
1230                            MSG_SMB_CONF_UPDATED, msg_reload_services);
1231         messaging_register(msg_ctx, NULL,
1232                            MSG_SHUTDOWN, msg_shutdown);
1233
1234         /* Handle online/offline messages. */
1235         messaging_register(msg_ctx, NULL,
1236                            MSG_WINBIND_OFFLINE, winbind_msg_offline);
1237         messaging_register(msg_ctx, NULL,
1238                            MSG_WINBIND_ONLINE, winbind_msg_online);
1239         messaging_register(msg_ctx, NULL,
1240                            MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1241
1242         /* Handle domain online/offline messages for domains */
1243         messaging_register(winbind_messaging_context(), NULL,
1244                            MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1245         messaging_register(winbind_messaging_context(), NULL,
1246                            MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1247
1248         messaging_register(msg_ctx, NULL,
1249                            MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
1250
1251         messaging_register(msg_ctx, NULL,
1252                            MSG_WINBIND_VALIDATE_CACHE,
1253                            winbind_msg_validate_cache);
1254
1255         messaging_register(msg_ctx, NULL,
1256                            MSG_WINBIND_DUMP_DOMAIN_LIST,
1257                            winbind_msg_dump_domain_list);
1258
1259         messaging_register(msg_ctx, NULL,
1260                            MSG_WINBIND_IP_DROPPED,
1261                            winbind_msg_ip_dropped_parent);
1262
1263         /* Register handler for MSG_DEBUG. */
1264         messaging_register(msg_ctx, NULL,
1265                            MSG_DEBUG,
1266                            winbind_msg_debug);
1267
1268         netsamlogon_cache_init(); /* Non-critical */
1269
1270         /* clear the cached list of trusted domains */
1271
1272         wcache_tdc_clear();
1273
1274         if (!init_domain_list()) {
1275                 DEBUG(0,("unable to initialize domain list\n"));
1276                 exit(1);
1277         }
1278
1279         init_idmap_child();
1280         init_locator_child();
1281
1282         smb_nscd_flush_user_cache();
1283         smb_nscd_flush_group_cache();
1284
1285         if (lp_allow_trusted_domains()) {
1286                 if (tevent_add_timer(winbind_event_context(), NULL, timeval_zero(),
1287                               rescan_trusted_domains, NULL) == NULL) {
1288                         DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1289                         exit(1);
1290                 }
1291         }
1292
1293         status = wb_irpc_register();
1294
1295         if (!NT_STATUS_IS_OK(status)) {
1296                 DEBUG(0, ("Could not register IRPC handlers\n"));
1297                 exit(1);
1298         }
1299 }
1300
1301 struct winbindd_addrchanged_state {
1302         struct addrchange_context *ctx;
1303         struct tevent_context *ev;
1304         struct messaging_context *msg_ctx;
1305 };
1306
1307 static void winbindd_addr_changed(struct tevent_req *req);
1308
1309 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1310                                      struct tevent_context *ev,
1311                                      struct messaging_context *msg_ctx)
1312 {
1313         struct winbindd_addrchanged_state *state;
1314         struct tevent_req *req;
1315         NTSTATUS status;
1316
1317         state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1318         if (state == NULL) {
1319                 DEBUG(10, ("talloc failed\n"));
1320                 return;
1321         }
1322         state->ev = ev;
1323         state->msg_ctx = msg_ctx;
1324
1325         status = addrchange_context_create(state, &state->ctx);
1326         if (!NT_STATUS_IS_OK(status)) {
1327                 DEBUG(10, ("addrchange_context_create failed: %s\n",
1328                            nt_errstr(status)));
1329                 TALLOC_FREE(state);
1330                 return;
1331         }
1332         req = addrchange_send(state, ev, state->ctx);
1333         if (req == NULL) {
1334                 DEBUG(0, ("addrchange_send failed\n"));
1335                 TALLOC_FREE(state);
1336                 return;
1337         }
1338         tevent_req_set_callback(req, winbindd_addr_changed, state);
1339 }
1340
1341 static void winbindd_addr_changed(struct tevent_req *req)
1342 {
1343         struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1344                 req, struct winbindd_addrchanged_state);
1345         enum addrchange_type type;
1346         struct sockaddr_storage addr;
1347         NTSTATUS status;
1348
1349         status = addrchange_recv(req, &type, &addr);
1350         TALLOC_FREE(req);
1351         if (!NT_STATUS_IS_OK(status)) {
1352                 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1353                            nt_errstr(status)));
1354                 TALLOC_FREE(state);
1355                 return;
1356         }
1357         if (type == ADDRCHANGE_DEL) {
1358                 char addrstr[INET6_ADDRSTRLEN];
1359                 DATA_BLOB blob;
1360
1361                 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1362
1363                 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1364                           addrstr));
1365
1366                 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1367
1368                 status = messaging_send(state->msg_ctx,
1369                                         messaging_server_id(state->msg_ctx),
1370                                         MSG_WINBIND_IP_DROPPED, &blob);
1371                 if (!NT_STATUS_IS_OK(status)) {
1372                         DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1373                                    nt_errstr(status)));
1374                 }
1375         }
1376         req = addrchange_send(state, state->ev, state->ctx);
1377         if (req == NULL) {
1378                 DEBUG(0, ("addrchange_send failed\n"));
1379                 TALLOC_FREE(state);
1380                 return;
1381         }
1382         tevent_req_set_callback(req, winbindd_addr_changed, state);
1383 }
1384
1385 /* Main function */
1386
1387 int main(int argc, const char **argv)
1388 {
1389         static bool is_daemon = False;
1390         static bool Fork = True;
1391         static bool log_stdout = False;
1392         static bool no_process_group = False;
1393         enum {
1394                 OPT_DAEMON = 1000,
1395                 OPT_FORK,
1396                 OPT_NO_PROCESS_GROUP,
1397                 OPT_LOG_STDOUT
1398         };
1399         struct poptOption long_options[] = {
1400                 POPT_AUTOHELP
1401                 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1402                 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1403                 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1404                 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1405                 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1406                 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1407                 POPT_COMMON_SAMBA
1408                 POPT_TABLEEND
1409         };
1410         poptContext pc;
1411         int opt;
1412         TALLOC_CTX *frame;
1413         NTSTATUS status;
1414         bool ok;
1415
1416         /*
1417          * Do this before any other talloc operation
1418          */
1419         talloc_enable_null_tracking();
1420         frame = talloc_stackframe();
1421
1422         /*
1423          * We want total control over the permissions on created files,
1424          * so set our umask to 0.
1425          */
1426         umask(0);
1427
1428         setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1429
1430         /* glibc (?) likes to print "User defined signal 1" and exit if a
1431            SIGUSR[12] is received before a handler is installed */
1432
1433         CatchSignal(SIGUSR1, SIG_IGN);
1434         CatchSignal(SIGUSR2, SIG_IGN);
1435
1436         fault_setup();
1437         dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1438
1439         smb_init_locale();
1440
1441         /* Initialise for running in non-root mode */
1442
1443         sec_init();
1444
1445         set_remote_machine_name("winbindd", False);
1446
1447         /* Set environment variable so we don't recursively call ourselves.
1448            This may also be useful interactively. */
1449
1450         if ( !winbind_off() ) {
1451                 DEBUG(0,("Failed to disable recusive winbindd calls.  Exiting.\n"));
1452                 exit(1);
1453         }
1454
1455         /* Initialise samba/rpc client stuff */
1456
1457         pc = poptGetContext("winbindd", argc, argv, long_options, 0);
1458
1459         while ((opt = poptGetNextOpt(pc)) != -1) {
1460                 switch (opt) {
1461                         /* Don't become a daemon */
1462                 case OPT_DAEMON:
1463                         is_daemon = True;
1464                         break;
1465                 case 'i':
1466                         interactive = True;
1467                         log_stdout = True;
1468                         Fork = False;
1469                         break;
1470                 case OPT_FORK:
1471                         Fork = false;
1472                         break;
1473                 case OPT_NO_PROCESS_GROUP:
1474                         no_process_group = true;
1475                         break;
1476                 case OPT_LOG_STDOUT:
1477                         log_stdout = true;
1478                         break;
1479                 case 'n':
1480                         opt_nocache = true;
1481                         break;
1482                 default:
1483                         d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1484                                   poptBadOption(pc, 0), poptStrerror(opt));
1485                         poptPrintUsage(pc, stderr, 0);
1486                         exit(1);
1487                 }
1488         }
1489
1490         /* We call dump_core_setup one more time because the command line can
1491          * set the log file or the log-basename and this will influence where
1492          * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1493          * the default value derived from build's prefix. For EOM this value
1494          * is often not related to the path where winbindd is actually run
1495          * in production.
1496          */
1497         dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1498         if (is_daemon && interactive) {
1499                 d_fprintf(stderr,"\nERROR: "
1500                           "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1501                 poptPrintUsage(pc, stderr, 0);
1502                 exit(1);
1503         }
1504
1505         if (log_stdout && Fork) {
1506                 d_fprintf(stderr, "\nERROR: "
1507                           "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1508                 poptPrintUsage(pc, stderr, 0);
1509                 exit(1);
1510         }
1511
1512         poptFreeContext(pc);
1513
1514         if (!override_logfile) {
1515                 char *lfile = NULL;
1516                 if (asprintf(&lfile,"%s/log.winbindd",
1517                                 get_dyn_LOGFILEBASE()) > 0) {
1518                         lp_set_logfile(lfile);
1519                         SAFE_FREE(lfile);
1520                 }
1521         }
1522
1523         if (log_stdout) {
1524                 setup_logging("winbindd", DEBUG_STDOUT);
1525         } else {
1526                 setup_logging("winbindd", DEBUG_FILE);
1527         }
1528         reopen_logs();
1529
1530         DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1531         DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1532
1533         if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1534                 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1535                 exit(1);
1536         }
1537         /* After parsing the configuration file we setup the core path one more time
1538          * as the log file might have been set in the configuration and cores's
1539          * path is by default basename(lp_logfile()).
1540          */
1541         dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1542
1543         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
1544             && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
1545                 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1546                 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"));
1547                 exit(1);
1548         }
1549
1550         if (!cluster_probe_ok()) {
1551                 exit(1);
1552         }
1553
1554         /* Initialise messaging system */
1555
1556         if (winbind_messaging_context() == NULL) {
1557                 exit(1);
1558         }
1559
1560         if (!reload_services_file(NULL)) {
1561                 DEBUG(0, ("error opening config file\n"));
1562                 exit(1);
1563         }
1564
1565         ok = directory_create_or_exist(lp_lock_directory(), 0755);
1566         if (!ok) {
1567                 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1568                           lp_lock_directory(), strerror(errno)));
1569                 exit(1);
1570         }
1571
1572         ok = directory_create_or_exist(lp_pid_directory(), 0755);
1573         if (!ok) {
1574                 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1575                           lp_pid_directory(), strerror(errno)));
1576                 exit(1);
1577         }
1578
1579         /* Setup names. */
1580
1581         if (!init_names())
1582                 exit(1);
1583
1584         load_interfaces();
1585
1586         if (!secrets_init()) {
1587
1588                 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1589                 return False;
1590         }
1591
1592         status = rpccli_pre_open_netlogon_creds();
1593         if (!NT_STATUS_IS_OK(status)) {
1594                 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1595                           nt_errstr(status)));
1596                 exit(1);
1597         }
1598
1599         /* Unblock all signals we are interested in as they may have been
1600            blocked by the parent process. */
1601
1602         BlockSignals(False, SIGINT);
1603         BlockSignals(False, SIGQUIT);
1604         BlockSignals(False, SIGTERM);
1605         BlockSignals(False, SIGUSR1);
1606         BlockSignals(False, SIGUSR2);
1607         BlockSignals(False, SIGHUP);
1608         BlockSignals(False, SIGCHLD);
1609
1610         if (!interactive)
1611                 become_daemon(Fork, no_process_group, log_stdout);
1612
1613         pidfile_create(lp_pid_directory(), "winbindd");
1614
1615 #if HAVE_SETPGID
1616         /*
1617          * If we're interactive we want to set our own process group for
1618          * signal management.
1619          */
1620         if (interactive && !no_process_group)
1621                 setpgid( (pid_t)0, (pid_t)0);
1622 #endif
1623
1624         TimeInit();
1625
1626         /* Don't use winbindd_reinit_after_fork here as
1627          * we're just starting up and haven't created any
1628          * winbindd-specific resources we must free yet. JRA.
1629          */
1630
1631         status = reinit_after_fork(winbind_messaging_context(),
1632                                    winbind_event_context(),
1633                                    false);
1634         if (!NT_STATUS_IS_OK(status)) {
1635                 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1636         }
1637
1638         /*
1639          * Do not initialize the parent-child-pipe before becoming
1640          * a daemon: this is used to detect a died parent in the child
1641          * process.
1642          */
1643         status = init_before_fork();
1644         if (!NT_STATUS_IS_OK(status)) {
1645                 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1646         }
1647
1648         winbindd_register_handlers(winbind_messaging_context(), !Fork);
1649
1650         if (!messaging_parent_dgm_cleanup_init(winbind_messaging_context())) {
1651                 exit(1);
1652         }
1653
1654         status = init_system_session_info();
1655         if (!NT_STATUS_IS_OK(status)) {
1656                 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1657         }
1658
1659         rpc_lsarpc_init(NULL);
1660         rpc_samr_init(NULL);
1661
1662         winbindd_init_addrchange(NULL, winbind_event_context(),
1663                                  winbind_messaging_context());
1664
1665         /* setup listen sockets */
1666
1667         if (!winbindd_setup_listeners()) {
1668                 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1669         }
1670
1671         irpc_add_name(winbind_imessaging_context(), "winbind_server");
1672
1673         TALLOC_FREE(frame);
1674
1675         if (!interactive) {
1676                 daemon_ready("winbindd");
1677         }
1678
1679         /* Loop waiting for requests */
1680         while (1) {
1681                 frame = talloc_stackframe();
1682
1683                 if (tevent_loop_once(winbind_event_context()) == -1) {
1684                         DEBUG(1, ("tevent_loop_once() failed: %s\n",
1685                                   strerror(errno)));
1686                         return 1;
1687                 }
1688
1689                 TALLOC_FREE(frame);
1690         }
1691
1692         return 0;
1693 }