1 /*
2  * util.c - routeup/tlsdated utility functions
3  * Copyright (c) 2012 The Chromium Authors. All rights reserved.
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "config.h"
9 #include "tlsdate.h"
10 
11 #include <fcntl.h>
12 #include <grp.h>
13 #include <limits.h>
14 #ifdef HAVE_LINUX_RTC_H
15 #include <linux/rtc.h>
16 #endif
17 #include <pwd.h>
18 #include <signal.h>
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/ioctl.h>
23 #include <sys/stat.h>
24 #include <sys/time.h>
25 #include <sys/types.h>
26 #include <sys/wait.h>
27 #include <syslog.h>
28 #include <time.h>
29 #include <unistd.h>
30 
31 #ifdef WITH_EVENTS
32 #include <event2/event.h>
33 #endif
34 
35 #include "src/tlsdate.h"
36 #include "src/util.h"
37 
38 #ifdef HAVE_SECCOMP_FILTER
39 #include "src/seccomp.h"
40 #endif
41 
42 #if defined(HAVE_STRUCT_RTC_TIME) && defined(RTC_SET_TIME) && defined(RTC_RD_TIME)
43 #define ENABLE_RTC
44 #endif
45 
46 const char *kTempSuffix = DEFAULT_DAEMON_TMPSUFFIX;
47 
48 /** helper function to print message and die */
49 void
die(const char * fmt,...)50 die (const char *fmt, ...)
51 {
52   va_list ap;
53   va_start (ap, fmt);
54   vfprintf (stderr, fmt, ap);
55   fprintf (stderr, "\n");
56   va_end (ap);
57   exit (1);
58 }
59 
60 /* Initalize syslog */
initalize_syslog(void)61 void initalize_syslog (void)
62 {
63   openlog ("tlsdated", LOG_PID, LOG_DAEMON);
64 }
65 
66 /* Signal to syslog that we're finished logging */
terminate_syslog(void)67 void terminate_syslog (void)
68 {
69   closelog ();
70 }
71 
72 /** helper function for 'verbose' output without syslog support */
73 void
verb_no_syslog(const char * fmt,...)74 verb_no_syslog (const char *fmt, ...)
75 {
76   va_list ap;
77 
78   if (! verbose ) return;
79   va_start(ap, fmt);
80   vfprintf(stderr, fmt, ap);
81   fprintf (stderr, "\n");
82   va_end(ap);
83 }
84 
85 /** helper function for 'verbose' output */
86 void
verb(const char * fmt,...)87 verb (const char *fmt, ...)
88 {
89   va_list ap;
90 
91   if (! verbose ) return;
92   va_start(ap, fmt);
93   vfprintf(stderr, fmt, ap);
94   fprintf (stderr, "\n");
95   va_end(ap);
96   va_start(ap, fmt);
97   vsyslog (LOG_DEBUG, fmt, ap);
98   va_end(ap);
99 }
100 
logat(int isverbose,const char * fmt,...)101 void API logat (int isverbose, const char *fmt, ...)
102 {
103   va_list ap;
104   if (isverbose && !verbose)
105     return;
106   va_start (ap, fmt);
107   vfprintf (stderr, fmt, ap);
108   fprintf (stderr, "\n");
109   va_end (ap);
110   va_start (ap, fmt);
111   vsyslog (LOG_INFO, fmt, ap);
112   va_end (ap);
113 }
114 
no_new_privs(void)115 void no_new_privs(void)
116 {
117 #ifdef TARGET_OS_LINUX
118 #ifdef HAVE_PRCTL // XXX: Make this specific to PR_SET_NO_NEW_PRIVS
119   // Check to see if we're already set PR_SET_NO_NEW_PRIVS
120   // This happens in tlsdated earlier than when tlsdate-helper drops
121   // privileges.
122   if (0 == prctl (PR_GET_NO_NEW_PRIVS)) {
123     // Remove the ability to regain privileges.
124     if (0 != prctl (PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
125       die ("Failed to PR_SET_NO_NEW_PRIVS");
126   } else {
127     verb ("V: Parent process has already set PR_SET_NO_NEW_PRIVS");
128   }
129 #else
130   verb ("V: we are unwilling to set PR_SET_NO_NEW_PRIVS");
131 #endif
132 #endif
133 }
134 
enable_seccomp(void)135 void enable_seccomp(void)
136 {
137 #ifdef HAVE_SECCOMP_FILTER
138   int status;
139   prctl (PR_SET_NAME, "tlsdate seccomp");
140   verb ("V: seccomp support is enabled");
141   if (enable_setter_seccomp())
142   {
143     status = SETTER_NO_SBOX;
144     _exit (status);
145   }
146 #else
147   verb ("V: seccomp support is disabled");
148 #endif
149 }
150 
151 static gid_t
get_unpriv_gid(const char * group)152 get_unpriv_gid (const char *group)
153 {
154   struct group  *gr = getgrnam (group);
155   if (NULL == gr)
156     die ("Failed to obtain GID for `%s'\n", group);
157   if (0 == gr->gr_gid)
158     die ("GID for `%s' is 0, refusing to run SSL\n", group);
159   return gr->gr_gid;
160 }
161 
162 void
drop_privs_to(const char * user,const char * group,const char ** supp_groups)163 drop_privs_to (const char *user, const char *group, const char **supp_groups)
164 {
165   uid_t uid;
166   gid_t gid;
167   struct passwd *pw;
168   size_t num_supp, i;
169 
170   if (0 != getuid ())
171     return; /* not running as root to begin with; should (!) be harmless to continue
172          without dropping to 'nobody' (setting time will fail in the end) */
173   pw = getpwnam (user);
174   if (NULL == pw)
175     die ("Failed to obtain UID for `%s'\n", user);
176   uid = pw->pw_uid;
177   if (0 == uid)
178     die ("UID for `%s' is 0, refusing to run SSL\n", user);
179   gid = get_unpriv_gid (group);
180   if (pw->pw_gid != gid)
181     die ("GID for `%s' is not `%s' as expected, refusing to run SSL\n",
182          user, group);
183   if (0 != initgroups ( (const char *) user, gid))
184     die ("Unable to initgroups for `%s' in group `%s' as expected\n",
185          user, group);
186 #ifdef HAVE_SETRESGID
187   if (0 != setresgid (gid, gid, gid))
188     die ("Failed to setresgid: %s\n", strerror (errno));
189 #else
190   if (0 != (setgid (gid) | setegid (gid)))
191     die ("Failed to setgid: %s\n", strerror (errno));
192 #endif
193   if (supp_groups)
194   {
195     for (num_supp = 0; supp_groups[num_supp]; num_supp++) ;
196     gid_t *supp_gids = (gid_t *) calloc (num_supp, sizeof (gid_t));
197     if (!supp_gids)
198       die ("Failed to allocate memory for supplementary GIDs\n");
199     for (i = 0; i < num_supp; i++)
200       supp_gids[i] = get_unpriv_gid (supp_groups[i]);
201     if (0 != setgroups (num_supp, supp_gids))
202       die ("Failed to setgroups: %s\n", strerror (errno));
203     free (supp_gids);
204   }
205 #ifdef HAVE_SETRESUID
206   if (0 != setresuid (uid, uid, uid))
207     die ("Failed to setresuid: %s\n", strerror (errno));
208 #else
209   if (0 != (setuid (uid) | seteuid (uid)))
210     die ("Failed to setuid: %s\n", strerror (errno));
211 #endif
212 }
213 
214 #ifdef ENABLE_RTC
rtc_open(struct rtc_handle * h)215 int rtc_open(struct rtc_handle *h)
216 {
217 	if (!h)
218 		return -1;
219 	h->fd = -1;
220 	/* TODO: Use platform->file_open but drop NOFOLLOW? */
221 	h->fd = open(DEFAULT_RTC_DEVICE, O_RDONLY);
222 	if (h->fd < 0)
223 	{
224 		pinfo("can't open rtc");
225 		return -1;
226 	}
227 	return 0;
228 }
229 
230 /*
231  * Set the hardware clock referred to by fd (which should be a descriptor to
232  * some device that implements the interface documented in rtc(4)) to the system
233  * time. See hwclock(8) for details of why this is important. If we fail, we
234  * just return - there's nothing the caller can really do about a failure of
235  * this function except try later.
236  */
rtc_write(struct rtc_handle * handle,const struct timeval * tv)237 int rtc_write(struct rtc_handle *handle, const struct timeval *tv)
238 {
239   struct tm tmr;
240   struct tm *tm;
241   struct rtc_time rtctm;
242   int fd = handle->fd;
243 
244   tm = gmtime_r (&tv->tv_sec, &tmr);
245 
246   /* these structs are identical, but separately defined */
247   rtctm.tm_sec = tm->tm_sec;
248   rtctm.tm_min = tm->tm_min;
249   rtctm.tm_hour = tm->tm_hour;
250   rtctm.tm_mday = tm->tm_mday;
251   rtctm.tm_mon = tm->tm_mon;
252   rtctm.tm_year = tm->tm_year;
253   rtctm.tm_wday = tm->tm_wday;
254   rtctm.tm_yday = tm->tm_yday;
255   rtctm.tm_isdst = tm->tm_isdst;
256 
257   if (ioctl (fd, RTC_SET_TIME, &rtctm))
258   {
259     pinfo ("ioctl(%d, RTC_SET_TIME, ...) failed", fd);
260     return 1;
261   }
262 
263   info ("synced rtc to sysclock");
264   return 0;
265 }
266 
rtc_read(struct rtc_handle * handle,struct timeval * tv)267 int rtc_read(struct rtc_handle *handle, struct timeval *tv)
268 {
269   struct tm tm;
270   struct rtc_time rtctm;
271   int fd = handle->fd;
272 
273   if (ioctl (fd, RTC_RD_TIME, &rtctm))
274   {
275     pinfo ("ioctl(%d, RTC_RD_TIME, ...) failed", fd);
276     return 1;
277   }
278 
279   tm.tm_sec = rtctm.tm_sec;
280   tm.tm_min = rtctm.tm_min;
281   tm.tm_hour = rtctm.tm_hour;
282   tm.tm_mday = rtctm.tm_mday;
283   tm.tm_mon = rtctm.tm_mon;
284   tm.tm_year = rtctm.tm_year;
285   tm.tm_wday = rtctm.tm_wday;
286   tm.tm_yday = rtctm.tm_yday;
287   tm.tm_isdst = rtctm.tm_isdst;
288 
289   tv->tv_sec = mktime(&tm);
290   tv->tv_usec = 0;
291 
292   return 0;
293 }
294 
rtc_close(struct rtc_handle * handle)295 int rtc_close(struct rtc_handle *handle)
296 {
297 	struct rtc_handle *h = handle;
298 	platform->file_close(h->fd);
299 	h->fd = -1;
300 	return 0;
301 }
302 #endif
303 
file_write(int fd,void * buf,size_t sz)304 int file_write(int fd, void *buf, size_t sz)
305 {
306 	ssize_t ret = IGNORE_EINTR (pwrite (fd, buf, sz, 0));
307 	return (ret >= 0 && ((size_t) ret) == sz ? 0 : -1);
308 }
309 
file_open(const char * path,int write,int cloexec)310 int file_open(const char *path, int write, int cloexec)
311 {
312 	int fd;
313 	int oflags = cloexec ? O_CLOEXEC : 0;
314 	if (write)
315 	{
316 		int perms = S_IRUSR | S_IWUSR;
317 		oflags |= O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC;
318 		/* Rely on atomic write calls rather than rename() calls. */
319 		fd = open(path, oflags, perms);
320 	}
321 	else
322 	{
323 		oflags |= O_RDONLY | O_NOFOLLOW;
324 		fd = open(path, oflags);
325 	}
326 	if (fd < 0)
327 	{
328 		pinfo("open(%s) failed", path);
329 		return -1;
330 	}
331 	return fd;
332 }
333 
file_close(int fd)334 int file_close(int fd)
335 {
336 	return close(fd);
337 }
338 
file_read(int fd,void * buf,size_t sz)339 int file_read(int fd, void *buf, size_t sz)
340 {
341 	ssize_t ret = IGNORE_EINTR (pread (fd, buf, sz, 0));
342 	return (ret >= 0 && ((size_t) ret) == sz ? 0 : -1);
343 }
344 
time_get(struct timeval * tv)345 int time_get(struct timeval *tv)
346 {
347 	return gettimeofday(tv, NULL);
348 }
349 
pgrp_enter(void)350 int pgrp_enter(void)
351 {
352 	return setpgid(0, 0);
353 }
354 
pgrp_kill(void)355 int pgrp_kill(void)
356 {
357 	pid_t grp = getpgrp();
358 	return kill(-grp, SIGKILL);
359 }
360 
process_signal(pid_t pid,int signal)361 int process_signal(pid_t pid, int signal)
362 {
363 	return kill (pid, signal);
364 }
365 
process_wait(pid_t pid,int * status,int forever)366 pid_t process_wait(pid_t pid, int *status, int forever)
367 {
368   int flag = forever ? 0 : WNOHANG;
369   return waitpid (pid, status, flag);
370 }
371 
372 static struct platform default_platform = {
373 #ifdef ENABLE_RTC
374 	.rtc_open = rtc_open,
375 	.rtc_write = rtc_write,
376 	.rtc_read = rtc_read,
377 	.rtc_close = rtc_close,
378 #endif
379 
380 	.file_open = file_open,
381 	.file_close = file_close,
382 	.file_write = file_write,
383 	.file_read = file_read,
384 
385 	.time_get = time_get,
386 
387 	.pgrp_enter = pgrp_enter,
388 	.pgrp_kill = pgrp_kill,
389 
390 	.process_signal = process_signal,
391 	.process_wait = process_wait
392 };
393 
394 struct platform *platform = &default_platform;
395 
396 /* TODO(wad) rename to schedule_event */
397 void
trigger_event(struct state * state,enum event_id_t id,int sec)398 trigger_event (struct state *state, enum event_id_t id, int sec)
399 {
400 #ifdef WITH_EVENTS
401   struct event *e = state->events[id];
402   struct timeval delay = { sec, 0 };
403   /* Fallthrough to tlsdate if there is no resolver. */
404   if (!e && id == E_RESOLVER)
405     e = state->events[E_TLSDATE];
406   if (!e)
407     {
408       info ("trigger_event with NULL |e|. I hope this is a test!");
409       return;
410     }
411   if (event_pending (e, EV_READ|EV_WRITE|EV_TIMEOUT|EV_SIGNAL, NULL))
412     event_del (e);
413   if (sec >= 0)
414     event_add (e, &delay);
415   else /* Note! This will not fire a TIMEOUT event. */
416     event_add (e, NULL);
417 #endif
418 }
419 
420 const char *
sync_type_str(int sync_type)421 sync_type_str (int sync_type)
422 {
423   switch (sync_type)
424     {
425     case SYNC_TYPE_NONE:
426       return "none";
427     case SYNC_TYPE_BUILD:
428       return "build-timestamp";
429     case SYNC_TYPE_DISK:
430       return "disk-timestamp";
431     case SYNC_TYPE_RTC:
432       return "system-clock";
433     case SYNC_TYPE_PLATFORM:
434       return "platform-feature";
435     case SYNC_TYPE_NET:
436       return "network";
437     default:
438       return "error";
439     }
440 }
441