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