72aabdb8bd29541013c23f6e26332d0224304f69
[abartlet/samba.git/.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/libwbclient/wbc_async.h"
30 #include "librpc/gen_ndr/messaging.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
36 #undef DBGC_CLASS
37 #define DBGC_CLASS DBGC_WINBIND
38
39 static bool opt_nocache = False;
40 static bool interactive = False;
41
42 extern bool override_logfile;
43
44 /* Reload configuration */
45
46 static bool reload_services_file(const char *lfile)
47 {
48         bool ret;
49
50         if (lp_loaded()) {
51                 const char *fname = lp_configfile();
52
53                 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
54                         set_dyn_CONFIGFILE(fname);
55                 }
56         }
57
58         /* if this is a child, restore the logfile to the special
59            name - <domain>, idmap, etc. */
60         if (lfile && *lfile) {
61                 lp_set_logfile(lfile);
62         }
63
64         reopen_logs();
65         ret = lp_load(get_dyn_CONFIGFILE(),False,False,True,True);
66
67         reopen_logs();
68         load_interfaces();
69
70         return(ret);
71 }
72
73
74 /**************************************************************************** **
75  Handle a fault..
76  **************************************************************************** */
77
78 static void fault_quit(void)
79 {
80         dump_core();
81 }
82
83 static void winbindd_status(void)
84 {
85         struct winbindd_cli_state *tmp;
86
87         DEBUG(0, ("winbindd status:\n"));
88
89         /* Print client state information */
90
91         DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
92
93         if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
94                 DEBUG(2, ("\tclient list:\n"));
95                 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
96                         DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
97                                      (unsigned long)tmp->pid, tmp->sock,
98                                      client_is_idle(tmp) ? "idle" : "active"));
99                 }
100         }
101 }
102
103 /* Flush client cache */
104
105 static void flush_caches(void)
106 {
107         /* We need to invalidate cached user list entries on a SIGHUP 
108            otherwise cached access denied errors due to restrict anonymous
109            hang around until the sequence number changes. */
110
111         if (!wcache_invalidate_cache()) {
112                 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
113                 if (!winbindd_cache_validate_and_initialize()) {
114                         exit(1);
115                 }
116         }
117 }
118
119 static void flush_caches_noinit(void)
120 {
121         /*
122          * We need to invalidate cached user list entries on a SIGHUP
123          * otherwise cached access denied errors due to restrict anonymous
124          * hang around until the sequence number changes.
125          * NB
126          * Skip uninitialized domains when flush cache.
127          * If domain is not initialized, it means it is never
128          * used or never become online. look, wcache_invalidate_cache()
129          * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
130          * for unused domains and large traffic for primay domain's DC if there
131          * are many domains..
132          */
133
134         if (!wcache_invalidate_cache_noinit()) {
135                 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
136                 if (!winbindd_cache_validate_and_initialize()) {
137                         exit(1);
138                 }
139         }
140 }
141
142 /* Handle the signal by unlinking socket and exiting */
143
144 static void terminate(bool is_parent)
145 {
146         if (is_parent) {
147                 /* When parent goes away we should
148                  * remove the socket file. Not so
149                  * when children terminate.
150                  */ 
151                 char *path = NULL;
152
153                 if (asprintf(&path, "%s/%s",
154                         get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME) > 0) {
155                         unlink(path);
156                         SAFE_FREE(path);
157                 }
158         }
159
160         idmap_close();
161
162         trustdom_cache_shutdown();
163
164         gencache_stabilize();
165
166 #if 0
167         if (interactive) {
168                 TALLOC_CTX *mem_ctx = talloc_init("end_description");
169                 char *description = talloc_describe_all(mem_ctx);
170
171                 DEBUG(3, ("tallocs left:\n%s\n", description));
172                 talloc_destroy(mem_ctx);
173         }
174 #endif
175
176         if (is_parent) {
177                 serverid_deregister(procid_self());
178                 pidfile_unlink();
179         }
180
181         exit(0);
182 }
183
184 static void winbindd_sig_term_handler(struct tevent_context *ev,
185                                       struct tevent_signal *se,
186                                       int signum,
187                                       int count,
188                                       void *siginfo,
189                                       void *private_data)
190 {
191         bool *is_parent = talloc_get_type_abort(private_data, bool);
192
193         DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
194                  signum, (int)*is_parent));
195         terminate(*is_parent);
196 }
197
198 bool winbindd_setup_sig_term_handler(bool parent)
199 {
200         struct tevent_signal *se;
201         bool *is_parent;
202
203         is_parent = talloc(winbind_event_context(), bool);
204         if (!is_parent) {
205                 return false;
206         }
207
208         *is_parent = parent;
209
210         se = tevent_add_signal(winbind_event_context(),
211                                is_parent,
212                                SIGTERM, 0,
213                                winbindd_sig_term_handler,
214                                is_parent);
215         if (!se) {
216                 DEBUG(0,("failed to setup SIGTERM handler"));
217                 talloc_free(is_parent);
218                 return false;
219         }
220
221         se = tevent_add_signal(winbind_event_context(),
222                                is_parent,
223                                SIGINT, 0,
224                                winbindd_sig_term_handler,
225                                is_parent);
226         if (!se) {
227                 DEBUG(0,("failed to setup SIGINT handler"));
228                 talloc_free(is_parent);
229                 return false;
230         }
231
232         se = tevent_add_signal(winbind_event_context(),
233                                is_parent,
234                                SIGQUIT, 0,
235                                winbindd_sig_term_handler,
236                                is_parent);
237         if (!se) {
238                 DEBUG(0,("failed to setup SIGINT handler"));
239                 talloc_free(is_parent);
240                 return false;
241         }
242
243         return true;
244 }
245
246 static void winbindd_sig_hup_handler(struct tevent_context *ev,
247                                      struct tevent_signal *se,
248                                      int signum,
249                                      int count,
250                                      void *siginfo,
251                                      void *private_data)
252 {
253         const char *file = (const char *)private_data;
254
255         DEBUG(1,("Reloading services after SIGHUP\n"));
256         flush_caches_noinit();
257         reload_services_file(file);
258 }
259
260 bool winbindd_setup_sig_hup_handler(const char *lfile)
261 {
262         struct tevent_signal *se;
263         char *file = NULL;
264
265         if (lfile) {
266                 file = talloc_strdup(winbind_event_context(),
267                                      lfile);
268                 if (!file) {
269                         return false;
270                 }
271         }
272
273         se = tevent_add_signal(winbind_event_context(),
274                                winbind_event_context(),
275                                SIGHUP, 0,
276                                winbindd_sig_hup_handler,
277                                file);
278         if (!se) {
279                 return false;
280         }
281
282         return true;
283 }
284
285 static void winbindd_sig_chld_handler(struct tevent_context *ev,
286                                       struct tevent_signal *se,
287                                       int signum,
288                                       int count,
289                                       void *siginfo,
290                                       void *private_data)
291 {
292         pid_t pid;
293
294         while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) {
295                 winbind_child_died(pid);
296         }
297 }
298
299 static bool winbindd_setup_sig_chld_handler(void)
300 {
301         struct tevent_signal *se;
302
303         se = tevent_add_signal(winbind_event_context(),
304                                winbind_event_context(),
305                                SIGCHLD, 0,
306                                winbindd_sig_chld_handler,
307                                NULL);
308         if (!se) {
309                 return false;
310         }
311
312         return true;
313 }
314
315 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
316                                       struct tevent_signal *se,
317                                       int signum,
318                                       int count,
319                                       void *siginfo,
320                                       void *private_data)
321 {
322         winbindd_status();
323 }
324
325 static bool winbindd_setup_sig_usr2_handler(void)
326 {
327         struct tevent_signal *se;
328
329         se = tevent_add_signal(winbind_event_context(),
330                                winbind_event_context(),
331                                SIGUSR2, 0,
332                                winbindd_sig_usr2_handler,
333                                NULL);
334         if (!se) {
335                 return false;
336         }
337
338         return true;
339 }
340
341 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
342 static void msg_reload_services(struct messaging_context *msg,
343                                 void *private_data,
344                                 uint32_t msg_type,
345                                 struct server_id server_id,
346                                 DATA_BLOB *data)
347 {
348         /* Flush various caches */
349         flush_caches();
350         reload_services_file((const char *) private_data);
351 }
352
353 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
354 static void msg_shutdown(struct messaging_context *msg,
355                          void *private_data,
356                          uint32_t msg_type,
357                          struct server_id server_id,
358                          DATA_BLOB *data)
359 {
360         /* only the parent waits for this message */
361         DEBUG(0,("Got shutdown message\n"));
362         terminate(true);
363 }
364
365
366 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
367                                        void *private_data,
368                                        uint32_t msg_type,
369                                        struct server_id server_id,
370                                        DATA_BLOB *data)
371 {
372         uint8 ret;
373         pid_t child_pid;
374
375         DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
376                    "message.\n"));
377
378         /*
379          * call the validation code from a child:
380          * so we don't block the main winbindd and the validation
381          * code can safely use fork/waitpid...
382          */
383         child_pid = sys_fork();
384
385         if (child_pid == -1) {
386                 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
387                           strerror(errno)));
388                 return;
389         }
390
391         if (child_pid != 0) {
392                 /* parent */
393                 DEBUG(5, ("winbind_msg_validate_cache: child created with "
394                           "pid %d.\n", (int)child_pid));
395                 return;
396         }
397
398         /* child */
399
400         if (!winbindd_reinit_after_fork(NULL)) {
401                 _exit(0);
402         }
403
404         /* install default SIGCHLD handler: validation code uses fork/waitpid */
405         CatchSignal(SIGCHLD, SIG_DFL);
406
407         ret = (uint8)winbindd_validate_cache_nobackup();
408         DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
409         messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
410                            (size_t)1);
411         _exit(0);
412 }
413
414 bool winbindd_use_idmap_cache(void)
415 {
416         return !opt_nocache;
417 }
418
419 bool winbindd_use_cache(void)
420 {
421         return !opt_nocache;
422 }
423
424 void winbindd_register_handlers(void)
425 {
426         struct tevent_timer *te;
427         /* Setup signal handlers */
428
429         if (!winbindd_setup_sig_term_handler(true))
430                 exit(1);
431         if (!winbindd_setup_sig_hup_handler(NULL))
432                 exit(1);
433         if (!winbindd_setup_sig_chld_handler())
434                 exit(1);
435         if (!winbindd_setup_sig_usr2_handler())
436                 exit(1);
437
438         CatchSignal(SIGPIPE, SIG_IGN);                 /* Ignore sigpipe */
439
440         /*
441          * Ensure all cache and idmap caches are consistent
442          * and initialized before we startup.
443          */
444         if (!winbindd_cache_validate_and_initialize()) {
445                 exit(1);
446         }
447
448         /* get broadcast messages */
449
450         if (!serverid_register(procid_self(),
451                                FLAG_MSG_GENERAL|FLAG_MSG_DBWRAP)) {
452                 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
453                 exit(1);
454         }
455
456         /* React on 'smbcontrol winbindd reload-config' in the same way
457            as to SIGHUP signal */
458         messaging_register(winbind_messaging_context(), NULL,
459                            MSG_SMB_CONF_UPDATED, msg_reload_services);
460         messaging_register(winbind_messaging_context(), NULL,
461                            MSG_SHUTDOWN, msg_shutdown);
462
463         /* Handle online/offline messages. */
464         messaging_register(winbind_messaging_context(), NULL,
465                            MSG_WINBIND_OFFLINE, winbind_msg_offline);
466         messaging_register(winbind_messaging_context(), NULL,
467                            MSG_WINBIND_ONLINE, winbind_msg_online);
468         messaging_register(winbind_messaging_context(), NULL,
469                            MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
470
471         messaging_register(winbind_messaging_context(), NULL,
472                            MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
473
474         messaging_register(winbind_messaging_context(), NULL,
475                            MSG_WINBIND_VALIDATE_CACHE,
476                            winbind_msg_validate_cache);
477
478         messaging_register(winbind_messaging_context(), NULL,
479                            MSG_WINBIND_DUMP_DOMAIN_LIST,
480                            winbind_msg_dump_domain_list);
481
482         /* Register handler for MSG_DEBUG. */
483         messaging_register(winbind_messaging_context(), NULL,
484                            MSG_DEBUG,
485                            winbind_msg_debug);
486
487         netsamlogon_cache_init(); /* Non-critical */
488
489         /* clear the cached list of trusted domains */
490
491         wcache_tdc_clear();
492
493         if (!init_domain_list()) {
494                 DEBUG(0,("unable to initialize domain list\n"));
495                 exit(1);
496         }
497
498         init_idmap_child();
499         init_locator_child();
500
501         smb_nscd_flush_user_cache();
502         smb_nscd_flush_group_cache();
503
504         te = tevent_add_timer(winbind_event_context(), NULL, timeval_zero(),
505                               rescan_trusted_domains, NULL);
506         if (te == NULL) {
507                 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
508                 exit(1);
509         }
510
511 }
512 int main(int argc, char **argv, char **envp)
513 {
514         static bool is_daemon = False;
515         static bool Fork = True;
516         static bool log_stdout = False;
517         static bool no_process_group = False;
518         enum {
519                 OPT_DAEMON = 1000,
520                 OPT_FORK,
521                 OPT_NO_PROCESS_GROUP,
522                 OPT_LOG_STDOUT
523         };
524         struct poptOption long_options[] = {
525                 POPT_AUTOHELP
526                 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
527                 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
528                 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
529                 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
530                 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
531                 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
532                 POPT_COMMON_SAMBA
533                 POPT_TABLEEND
534         };
535         poptContext pc;
536         int opt;
537         TALLOC_CTX *frame = talloc_stackframe();
538         NTSTATUS status;
539
540         /* glibc (?) likes to print "User defined signal 1" and exit if a
541            SIGUSR[12] is received before a handler is installed */
542
543         CatchSignal(SIGUSR1, SIG_IGN);
544         CatchSignal(SIGUSR2, SIG_IGN);
545
546         fault_setup((void (*)(void *))fault_quit );
547         dump_core_setup("winbindd");
548
549         load_case_tables();
550
551         /* Initialise for running in non-root mode */
552
553         sec_init();
554
555         set_remote_machine_name("winbindd", False);
556
557         /* Set environment variable so we don't recursively call ourselves.
558            This may also be useful interactively. */
559
560         if ( !winbind_off() ) {
561                 DEBUG(0,("Failed to disable recusive winbindd calls.  Exiting.\n"));
562                 exit(1);
563         }
564
565         /* Initialise samba/rpc client stuff */
566
567         pc = poptGetContext("winbindd", argc, (const char **)argv, long_options, 0);
568
569         while ((opt = poptGetNextOpt(pc)) != -1) {
570                 switch (opt) {
571                         /* Don't become a daemon */
572                 case OPT_DAEMON:
573                         is_daemon = True;
574                         break;
575                 case 'i':
576                         interactive = True;
577                         log_stdout = True;
578                         Fork = False;
579                         break;
580                 case OPT_FORK:
581                         Fork = false;
582                         break;
583                 case OPT_NO_PROCESS_GROUP:
584                         no_process_group = true;
585                         break;
586                 case OPT_LOG_STDOUT:
587                         log_stdout = true;
588                         break;
589                 case 'n':
590                         opt_nocache = true;
591                         break;
592                 default:
593                         d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
594                                   poptBadOption(pc, 0), poptStrerror(opt));
595                         poptPrintUsage(pc, stderr, 0);
596                         exit(1);
597                 }
598         }
599
600         if (is_daemon && interactive) {
601                 d_fprintf(stderr,"\nERROR: "
602                           "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
603                 poptPrintUsage(pc, stderr, 0);
604                 exit(1);
605         }
606
607         if (log_stdout && Fork) {
608                 d_fprintf(stderr, "\nERROR: "
609                           "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
610                 poptPrintUsage(pc, stderr, 0);
611                 exit(1);
612         }
613
614         poptFreeContext(pc);
615
616         if (!override_logfile) {
617                 char *lfile = NULL;
618                 if (asprintf(&lfile,"%s/log.winbindd",
619                                 get_dyn_LOGFILEBASE()) > 0) {
620                         lp_set_logfile(lfile);
621                         SAFE_FREE(lfile);
622                 }
623         }
624         setup_logging("winbindd", log_stdout);
625         reopen_logs();
626
627         DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
628         DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
629
630         if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
631                 DEBUG(0, ("error opening config file\n"));
632                 exit(1);
633         }
634
635         /* Initialise messaging system */
636
637         if (winbind_messaging_context() == NULL) {
638                 exit(1);
639         }
640
641         if (!reload_services_file(NULL)) {
642                 DEBUG(0, ("error opening config file\n"));
643                 exit(1);
644         }
645
646         if (!directory_exist(lp_lockdir())) {
647                 mkdir(lp_lockdir(), 0755);
648         }
649
650         /* Setup names. */
651
652         if (!init_names())
653                 exit(1);
654
655         load_interfaces();
656
657         if (!secrets_init()) {
658
659                 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
660                 return False;
661         }
662
663         /* Unblock all signals we are interested in as they may have been
664            blocked by the parent process. */
665
666         BlockSignals(False, SIGINT);
667         BlockSignals(False, SIGQUIT);
668         BlockSignals(False, SIGTERM);
669         BlockSignals(False, SIGUSR1);
670         BlockSignals(False, SIGUSR2);
671         BlockSignals(False, SIGHUP);
672         BlockSignals(False, SIGCHLD);
673
674         if (!interactive)
675                 become_daemon(Fork, no_process_group, log_stdout);
676
677         pidfile_create("winbindd");
678
679 #if HAVE_SETPGID
680         /*
681          * If we're interactive we want to set our own process group for
682          * signal management.
683          */
684         if (interactive && !no_process_group)
685                 setpgid( (pid_t)0, (pid_t)0);
686 #endif
687
688         TimeInit();
689
690         /* Don't use winbindd_reinit_after_fork here as
691          * we're just starting up and haven't created any
692          * winbindd-specific resources we must free yet. JRA.
693          */
694
695         status = reinit_after_fork(winbind_messaging_context(),
696                                    winbind_event_context(),
697                                    procid_self(), false);
698         if (!NT_STATUS_IS_OK(status)) {
699                 DEBUG(0,("reinit_after_fork() failed\n"));
700                 exit(1);
701         }
702
703         winbindd_register_handlers();
704
705         rpc_lsarpc_init(NULL);
706         rpc_samr_init(NULL);
707
708         if (!init_system_info()) {
709                 DEBUG(0,("ERROR: failed to setup system user info.\n"));
710                 exit(1);
711         }
712
713         /* setup listen sockets */
714
715         if (!winbindd_setup_listeners()) {
716                 DEBUG(0,("winbindd_setup_listeners() failed\n"));
717                 exit(1);
718         }
719
720         TALLOC_FREE(frame);
721         /* Loop waiting for requests */
722         while (1) {
723                 frame = talloc_stackframe();
724
725                 if (tevent_loop_once(winbind_event_context()) == -1) {
726                         DEBUG(1, ("tevent_loop_once() failed: %s\n",
727                                   strerror(errno)));
728                         return 1;
729                 }
730
731                 TALLOC_FREE(frame);
732         }
733
734         return 0;
735 }