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