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 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 */ 61 void initalize_syslog (void) 62 { 63 openlog ("tlsdated", LOG_PID, LOG_DAEMON); 64 } 65 66 /* Signal to syslog that we're finished logging */ 67 void terminate_syslog (void) 68 { 69 closelog (); 70 } 71 72 /** helper function for 'verbose' output without syslog support */ 73 void 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 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 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 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 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 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 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 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 */ 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 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 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 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 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 334 int file_close(int fd) 335 { 336 return close(fd); 337 } 338 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 345 int time_get(struct timeval *tv) 346 { 347 return gettimeofday(tv, NULL); 348 } 349 350 int pgrp_enter(void) 351 { 352 return setpgid(0, 0); 353 } 354 355 int pgrp_kill(void) 356 { 357 pid_t grp = getpgrp(); 358 return kill(-grp, SIGKILL); 359 } 360 361 int process_signal(pid_t pid, int signal) 362 { 363 return kill (pid, signal); 364 } 365 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 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 * 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