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