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