Home | History | Annotate | Download | only in src
      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