|
|
|
@ -1,4 +1,5 @@ |
|
|
|
|
#define _POSIX_C_SOURCE 200809L |
|
|
|
|
#define _DEFAULT_SOURCE |
|
|
|
|
|
|
|
|
|
#include <sys/types.h> |
|
|
|
|
#include <stdio.h> |
|
|
|
@ -7,11 +8,13 @@ |
|
|
|
|
#include <errno.h> |
|
|
|
|
#include <pwd.h> |
|
|
|
|
#include <unistd.h> |
|
|
|
|
#include <limits.h> |
|
|
|
|
#include <grp.h> |
|
|
|
|
#include <security/pam_appl.h> |
|
|
|
|
#include <security/pam_misc.h> |
|
|
|
|
|
|
|
|
|
static void usage (void); |
|
|
|
|
static int perm_set (uid_t, gid_t); |
|
|
|
|
static int perm_set (const char *, const char *); |
|
|
|
|
|
|
|
|
|
// FIXME: misc_conv is a separate library, should stick to plain PAM
|
|
|
|
|
static struct pam_conv conv = {misc_conv, NULL}; |
|
|
|
@ -25,7 +28,7 @@ int main (int argc, char *argv[]) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uid_t ruid = getuid(); |
|
|
|
|
gid_t rgid = getgid(); |
|
|
|
|
// gid_t rgid = getgid();
|
|
|
|
|
struct passwd *pw = getpwuid(ruid); |
|
|
|
|
if (!pw) { |
|
|
|
|
fprintf(stderr, "getpwid: %s\n", strerror(errno)); |
|
|
|
@ -77,7 +80,7 @@ int main (int argc, char *argv[]) |
|
|
|
|
|
|
|
|
|
errno = 0; |
|
|
|
|
/* Set permissions */ |
|
|
|
|
if (perm_set(0, 0) == -1) { // 0 = root
|
|
|
|
|
if (perm_set(NULL, NULL) == -1) { // 0 = root
|
|
|
|
|
fprintf(stderr, "perm_set: %s\n", strerror(errno)); |
|
|
|
|
goto fail_end; |
|
|
|
|
} |
|
|
|
@ -86,11 +89,13 @@ int main (int argc, char *argv[]) |
|
|
|
|
if (execvp(*c_argv, c_argv) == -1) // execvp searches in path
|
|
|
|
|
fprintf(stderr, "execv: %s\n", strerror(errno)); |
|
|
|
|
|
|
|
|
|
/* If exec fails reset the permissions */ |
|
|
|
|
if (perm_set(ruid, rgid) == -1) { // 0 = root
|
|
|
|
|
|
|
|
|
|
/* We may no longer have permission to reset the permissions
|
|
|
|
|
// If exec fails reset the permissions
|
|
|
|
|
if (perm_set(pw->pw_name, NULL) == -1) { // 0 = root
|
|
|
|
|
fprintf(stderr, "perm_set: %s\n", strerror(errno)); |
|
|
|
|
goto fail_end; |
|
|
|
|
} |
|
|
|
|
} */ |
|
|
|
|
|
|
|
|
|
/* Cleanup and return */ |
|
|
|
|
fail_end: |
|
|
|
@ -115,23 +120,79 @@ static inline void usage (void) |
|
|
|
|
printf("usage: us [command]\n"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int perm_set (uid_t uid, gid_t gid) |
|
|
|
|
static int perm_set (const char *user, const char *group) |
|
|
|
|
{ |
|
|
|
|
// FIXME: This doesn't change the uid and gid, it only changes the
|
|
|
|
|
// e(ffective)uid and egid keeping the original gid, uid and groups list
|
|
|
|
|
// to make it work like sudo, the uid gid and groups list must be all
|
|
|
|
|
// set to 0 (or the corresponding value for other users).
|
|
|
|
|
// An option could be to add an argument to keep the groups list,
|
|
|
|
|
// another to change only the euid/egid.
|
|
|
|
|
// For more information run:
|
|
|
|
|
// $ sudo id
|
|
|
|
|
// and check the output
|
|
|
|
|
int err = 0; |
|
|
|
|
// FIXME: using setresuid() and setresgid() is preferred
|
|
|
|
|
if ((err = seteuid(uid)) == -1) |
|
|
|
|
return err; |
|
|
|
|
else if ((err = setegid(gid)) == -1) |
|
|
|
|
return err; |
|
|
|
|
// FIXME: to set the group list use initgroups()
|
|
|
|
|
return err; |
|
|
|
|
if (!user) |
|
|
|
|
user = "root"; |
|
|
|
|
|
|
|
|
|
struct passwd *pw; |
|
|
|
|
struct group *gr; |
|
|
|
|
uid_t uid; |
|
|
|
|
gid_t gid; |
|
|
|
|
long uid_l, gid_l; |
|
|
|
|
|
|
|
|
|
errno = 0; |
|
|
|
|
if (user[0] != '#') { |
|
|
|
|
pw = getpwnam(user); |
|
|
|
|
} else { |
|
|
|
|
uid_l = strtol(&user[1], NULL, 10); |
|
|
|
|
if (uid_l < 0 || errno) { |
|
|
|
|
errno = errno ? errno : EINVAL; |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
pw = getpwuid((uid_t)uid_l); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!pw) { |
|
|
|
|
if (!errno) |
|
|
|
|
errno = EINVAL; |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uid = pw->pw_uid; |
|
|
|
|
gid = pw->pw_gid; |
|
|
|
|
|
|
|
|
|
if (group) { |
|
|
|
|
if (group[0] != '#') { |
|
|
|
|
gr = getgrnam(group); |
|
|
|
|
} else { |
|
|
|
|
gid_l = strtol(&group[1], NULL, 10); |
|
|
|
|
if (gid_l < 0 || errno) { |
|
|
|
|
errno = errno ? errno : EINVAL; |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
gr = getgrgid((gid_t)gid_l); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!gr) { |
|
|
|
|
if (!errno) |
|
|
|
|
errno = EINVAL; |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
gid = gr->gr_gid; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Set permissions, setting group perms first because in the case of
|
|
|
|
|
* dropping from higher permissions setting the uid first results in |
|
|
|
|
* an error */ |
|
|
|
|
int err; |
|
|
|
|
/* Non POSIX but implemented in most systems anyways */ |
|
|
|
|
err = initgroups(pw->pw_name, pw->pw_gid); |
|
|
|
|
if (err == -1) { |
|
|
|
|
printf("initgroups failed\n"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// FIXME: ideally when failing reset the permissions
|
|
|
|
|
if (setregid(gid, gid) == -1) { |
|
|
|
|
printf("setregid failed\n"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (setreuid(uid, uid) == -1) { |
|
|
|
|
printf("setreuid failed\n"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|