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