int in_gid(gid_t gid) { gid_t *gids; int ngroups_max, r, i; if (getgid() == gid) return 1; if (getegid() == gid) return 1; if (!gid_is_valid(gid)) return -EINVAL; ngroups_max = sysconf(_SC_NGROUPS_MAX); assert(ngroups_max > 0); gids = alloca(sizeof(gid_t) * ngroups_max); r = getgroups(ngroups_max, gids); if (r < 0) return -errno; for (i = 0; i < r; i++) if (gids[i] == gid) return 1; return 0; }
static void client_context_read_uid_gid(ClientContext *c, const struct ucred *ucred) { assert(c); assert(pid_is_valid(c->pid)); /* The ucred data passed in is always the most current and accurate, if we have any. Use it. */ if (ucred && uid_is_valid(ucred->uid)) c->uid = ucred->uid; else (void) get_process_uid(c->pid, &c->uid); if (ucred && gid_is_valid(ucred->gid)) c->gid = ucred->gid; else (void) get_process_gid(c->pid, &c->gid); }
int get_group_creds(const char **groupname, gid_t *gid) { struct group *g; gid_t id; assert(groupname); /* We enforce some special rules for gid=0: in order to avoid * NSS lookups for root we hardcode its data. */ if (streq(*groupname, "root") || streq(*groupname, "0")) { *groupname = "root"; if (gid) *gid = 0; return 0; } if (parse_gid(*groupname, &id) >= 0) { errno = 0; g = getgrgid(id); if (g) *groupname = g->gr_name; } else { errno = 0; g = getgrnam(*groupname); } if (!g) return errno > 0 ? -errno : -ESRCH; if (gid) { if (!gid_is_valid(g->gr_gid)) return -EBADMSG; *gid = g->gr_gid; } return 0; }
char* gid_to_name(gid_t gid) { char *ret; int r; if (gid == 0) return strdup("root"); if (gid_is_valid(gid)) { long bufsize; bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); if (bufsize <= 0) bufsize = 4096; for (;;) { struct group grbuf, *gr = NULL; _cleanup_free_ char *buf = NULL; buf = malloc(bufsize); if (!buf) return NULL; r = getgrgid_r(gid, &grbuf, buf, (size_t) bufsize, &gr); if (r == 0 && gr) return strdup(gr->gr_name); if (r != ERANGE) break; bufsize *= 2; } } if (asprintf(&ret, GID_FMT, gid) < 0) return NULL; return ret; }
int get_user_creds( const char **username, uid_t *uid, gid_t *gid, const char **home, const char **shell) { struct passwd *p; uid_t u; assert(username); assert(*username); /* We enforce some special rules for uid=0: in order to avoid * NSS lookups for root we hardcode its data. */ if (streq(*username, "root") || streq(*username, "0")) { *username = "******"; if (uid) *uid = 0; if (gid) *gid = 0; if (home) *home = "/root"; if (shell) *shell = "/bin/sh"; return 0; } if (parse_uid(*username, &u) >= 0) { errno = 0; p = getpwuid(u); /* If there are multiple users with the same id, make * sure to leave $USER to the configured value instead * of the first occurrence in the database. However if * the uid was configured by a numeric uid, then let's * pick the real username from /etc/passwd. */ if (p) *username = p->pw_name; } else { errno = 0; p = getpwnam(*username); } if (!p) return errno > 0 ? -errno : -ESRCH; if (uid) { if (!uid_is_valid(p->pw_uid)) return -EBADMSG; *uid = p->pw_uid; } if (gid) { if (!gid_is_valid(p->pw_gid)) return -EBADMSG; *gid = p->pw_gid; } if (home) *home = p->pw_dir; if (shell) *shell = p->pw_shell; return 0; }
enum nss_status _nss_systemd_getgrgid_r( gid_t gid, struct group *gr, char *buffer, size_t buflen, int *errnop) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; const char *translated; size_t l; int r; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); if (!gid_is_valid(gid)) { r = -EINVAL; goto fail; } if (gid <= SYSTEM_GID_MAX) goto not_found; if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) goto not_found; r = sd_bus_open_system(&bus); if (r < 0) goto fail; r = sd_bus_call_method(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "LookupDynamicUserByUID", &error, &reply, "u", (uint32_t) gid); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) goto not_found; goto fail; } r = sd_bus_message_read(reply, "s", &translated); if (r < 0) goto fail; l = sizeof(char*) + strlen(translated) + 1; if (buflen < l) { *errnop = ENOMEM; return NSS_STATUS_TRYAGAIN; } memzero(buffer, sizeof(char*)); strcpy(buffer + sizeof(char*), translated); gr->gr_name = buffer + sizeof(char*); gr->gr_gid = gid; gr->gr_passwd = (char*) "*"; /* locked */ gr->gr_mem = (char**) buffer; *errnop = 0; return NSS_STATUS_SUCCESS; not_found: *errnop = 0; return NSS_STATUS_NOTFOUND; fail: *errnop = -r; return NSS_STATUS_UNAVAIL; }