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