From db9e7c9a30e9430119efb34ca9b5324314e6b4a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20Ko=C4=8D=C3=AD?= Date: Fri, 11 Feb 2022 13:06:01 +0100 Subject: Read subuid and subgid files instead of hard coded values This implements reading of /etc/subuid and /etc/subgid files to correctly map user and group IDs. It also allows just mapping the user itself if there is no mapping configured. --- main.c | 4 ++-- utils.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++---- utils.h | 9 +++++++-- 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/main.c b/main.c index 058aa3b..9ffaf6a 100644 --- a/main.c +++ b/main.c @@ -107,9 +107,9 @@ int main(int argc, char **argv) { &chargs); #define FAIL(MSG) do { fputs(MSG, stderr); kill(chpid, SIGKILL); return 1; } while (false); - if (new_map_id("uid", chpid, getuid())) + if (new_map_id(MAP_ID_USER, chpid, getuid())) FAIL("Mapping of uid failed!\n"); - if (new_map_id("gid", chpid, getgid())) + if (new_map_id(MAP_ID_GROUP, chpid, getgid())) FAIL("Mapping of gid failed!\n"); sigpipe_signal(chargs.sigpipe); diff --git a/utils.c b/utils.c index e4f771d..e30b4db 100644 --- a/utils.c +++ b/utils.c @@ -24,6 +24,9 @@ #include #include #include +#include +#include +#include #include "utils.h" #include "conf.h" @@ -53,15 +56,57 @@ const char *get_shell() { return ret; } -int new_map_id(const char *idtp, pid_t pid, int id) { - // TODO check /etc/sub* for current user subids and map them +struct subid { + char *start; + char *count; +}; + +struct subid parse_sub(const char *idtp, const char *name) { + FILE *f = fopen(aprintf("/etc/sub%s", idtp), "r"); + struct subid res = {NULL, NULL}; + char *line = NULL; + ssize_t len = 0; + while ((len = getline(&line, &len, f)) != -1) { + char *firstcol = strchr(line, ':'); + if (firstcol == NULL || strncmp(name, line, firstcol - line)) + continue; + char *seccol = strchr(firstcol + 1, ':'); + if (seccol == NULL) + continue; + res.start = strndup(firstcol + 1, (seccol - firstcol) - 1); + res.count = strndup(seccol + 1, len - 1 - (seccol - line) - (line[len - 1] == '\n' ? 1 : 0)); + } + free(line); + fclose(f); + return res; +} + +int new_map_id(enum mapidtype type, pid_t pid, int id) { + // TODO possibly we should use all maps provided by sub* files for given + // account. It is common that there is only one mapping but there can + // technically be multiple ones. + char const *idtp; + struct subid subid; + switch (type) { + case MAP_ID_USER: + idtp = "uid"; + struct passwd *upass = getpwuid(getuid()); + subid = parse_sub(idtp, upass->pw_name); + break; + case MAP_ID_GROUP: + idtp = "gid"; + struct group *gpass = getgrgid(getgid()); + subid = parse_sub(idtp, gpass->gr_name); + break; + } pid_t chld = fork(); if (!chld) { char *tool = aprintf("new%smap", idtp); char *const args[] = { - tool, aprintf("%d", pid), + tool, + aprintf("%d", pid), "0", aprintf("%d", id), "1", - "1", "65537", "65536", + subid.start && subid.count ? "1" : NULL, subid.start, subid.count, NULL }; execvp(tool, args); diff --git a/utils.h b/utils.h index b9c943f..3a41956 100644 --- a/utils.h +++ b/utils.h @@ -35,7 +35,12 @@ char *printf_into(char *dst, const char *msg, ...) __attribute__((format(printf, // returns path to shell interpreter const char *get_shell(); -// call newuidmap and newgidmap for process of given pid -int new_map_id(const char *idtp, pid_t pid, int id); +enum mapidtype { + MAP_ID_USER, + MAP_ID_GROUP +}; + +// call newuidmap or newgidmap for process of given pid +int new_map_id(enum mapidtype type, pid_t pid, int id); #endif -- cgit v1.2.3