Add struct sudo_cred to hold the invoking or runas user credentials.
We can use this when we need to pass around credential info instead of the user_details and command_details structs.
This commit is contained in:
@@ -47,7 +47,7 @@ switch_user(uid_t euid, gid_t egid, int ngroups, GETGROUPS_T *groups)
|
|||||||
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
||||||
"set uid:gid to %u:%u(%u)", (unsigned int)euid, (unsigned int)egid,
|
"set uid:gid to %u:%u(%u)", (unsigned int)euid, (unsigned int)egid,
|
||||||
ngroups ? (unsigned int)groups[0] : (unsigned int)egid);
|
ngroups > 0 ? (unsigned int)groups[0] : (unsigned int)egid);
|
||||||
|
|
||||||
/* When restoring root, change euid first; otherwise change it last. */
|
/* When restoring root, change euid first; otherwise change it last. */
|
||||||
if (euid == ROOT_UID) {
|
if (euid == ROOT_UID) {
|
||||||
@@ -74,7 +74,7 @@ switch_user(uid_t euid, gid_t egid, int ngroups, GETGROUPS_T *groups)
|
|||||||
* Returns true if the open directory fd is owned or writable by the user.
|
* Returns true if the open directory fd is owned or writable by the user.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
dir_is_writable(int dfd, struct user_details *ud, struct command_details *cd)
|
dir_is_writable(int dfd, struct sudo_cred *user_cred, struct sudo_cred *run_cred)
|
||||||
{
|
{
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -84,29 +84,31 @@ dir_is_writable(int dfd, struct user_details *ud, struct command_details *cd)
|
|||||||
debug_return_int(-1);
|
debug_return_int(-1);
|
||||||
|
|
||||||
/* If the user owns the dir we always consider it writable. */
|
/* If the user owns the dir we always consider it writable. */
|
||||||
if (sb.st_uid == ud->uid) {
|
if (sb.st_uid == user_cred->uid) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
||||||
"user uid %u matches directory uid %u", (unsigned int)ud->uid,
|
"user uid %u matches directory uid %u",
|
||||||
(unsigned int)sb.st_uid);
|
(unsigned int)user_cred->uid, (unsigned int)sb.st_uid);
|
||||||
debug_return_int(true);
|
debug_return_int(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change uid/gid/groups to invoking user, usually needs root perms. */
|
/* Change uid/gid/groups to invoking user, usually needs root perms. */
|
||||||
if (cd->euid != ROOT_UID) {
|
if (run_cred->euid != ROOT_UID) {
|
||||||
if (seteuid(ROOT_UID) != 0)
|
if (seteuid(ROOT_UID) != 0)
|
||||||
sudo_fatal("seteuid(ROOT_UID)");
|
sudo_fatal("seteuid(ROOT_UID)");
|
||||||
}
|
}
|
||||||
switch_user(ud->uid, ud->gid, ud->ngroups, ud->groups);
|
switch_user(user_cred->uid, user_cred->gid, user_cred->ngroups,
|
||||||
|
user_cred->groups);
|
||||||
|
|
||||||
/* Access checks are done using the euid/egid and group vector. */
|
/* Access checks are done using the euid/egid and group vector. */
|
||||||
rc = faccessat(dfd, ".", W_OK, AT_EACCESS);
|
rc = faccessat(dfd, ".", W_OK, AT_EACCESS);
|
||||||
|
|
||||||
/* Change uid/gid/groups back to target user, may need root perms. */
|
/* Change uid/gid/groups back to target user, may need root perms. */
|
||||||
if (ud->uid != ROOT_UID) {
|
if (user_cred->uid != ROOT_UID) {
|
||||||
if (seteuid(ROOT_UID) != 0)
|
if (seteuid(ROOT_UID) != 0)
|
||||||
sudo_fatal("seteuid(ROOT_UID)");
|
sudo_fatal("seteuid(ROOT_UID)");
|
||||||
}
|
}
|
||||||
switch_user(cd->euid, cd->egid, cd->ngroups, cd->groups);
|
switch_user(run_cred->euid, run_cred->egid, run_cred->ngroups,
|
||||||
|
run_cred->groups);
|
||||||
|
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
debug_return_int(true);
|
debug_return_int(true);
|
||||||
@@ -116,21 +118,21 @@ dir_is_writable(int dfd, struct user_details *ud, struct command_details *cd)
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static bool
|
static bool
|
||||||
group_matches(gid_t target, gid_t gid, int ngroups, GETGROUPS_T *groups)
|
group_matches(gid_t target, struct sudo_cred *cred)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
debug_decl(group_matches, SUDO_DEBUG_EDIT);
|
debug_decl(group_matches, SUDO_DEBUG_EDIT);
|
||||||
|
|
||||||
if (target == gid) {
|
if (target == cred->gid) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
||||||
"user gid %u matches directory gid %u", (unsigned int)gid,
|
"user gid %u matches directory gid %u", (unsigned int)cred->gid,
|
||||||
(unsigned int)target);
|
(unsigned int)target);
|
||||||
debug_return_bool(true);
|
debug_return_bool(true);
|
||||||
}
|
}
|
||||||
for (i = 0; i < ngroups; i++) {
|
for (i = 0; i < cred->ngroups; i++) {
|
||||||
if (target == groups[i]) {
|
if (target == cred->groups[i]) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
||||||
"user gid %u matches directory gid %u", (unsigned int)gid,
|
"user gid %u matches directory gid %u", cred->groups[i],
|
||||||
(unsigned int)target);
|
(unsigned int)target);
|
||||||
debug_return_bool(true);
|
debug_return_bool(true);
|
||||||
}
|
}
|
||||||
@@ -142,7 +144,7 @@ group_matches(gid_t target, gid_t gid, int ngroups, GETGROUPS_T *groups)
|
|||||||
* Returns true if the open directory fd is owned or writable by the user.
|
* Returns true if the open directory fd is owned or writable by the user.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
dir_is_writable(int dfd, struct user_details *ud, struct command_details *cd)
|
dir_is_writable(int dfd, struct sudo_cred *user_cred, struct sudo_cred *run_cred)
|
||||||
{
|
{
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
debug_decl(dir_is_writable, SUDO_DEBUG_EDIT);
|
debug_decl(dir_is_writable, SUDO_DEBUG_EDIT);
|
||||||
@@ -151,10 +153,10 @@ dir_is_writable(int dfd, struct user_details *ud, struct command_details *cd)
|
|||||||
debug_return_int(-1);
|
debug_return_int(-1);
|
||||||
|
|
||||||
/* If the user owns the dir we always consider it writable. */
|
/* If the user owns the dir we always consider it writable. */
|
||||||
if (sb.st_uid == ud->uid) {
|
if (sb.st_uid == user_cred->uid) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
||||||
"user uid %u matches directory uid %u", (unsigned int)ud->uid,
|
"user uid %u matches directory uid %u",
|
||||||
(unsigned int)sb.st_uid);
|
(unsigned int)user_cred->uid, (unsigned int)sb.st_uid);
|
||||||
debug_return_int(true);
|
debug_return_int(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +169,7 @@ dir_is_writable(int dfd, struct user_details *ud, struct command_details *cd)
|
|||||||
|
|
||||||
/* Group writable? */
|
/* Group writable? */
|
||||||
if (ISSET(sb.st_mode, S_IWGRP)) {
|
if (ISSET(sb.st_mode, S_IWGRP)) {
|
||||||
if (group_matches(sb.st_gid, ud->gid, ud->ngroups, ud->groups)) {
|
if (group_matches(sb.st_gid, user_cred)) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
||||||
"directory is writable by one of the user's groups");
|
"directory is writable by one of the user's groups");
|
||||||
debug_return_int(true);
|
debug_return_int(true);
|
||||||
@@ -270,7 +272,7 @@ done:
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
sudo_edit_open_nonwritable(char *path, int oflags, mode_t mode,
|
sudo_edit_open_nonwritable(char *path, int oflags, mode_t mode,
|
||||||
struct user_details *ud, struct command_details *cd)
|
struct sudo_cred *user_cred, struct sudo_cred *run_cred)
|
||||||
{
|
{
|
||||||
const int dflags = DIR_OPEN_FLAGS;
|
const int dflags = DIR_OPEN_FLAGS;
|
||||||
int dfd, fd, is_writable;
|
int dfd, fd, is_writable;
|
||||||
@@ -295,7 +297,7 @@ sudo_edit_open_nonwritable(char *path, int oflags, mode_t mode,
|
|||||||
* Look up one component at a time, avoiding symbolic links in
|
* Look up one component at a time, avoiding symbolic links in
|
||||||
* writable directories.
|
* writable directories.
|
||||||
*/
|
*/
|
||||||
is_writable = dir_is_writable(dfd, ud, cd);
|
is_writable = dir_is_writable(dfd, user_cred, run_cred);
|
||||||
if (is_writable == -1) {
|
if (is_writable == -1) {
|
||||||
close(dfd);
|
close(dfd);
|
||||||
debug_return_int(-1);
|
debug_return_int(-1);
|
||||||
@@ -336,17 +338,17 @@ sudo_edit_open_nonwritable(char *path, int oflags, mode_t mode,
|
|||||||
|
|
||||||
#ifdef O_NOFOLLOW
|
#ifdef O_NOFOLLOW
|
||||||
int
|
int
|
||||||
sudo_edit_open(char *path, int oflags, mode_t mode, struct user_details *ud,
|
sudo_edit_open(char *path, int oflags, mode_t mode, int sflags,
|
||||||
struct command_details *cd)
|
struct sudo_cred *user_cred, struct sudo_cred *run_cred)
|
||||||
{
|
{
|
||||||
const int sflags = cd ? cd->flags : 0;
|
|
||||||
int fd;
|
int fd;
|
||||||
debug_decl(sudo_edit_open, SUDO_DEBUG_EDIT);
|
debug_decl(sudo_edit_open, SUDO_DEBUG_EDIT);
|
||||||
|
|
||||||
if (!ISSET(sflags, CD_SUDOEDIT_FOLLOW))
|
if (!ISSET(sflags, CD_SUDOEDIT_FOLLOW))
|
||||||
oflags |= O_NOFOLLOW;
|
oflags |= O_NOFOLLOW;
|
||||||
if (ISSET(sflags, CD_SUDOEDIT_CHECKDIR) && ud->uid != ROOT_UID) {
|
if (ISSET(sflags, CD_SUDOEDIT_CHECKDIR) && user_cred->uid != ROOT_UID) {
|
||||||
fd = sudo_edit_open_nonwritable(path, oflags|O_NONBLOCK, mode, ud, cd);
|
fd = sudo_edit_open_nonwritable(path, oflags|O_NONBLOCK, mode,
|
||||||
|
user_cred, run_cred);
|
||||||
} else {
|
} else {
|
||||||
fd = open(path, oflags|O_NONBLOCK, mode);
|
fd = open(path, oflags|O_NONBLOCK, mode);
|
||||||
}
|
}
|
||||||
@@ -356,10 +358,9 @@ sudo_edit_open(char *path, int oflags, mode_t mode, struct user_details *ud,
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int
|
int
|
||||||
sudo_edit_open(char *path, int oflags, mode_t mode, struct user_details *ud,
|
sudo_edit_open(char *path, int oflags, mode_t mode, int sflags,
|
||||||
struct command_details *cd)
|
struct sudo_cred *user_cred, struct sudo_cred *run_cred)
|
||||||
{
|
{
|
||||||
const int sflags = cd ? cd->flags : 0;
|
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
int fd;
|
int fd;
|
||||||
debug_decl(sudo_edit_open, SUDO_DEBUG_EDIT);
|
debug_decl(sudo_edit_open, SUDO_DEBUG_EDIT);
|
||||||
@@ -377,8 +378,9 @@ sudo_edit_open(char *path, int oflags, mode_t mode, struct user_details *ud,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ISSET(sflags, CD_SUDOEDIT_CHECKDIR) && ud->uid != ROOT_UID) {
|
if (ISSET(sflags, CD_SUDOEDIT_CHECKDIR) && user_cred->uid != ROOT_UID) {
|
||||||
fd = sudo_edit_open_nonwritable(path, oflags|O_NONBLOCK, mode, ud, cd);
|
fd = sudo_edit_open_nonwritable(path, oflags|O_NONBLOCK, mode,
|
||||||
|
user_cred, run_cred);
|
||||||
} else {
|
} else {
|
||||||
fd = open(path, oflags|O_NONBLOCK, mode);
|
fd = open(path, oflags|O_NONBLOCK, mode);
|
||||||
}
|
}
|
||||||
@@ -409,11 +411,10 @@ sudo_edit_open(char *path, int oflags, mode_t mode, struct user_details *ud,
|
|||||||
* Does not modify the value of errno.
|
* Does not modify the value of errno.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
sudo_edit_parent_valid(char *path, struct user_details *ud,
|
sudo_edit_parent_valid(char *path, int sflags, struct sudo_cred *user_cred,
|
||||||
struct command_details *cd)
|
struct sudo_cred *run_cred)
|
||||||
{
|
{
|
||||||
const int serrno = errno;
|
const int serrno = errno;
|
||||||
const int sflags = cd->flags;
|
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
char *slash;
|
char *slash;
|
||||||
@@ -436,10 +437,8 @@ sudo_edit_parent_valid(char *path, struct user_details *ud,
|
|||||||
* The parent directory is allowed to be a symbolic link unless
|
* The parent directory is allowed to be a symbolic link unless
|
||||||
* *its* parent is writable and CD_SUDOEDIT_CHECK is set.
|
* *its* parent is writable and CD_SUDOEDIT_CHECK is set.
|
||||||
*/
|
*/
|
||||||
SET(cd->flags, CD_SUDOEDIT_FOLLOW);
|
|
||||||
dfd = sudo_edit_open(path, DIR_OPEN_FLAGS, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
|
dfd = sudo_edit_open(path, DIR_OPEN_FLAGS, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
|
||||||
ud, cd);
|
sflags|CD_SUDOEDIT_FOLLOW, user_cred, run_cred);
|
||||||
cd->flags = sflags;
|
|
||||||
if (dfd != -1) {
|
if (dfd != -1) {
|
||||||
if (fstat(dfd, &sb) == 0 && S_ISDIR(sb.st_mode))
|
if (fstat(dfd, &sb) == 0 && S_ISDIR(sb.st_mode))
|
||||||
ret = true;
|
ret = true;
|
||||||
|
14
src/exec.c
14
src/exec.c
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-License-Identifier: ISC
|
* SPDX-License-Identifier: ISC
|
||||||
*
|
*
|
||||||
* Copyright (c) 2009-2020 Todd C. Miller <Todd.Miller@sudo.ws>
|
* Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -179,22 +179,22 @@ exec_setup(struct command_details *details, int errfd)
|
|||||||
unlimit_nproc();
|
unlimit_nproc();
|
||||||
|
|
||||||
#if defined(HAVE_SETRESUID)
|
#if defined(HAVE_SETRESUID)
|
||||||
if (setresuid(details->uid, details->euid, details->euid) != 0) {
|
if (setresuid(details->cred.uid, details->cred.euid, details->cred.euid) != 0) {
|
||||||
sudo_warn(U_("unable to change to runas uid (%u, %u)"),
|
sudo_warn(U_("unable to change to runas uid (%u, %u)"),
|
||||||
(unsigned int)details->uid, (unsigned int)details->euid);
|
(unsigned int)details->cred.uid, (unsigned int)details->cred.euid);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
#elif defined(HAVE_SETREUID)
|
#elif defined(HAVE_SETREUID)
|
||||||
if (setreuid(details->uid, details->euid) != 0) {
|
if (setreuid(details->cred.uid, details->cred.euid) != 0) {
|
||||||
sudo_warn(U_("unable to change to runas uid (%u, %u)"),
|
sudo_warn(U_("unable to change to runas uid (%u, %u)"),
|
||||||
(unsigned int)details->uid, (unsigned int)details->euid);
|
(unsigned int)details->cred.uid, (unsigned int)details->cred.euid);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/* Cannot support real user-ID that is different from effective user-ID. */
|
/* Cannot support real user-ID that is different from effective user-ID. */
|
||||||
if (setuid(details->euid) != 0) {
|
if (setuid(details->cred.euid) != 0) {
|
||||||
sudo_warn(U_("unable to change to runas uid (%u, %u)"),
|
sudo_warn(U_("unable to change to runas uid (%u, %u)"),
|
||||||
(unsigned int)details->euid, (unsigned int)details->euid);
|
(unsigned int)details->cred.euid, (unsigned int)details->cred.euid);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
#endif /* !HAVE_SETRESUID && !HAVE_SETREUID */
|
#endif /* !HAVE_SETRESUID && !HAVE_SETREUID */
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-License-Identifier: ISC
|
* SPDX-License-Identifier: ISC
|
||||||
*
|
*
|
||||||
* Copyright (c) 2009-2020 Todd C. Miller <Todd.Miller@sudo.ws>
|
* Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -148,7 +148,7 @@ pty_setup(struct command_details *details, const char *tty)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!get_pty(&io_fds[SFD_LEADER], &io_fds[SFD_FOLLOWER],
|
if (!get_pty(&io_fds[SFD_LEADER], &io_fds[SFD_FOLLOWER],
|
||||||
ptyname, sizeof(ptyname), details->euid))
|
ptyname, sizeof(ptyname), details->cred.euid))
|
||||||
sudo_fatal("%s", U_("unable to allocate pty"));
|
sudo_fatal("%s", U_("unable to allocate pty"));
|
||||||
|
|
||||||
/* Update tty name in command details (used by SELinux and AIX). */
|
/* Update tty name in command details (used by SELinux and AIX). */
|
||||||
|
50
src/sesh.c
50
src/sesh.c
@@ -131,7 +131,7 @@ main(int argc, char *argv[], char *envp[])
|
|||||||
* On success, fills in ud and returns true, else false.
|
* On success, fills in ud and returns true, else false.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
parse_user(char *userstr, struct user_details *ud)
|
parse_user(char *userstr, struct sudo_cred *cred)
|
||||||
{
|
{
|
||||||
char *cp, *ep;
|
char *cp, *ep;
|
||||||
const char *errstr;
|
const char *errstr;
|
||||||
@@ -144,7 +144,7 @@ parse_user(char *userstr, struct user_details *ud)
|
|||||||
debug_return_bool(false);
|
debug_return_bool(false);
|
||||||
}
|
}
|
||||||
*ep++ = '\0';
|
*ep++ = '\0';
|
||||||
ud->uid = sudo_strtoid(cp, &errstr);
|
cred->uid = cred->euid = sudo_strtoid(cp, &errstr);
|
||||||
if (errstr != NULL) {
|
if (errstr != NULL) {
|
||||||
sudo_warnx(U_("%s: %s"), cp, errstr);
|
sudo_warnx(U_("%s: %s"), cp, errstr);
|
||||||
debug_return_bool(false);
|
debug_return_bool(false);
|
||||||
@@ -157,7 +157,7 @@ parse_user(char *userstr, struct user_details *ud)
|
|||||||
debug_return_bool(false);
|
debug_return_bool(false);
|
||||||
}
|
}
|
||||||
*ep++ = '\0';
|
*ep++ = '\0';
|
||||||
ud->gid = sudo_strtoid(cp, &errstr);
|
cred->gid = cred->egid = sudo_strtoid(cp, &errstr);
|
||||||
if (errstr != NULL) {
|
if (errstr != NULL) {
|
||||||
sudo_warnx(U_("%s: %s"), cp, errstr);
|
sudo_warnx(U_("%s: %s"), cp, errstr);
|
||||||
debug_return_bool(false);
|
debug_return_bool(false);
|
||||||
@@ -165,8 +165,8 @@ parse_user(char *userstr, struct user_details *ud)
|
|||||||
|
|
||||||
/* group vector */
|
/* group vector */
|
||||||
cp = ep;
|
cp = ep;
|
||||||
ud->ngroups = sudo_parse_gids(cp, NULL, &ud->groups);
|
cred->ngroups = sudo_parse_gids(cp, NULL, &cred->groups);
|
||||||
if (ud->ngroups == -1)
|
if (cred->ngroups == -1)
|
||||||
debug_return_bool(false);
|
debug_return_bool(false);
|
||||||
|
|
||||||
debug_return_bool(true);
|
debug_return_bool(true);
|
||||||
@@ -176,30 +176,29 @@ static int
|
|||||||
sesh_sudoedit(int argc, char *argv[])
|
sesh_sudoedit(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int i, post, ret = SESH_ERR_FAILURE;
|
int i, post, ret = SESH_ERR_FAILURE;
|
||||||
int fd_src = -1, fd_dst = -1;
|
int edit_flags, fd_src = -1, fd_dst = -1;
|
||||||
struct command_details command_details;
|
struct sudo_cred user_cred, run_cred;
|
||||||
struct user_details edit_user;
|
|
||||||
struct timespec times[2];
|
struct timespec times[2];
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
debug_decl(sesh_sudoedit, SUDO_DEBUG_EDIT);
|
debug_decl(sesh_sudoedit, SUDO_DEBUG_EDIT);
|
||||||
|
|
||||||
memset(&edit_user, 0, sizeof(edit_user));
|
memset(&user_cred, 0, sizeof(user_cred));
|
||||||
memset(&command_details, 0, sizeof(command_details));
|
memset(&run_cred, 0, sizeof(run_cred));
|
||||||
command_details.flags = CD_SUDOEDIT_FOLLOW;
|
edit_flags = CD_SUDOEDIT_FOLLOW;
|
||||||
|
|
||||||
/* Check for -h flag (don't follow links). */
|
/* Check for -h flag (don't follow links). */
|
||||||
if (argv[2] != NULL && strcmp(argv[2], "-h") == 0) {
|
if (argv[2] != NULL && strcmp(argv[2], "-h") == 0) {
|
||||||
argv++;
|
argv++;
|
||||||
argc--;
|
argc--;
|
||||||
CLR(command_details.flags, CD_SUDOEDIT_FOLLOW);
|
CLR(edit_flags, CD_SUDOEDIT_FOLLOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for -w flag (disallow directories writable by the user). */
|
/* Check for -w flag (disallow directories writable by the user). */
|
||||||
if (argv[2] != NULL && strcmp(argv[2], "-w") == 0) {
|
if (argv[2] != NULL && strcmp(argv[2], "-w") == 0) {
|
||||||
SET(command_details.flags, CD_SUDOEDIT_CHECKDIR);
|
SET(edit_flags, CD_SUDOEDIT_CHECKDIR);
|
||||||
|
|
||||||
/* Parse uid:gid:gid1,gid2,... */
|
/* Parse uid:gid:gid1,gid2,... */
|
||||||
if (argv[3] == NULL || !parse_user(argv[3], &edit_user))
|
if (argv[3] == NULL || !parse_user(argv[3], &user_cred))
|
||||||
debug_return_int(SESH_ERR_FAILURE);
|
debug_return_int(SESH_ERR_FAILURE);
|
||||||
argv += 2;
|
argv += 2;
|
||||||
argc -= 2;
|
argc -= 2;
|
||||||
@@ -237,18 +236,18 @@ sesh_sudoedit(int argc, char *argv[])
|
|||||||
* sudoedit runs us with the effective user-ID and group-ID of
|
* sudoedit runs us with the effective user-ID and group-ID of
|
||||||
* the target user as well as with the target user's group list.
|
* the target user as well as with the target user's group list.
|
||||||
*/
|
*/
|
||||||
command_details.uid = command_details.euid = geteuid();
|
run_cred.uid = run_cred.euid = geteuid();
|
||||||
command_details.gid = command_details.egid = getegid();
|
run_cred.gid = run_cred.egid = getegid();
|
||||||
command_details.ngroups = getgroups(0, NULL);
|
run_cred.ngroups = getgroups(0, NULL);
|
||||||
if (command_details.ngroups > 0) {
|
if (run_cred.ngroups > 0) {
|
||||||
command_details.groups = reallocarray(NULL, command_details.ngroups,
|
run_cred.groups = reallocarray(NULL, run_cred.ngroups,
|
||||||
sizeof(GETGROUPS_T));
|
sizeof(GETGROUPS_T));
|
||||||
if (command_details.groups == NULL) {
|
if (run_cred.groups == NULL) {
|
||||||
sudo_warnx(U_("%s: %s"), __func__,
|
sudo_warnx(U_("%s: %s"), __func__,
|
||||||
U_("unable to allocate memory"));
|
U_("unable to allocate memory"));
|
||||||
debug_return_int(SESH_ERR_FAILURE);
|
debug_return_int(SESH_ERR_FAILURE);
|
||||||
}
|
}
|
||||||
if (getgroups(command_details.ngroups, command_details.groups) < 0) {
|
if (getgroups(run_cred.ngroups, run_cred.groups) < 0) {
|
||||||
sudo_warn("%s", U_("unable to get group list"));
|
sudo_warn("%s", U_("unable to get group list"));
|
||||||
debug_return_int(SESH_ERR_FAILURE);
|
debug_return_int(SESH_ERR_FAILURE);
|
||||||
}
|
}
|
||||||
@@ -265,7 +264,7 @@ sesh_sudoedit(int argc, char *argv[])
|
|||||||
fd_src = open(path_src, O_RDONLY|O_NONBLOCK|O_NOFOLLOW);
|
fd_src = open(path_src, O_RDONLY|O_NONBLOCK|O_NOFOLLOW);
|
||||||
} else {
|
} else {
|
||||||
fd_src = sudo_edit_open(path_src, post ? O_RDONLY|O_NOFOLLOW : O_RDONLY,
|
fd_src = sudo_edit_open(path_src, post ? O_RDONLY|O_NOFOLLOW : O_RDONLY,
|
||||||
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, &edit_user, &command_details);
|
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, &user_cred, &run_cred);
|
||||||
}
|
}
|
||||||
if (fd_src == -1) {
|
if (fd_src == -1) {
|
||||||
if (post || errno != ENOENT) {
|
if (post || errno != ENOENT) {
|
||||||
@@ -285,12 +284,12 @@ sesh_sudoedit(int argc, char *argv[])
|
|||||||
goto cleanup_0;
|
goto cleanup_0;
|
||||||
}
|
}
|
||||||
/* New file, verify parent dir exists and is not writable. */
|
/* New file, verify parent dir exists and is not writable. */
|
||||||
if (!sudo_edit_parent_valid(path_src, &edit_user, &command_details))
|
if (!sudo_edit_parent_valid(path_src, edit_flags, &user_cred, &run_cred))
|
||||||
goto cleanup_0;
|
goto cleanup_0;
|
||||||
}
|
}
|
||||||
if (post) {
|
if (post) {
|
||||||
/* Make sure the temporary file is safe and has the proper owner. */
|
/* Make sure the temporary file is safe and has the proper owner. */
|
||||||
if (!sudo_check_temp_file(fd_src, path_src, command_details.uid, &sb)) {
|
if (!sudo_check_temp_file(fd_src, path_src, run_cred.uid, &sb)) {
|
||||||
ret = SESH_ERR_SOME_FILES;
|
ret = SESH_ERR_SOME_FILES;
|
||||||
goto nocleanup;
|
goto nocleanup;
|
||||||
}
|
}
|
||||||
@@ -298,7 +297,8 @@ sesh_sudoedit(int argc, char *argv[])
|
|||||||
|
|
||||||
/* Create destination file. */
|
/* Create destination file. */
|
||||||
fd_dst = sudo_edit_open(path_dst, O_WRONLY|O_CREAT,
|
fd_dst = sudo_edit_open(path_dst, O_WRONLY|O_CREAT,
|
||||||
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, &edit_user, &command_details);
|
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, edit_flags, &user_cred,
|
||||||
|
&run_cred);
|
||||||
} else {
|
} else {
|
||||||
if (fd_src == -1) {
|
if (fd_src == -1) {
|
||||||
/* New file. */
|
/* New file. */
|
||||||
|
126
src/sudo.c
126
src/sudo.c
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-License-Identifier: ISC
|
* SPDX-License-Identifier: ISC
|
||||||
*
|
*
|
||||||
* Copyright (c) 2009-2020 Todd C. Miller <Todd.Miller@sudo.ws>
|
* Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -220,7 +220,7 @@ main(int argc, char *argv[], char *envp[])
|
|||||||
/* Print sudo version early, in case of plugin init failure. */
|
/* Print sudo version early, in case of plugin init failure. */
|
||||||
if (ISSET(sudo_mode, MODE_VERSION)) {
|
if (ISSET(sudo_mode, MODE_VERSION)) {
|
||||||
printf(_("Sudo version %s\n"), PACKAGE_VERSION);
|
printf(_("Sudo version %s\n"), PACKAGE_VERSION);
|
||||||
if (user_details.uid == ROOT_UID)
|
if (user_details.cred.uid == ROOT_UID)
|
||||||
(void) printf(_("Configure options: %s\n"), CONFIGURE_ARGS);
|
(void) printf(_("Configure options: %s\n"), CONFIGURE_ARGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,12 +242,12 @@ main(int argc, char *argv[], char *envp[])
|
|||||||
|
|
||||||
switch (sudo_mode & MODE_MASK) {
|
switch (sudo_mode & MODE_MASK) {
|
||||||
case MODE_VERSION:
|
case MODE_VERSION:
|
||||||
policy_show_version(!user_details.uid);
|
policy_show_version(!user_details.cred.uid);
|
||||||
iolog_show_version(!user_details.uid, settings, user_info,
|
iolog_show_version(!user_details.cred.uid, settings, user_info,
|
||||||
nargc, nargv, envp);
|
nargc, nargv, envp);
|
||||||
approval_show_version(!user_details.uid, settings, user_info,
|
approval_show_version(!user_details.cred.uid, settings, user_info,
|
||||||
submit_optind, argv, envp);
|
submit_optind, argv, envp);
|
||||||
audit_show_version(!user_details.uid);
|
audit_show_version(!user_details.cred.uid);
|
||||||
break;
|
break;
|
||||||
case MODE_VALIDATE:
|
case MODE_VALIDATE:
|
||||||
case MODE_VALIDATE|MODE_INVALIDATE:
|
case MODE_VALIDATE|MODE_INVALIDATE:
|
||||||
@@ -383,7 +383,7 @@ fix_fds(void)
|
|||||||
* Returns 0 on success and -1 on failure.
|
* Returns 0 on success and -1 on failure.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
fill_group_list(struct user_details *ud)
|
fill_group_list(const char *user, struct sudo_cred *cred)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
debug_decl(fill_group_list, SUDO_DEBUG_UTIL);
|
debug_decl(fill_group_list, SUDO_DEBUG_UTIL);
|
||||||
@@ -392,41 +392,41 @@ fill_group_list(struct user_details *ud)
|
|||||||
* If user specified a max number of groups, use it, otherwise let
|
* If user specified a max number of groups, use it, otherwise let
|
||||||
* sudo_getgrouplist2() allocate the group vector.
|
* sudo_getgrouplist2() allocate the group vector.
|
||||||
*/
|
*/
|
||||||
ud->ngroups = sudo_conf_max_groups();
|
cred->ngroups = sudo_conf_max_groups();
|
||||||
if (ud->ngroups > 0) {
|
if (cred->ngroups > 0) {
|
||||||
ud->groups = reallocarray(NULL, ud->ngroups, sizeof(GETGROUPS_T));
|
cred->groups = reallocarray(NULL, cred->ngroups, sizeof(GETGROUPS_T));
|
||||||
if (ud->groups != NULL) {
|
if (cred->groups != NULL) {
|
||||||
/* No error on insufficient space if user specified max_groups. */
|
/* No error on insufficient space if user specified max_groups. */
|
||||||
(void)sudo_getgrouplist2(ud->username, ud->gid, &ud->groups,
|
(void)sudo_getgrouplist2(user, cred->gid,
|
||||||
&ud->ngroups);
|
&cred->groups, &cred->ngroups);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ud->groups = NULL;
|
cred->groups = NULL;
|
||||||
ret = sudo_getgrouplist2(ud->username, ud->gid, &ud->groups,
|
ret = sudo_getgrouplist2(user, cred->gid, &cred->groups,
|
||||||
&ud->ngroups);
|
&cred->ngroups);
|
||||||
}
|
}
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
||||||
"%s: %s: unable to get groups via sudo_getgrouplist2()",
|
"%s: %s: unable to get groups via sudo_getgrouplist2()",
|
||||||
__func__, ud->username);
|
__func__, user);
|
||||||
} else {
|
} else {
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO,
|
sudo_debug_printf(SUDO_DEBUG_INFO,
|
||||||
"%s: %s: got %d groups via sudo_getgrouplist2()",
|
"%s: %s: got %d groups via sudo_getgrouplist2()",
|
||||||
__func__, ud->username, ud->ngroups);
|
__func__, user, cred->ngroups);
|
||||||
}
|
}
|
||||||
debug_return_int(ret);
|
debug_return_int(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
get_user_groups(struct user_details *ud)
|
get_user_groups(const char *user, struct sudo_cred *cred)
|
||||||
{
|
{
|
||||||
char *cp, *gid_list = NULL;
|
char *cp, *gid_list = NULL;
|
||||||
size_t glsize;
|
size_t glsize;
|
||||||
int i, len, group_source;
|
int i, len, group_source;
|
||||||
debug_decl(get_user_groups, SUDO_DEBUG_UTIL);
|
debug_decl(get_user_groups, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
ud->groups = NULL;
|
cred->groups = NULL;
|
||||||
group_source = sudo_conf_group_source();
|
group_source = sudo_conf_group_source();
|
||||||
if (group_source != GROUP_SOURCE_DYNAMIC) {
|
if (group_source != GROUP_SOURCE_DYNAMIC) {
|
||||||
int maxgroups = (int)sysconf(_SC_NGROUPS_MAX);
|
int maxgroups = (int)sysconf(_SC_NGROUPS_MAX);
|
||||||
@@ -434,46 +434,46 @@ get_user_groups(struct user_details *ud)
|
|||||||
maxgroups = NGROUPS_MAX;
|
maxgroups = NGROUPS_MAX;
|
||||||
|
|
||||||
/* Note that macOS may return ngroups > NGROUPS_MAX. */
|
/* Note that macOS may return ngroups > NGROUPS_MAX. */
|
||||||
if ((ud->ngroups = getgroups(0, NULL)) > 0) {
|
if ((cred->ngroups = getgroups(0, NULL)) > 0) {
|
||||||
/* Use groups from kernel if not at limit or source is static. */
|
/* Use groups from kernel if not at limit or source is static. */
|
||||||
if (ud->ngroups != maxgroups || group_source == GROUP_SOURCE_STATIC) {
|
if (cred->ngroups != maxgroups || group_source == GROUP_SOURCE_STATIC) {
|
||||||
ud->groups = reallocarray(NULL, ud->ngroups, sizeof(GETGROUPS_T));
|
cred->groups = reallocarray(NULL, cred->ngroups, sizeof(GETGROUPS_T));
|
||||||
if (ud->groups == NULL)
|
if (cred->groups == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (getgroups(ud->ngroups, ud->groups) < 0) {
|
if (getgroups(cred->ngroups, cred->groups) < 0) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
||||||
"%s: %s: unable to get %d groups via getgroups()",
|
"%s: unable to get %d groups via getgroups()",
|
||||||
__func__, ud->username, ud->ngroups);
|
__func__, cred->ngroups);
|
||||||
free(ud->groups);
|
free(cred->groups);
|
||||||
ud->groups = NULL;
|
cred->groups = NULL;
|
||||||
} else {
|
} else {
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO,
|
sudo_debug_printf(SUDO_DEBUG_INFO,
|
||||||
"%s: %s: got %d groups via getgroups()",
|
"%s: got %d groups via getgroups()",
|
||||||
__func__, ud->username, ud->ngroups);
|
__func__, cred->ngroups);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ud->groups == NULL) {
|
if (cred->groups == NULL) {
|
||||||
/*
|
/*
|
||||||
* Query group database if kernel list is too small or disabled.
|
* Query group database if kernel list is too small or disabled.
|
||||||
* Typically, this is because NFS can only support up to 16 groups.
|
* Typically, this is because NFS can only support up to 16 groups.
|
||||||
*/
|
*/
|
||||||
if (fill_group_list(ud) == -1)
|
if (fill_group_list(user, cred) == -1)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Format group list as a comma-separated string of gids.
|
* Format group list as a comma-separated string of gids.
|
||||||
*/
|
*/
|
||||||
glsize = sizeof("groups=") - 1 + (ud->ngroups * (MAX_UID_T_LEN + 1));
|
glsize = sizeof("groups=") - 1 + (cred->ngroups * (MAX_UID_T_LEN + 1));
|
||||||
if ((gid_list = malloc(glsize)) == NULL)
|
if ((gid_list = malloc(glsize)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
memcpy(gid_list, "groups=", sizeof("groups=") - 1);
|
memcpy(gid_list, "groups=", sizeof("groups=") - 1);
|
||||||
cp = gid_list + sizeof("groups=") - 1;
|
cp = gid_list + sizeof("groups=") - 1;
|
||||||
for (i = 0; i < ud->ngroups; i++) {
|
for (i = 0; i < cred->ngroups; i++) {
|
||||||
len = snprintf(cp, glsize - (cp - gid_list), "%s%u",
|
len = snprintf(cp, glsize - (cp - gid_list), "%s%u",
|
||||||
i ? "," : "", (unsigned int)ud->groups[i]);
|
i ? "," : "", (unsigned int)cred->groups[i]);
|
||||||
if (len < 0 || (size_t)len >= glsize - (cp - gid_list))
|
if (len < 0 || (size_t)len >= glsize - (cp - gid_list))
|
||||||
sudo_fatalx(U_("internal error, %s overflow"), __func__);
|
sudo_fatalx(U_("internal error, %s overflow"), __func__);
|
||||||
cp += len;
|
cp += len;
|
||||||
@@ -529,15 +529,15 @@ get_user_info(struct user_details *ud)
|
|||||||
if ((ud->sid = getsid(0)) == -1)
|
if ((ud->sid = getsid(0)) == -1)
|
||||||
ud->sid = 0;
|
ud->sid = 0;
|
||||||
|
|
||||||
ud->uid = getuid();
|
ud->cred.uid = getuid();
|
||||||
ud->euid = geteuid();
|
ud->cred.euid = geteuid();
|
||||||
ud->gid = getgid();
|
ud->cred.gid = getgid();
|
||||||
ud->egid = getegid();
|
ud->cred.egid = getegid();
|
||||||
|
|
||||||
#ifdef HAVE_SETAUTHDB
|
#ifdef HAVE_SETAUTHDB
|
||||||
aix_setauthdb(IDtouser(ud->uid), NULL);
|
aix_setauthdb(IDtouser(ud->cred.uid), NULL);
|
||||||
#endif
|
#endif
|
||||||
pw = getpwuid(ud->uid);
|
pw = getpwuid(ud->cred.uid);
|
||||||
#ifdef HAVE_SETAUTHDB
|
#ifdef HAVE_SETAUTHDB
|
||||||
aix_restoreauthdb();
|
aix_restoreauthdb();
|
||||||
#endif
|
#endif
|
||||||
@@ -566,16 +566,16 @@ get_user_info(struct user_details *ud)
|
|||||||
goto oom;
|
goto oom;
|
||||||
if (asprintf(&user_info[++i], "sid=%d", (int)ud->sid) == -1)
|
if (asprintf(&user_info[++i], "sid=%d", (int)ud->sid) == -1)
|
||||||
goto oom;
|
goto oom;
|
||||||
if (asprintf(&user_info[++i], "uid=%u", (unsigned int)ud->uid) == -1)
|
if (asprintf(&user_info[++i], "uid=%u", (unsigned int)ud->cred.uid) == -1)
|
||||||
goto oom;
|
goto oom;
|
||||||
if (asprintf(&user_info[++i], "euid=%u", (unsigned int)ud->euid) == -1)
|
if (asprintf(&user_info[++i], "euid=%u", (unsigned int)ud->cred.euid) == -1)
|
||||||
goto oom;
|
goto oom;
|
||||||
if (asprintf(&user_info[++i], "gid=%u", (unsigned int)ud->gid) == -1)
|
if (asprintf(&user_info[++i], "gid=%u", (unsigned int)ud->cred.gid) == -1)
|
||||||
goto oom;
|
goto oom;
|
||||||
if (asprintf(&user_info[++i], "egid=%u", (unsigned int)ud->egid) == -1)
|
if (asprintf(&user_info[++i], "egid=%u", (unsigned int)ud->cred.egid) == -1)
|
||||||
goto oom;
|
goto oom;
|
||||||
|
|
||||||
if ((cp = get_user_groups(ud)) == NULL)
|
if ((cp = get_user_groups(ud->username, &ud->cred)) == NULL)
|
||||||
goto oom;
|
goto oom;
|
||||||
user_info[++i] = cp;
|
user_info[++i] = cp;
|
||||||
|
|
||||||
@@ -749,7 +749,7 @@ command_info_to_details(char * const info[], struct command_details *details)
|
|||||||
id = sudo_strtoid(cp, &errstr);
|
id = sudo_strtoid(cp, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
|
sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
|
||||||
details->egid = (gid_t)id;
|
details->cred.egid = (gid_t)id;
|
||||||
SET(details->flags, CD_SET_EGID);
|
SET(details->flags, CD_SET_EGID);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -758,7 +758,7 @@ command_info_to_details(char * const info[], struct command_details *details)
|
|||||||
id = sudo_strtoid(cp, &errstr);
|
id = sudo_strtoid(cp, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
|
sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
|
||||||
details->euid = (uid_t)id;
|
details->cred.euid = (uid_t)id;
|
||||||
SET(details->flags, CD_SET_EUID);
|
SET(details->flags, CD_SET_EUID);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -767,15 +767,15 @@ command_info_to_details(char * const info[], struct command_details *details)
|
|||||||
id = sudo_strtoid(cp, &errstr);
|
id = sudo_strtoid(cp, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
|
sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
|
||||||
details->gid = (gid_t)id;
|
details->cred.gid = (gid_t)id;
|
||||||
SET(details->flags, CD_SET_GID);
|
SET(details->flags, CD_SET_GID);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (strncmp("runas_groups=", info[i], sizeof("runas_groups=") - 1) == 0) {
|
if (strncmp("runas_groups=", info[i], sizeof("runas_groups=") - 1) == 0) {
|
||||||
cp = info[i] + sizeof("runas_groups=") - 1;
|
cp = info[i] + sizeof("runas_groups=") - 1;
|
||||||
details->ngroups = sudo_parse_gids(cp, NULL, &details->groups);
|
details->cred.ngroups = sudo_parse_gids(cp, NULL, &details->cred.groups);
|
||||||
/* sudo_parse_gids() will print a warning on error. */
|
/* sudo_parse_gids() will print a warning on error. */
|
||||||
if (details->ngroups == -1)
|
if (details->cred.ngroups == -1)
|
||||||
exit(EXIT_FAILURE); /* XXX */
|
exit(EXIT_FAILURE); /* XXX */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -784,7 +784,7 @@ command_info_to_details(char * const info[], struct command_details *details)
|
|||||||
id = sudo_strtoid(cp, &errstr);
|
id = sudo_strtoid(cp, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
|
sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
|
||||||
details->uid = (uid_t)id;
|
details->cred.uid = (uid_t)id;
|
||||||
SET(details->flags, CD_SET_UID);
|
SET(details->flags, CD_SET_UID);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -847,19 +847,19 @@ command_info_to_details(char * const info[], struct command_details *details)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!ISSET(details->flags, CD_SET_EUID))
|
if (!ISSET(details->flags, CD_SET_EUID))
|
||||||
details->euid = details->uid;
|
details->cred.euid = details->cred.uid;
|
||||||
if (!ISSET(details->flags, CD_SET_EGID))
|
if (!ISSET(details->flags, CD_SET_EGID))
|
||||||
details->egid = details->gid;
|
details->cred.egid = details->cred.gid;
|
||||||
if (!ISSET(details->flags, CD_SET_UMASK))
|
if (!ISSET(details->flags, CD_SET_UMASK))
|
||||||
CLR(details->flags, CD_OVERRIDE_UMASK);
|
CLR(details->flags, CD_OVERRIDE_UMASK);
|
||||||
|
|
||||||
#ifdef HAVE_SETAUTHDB
|
#ifdef HAVE_SETAUTHDB
|
||||||
aix_setauthdb(IDtouser(details->euid), NULL);
|
aix_setauthdb(IDtouser(details->cred.euid), NULL);
|
||||||
#endif
|
#endif
|
||||||
if (details->runas_user != NULL)
|
if (details->runas_user != NULL)
|
||||||
details->pw = getpwnam(details->runas_user);
|
details->pw = getpwnam(details->runas_user);
|
||||||
if (details->pw == NULL)
|
if (details->pw == NULL)
|
||||||
details->pw = getpwuid(details->euid);
|
details->pw = getpwuid(details->cred.euid);
|
||||||
#ifdef HAVE_SETAUTHDB
|
#ifdef HAVE_SETAUTHDB
|
||||||
aix_restoreauthdb();
|
aix_restoreauthdb();
|
||||||
#endif
|
#endif
|
||||||
@@ -933,23 +933,23 @@ set_user_groups(struct command_details *details)
|
|||||||
debug_decl(set_user_groups, SUDO_DEBUG_EXEC);
|
debug_decl(set_user_groups, SUDO_DEBUG_EXEC);
|
||||||
|
|
||||||
if (!ISSET(details->flags, CD_PRESERVE_GROUPS)) {
|
if (!ISSET(details->flags, CD_PRESERVE_GROUPS)) {
|
||||||
if (details->ngroups >= 0) {
|
if (details->cred.ngroups >= 0) {
|
||||||
if (sudo_setgroups(details->ngroups, details->groups) < 0) {
|
if (sudo_setgroups(details->cred.ngroups, details->cred.groups) < 0) {
|
||||||
sudo_warn("%s", U_("unable to set supplementary group IDs"));
|
sudo_warn("%s", U_("unable to set supplementary group IDs"));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef HAVE_SETEUID
|
#ifdef HAVE_SETEUID
|
||||||
if (ISSET(details->flags, CD_SET_EGID) && setegid(details->egid)) {
|
if (ISSET(details->flags, CD_SET_EGID) && setegid(details->cred.egid)) {
|
||||||
sudo_warn(U_("unable to set effective gid to runas gid %u"),
|
sudo_warn(U_("unable to set effective gid to runas gid %u"),
|
||||||
(unsigned int)details->egid);
|
(unsigned int)details->cred.egid);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (ISSET(details->flags, CD_SET_GID) && setgid(details->gid)) {
|
if (ISSET(details->flags, CD_SET_GID) && setgid(details->cred.gid)) {
|
||||||
sudo_warn(U_("unable to set gid to runas gid %u"),
|
sudo_warn(U_("unable to set gid to runas gid %u"),
|
||||||
(unsigned int)details->gid);
|
(unsigned int)details->cred.gid);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
ret = true;
|
ret = true;
|
||||||
|
26
src/sudo.h
26
src/sudo.h
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-License-Identifier: ISC
|
* SPDX-License-Identifier: ISC
|
||||||
*
|
*
|
||||||
* Copyright (c) 1993-1996, 1998-2005, 2007-2016
|
* Copyright (c) 1993-1996, 1998-2005, 2007-2021
|
||||||
* Todd C. Miller <Todd.Miller@sudo.ws>
|
* Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
@@ -92,23 +92,28 @@ struct sudo_settings {
|
|||||||
const char *value;
|
const char *value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Sudo user credentials */
|
||||||
|
struct sudo_cred {
|
||||||
|
uid_t uid;
|
||||||
|
uid_t euid;
|
||||||
|
uid_t gid;
|
||||||
|
uid_t egid;
|
||||||
|
int ngroups;
|
||||||
|
GETGROUPS_T *groups;
|
||||||
|
};
|
||||||
|
|
||||||
struct user_details {
|
struct user_details {
|
||||||
|
struct sudo_cred cred;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
pid_t ppid;
|
pid_t ppid;
|
||||||
pid_t pgid;
|
pid_t pgid;
|
||||||
pid_t tcpgid;
|
pid_t tcpgid;
|
||||||
pid_t sid;
|
pid_t sid;
|
||||||
uid_t uid;
|
|
||||||
uid_t euid;
|
|
||||||
uid_t gid;
|
|
||||||
uid_t egid;
|
|
||||||
const char *username;
|
const char *username;
|
||||||
const char *cwd;
|
const char *cwd;
|
||||||
const char *tty;
|
const char *tty;
|
||||||
const char *host;
|
const char *host;
|
||||||
const char *shell;
|
const char *shell;
|
||||||
GETGROUPS_T *groups;
|
|
||||||
int ngroups;
|
|
||||||
int ts_rows;
|
int ts_rows;
|
||||||
int ts_cols;
|
int ts_cols;
|
||||||
};
|
};
|
||||||
@@ -143,21 +148,16 @@ struct preserved_fd {
|
|||||||
TAILQ_HEAD(preserved_fd_list, preserved_fd);
|
TAILQ_HEAD(preserved_fd_list, preserved_fd);
|
||||||
|
|
||||||
struct command_details {
|
struct command_details {
|
||||||
uid_t uid;
|
struct sudo_cred cred;
|
||||||
uid_t euid;
|
|
||||||
gid_t gid;
|
|
||||||
gid_t egid;
|
|
||||||
mode_t umask;
|
mode_t umask;
|
||||||
int priority;
|
int priority;
|
||||||
int timeout;
|
int timeout;
|
||||||
int ngroups;
|
|
||||||
int closefrom;
|
int closefrom;
|
||||||
int flags;
|
int flags;
|
||||||
int execfd;
|
int execfd;
|
||||||
int cwd_optional;
|
int cwd_optional;
|
||||||
struct preserved_fd_list preserved_fds;
|
struct preserved_fd_list preserved_fds;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
GETGROUPS_T *groups;
|
|
||||||
const char *command;
|
const char *command;
|
||||||
const char *runas_user;
|
const char *runas_user;
|
||||||
const char *cwd;
|
const char *cwd;
|
||||||
|
@@ -77,7 +77,7 @@ set_tmpdir(struct command_details *command_details)
|
|||||||
|
|
||||||
for (i = 0; tdir == NULL && i < nitems(tmpdirs); i++) {
|
for (i = 0; tdir == NULL && i < nitems(tmpdirs); i++) {
|
||||||
if ((dfd = open(tmpdirs[i], O_RDONLY)) != -1) {
|
if ((dfd = open(tmpdirs[i], O_RDONLY)) != -1) {
|
||||||
if (dir_is_writable(dfd, &user_details, command_details) == true)
|
if (dir_is_writable(dfd, &user_details.cred, &command_details->cred) == true)
|
||||||
tdir = tmpdirs[i];
|
tdir = tmpdirs[i];
|
||||||
close(dfd);
|
close(dfd);
|
||||||
}
|
}
|
||||||
@@ -150,22 +150,23 @@ sudo_edit_create_tfiles(struct command_details *command_details,
|
|||||||
*/
|
*/
|
||||||
for (i = 0, j = 0; i < nfiles; i++) {
|
for (i = 0, j = 0; i < nfiles; i++) {
|
||||||
rc = -1;
|
rc = -1;
|
||||||
switch_user(command_details->euid, command_details->egid,
|
switch_user(command_details->cred.euid, command_details->cred.egid,
|
||||||
command_details->ngroups, command_details->groups);
|
command_details->cred.ngroups, command_details->cred.groups);
|
||||||
ofd = sudo_edit_open(files[i], O_RDONLY,
|
ofd = sudo_edit_open(files[i], O_RDONLY,
|
||||||
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, &user_details, command_details);
|
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, command_details->flags,
|
||||||
|
&user_details.cred, &command_details->cred);
|
||||||
if (ofd != -1 || errno == ENOENT) {
|
if (ofd != -1 || errno == ENOENT) {
|
||||||
if (ofd != -1) {
|
if (ofd != -1) {
|
||||||
rc = fstat(ofd, &sb);
|
rc = fstat(ofd, &sb);
|
||||||
} else {
|
} else {
|
||||||
/* New file, verify parent dir exists and is not writable. */
|
/* New file, verify parent dir exists and is not writable. */
|
||||||
memset(&sb, 0, sizeof(sb));
|
memset(&sb, 0, sizeof(sb));
|
||||||
if (sudo_edit_parent_valid(files[i], &user_details, command_details))
|
if (sudo_edit_parent_valid(files[i], command_details->flags, &user_details.cred, &command_details->cred))
|
||||||
rc = 0;
|
rc = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch_user(ROOT_UID, user_details.egid,
|
switch_user(ROOT_UID, user_details.cred.egid,
|
||||||
user_details.ngroups, user_details.groups);
|
user_details.cred.ngroups, user_details.cred.groups);
|
||||||
if (ofd != -1 && !S_ISREG(sb.st_mode)) {
|
if (ofd != -1 && !S_ISREG(sb.st_mode)) {
|
||||||
sudo_warnx(U_("%s: not a regular file"), files[i]);
|
sudo_warnx(U_("%s: not a regular file"), files[i]);
|
||||||
close(ofd);
|
close(ofd);
|
||||||
@@ -190,9 +191,9 @@ sudo_edit_create_tfiles(struct command_details *command_details,
|
|||||||
tf[j].osize = sb.st_size;
|
tf[j].osize = sb.st_size;
|
||||||
mtim_get(&sb, tf[j].omtim);
|
mtim_get(&sb, tf[j].omtim);
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
||||||
"seteuid(%u)", (unsigned int)user_details.uid);
|
"seteuid(%u)", (unsigned int)user_details.cred.uid);
|
||||||
if (seteuid(user_details.uid) != 0)
|
if (seteuid(user_details.cred.uid) != 0)
|
||||||
sudo_fatal("seteuid(%u)", (unsigned int)user_details.uid);
|
sudo_fatal("seteuid(%u)", (unsigned int)user_details.cred.uid);
|
||||||
tfd = sudo_edit_mktemp(tf[j].ofile, &tf[j].tfile);
|
tfd = sudo_edit_mktemp(tf[j].ofile, &tf[j].tfile);
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
||||||
"seteuid(%u)", ROOT_UID);
|
"seteuid(%u)", ROOT_UID);
|
||||||
@@ -251,16 +252,16 @@ sudo_edit_copy_tfiles(struct command_details *command_details,
|
|||||||
/* Copy contents of temp files to real ones. */
|
/* Copy contents of temp files to real ones. */
|
||||||
for (i = 0; i < nfiles; i++) {
|
for (i = 0; i < nfiles; i++) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
||||||
"seteuid(%u)", (unsigned int)user_details.uid);
|
"seteuid(%u)", (unsigned int)user_details.cred.uid);
|
||||||
if (seteuid(user_details.uid) != 0)
|
if (seteuid(user_details.cred.uid) != 0)
|
||||||
sudo_fatal("seteuid(%u)", (unsigned int)user_details.uid);
|
sudo_fatal("seteuid(%u)", (unsigned int)user_details.cred.uid);
|
||||||
tfd = sudo_edit_open(tf[i].tfile, O_RDONLY,
|
tfd = sudo_edit_open(tf[i].tfile, O_RDONLY,
|
||||||
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, &user_details, NULL);
|
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 0, &user_details.cred, NULL);
|
||||||
if (seteuid(ROOT_UID) != 0)
|
if (seteuid(ROOT_UID) != 0)
|
||||||
sudo_fatal("seteuid(ROOT_UID)");
|
sudo_fatal("seteuid(ROOT_UID)");
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
||||||
"seteuid(%u)", ROOT_UID);
|
"seteuid(%u)", ROOT_UID);
|
||||||
if (tfd == -1 || !sudo_check_temp_file(tfd, tf[i].tfile, user_details.uid, &sb)) {
|
if (tfd == -1 || !sudo_check_temp_file(tfd, tf[i].tfile, user_details.cred.uid, &sb)) {
|
||||||
sudo_warnx(U_("%s left unmodified"), tf[i].ofile);
|
sudo_warnx(U_("%s left unmodified"), tf[i].ofile);
|
||||||
if (tfd != -1)
|
if (tfd != -1)
|
||||||
close(tfd);
|
close(tfd);
|
||||||
@@ -280,14 +281,15 @@ sudo_edit_copy_tfiles(struct command_details *command_details,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch_user(command_details->euid, command_details->egid,
|
switch_user(command_details->cred.euid, command_details->cred.egid,
|
||||||
command_details->ngroups, command_details->groups);
|
command_details->cred.ngroups, command_details->cred.groups);
|
||||||
oldmask = umask(command_details->umask);
|
oldmask = umask(command_details->umask);
|
||||||
ofd = sudo_edit_open(tf[i].ofile, O_WRONLY|O_CREAT,
|
ofd = sudo_edit_open(tf[i].ofile, O_WRONLY|O_CREAT,
|
||||||
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, &user_details, command_details);
|
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, command_details->flags,
|
||||||
|
&user_details.cred, &command_details->cred);
|
||||||
umask(oldmask);
|
umask(oldmask);
|
||||||
switch_user(ROOT_UID, user_details.egid,
|
switch_user(ROOT_UID, user_details.cred.egid,
|
||||||
user_details.ngroups, user_details.groups);
|
user_details.cred.ngroups, user_details.cred.groups);
|
||||||
if (ofd == -1) {
|
if (ofd == -1) {
|
||||||
sudo_warn(U_("unable to write to %s"), tf[i].ofile);
|
sudo_warn(U_("unable to write to %s"), tf[i].ofile);
|
||||||
goto bad;
|
goto bad;
|
||||||
@@ -359,21 +361,21 @@ selinux_fmt_sudo_user(void)
|
|||||||
int i, len;
|
int i, len;
|
||||||
debug_decl(selinux_fmt_sudo_user, SUDO_DEBUG_EDIT);
|
debug_decl(selinux_fmt_sudo_user, SUDO_DEBUG_EDIT);
|
||||||
|
|
||||||
user_size = (MAX_UID_T_LEN + 1) * (2 + user_details.ngroups);
|
user_size = (MAX_UID_T_LEN + 1) * (2 + user_details.cred.ngroups);
|
||||||
if ((user_str = malloc(user_size)) == NULL)
|
if ((user_str = malloc(user_size)) == NULL)
|
||||||
debug_return_ptr(NULL);
|
debug_return_ptr(NULL);
|
||||||
|
|
||||||
/* UID:GID: */
|
/* UID:GID: */
|
||||||
len = snprintf(user_str, user_size, "%u:%u:",
|
len = snprintf(user_str, user_size, "%u:%u:",
|
||||||
(unsigned int)user_details.uid, (unsigned int)user_details.gid);
|
(unsigned int)user_details.cred.uid, (unsigned int)user_details.cred.gid);
|
||||||
if (len < 0 || (size_t)len >= user_size)
|
if (len < 0 || (size_t)len >= user_size)
|
||||||
sudo_fatalx(U_("internal error, %s overflow"), __func__);
|
sudo_fatalx(U_("internal error, %s overflow"), __func__);
|
||||||
|
|
||||||
/* Supplementary GIDs */
|
/* Supplementary GIDs */
|
||||||
cp = user_str + len;
|
cp = user_str + len;
|
||||||
for (i = 0; i < user_details.ngroups; i++) {
|
for (i = 0; i < user_details.cred.ngroups; i++) {
|
||||||
len = snprintf(cp, user_size - (cp - user_str), "%s%u",
|
len = snprintf(cp, user_size - (cp - user_str), "%s%u",
|
||||||
i ? "," : "", (unsigned int)user_details.groups[i]);
|
i ? "," : "", (unsigned int)user_details.cred.groups[i]);
|
||||||
if (len < 0 || (size_t)len >= user_size - (cp - user_str))
|
if (len < 0 || (size_t)len >= user_size - (cp - user_str))
|
||||||
sudo_fatalx(U_("internal error, %s overflow"), __func__);
|
sudo_fatalx(U_("internal error, %s overflow"), __func__);
|
||||||
cp += len;
|
cp += len;
|
||||||
@@ -443,8 +445,8 @@ selinux_edit_create_tfiles(struct command_details *command_details,
|
|||||||
*sesh_ap = NULL;
|
*sesh_ap = NULL;
|
||||||
|
|
||||||
/* Run sesh -e [-h] 0 <o1> <t1> ... <on> <tn> */
|
/* Run sesh -e [-h] 0 <o1> <t1> ... <on> <tn> */
|
||||||
error = selinux_run_helper(command_details->uid, command_details->gid,
|
error = selinux_run_helper(command_details->cred.uid, command_details->cred.gid,
|
||||||
command_details->ngroups, command_details->groups, sesh_args,
|
command_details->cred.ngroups, command_details->cred.groups, sesh_args,
|
||||||
command_details->envp);
|
command_details->envp);
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case SESH_SUCCESS:
|
case SESH_SUCCESS:
|
||||||
@@ -466,13 +468,13 @@ selinux_edit_create_tfiles(struct command_details *command_details,
|
|||||||
sudo_warn(U_("unable to open %s"), tf[i].tfile);
|
sudo_warn(U_("unable to open %s"), tf[i].tfile);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (!sudo_check_temp_file(tfd, tf[i].tfile, command_details->uid, NULL)) {
|
if (!sudo_check_temp_file(tfd, tf[i].tfile, command_details->cred.uid, NULL)) {
|
||||||
close(tfd);
|
close(tfd);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (fchown(tfd, user_details.uid, user_details.gid) != 0) {
|
if (fchown(tfd, user_details.cred.uid, user_details.cred.gid) != 0) {
|
||||||
sudo_warn("unable to chown(%s) to %d:%d for editing",
|
sudo_warn("unable to chown(%s) to %d:%d for editing",
|
||||||
tf[i].tfile, user_details.uid, user_details.gid);
|
tf[i].tfile, user_details.cred.uid, user_details.cred.gid);
|
||||||
close(tfd);
|
close(tfd);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@@ -529,7 +531,7 @@ selinux_edit_copy_tfiles(struct command_details *command_details,
|
|||||||
sudo_warn(U_("unable to open %s"), tf[i].tfile);
|
sudo_warn(U_("unable to open %s"), tf[i].tfile);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!sudo_check_temp_file(tfd, tf[i].tfile, user_details.uid, &sb))
|
if (!sudo_check_temp_file(tfd, tf[i].tfile, user_details.cred.uid, &sb))
|
||||||
continue;
|
continue;
|
||||||
mtim_get(&sb, ts);
|
mtim_get(&sb, ts);
|
||||||
if (tf[i].osize == sb.st_size && sudo_timespeccmp(&tf[i].omtim, &ts, ==)) {
|
if (tf[i].osize == sb.st_size && sudo_timespeccmp(&tf[i].omtim, &ts, ==)) {
|
||||||
@@ -545,9 +547,9 @@ selinux_edit_copy_tfiles(struct command_details *command_details,
|
|||||||
}
|
}
|
||||||
*sesh_ap++ = tf[i].tfile;
|
*sesh_ap++ = tf[i].tfile;
|
||||||
*sesh_ap++ = tf[i].ofile;
|
*sesh_ap++ = tf[i].ofile;
|
||||||
if (fchown(tfd, command_details->uid, command_details->gid) != 0) {
|
if (fchown(tfd, command_details->cred.uid, command_details->cred.gid) != 0) {
|
||||||
sudo_warn("unable to chown(%s) back to %d:%d", tf[i].tfile,
|
sudo_warn("unable to chown(%s) back to %d:%d", tf[i].tfile,
|
||||||
command_details->uid, command_details->gid);
|
command_details->cred.uid, command_details->cred.gid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*sesh_ap = NULL;
|
*sesh_ap = NULL;
|
||||||
@@ -556,8 +558,8 @@ selinux_edit_copy_tfiles(struct command_details *command_details,
|
|||||||
|
|
||||||
if (sesh_ap - sesh_args > 3) {
|
if (sesh_ap - sesh_args > 3) {
|
||||||
/* Run sesh -e 1 <t1> <o1> ... <tn> <on> */
|
/* Run sesh -e 1 <t1> <o1> ... <tn> <on> */
|
||||||
error = selinux_run_helper(command_details->uid, command_details->gid,
|
error = selinux_run_helper(command_details->cred.uid, command_details->cred.gid,
|
||||||
command_details->ngroups, command_details->groups, sesh_args,
|
command_details->cred.ngroups, command_details->cred.groups, sesh_args,
|
||||||
command_details->envp);
|
command_details->envp);
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case SESH_SUCCESS:
|
case SESH_SUCCESS:
|
||||||
@@ -689,12 +691,7 @@ sudo_edit(struct command_details *command_details)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
memcpy(&saved_command_details, command_details, sizeof(struct command_details));
|
memcpy(&saved_command_details, command_details, sizeof(struct command_details));
|
||||||
command_details->uid = user_details.uid;
|
command_details->cred = user_details.cred;
|
||||||
command_details->euid = user_details.uid;
|
|
||||||
command_details->gid = user_details.gid;
|
|
||||||
command_details->egid = user_details.gid;
|
|
||||||
command_details->ngroups = user_details.ngroups;
|
|
||||||
command_details->groups = user_details.groups;
|
|
||||||
command_details->argv = nargv;
|
command_details->argv = nargv;
|
||||||
ret = run_command(command_details);
|
ret = run_command(command_details);
|
||||||
if (sudo_gettime_real(×[1]) == -1) {
|
if (sudo_gettime_real(×[1]) == -1) {
|
||||||
@@ -703,12 +700,7 @@ sudo_edit(struct command_details *command_details)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Restore saved command_details. */
|
/* Restore saved command_details. */
|
||||||
command_details->uid = saved_command_details.uid;
|
command_details->cred = saved_command_details.cred;
|
||||||
command_details->euid = saved_command_details.euid;
|
|
||||||
command_details->gid = saved_command_details.gid;
|
|
||||||
command_details->egid = saved_command_details.egid;
|
|
||||||
command_details->ngroups = saved_command_details.ngroups;
|
|
||||||
command_details->groups = saved_command_details.groups;
|
|
||||||
command_details->argv = saved_command_details.argv;
|
command_details->argv = saved_command_details.argv;
|
||||||
|
|
||||||
/* Copy contents of temp files to real ones. */
|
/* Copy contents of temp files to real ones. */
|
||||||
|
@@ -46,9 +46,10 @@ int sudo_copy_file(const char *src, int src_fd, off_t src_len, const char *dst,
|
|||||||
bool sudo_check_temp_file(int tfd, const char *tname, uid_t uid, struct stat *sb);
|
bool sudo_check_temp_file(int tfd, const char *tname, uid_t uid, struct stat *sb);
|
||||||
|
|
||||||
/* edit_open.c */
|
/* edit_open.c */
|
||||||
|
struct sudo_cred;
|
||||||
void switch_user(uid_t euid, gid_t egid, int ngroups, GETGROUPS_T *groups);
|
void switch_user(uid_t euid, gid_t egid, int ngroups, GETGROUPS_T *groups);
|
||||||
int sudo_edit_open(char *path, int oflags, mode_t mode, struct user_details *ud, struct command_details *cd);
|
int sudo_edit_open(char *path, int oflags, mode_t mode, int sflags, struct sudo_cred *user_cred, struct sudo_cred *run_cred);
|
||||||
int dir_is_writable(int dfd, struct user_details *ud, struct command_details *cd);
|
int dir_is_writable(int dfd, struct sudo_cred *user_cred, struct sudo_cred *run_cred);
|
||||||
bool sudo_edit_parent_valid(char *path, struct user_details *ud, struct command_details *cd);
|
bool sudo_edit_parent_valid(char *path, int sflags, struct sudo_cred *user_cred, struct sudo_cred *run_cred);
|
||||||
|
|
||||||
#endif /* SUDO_EDIT_H */
|
#endif /* SUDO_EDIT_H */
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-License-Identifier: ISC
|
* SPDX-License-Identifier: ISC
|
||||||
*
|
*
|
||||||
* Copyright (c) 1996, 1998-2005, 2007-2018
|
* Copyright (c) 1996, 1998-2005, 2007-2021
|
||||||
* Todd C. Miller <Todd.Miller@sudo.ws>
|
* Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
@@ -323,12 +323,12 @@ sudo_askpass(const char *askpass, const char *prompt)
|
|||||||
restore_limits();
|
restore_limits();
|
||||||
/* But avoid a setuid() failure on Linux due to RLIMIT_NPROC. */
|
/* But avoid a setuid() failure on Linux due to RLIMIT_NPROC. */
|
||||||
unlimit_nproc();
|
unlimit_nproc();
|
||||||
if (setgid(user_details.gid)) {
|
if (setgid(user_details.cred.gid)) {
|
||||||
sudo_warn(U_("unable to set gid to %u"), (unsigned int)user_details.gid);
|
sudo_warn(U_("unable to set gid to %u"), (unsigned int)user_details.cred.gid);
|
||||||
_exit(255);
|
_exit(255);
|
||||||
}
|
}
|
||||||
if (setuid(user_details.uid)) {
|
if (setuid(user_details.cred.uid)) {
|
||||||
sudo_warn(U_("unable to set uid to %u"), (unsigned int)user_details.uid);
|
sudo_warn(U_("unable to set uid to %u"), (unsigned int)user_details.cred.uid);
|
||||||
_exit(255);
|
_exit(255);
|
||||||
}
|
}
|
||||||
restore_nproc();
|
restore_nproc();
|
||||||
|
Reference in New Issue
Block a user