1 /*
2   chronyd/chronyc - Programs for keeping computer clocks accurate.
3 
4  **********************************************************************
5  * Copyright (C) Richard P. Curnow  1997-2003
6  * Copyright (C) John G. Hasler  2009
7  * Copyright (C) Miroslav Lichvar  2012-2020
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of version 2 of the GNU General Public License as
11  * published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  *
22  **********************************************************************
23 
24   =======================================================================
25 
26   The main program
27   */
28 
29 #include "config.h"
30 
31 #include "sysincl.h"
32 
33 #include "main.h"
34 #include "sched.h"
35 #include "local.h"
36 #include "sys.h"
37 #include "ntp_io.h"
38 #include "ntp_signd.h"
39 #include "ntp_sources.h"
40 #include "ntp_core.h"
41 #include "nts_ke_server.h"
42 #include "nts_ntp_server.h"
43 #include "socket.h"
44 #include "sources.h"
45 #include "sourcestats.h"
46 #include "reference.h"
47 #include "logging.h"
48 #include "conf.h"
49 #include "cmdmon.h"
50 #include "keys.h"
51 #include "manual.h"
52 #include "rtc.h"
53 #include "refclock.h"
54 #include "clientlog.h"
55 #include "nameserv.h"
56 #include "privops.h"
57 #include "smooth.h"
58 #include "tempcomp.h"
59 #include "util.h"
60 
61 /* ================================================== */
62 
63 /* Set when the initialisation chain has been completed.  Prevents finalisation
64  * chain being run if a fatal error happened early. */
65 
66 static int initialised = 0;
67 
68 static int exit_status = 0;
69 
70 static int reload = 0;
71 
72 static REF_Mode ref_mode = REF_ModeNormal;
73 
74 /* ================================================== */
75 
76 static void
do_platform_checks(void)77 do_platform_checks(void)
78 {
79   struct timespec ts;
80 
81   /* Require at least 32-bit integers, two's complement representation and
82      the usual implementation of conversion of unsigned integers */
83   assert(sizeof (int) >= 4);
84   assert(-1 == ~0);
85   assert((int32_t)4294967295U == (int32_t)-1);
86 
87   /* Require time_t and tv_nsec in timespec to be signed */
88   ts.tv_sec = -1;
89   ts.tv_nsec = -1;
90   assert(ts.tv_sec < 0 && ts.tv_nsec < 0);
91 }
92 
93 /* ================================================== */
94 
95 static void
delete_pidfile(void)96 delete_pidfile(void)
97 {
98   const char *pidfile = CNF_GetPidFile();
99 
100   if (!pidfile)
101     return;
102 
103   if (!UTI_RemoveFile(NULL, pidfile, NULL))
104     ;
105 }
106 
107 /* ================================================== */
108 
109 void
MAI_CleanupAndExit(void)110 MAI_CleanupAndExit(void)
111 {
112   if (!initialised) exit(exit_status);
113 
114   LCL_CancelOffsetCorrection();
115   SRC_DumpSources();
116 
117   /* Don't update clock when removing sources */
118   REF_SetMode(REF_ModeIgnore);
119 
120   SMT_Finalise();
121   TMC_Finalise();
122   MNL_Finalise();
123   CLG_Finalise();
124   NKS_Finalise();
125   NNS_Finalise();
126   NSD_Finalise();
127   NSR_Finalise();
128   SST_Finalise();
129   NCR_Finalise();
130   NIO_Finalise();
131   CAM_Finalise();
132 
133   KEY_Finalise();
134   RCL_Finalise();
135   SRC_Finalise();
136   REF_Finalise();
137   RTC_Finalise();
138   SYS_Finalise();
139 
140   SCK_Finalise();
141   SCH_Finalise();
142   LCL_Finalise();
143   PRV_Finalise();
144 
145   delete_pidfile();
146 
147   CNF_Finalise();
148   HSH_Finalise();
149   LOG_Finalise();
150 
151   UTI_ResetGetRandomFunctions();
152 
153   exit(exit_status);
154 }
155 
156 /* ================================================== */
157 
158 static void
signal_cleanup(int x)159 signal_cleanup(int x)
160 {
161   SCH_QuitProgram();
162 }
163 
164 /* ================================================== */
165 
166 static void
quit_timeout(void * arg)167 quit_timeout(void *arg)
168 {
169   /* Return with non-zero status if the clock is not synchronised */
170   exit_status = REF_GetOurStratum() >= NTP_MAX_STRATUM;
171   SCH_QuitProgram();
172 }
173 
174 /* ================================================== */
175 
176 static void
ntp_source_resolving_end(void)177 ntp_source_resolving_end(void)
178 {
179   NSR_SetSourceResolvingEndHandler(NULL);
180 
181   if (reload) {
182     /* Note, we want reload to come well after the initialisation from
183        the real time clock - this gives us a fighting chance that the
184        system-clock scale for the reloaded samples still has a
185        semblence of validity about it. */
186     SRC_ReloadSources();
187   }
188 
189   SRC_RemoveDumpFiles();
190   RTC_StartMeasurements();
191   RCL_StartRefclocks();
192   NSR_StartSources();
193   NSR_AutoStartSources();
194 
195   /* Special modes can end only when sources update their reachability.
196      Give up immediately if there are no active sources. */
197   if (ref_mode != REF_ModeNormal && !SRC_ActiveSources()) {
198     REF_SetUnsynchronised();
199   }
200 }
201 
202 /* ================================================== */
203 
204 static void
post_init_ntp_hook(void * anything)205 post_init_ntp_hook(void *anything)
206 {
207   if (ref_mode == REF_ModeInitStepSlew) {
208     /* Remove the initstepslew sources and set normal mode */
209     NSR_RemoveAllSources();
210     ref_mode = REF_ModeNormal;
211     REF_SetMode(ref_mode);
212   }
213 
214   /* Close the pipe to the foreground process so it can exit */
215   LOG_CloseParentFd();
216 
217   CNF_AddSources();
218   CNF_AddBroadcasts();
219 
220   NSR_SetSourceResolvingEndHandler(ntp_source_resolving_end);
221   NSR_ResolveSources();
222 }
223 
224 /* ================================================== */
225 
226 static void
reference_mode_end(int result)227 reference_mode_end(int result)
228 {
229   switch (ref_mode) {
230     case REF_ModeNormal:
231     case REF_ModeUpdateOnce:
232     case REF_ModePrintOnce:
233       exit_status = !result;
234       SCH_QuitProgram();
235       break;
236     case REF_ModeInitStepSlew:
237       /* Switch to the normal mode, the delay is used to prevent polling
238          interval shorter than the burst interval if some configured servers
239          were used also for initstepslew */
240       SCH_AddTimeoutByDelay(2.0, post_init_ntp_hook, NULL);
241       break;
242     default:
243       assert(0);
244   }
245 }
246 
247 /* ================================================== */
248 
249 static void
post_init_rtc_hook(void * anything)250 post_init_rtc_hook(void *anything)
251 {
252   if (CNF_GetInitSources() > 0) {
253     CNF_AddInitSources();
254     NSR_StartSources();
255     assert(REF_GetMode() != REF_ModeNormal);
256     /* Wait for mode end notification */
257   } else {
258     (post_init_ntp_hook)(NULL);
259   }
260 }
261 
262 /* ================================================== */
263 
264 static void
check_pidfile(void)265 check_pidfile(void)
266 {
267   const char *pidfile = CNF_GetPidFile();
268   FILE *in;
269   int pid, count;
270 
271   if (!pidfile)
272     return;
273 
274   in = UTI_OpenFile(NULL, pidfile, NULL, 'r', 0);
275   if (!in)
276     return;
277 
278   count = fscanf(in, "%d", &pid);
279   fclose(in);
280 
281   if (count != 1)
282     return;
283 
284   if (getsid(pid) < 0)
285     return;
286 
287   LOG_FATAL("Another chronyd may already be running (pid=%d), check %s",
288             pid, pidfile);
289 }
290 
291 /* ================================================== */
292 
293 static void
write_pidfile(void)294 write_pidfile(void)
295 {
296   const char *pidfile = CNF_GetPidFile();
297   FILE *out;
298 
299   if (!pidfile)
300     return;
301 
302   out = UTI_OpenFile(NULL, pidfile, NULL, 'W', 0644);
303   fprintf(out, "%d\n", (int)getpid());
304   fclose(out);
305 }
306 
307 /* ================================================== */
308 
309 #define DEV_NULL "/dev/null"
310 
311 static void
go_daemon(void)312 go_daemon(void)
313 {
314   int pid, fd, pipefd[2];
315 
316   /* Create pipe which will the daemon use to notify the grandparent
317      when it's initialised or send an error message */
318   if (pipe(pipefd)) {
319     LOG_FATAL("pipe() failed : %s", strerror(errno));
320   }
321 
322   /* Does this preserve existing signal handlers? */
323   pid = fork();
324 
325   if (pid < 0) {
326     LOG_FATAL("fork() failed : %s", strerror(errno));
327   } else if (pid > 0) {
328     /* In the 'grandparent' */
329     char message[1024];
330     int r;
331 
332     close(pipefd[1]);
333     r = read(pipefd[0], message, sizeof (message));
334     if (r) {
335       if (r > 0) {
336         /* Print the error message from the child */
337         message[sizeof (message) - 1] = '\0';
338         fprintf(stderr, "%s\n", message);
339       }
340       exit(1);
341     } else
342       exit(0);
343   } else {
344     close(pipefd[0]);
345 
346     setsid();
347 
348     /* Do 2nd fork, as-per recommended practice for launching daemons. */
349     pid = fork();
350 
351     if (pid < 0) {
352       LOG_FATAL("fork() failed : %s", strerror(errno));
353     } else if (pid > 0) {
354       exit(0); /* In the 'parent' */
355     } else {
356       /* In the child we want to leave running as the daemon */
357 
358       /* Change current directory to / */
359       if (chdir("/") < 0) {
360         LOG_FATAL("chdir() failed : %s", strerror(errno));
361       }
362 
363       /* Don't keep stdin/out/err from before. But don't close
364          the parent pipe yet. */
365       for (fd=0; fd<1024; fd++) {
366         if (fd != pipefd[1])
367           close(fd);
368       }
369 
370       LOG_SetParentFd(pipefd[1]);
371 
372       /* Open /dev/null as new stdin/out/err */
373       errno = 0;
374       if (open(DEV_NULL, O_RDONLY) != STDIN_FILENO ||
375           open(DEV_NULL, O_WRONLY) != STDOUT_FILENO ||
376           open(DEV_NULL, O_RDWR) != STDERR_FILENO)
377         LOG_FATAL("Could not open %s : %s", DEV_NULL, strerror(errno));
378     }
379   }
380 }
381 
382 /* ================================================== */
383 
384 static void
print_help(const char * progname)385 print_help(const char *progname)
386 {
387       printf("Usage: %s [OPTION]... [DIRECTIVE]...\n\n"
388              "Options:\n"
389              "  -4\t\tUse IPv4 addresses only\n"
390              "  -6\t\tUse IPv6 addresses only\n"
391              "  -f FILE\tSpecify configuration file (%s)\n"
392              "  -n\t\tDon't run as daemon\n"
393              "  -d\t\tDon't run as daemon and log to stderr\n"
394 #if DEBUG > 0
395              "  -d -d\t\tEnable debug messages\n"
396 #endif
397              "  -l FILE\tLog to file\n"
398              "  -L LEVEL\tSet logging threshold (0)\n"
399              "  -p\t\tPrint configuration and exit\n"
400              "  -q\t\tSet clock and exit\n"
401              "  -Q\t\tLog offset and exit\n"
402              "  -r\t\tReload dump files\n"
403              "  -R\t\tAdapt configuration for restart\n"
404              "  -s\t\tSet clock from RTC\n"
405              "  -t SECONDS\tExit after elapsed time\n"
406              "  -u USER\tSpecify user (%s)\n"
407              "  -U\t\tDon't check for root\n"
408              "  -F LEVEL\tSet system call filter level (0)\n"
409              "  -P PRIORITY\tSet process priority (0)\n"
410              "  -m\t\tLock memory\n"
411              "  -x\t\tDon't control clock\n"
412              "  -v, --version\tPrint version and exit\n"
413              "  -h, --help\tPrint usage and exit\n",
414              progname, DEFAULT_CONF_FILE, DEFAULT_USER);
415 }
416 
417 /* ================================================== */
418 
419 static void
print_version(void)420 print_version(void)
421 {
422   printf("chronyd (chrony) version %s (%s)\n", CHRONY_VERSION, CHRONYD_FEATURES);
423 }
424 
425 /* ================================================== */
426 
427 static int
parse_int_arg(const char * arg)428 parse_int_arg(const char *arg)
429 {
430   int i;
431 
432   if (sscanf(arg, "%d", &i) != 1)
433     LOG_FATAL("Invalid argument %s", arg);
434   return i;
435 }
436 
437 /* ================================================== */
438 
main(int argc,char ** argv)439 int main
440 (int argc, char **argv)
441 {
442   const char *conf_file = DEFAULT_CONF_FILE;
443   const char *progname = argv[0];
444   char *user = NULL, *log_file = NULL;
445   struct passwd *pw;
446   int opt, debug = 0, nofork = 0, address_family = IPADDR_UNSPEC;
447   int do_init_rtc = 0, restarted = 0, client_only = 0, timeout = -1;
448   int scfilter_level = 0, lock_memory = 0, sched_priority = 0;
449   int clock_control = 1, system_log = 1, log_severity = LOGS_INFO;
450   int user_check = 1, config_args = 0, print_config = 0;
451 
452   do_platform_checks();
453 
454   LOG_Initialise();
455 
456   /* Parse long command-line options */
457   for (optind = 1; optind < argc; optind++) {
458     if (!strcmp("--help", argv[optind])) {
459       print_help(progname);
460       return 0;
461     } else if (!strcmp("--version", argv[optind])) {
462       print_version();
463       return 0;
464     }
465   }
466 
467   optind = 1;
468 
469   /* Parse short command-line options */
470   while ((opt = getopt(argc, argv, "46df:F:hl:L:mnpP:qQrRst:u:Uvx")) != -1) {
471     switch (opt) {
472       case '4':
473       case '6':
474         address_family = opt == '4' ? IPADDR_INET4 : IPADDR_INET6;
475         break;
476       case 'd':
477         debug++;
478         nofork = 1;
479         system_log = 0;
480         break;
481       case 'f':
482         conf_file = optarg;
483         break;
484       case 'F':
485         scfilter_level = parse_int_arg(optarg);
486         break;
487       case 'l':
488         log_file = optarg;
489         break;
490       case 'L':
491         log_severity = parse_int_arg(optarg);
492         break;
493       case 'm':
494         lock_memory = 1;
495         break;
496       case 'n':
497         nofork = 1;
498         break;
499       case 'p':
500         print_config = 1;
501         user_check = 0;
502         nofork = 1;
503         system_log = 0;
504         log_severity = LOGS_WARN;
505         break;
506       case 'P':
507         sched_priority = parse_int_arg(optarg);
508         break;
509       case 'q':
510         ref_mode = REF_ModeUpdateOnce;
511         nofork = 1;
512         client_only = 0;
513         system_log = 0;
514         break;
515       case 'Q':
516         ref_mode = REF_ModePrintOnce;
517         nofork = 1;
518         client_only = 1;
519         user_check = 0;
520         clock_control = 0;
521         system_log = 0;
522         break;
523       case 'r':
524         reload = 1;
525         break;
526       case 'R':
527         restarted = 1;
528         break;
529       case 's':
530         do_init_rtc = 1;
531         break;
532       case 't':
533         timeout = parse_int_arg(optarg);
534         break;
535       case 'u':
536         user = optarg;
537         break;
538       case 'U':
539         user_check = 0;
540         break;
541       case 'v':
542         print_version();
543         return 0;
544       case 'x':
545         clock_control = 0;
546         break;
547       default:
548         print_help(progname);
549         return opt != 'h';
550     }
551   }
552 
553   if (user_check && getuid() != 0)
554     LOG_FATAL("Not superuser");
555 
556   /* Turn into a daemon */
557   if (!nofork) {
558     go_daemon();
559   }
560 
561   if (log_file) {
562     LOG_OpenFileLog(log_file);
563   } else if (system_log) {
564     LOG_OpenSystemLog();
565   }
566 
567   LOG_SetMinSeverity(debug >= 2 ? LOGS_DEBUG : log_severity);
568 
569   LOG(LOGS_INFO, "chronyd version %s starting (%s)", CHRONY_VERSION, CHRONYD_FEATURES);
570 
571   DNS_SetAddressFamily(address_family);
572 
573   CNF_Initialise(restarted, client_only);
574   if (print_config)
575     CNF_EnablePrint();
576 
577   /* Parse the config file or the remaining command line arguments */
578   config_args = argc - optind;
579   if (!config_args) {
580     CNF_ReadFile(conf_file);
581   } else {
582     for (; optind < argc; optind++)
583       CNF_ParseLine(NULL, config_args + optind - argc + 1, argv[optind]);
584   }
585 
586   if (print_config)
587     return 0;
588 
589   /* Check whether another chronyd may already be running */
590   check_pidfile();
591 
592   if (!user)
593     user = CNF_GetUser();
594 
595   pw = getpwnam(user);
596   if (!pw)
597     LOG_FATAL("Could not get user/group ID of %s", user);
598 
599   /* Create directories for sockets, log files, and dump files */
600   CNF_CreateDirs(pw->pw_uid, pw->pw_gid);
601 
602   /* Write our pidfile to prevent other instances from running */
603   write_pidfile();
604 
605   PRV_Initialise();
606   LCL_Initialise();
607   SCH_Initialise();
608   SCK_Initialise(address_family);
609 
610   /* Start helper processes if needed */
611   NKS_PreInitialise(pw->pw_uid, pw->pw_gid, scfilter_level);
612 
613   SYS_Initialise(clock_control);
614   RTC_Initialise(do_init_rtc);
615   SRC_Initialise();
616   RCL_Initialise();
617   KEY_Initialise();
618 
619   /* Open privileged ports before dropping root */
620   CAM_Initialise();
621   NIO_Initialise();
622   NCR_Initialise();
623   CNF_SetupAccessRestrictions();
624 
625   /* Command-line switch must have priority */
626   if (!sched_priority) {
627     sched_priority = CNF_GetSchedPriority();
628   }
629   if (sched_priority) {
630     SYS_SetScheduler(sched_priority);
631   }
632 
633   if (lock_memory || CNF_GetLockMemory()) {
634     SYS_LockMemory();
635   }
636 
637   /* Drop root privileges if the specified user has a non-zero UID */
638   if (!geteuid() && (pw->pw_uid || pw->pw_gid))
639     SYS_DropRoot(pw->pw_uid, pw->pw_gid, SYS_MAIN_PROCESS);
640 
641   if (!geteuid())
642     LOG(LOGS_WARN, "Running with root privileges");
643 
644   REF_Initialise();
645   SST_Initialise();
646   NSR_Initialise();
647   NSD_Initialise();
648   NNS_Initialise();
649   NKS_Initialise();
650   CLG_Initialise();
651   MNL_Initialise();
652   TMC_Initialise();
653   SMT_Initialise();
654 
655   /* From now on, it is safe to do finalisation on exit */
656   initialised = 1;
657 
658   UTI_SetQuitSignalsHandler(signal_cleanup, 1);
659 
660   CAM_OpenUnixSocket();
661 
662   if (scfilter_level)
663     SYS_EnableSystemCallFilter(scfilter_level, SYS_MAIN_PROCESS);
664 
665   if (ref_mode == REF_ModeNormal && CNF_GetInitSources() > 0) {
666     ref_mode = REF_ModeInitStepSlew;
667   }
668 
669   REF_SetModeEndHandler(reference_mode_end);
670   REF_SetMode(ref_mode);
671 
672   if (timeout >= 0)
673     SCH_AddTimeoutByDelay(timeout, quit_timeout, NULL);
674 
675   if (do_init_rtc) {
676     RTC_TimeInit(post_init_rtc_hook, NULL);
677   } else {
678     post_init_rtc_hook(NULL);
679   }
680 
681   /* The program normally runs under control of the main loop in
682      the scheduler. */
683   SCH_MainLoop();
684 
685   LOG(LOGS_INFO, "chronyd exiting");
686 
687   MAI_CleanupAndExit();
688 
689   return 0;
690 }
691 
692 /* ================================================== */
693