]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/basic/user-util.c
util-lib: split string parsing related calls from util.[ch] into parse-util.[ch]
[thirdparty/systemd.git] / src / basic / user-util.c
index ebeac99d3121a7fc62b404320a7e9046071b77a4..0b3cf3d733bea4554543b080a0a6d76fd3141191 100644 (file)
 #include <pwd.h>
 #include <grp.h>
 
-#include "user-util.h"
 #include "macro.h"
-#include "util.h"
-#include "string-util.h"
+#include "parse-util.h"
 #include "path-util.h"
+#include "string-util.h"
+#include "user-util.h"
+#include "util.h"
 
 bool uid_is_valid(uid_t uid) {
 
@@ -64,33 +65,6 @@ int parse_uid(const char *s, uid_t *ret) {
         return 0;
 }
 
-char *lookup_uid(uid_t uid) {
-        long bufsize;
-        char *name;
-        _cleanup_free_ char *buf = NULL;
-        struct passwd pwbuf, *pw = NULL;
-
-        /* Shortcut things to avoid NSS lookups */
-        if (uid == 0)
-                return strdup("root");
-
-        bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
-        if (bufsize <= 0)
-                bufsize = 4096;
-
-        buf = malloc(bufsize);
-        if (!buf)
-                return NULL;
-
-        if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw)
-                return strdup(pw->pw_name);
-
-        if (asprintf(&name, UID_FMT, uid) < 0)
-                return NULL;
-
-        return name;
-}
-
 char* getlogname_malloc(void) {
         uid_t uid;
         struct stat st;
@@ -100,7 +74,7 @@ char* getlogname_malloc(void) {
         else
                 uid = getuid();
 
-        return lookup_uid(uid);
+        return uid_to_name(uid);
 }
 
 char *getusername_malloc(void) {
@@ -110,7 +84,7 @@ char *getusername_malloc(void) {
         if (e)
                 return strdup(e);
 
-        return lookup_uid(getuid());
+        return uid_to_name(getuid());
 }
 
 int get_user_creds(
@@ -165,11 +139,19 @@ int get_user_creds(
         if (!p)
                 return errno > 0 ? -errno : -ESRCH;
 
-        if (uid)
+        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;
 
-        if (gid)
                 *gid = p->pw_gid;
+        }
 
         if (home)
                 *home = p->pw_dir;
@@ -212,44 +194,91 @@ int get_group_creds(const char **groupname, gid_t *gid) {
         if (!g)
                 return errno > 0 ? -errno : -ESRCH;
 
-        if (gid)
+        if (gid) {
+                if (!gid_is_valid(g->gr_gid))
+                        return -EBADMSG;
+
                 *gid = g->gr_gid;
+        }
 
         return 0;
 }
 
 char* uid_to_name(uid_t uid) {
-        struct passwd *p;
-        char *r;
+        char *ret;
+        int r;
 
+        /* Shortcut things to avoid NSS lookups */
         if (uid == 0)
                 return strdup("root");
 
-        p = getpwuid(uid);
-        if (p)
-                return strdup(p->pw_name);
+        if (uid_is_valid(uid)) {
+                long bufsize;
 
-        if (asprintf(&r, UID_FMT, uid) < 0)
+                bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
+                if (bufsize <= 0)
+                        bufsize = 4096;
+
+                for (;;) {
+                        struct passwd pwbuf, *pw = NULL;
+                        _cleanup_free_ char *buf = NULL;
+
+                        buf = malloc(bufsize);
+                        if (!buf)
+                                return NULL;
+
+                        r = getpwuid_r(uid, &pwbuf, buf, (size_t) bufsize, &pw);
+                        if (r == 0 && pw)
+                                return strdup(pw->pw_name);
+                        if (r != ERANGE)
+                                break;
+
+                        bufsize *= 2;
+                }
+        }
+
+        if (asprintf(&ret, UID_FMT, uid) < 0)
                 return NULL;
 
-        return r;
+        return ret;
 }
 
 char* gid_to_name(gid_t gid) {
-        struct group *p;
-        char *r;
+        char *ret;
+        int r;
 
         if (gid == 0)
                 return strdup("root");
 
-        p = getgrgid(gid);
-        if (p)
-                return strdup(p->gr_name);
+        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;
 
-        if (asprintf(&r, GID_FMT, gid) < 0)
+                        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 r;
+        return ret;
 }
 
 int in_gid(gid_t gid) {
@@ -262,6 +291,9 @@ int in_gid(gid_t gid) {
         if (getegid() == gid)
                 return 1;
 
+        if (!gid_is_valid(gid))
+                return -EINVAL;
+
         ngroups_max = sysconf(_SC_NGROUPS_MAX);
         assert(ngroups_max > 0);