working permissions
fixed problem where only euid and egid were set so programs complained, now us correctly sets e/ruid, e/rgid and groups list to match the wanted user
This commit is contained in:
parent
981fed3499
commit
1c75e7dd3c
109
us.c
109
us.c
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user