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