char arch[ARCH_MAX];
char keystore_path[PATH_MAX];
- uid_t uid;
int flags;
// Lock
FILE* lock;
+ // UID/GID of running user
+ uid_t uid;
+ gid_t gid;
+
+ // Mapped UID/GID
+ struct pakfire_subuid subuid;
+ struct pakfire_subgid subgid;
+
// Pool
Pool* pool;
p->nrefs = 1;
p->flags = flags;
- // Store the UID we are running as
+ // Store the UID/GID we are running as
p->uid = getuid();
+ p->gid = getgid();
// Set architecture
pakfire_string_set(p->arch, arch);
}
}
+ // Fetch sub UID/GIDs
+ if (p->uid) {
+ // UID
+ r = pakfire_getsubuid(p, p->uid, &p->subuid);
+ if (r) {
+ ERROR(p, "Could not fetch subuid: %m\n");
+ goto ERROR;
+ }
+
+ // GID
+ r = pakfire_getsubgid(p, p->gid, &p->subgid);
+ if (r) {
+ ERROR(p, "Could not fetch subgid: %m\n");
+ goto ERROR;
+ }
+
+ // Log
+ DEBUG(p, " subuid = %u - %zu\n", p->subuid.uid, p->subuid.uid + p->subuid.length);
+ DEBUG(p, " subgid = %u - %zu\n", p->subgid.gid, p->subgid.gid + p->subgid.length);
+ }
+
// Perform some safety checks
r = pakfire_safety_checks(p);
if (r)
#include <stdio.h>
#include <stdlib.h>
+#include <pakfire/logging.h>
#include <pakfire/pakfire.h>
#include <pakfire/pwd.h>
+#include <pakfire/util.h>
+
+#define ETC_SUBUID "/etc/subuid"
+#define ETC_SUBGID "/etc/subgid"
static struct passwd* pakfire_getpwent(struct pakfire* pakfire,
int(*cmp)(struct passwd* entry, const void* value), const void* value) {
struct group* pakfire_getgrgid(struct pakfire* pakfire, gid_t gid) {
return pakfire_getgrent(pakfire, __pakfire_getgrgid, &gid);
}
+
+// SUBUID/SUBGID
+
+static struct pakfire_subuid __pakfire_subuid;
+static struct pakfire_subgid __pakfire_subgid;
+
+static struct pakfire_subuid* pakfire_fgetsubuid(struct pakfire* pakfire, FILE* f) {
+ int r;
+
+ char* line = NULL;
+ size_t length = 0;
+ char* p = NULL;
+
+ // Read the next line
+ while (1) {
+ r = getline(&line, &length, f);
+ if (r < 0)
+ goto ERROR;
+
+ // Try reading the next line if this one was empty
+ else if (r == 0)
+ continue;
+
+ // Fall through
+ else
+ break;
+ }
+
+ // Reset r
+ r = 0;
+
+ int i = 0;
+
+ char* token = strtok_r(line, ":", &p);
+ while (token) {
+ switch (i++) {
+ // First field has the name
+ case 0:
+ pakfire_string_set(__pakfire_subuid.name, token);
+ break;
+
+ // Second field has the UID
+ case 1:
+ __pakfire_subuid.uid = strtoul(token, NULL, 10);
+ break;
+
+ // Third field has the length
+ case 2:
+ __pakfire_subuid.length = strtoul(token, NULL, 10);
+ break;
+ }
+
+ token = strtok_r(NULL, ":", &p);
+ }
+
+ERROR:
+ if (line)
+ free(line);
+
+ if (r)
+ return NULL;
+
+ DEBUG(pakfire, "Parsed SUBUID entry: name=%s, subuid=%d, length=%zu\n",
+ __pakfire_subuid.name, __pakfire_subuid.uid, __pakfire_subuid.length);
+
+ return &__pakfire_subuid;
+}
+
+int pakfire_getsubuid(struct pakfire* pakfire, const uid_t uid,
+ struct pakfire_subuid* subuid) {
+ struct pakfire_subuid* entry = NULL;
+ int r = 1;
+
+ // Fetch information about the running user
+ struct passwd* passwd = getpwuid(uid);
+ if (!passwd) {
+ ERROR(pakfire, "Could not fetch passwd entry for UID %d: %m\n", uid);
+ return 1;
+ }
+
+ DEBUG(pakfire, "Fetching SUBUID for %s (%d)\n", passwd->pw_name, uid);
+
+ // Open /etc/subuid
+ FILE* f = fopen(ETC_SUBUID, "r");
+ if (!f) {
+ ERROR(pakfire, "Could not open %s: %m\n", ETC_SUBUID);
+ goto ERROR;
+ }
+
+ // Walk through all entries
+ while (1) {
+ entry = pakfire_fgetsubuid(pakfire, f);
+ if (!entry)
+ break;
+
+ // TODO Check if name matches UID
+
+ // Check for match
+ if (strcmp(entry->name, passwd->pw_name) == 0) {
+ subuid->uid = entry->uid;
+ subuid->length = entry->length;
+ r = 0;
+
+ break;
+ }
+ }
+
+ERROR:
+ if (f)
+ fclose(f);
+
+ return r;
+}
+
+static struct pakfire_subgid* pakfire_fgetsubgid(struct pakfire* pakfire, FILE* f) {
+ int r;
+
+ char* line = NULL;
+ size_t length = 0;
+ char* p = NULL;
+
+ // Read the next line
+ while (1) {
+ r = getline(&line, &length, f);
+ if (r < 0)
+ goto ERROR;
+
+ // Try reading the next line if this one was empty
+ else if (r == 0)
+ continue;
+
+ // Fall through
+ else
+ break;
+ }
+
+ // Reset r
+ r = 0;
+
+ int i = 0;
+
+ char* token = strtok_r(line, ":", &p);
+ while (token) {
+ switch (i++) {
+ // First field has the name
+ case 0:
+ pakfire_string_set(__pakfire_subgid.name, token);
+ break;
+
+ // Second field has the GID
+ case 1:
+ __pakfire_subgid.gid = strtoul(token, NULL, 10);
+ break;
+
+ // Third field has the length
+ case 2:
+ __pakfire_subgid.length = strtoul(token, NULL, 10);
+ break;
+ }
+
+ token = strtok_r(NULL, ":", &p);
+ }
+
+ERROR:
+ if (line)
+ free(line);
+
+ if (r)
+ return NULL;
+
+ DEBUG(pakfire, "Parsed SUBGID entry: name=%s, subgid=%d, length=%zu\n",
+ __pakfire_subgid.name, __pakfire_subgid.gid, __pakfire_subgid.length);
+
+ return &__pakfire_subgid;
+}
+
+int pakfire_getsubgid(struct pakfire* pakfire, const gid_t gid,
+ struct pakfire_subgid* subgid) {
+ struct pakfire_subgid* entry = NULL;
+ int r = 1;
+
+ // Fetch information about the running user
+ struct group* group = getgrgid(gid);
+ if (!group) {
+ ERROR(pakfire, "Could not fetch group entry for GID %d: %m\n", gid);
+ return 1;
+ }
+
+ DEBUG(pakfire, "Fetching SUBGID for %s (%d)\n", group->gr_name, gid);
+
+ // Open /etc/subgid
+ FILE* f = fopen(ETC_SUBGID, "r");
+ if (!f) {
+ ERROR(pakfire, "Could not open %s: %m\n", ETC_SUBGID);
+ goto ERROR;
+ }
+
+ // Walk through all entries
+ while (1) {
+ entry = pakfire_fgetsubgid(pakfire, f);
+ if (!entry)
+ break;
+
+ // TODO Check if name matches GID
+
+ // Check for match
+ if (strcmp(entry->name, group->gr_name) == 0) {
+ subgid->gid = entry->gid;
+ subgid->length = entry->length;
+ r = 0;
+
+ break;
+ }
+ }
+
+ERROR:
+ if (f)
+ fclose(f);
+
+ return r;
+}