From 99a1ece116fa46b7020e5e7a3f8d7825d8e8a1ba Mon Sep 17 00:00:00 2001 From: Rayson zhu Date: Wed, 16 Nov 2016 01:12:38 +0800 Subject: [PATCH] Feature: uid support in run_as --- src/utils.c | 27 +++++++++++++++++++++++++-- src/utils.h | 1 + 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/utils.c b/src/utils.c index 367d4c2d..2ac2dfac 100644 --- a/src/utils.c +++ b/src/utils.c @@ -28,6 +28,7 @@ #include #include #include +#include #ifndef __MINGW32__ #include #endif @@ -86,6 +87,15 @@ ss_itoa(int i) return p; } +int +ss_isnumeric(const char *s) { + if (!s || !*s) + return 0; + while (isdigit(*s)) + ++s; + return *s == '\0'; +} + /* * setuid() and setgid() for a specified user. */ @@ -94,6 +104,18 @@ run_as(const char *user) { #ifndef __MINGW32__ if (user[0]) { + printf("user: %s\n", user); + /* Convert user to a long integer if it is a non-negative number. + * -1 means it is a user name. */ + long uid = -1; + if (ss_isnumeric(user)) { + errno = 0; + char *endptr; + uid = strtol(user, &endptr, 10); + if (errno || endptr == user) + uid = -1; + } + #ifdef HAVE_GETPWNAM_R struct passwd pwdbuf, *pwd; size_t buflen; @@ -105,7 +127,8 @@ run_as(const char *user) /* Note that we use getpwnam_r() instead of getpwnam(), * which returns its result in a statically allocated buffer and * cannot be considered thread safe. */ - err = getpwnam_r(user, &pwdbuf, buf, buflen, &pwd); + err = uid >= 0 ? getpwuid_r((uid_t)uid, &pwdbuf, buf, buflen, &pwd) + : getpwnam_r(user, &pwdbuf, buf, buflen, &pwd); if (err == 0 && pwd) { /* setgid first, because we may not be allowed to do it anymore after setuid */ @@ -145,7 +168,7 @@ run_as(const char *user) /* No getpwnam_r() :-( We'll use getpwnam() and hope for the best. */ struct passwd *pwd; - if (!(pwd = getpwnam(user))) { + if (!(pwd = uid >=0 ? getpwuid((uid_t)uid) : getpwnam(user))) { LOGE("run_as user %s could not be found.", user); return 0; } diff --git a/src/utils.h b/src/utils.h index 755b6119..8574a19c 100644 --- a/src/utils.h +++ b/src/utils.h @@ -209,6 +209,7 @@ void ERROR(const char *s); #endif char *ss_itoa(int i); +int ss_isnumeric(const char *s); int run_as(const char *user); void FATAL(const char *msg); void usage(void);