diff options
-rw-r--r-- | init/tlsdated.rc | 2 | ||||
-rw-r--r-- | src/tlsdate-helper-plan9.c | 4 | ||||
-rw-r--r-- | src/tlsdate-helper.c | 4 | ||||
-rw-r--r-- | src/tlsdate.h | 1 | ||||
-rw-r--r-- | src/tlsdated.c | 31 | ||||
-rw-r--r-- | src/util-plan9.c | 6 | ||||
-rw-r--r-- | src/util-plan9.h | 3 | ||||
-rw-r--r-- | src/util.c | 38 | ||||
-rw-r--r-- | src/util.h | 3 |
9 files changed, 72 insertions, 20 deletions
diff --git a/init/tlsdated.rc b/init/tlsdated.rc index c36b920..2418255 100644 --- a/init/tlsdated.rc +++ b/init/tlsdated.rc @@ -1,5 +1,5 @@ # Init file for starting tlsdated on Android. -service tlsdated /system/bin/tlsdated -v -l -s -U -- /system/bin/tlsdate -v -C /system/etc/security/cacerts -l +service tlsdated /system/bin/tlsdated -v -l -s -G dbus -- /system/bin/tlsdate -v -C /system/etc/security/cacerts -l class main # This daemon needs to start as root and drops privileges early on. user root diff --git a/src/tlsdate-helper-plan9.c b/src/tlsdate-helper-plan9.c index 3c532aa..c245a6b 100644 --- a/src/tlsdate-helper-plan9.c +++ b/src/tlsdate-helper-plan9.c @@ -1109,7 +1109,7 @@ main(int argc, char **argv) /* We are not going to set the clock, thus no need to stay root */ if (0 == setclock && 0 == timewarp) { - drop_privs_to (UNPRIV_USER, UNPRIV_GROUP); + drop_privs_to (UNPRIV_USER, UNPRIV_GROUP, NULL); } /* XXX: KILL ME @@ -1171,7 +1171,7 @@ main(int argc, char **argv) die ("fork failed: %s\n", strerror (errno)); if (0 == ssl_child) { - drop_privs_to (UNPRIV_USER, UNPRIV_GROUP); + drop_privs_to (UNPRIV_USER, UNPRIV_GROUP, NULL); run_ssl (time_map, leap); /* XXX: should be a pipe close diff --git a/src/tlsdate-helper.c b/src/tlsdate-helper.c index 9322517..d923efd 100644 --- a/src/tlsdate-helper.c +++ b/src/tlsdate-helper.c @@ -1276,7 +1276,7 @@ main(int argc, char **argv) if (0 == setclock && 0 == timewarp) { verb ("V: attemping to drop administrator privileges"); - drop_privs_to (UNPRIV_USER, UNPRIV_GROUP); + drop_privs_to (UNPRIV_USER, UNPRIV_GROUP, NULL); } // We cast the mmap value to remove this error when compiling with g++: @@ -1337,7 +1337,7 @@ main(int argc, char **argv) die ("fork failed: %s", strerror (errno)); if (0 == ssl_child) { - drop_privs_to (UNPRIV_USER, UNPRIV_GROUP); + drop_privs_to (UNPRIV_USER, UNPRIV_GROUP, NULL); run_ssl (time_map, leap, http); (void) munmap (time_map, sizeof (uint32_t)); _exit (0); diff --git a/src/tlsdate.h b/src/tlsdate.h index 52305eb..97d4fec 100644 --- a/src/tlsdate.h +++ b/src/tlsdate.h @@ -111,6 +111,7 @@ struct opts { const char *user; const char *group; + char *supp_groups; int max_tries; int min_steady_state_interval; int wait_between_tries; diff --git a/src/tlsdated.c b/src/tlsdated.c index a4af628..aa852ac 100644 --- a/src/tlsdated.c +++ b/src/tlsdated.c @@ -42,6 +42,8 @@ #include "src/dbus.h" #include "src/platform.h" + +static const char kTlsdatedOpts[] = "hwrpt:d:T:D:c:a:lsvbm:j:f:x:Uu:g:G:"; const char *kCacheDir = DEFAULT_DAEMON_CACHEDIR; int @@ -102,6 +104,7 @@ usage (const char *progn) printf (" -U don't use DBus if supported\n"); printf (" -u <user> user to change to\n"); printf (" -g <grp> group to change to\n"); + printf (" -G <grps> comma-separated list of supplementary groups\n"); printf (" -v be verbose\n"); printf (" -b use verbose debugging\n"); printf (" -x <h> set proxy for subprocs to h\n"); @@ -117,6 +120,7 @@ set_conf_defaults (struct opts *opts) }; opts->user = UNPRIV_USER; opts->group = UNPRIV_GROUP; + opts->supp_groups = NULL; opts->max_tries = MAX_TRIES; opts->min_steady_state_interval = STEADY_STATE_INTERVAL; opts->wait_between_tries = WAIT_BETWEEN_TRIES; @@ -145,7 +149,7 @@ void parse_argv (struct opts *opts, int argc, char *argv[]) { int opt; - while ((opt = getopt (argc, argv, "hwrpt:d:T:D:c:a:lsvbm:j:f:x:Uu:g:")) != -1) + while ((opt = getopt (argc, argv, kTlsdatedOpts)) != -1) { switch (opt) { @@ -209,6 +213,9 @@ parse_argv (struct opts *opts, int argc, char *argv[]) case 'g': opts->group = optarg; break; + case 'G': + opts->supp_groups = optarg; + break; case 'h': default: usage (argv[0]); @@ -220,6 +227,21 @@ parse_argv (struct opts *opts, int argc, char *argv[]) /* Validate arguments */ } +static const char ** +parse_supp_groups (char *arg) +{ + size_t i; + char *scan; + const char **supp_groups; + + for (i = 1, scan = arg; (scan = strchr (scan, ',')); i++, scan++) ; + supp_groups = (const char **) calloc (i + 1, sizeof (const char *)); + if (!supp_groups) + die ("Failed to allocate memory for supplementary group names\n"); + for (i = 0; (supp_groups[i] = strsep (&arg, ",")); i++) ; + return supp_groups; +} + static void add_source_to_conf (struct opts *opts, char *host, char *port, char *proxy) { @@ -446,6 +468,8 @@ cleanup_main (struct state *state) int API main (int argc, char *argv[], char *envp[]) { + const char **supp_groups = NULL; + initalize_syslog (); struct state state; /* TODO(wad) EVENT_BASE_FLAG_PRECISE_TIMER | EVENT_BASE_FLAG_PRECISE_TIMER */ @@ -498,7 +522,9 @@ main (int argc, char *argv[], char *envp[]) platform->rtc_close (&state.hwclock); } /* drop privileges before touching any untrusted data */ - drop_privs_to (state.opts.user, state.opts.group); + if (state.opts.supp_groups) + supp_groups = parse_supp_groups (state.opts.supp_groups); + drop_privs_to (state.opts.user, state.opts.group, supp_groups); /* register a signal handler to save time at shutdown */ if (state.opts.should_save_disk) { @@ -598,6 +624,7 @@ main (int argc, char *argv[], char *envp[]) event_base_dispatch (base); verb ("tlsdated event dispatch terminating gracefully"); out: + free (supp_groups); return cleanup_main (&state); } #endif /* !TLSDATED_MAIN */ diff --git a/src/util-plan9.c b/src/util-plan9.c index 77d2077..84b68fc 100644 --- a/src/util-plan9.c +++ b/src/util-plan9.c @@ -61,7 +61,7 @@ void API logat(int isverbose, const char *fmt, ...) void -drop_privs_to (const char *user, const char *group) +drop_privs_to (const char *user, const char *group, const char **supp_groups) { #if !_PLAN9_SOURCE @@ -70,6 +70,10 @@ drop_privs_to (const char *user, const char *group) struct passwd *pw; struct group *gr; + /* TODO(garnold) Implement supplementary group support. */ + if (supp_groups) + die ("Supplementary groups not supported\n"); + if (0 != getuid ()) return; /* not running as root to begin with; should (!) be harmless to continue without dropping to 'nobody' (setting time will fail in the end) */ diff --git a/src/util-plan9.h b/src/util-plan9.h index 7453235..62f2329 100644 --- a/src/util-plan9.h +++ b/src/util-plan9.h @@ -36,6 +36,7 @@ extern void logat(int isverbose, const char *fmt, ...); static inline int min(int x, int y) { return x < y ? x : y; } -void drop_privs_to (const char *user, const char *group); +void drop_privs_to (const char *user, const char *group, + const char **supp_groups); #endif /* !UTIL_H */ @@ -148,33 +148,39 @@ void enable_seccomp(void) #endif } +static gid_t +get_unpriv_gid (const char *group) +{ + struct group *gr = getgrnam (group); + if (NULL == gr) + die ("Failed to obtain GID for `%s'\n", group); + if (0 == gr->gr_gid) + die ("GID for `%s' is 0, refusing to run SSL\n", group); + return gr->gr_gid; +} + void -drop_privs_to (const char *user, const char *group) +drop_privs_to (const char *user, const char *group, const char **supp_groups) { uid_t uid; gid_t gid; struct passwd *pw; - struct group *gr; + size_t num_supp, i; if (0 != getuid ()) return; /* not running as root to begin with; should (!) be harmless to continue without dropping to 'nobody' (setting time will fail in the end) */ pw = getpwnam (user); - gr = getgrnam (group); if (NULL == pw) die ("Failed to obtain UID for `%s'\n", user); - if (NULL == gr) - die ("Failed to obtain GID for `%s'\n", group); uid = pw->pw_uid; if (0 == uid) die ("UID for `%s' is 0, refusing to run SSL\n", user); - gid = pw->pw_gid; - if (0 == gid || 0 == gr->gr_gid) - die ("GID for `%s' is 0, refusing to run SSL\n", user); - if (pw->pw_gid != gr->gr_gid) + gid = get_unpriv_gid (group); + if (pw->pw_gid != gid) die ("GID for `%s' is not `%s' as expected, refusing to run SSL\n", user, group); - if (0 != initgroups ( (const char *) user, gr->gr_gid)) + if (0 != initgroups ( (const char *) user, gid)) die ("Unable to initgroups for `%s' in group `%s' as expected\n", user, group); #ifdef HAVE_SETRESGID @@ -184,6 +190,18 @@ drop_privs_to (const char *user, const char *group) if (0 != (setgid (gid) | setegid (gid))) die ("Failed to setgid: %s\n", strerror (errno)); #endif + if (supp_groups) + { + for (num_supp = 0; supp_groups[num_supp]; num_supp++) ; + gid_t *supp_gids = (gid_t *) calloc (num_supp, sizeof (gid_t)); + if (!supp_gids) + die ("Failed to allocate memory for supplementary GIDs\n"); + for (i = 0; i < num_supp; i++) + supp_gids[i] = get_unpriv_gid (supp_groups[i]); + if (0 != setgroups (num_supp, supp_gids)) + die ("Failed to setgroups: %s\n", strerror (errno)); + free (supp_gids); + } #ifdef HAVE_SETRESUID if (0 != setresuid (uid, uid, uid)) die ("Failed to setresuid: %s\n", strerror (errno)); @@ -63,7 +63,8 @@ static inline int min (int x, int y) return x < y ? x : y; } -void drop_privs_to (const char *user, const char *group); +void drop_privs_to (const char *user, const char *group, + const char **supp_groups); void no_new_privs (void); const char *sync_type_str (int sync_type); |