Make the I/O log file/dir permissions and owner configurable.

This commit is contained in:
Todd C. Miller
2016-10-29 12:45:55 -06:00
parent b058ac5299
commit 271a07ff00
10 changed files with 325 additions and 72 deletions

View File

@@ -1543,6 +1543,30 @@ SSUUDDOOEERRSS OOPPTTIIOONNSS
will be truncated and overwritten unless _i_o_l_o_g___f_i_l_e will be truncated and overwritten unless _i_o_l_o_g___f_i_l_e
ends in six or more Xs. ends in six or more Xs.
iolog_group The group name to look up when setting the group ID on
new I/O log files and directories. By default, I/O log
files and directories inherit the group ID of the
parent directory.
This setting is only supported by version 1.8.19 or
higher.
iolog_mode The file permision mode to use when creating I/O log
files. When creating I/O log directories, search
(execute) bits are added to to match the read and write
bits specified by _i_o_l_o_g___m_o_d_e. Defaults to 0600.
This setting is only supported by version 1.8.19 or
higher.
iolog_user The user name to look up when setting the user ID on
new I/O log files and directories. By default, I/O log
files and directories are owned by the superuser (user
ID 0).
This setting is only supported by version 1.8.19 or
higher.
lecture_status_dir lecture_status_dir
The directory in which ssuuddoo stores per-user lecture The directory in which ssuuddoo stores per-user lecture
status files. Once a user has received the lecture, a status files. Once a user has received the lecture, a
@@ -2607,4 +2631,4 @@ DDIISSCCLLAAIIMMEERR
file distributed with ssuuddoo or https://www.sudo.ws/license.html for file distributed with ssuuddoo or https://www.sudo.ws/license.html for
complete details. complete details.
Sudo 1.8.18 October 19, 2016 Sudo 1.8.18 Sudo 1.8.19 October 29, 2016 Sudo 1.8.19

View File

@@ -21,7 +21,7 @@
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force .\" Agency (DARPA) and Air Force Research Laboratory, Air Force
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512. .\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\" .\"
.TH "SUDOERS" "5" "October 19, 2016" "Sudo @PACKAGE_VERSION@" "File Formats Manual" .TH "SUDOERS" "5" "October 29, 2016" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.nh .nh
.if n .ad l .if n .ad l
.SH "NAME" .SH "NAME"
@@ -3188,6 +3188,31 @@ ends in six or
more more
\fRX\fRs. \fRX\fRs.
.TP 18n .TP 18n
iolog_group
The group name to look up when setting the group ID on new I/O log
files and directories.
By default, I/O log files and directories inherit the group ID of
the parent directory.
.sp
This setting is only supported by version 1.8.19 or higher.
.TP 18n
iolog_mode
The file permision mode to use when creating I/O log files.
When creating I/O log directories, search (execute) bits are added
to to match the read and write bits specified by
\fIiolog_mode\fR.
Defaults to 0600.
.sp
This setting is only supported by version 1.8.19 or higher.
.TP 18n
iolog_user
The user name to look up when setting the user ID on new I/O log
files and directories.
By default, I/O log files and directories are owned by the superuser
(user ID 0).
.sp
This setting is only supported by version 1.8.19 or higher.
.TP 18n
lecture_status_dir lecture_status_dir
The directory in which The directory in which
\fBsudo\fR \fBsudo\fR

View File

@@ -19,7 +19,7 @@
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force .\" Agency (DARPA) and Air Force Research Laboratory, Air Force
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512. .\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\" .\"
.Dd October 19, 2016 .Dd October 29, 2016
.Dt SUDOERS @mansectform@ .Dt SUDOERS @mansectform@
.Os Sudo @PACKAGE_VERSION@ .Os Sudo @PACKAGE_VERSION@
.Sh NAME .Sh NAME
@@ -2988,6 +2988,28 @@ overwritten unless
ends in six or ends in six or
more more
.Li X Ns s . .Li X Ns s .
.It iolog_group
The group name to look up when setting the group ID on new I/O log
files and directories.
By default, I/O log files and directories inherit the group ID of
the parent directory.
.Pp
This setting is only supported by version 1.8.19 or higher.
.It iolog_mode
The file permision mode to use when creating I/O log files.
When creating I/O log directories, search (execute) bits are added
to to match the read and write bits specified by
.Em iolog_mode .
Defaults to 0600.
.Pp
This setting is only supported by version 1.8.19 or higher.
.It iolog_user
The user name to look up when setting the user ID on new I/O log
files and directories.
By default, I/O log files and directories are owned by the superuser
(user ID 0).
.Pp
This setting is only supported by version 1.8.19 or higher.
.It lecture_status_dir .It lecture_status_dir
The directory in which The directory in which
.Nm sudo .Nm sudo

View File

@@ -422,6 +422,18 @@ struct sudo_defs_types sudo_defs_table[] = {
"syslog_maxlen", T_UINT, "syslog_maxlen", T_UINT,
N_("Log entries larger than this value will be split into multiple syslog messages"), N_("Log entries larger than this value will be split into multiple syslog messages"),
NULL, NULL,
}, {
"iolog_user", T_STR|T_BOOL,
N_("User that will own the I/O log files: %s"),
NULL,
}, {
"iolog_group", T_STR|T_BOOL,
N_("Group that will own the I/O log files: %s"),
NULL,
}, {
"iolog_mode", T_MODE,
N_("File mode to use for the I/O log files: 0%o"),
NULL,
}, { }, {
NULL, 0, NULL NULL, 0, NULL
} }

View File

@@ -198,6 +198,12 @@
#define def_match_group_by_gid (sudo_defs_table[I_MATCH_GROUP_BY_GID].sd_un.flag) #define def_match_group_by_gid (sudo_defs_table[I_MATCH_GROUP_BY_GID].sd_un.flag)
#define I_SYSLOG_MAXLEN 99 #define I_SYSLOG_MAXLEN 99
#define def_syslog_maxlen (sudo_defs_table[I_SYSLOG_MAXLEN].sd_un.uival) #define def_syslog_maxlen (sudo_defs_table[I_SYSLOG_MAXLEN].sd_un.uival)
#define I_IOLOG_USER 100
#define def_iolog_user (sudo_defs_table[I_IOLOG_USER].sd_un.str)
#define I_IOLOG_GROUP 101
#define def_iolog_group (sudo_defs_table[I_IOLOG_GROUP].sd_un.str)
#define I_IOLOG_MODE 102
#define def_iolog_mode (sudo_defs_table[I_IOLOG_MODE].sd_un.mode)
enum def_tuple { enum def_tuple {
never, never,

View File

@@ -313,3 +313,12 @@ match_group_by_gid
syslog_maxlen syslog_maxlen
T_UINT T_UINT
"Log entries larger than this value will be split into multiple syslog messages" "Log entries larger than this value will be split into multiple syslog messages"
iolog_user
T_STR|T_BOOL
"User that will own the I/O log files: %s"
iolog_group
T_STR|T_BOOL
"Group that will own the I/O log files: %s"
iolog_mode
T_MODE
"File mode to use for the I/O log files: 0%o"

View File

@@ -22,6 +22,7 @@
#include <config.h> #include <config.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef HAVE_STRING_H #ifdef HAVE_STRING_H
@@ -493,6 +494,7 @@ init_defaults(void)
#endif #endif
def_netgroup_tuple = false; def_netgroup_tuple = false;
def_sudoedit_checkdir = true; def_sudoedit_checkdir = true;
def_iolog_mode = S_IRUSR|S_IWUSR;
/* Syslog options need special care since they both strings and ints */ /* Syslog options need special care since they both strings and ints */
#if (LOGGING & SLOG_SYSLOG) #if (LOGGING & SLOG_SYSLOG)

View File

@@ -71,89 +71,163 @@ static bool iolog_compress = false;
static bool warned = false; static bool warned = false;
static struct timeval last_time; static struct timeval last_time;
static unsigned int sessid_max = SESSID_MAX; static unsigned int sessid_max = SESSID_MAX;
static uid_t iolog_uid = ROOT_UID;
static gid_t iolog_gid = (gid_t)-1;
static mode_t iolog_dirmode = S_IRWXU;
/* sudoers_io is declared at the end of this file. */ /* sudoers_io is declared at the end of this file. */
extern __dso_public struct io_plugin sudoers_io; extern __dso_public struct io_plugin sudoers_io;
/* /*
* Create path and any parent directories as needed. * Create path and any parent directories as needed.
* If is_temp is set, use mkdtemp() for the final directory.
*/ */
static bool static bool
io_mkdirs(char *path, mode_t mode, gid_t *gidp, bool is_temp) io_mkdir_parents(char *path, uid_t uid, gid_t *gidp, mode_t mode)
{ {
struct stat sb; struct stat sb;
gid_t parent_gid = 0; gid_t parent_gid;
char *slash = path; char *slash = path;
bool ok = true; bool rval = true;
debug_decl(io_mkdirs, SUDOERS_DEBUG_UTIL) debug_decl(io_mkdir_parents, SUDOERS_DEBUG_UTIL)
/* Fast path: not a temporary and already exists. */
if (!is_temp && stat(path, &sb) == 0) {
if (!S_ISDIR(sb.st_mode)) {
log_warningx(SLOG_SEND_MAIL,
N_("%s exists but is not a directory (0%o)"),
path, (unsigned int) sb.st_mode);
ok = false;
}
if (gidp != NULL)
*gidp = sb.st_gid;
debug_return_bool(ok);
}
/* Create parent directories as needed. */
parent_gid = *gidp != (gid_t)-1 ? *gidp : 0;
while ((slash = strchr(slash + 1, '/')) != NULL) { while ((slash = strchr(slash + 1, '/')) != NULL) {
*slash = '\0'; *slash = '\0';
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdir %s, mode 0%o", path, (unsigned int) mode); "mkdir %s, mode 0%o, uid %d, gid %d", path, mode,
(int)uid, (int)parent_gid);
if (mkdir(path, mode) == 0) { if (mkdir(path, mode) == 0) {
ignore_result(chown(path, (uid_t)-1, parent_gid)); ignore_result(chown(path, uid, parent_gid));
} else { } else {
if (errno != EEXIST) { if (errno != EEXIST) {
log_warning(SLOG_SEND_MAIL, N_("unable to mkdir %s"), path); log_warning(SLOG_SEND_MAIL, N_("unable to mkdir %s"), path);
ok = false; rval = false;
break; break;
} }
/* Already exists, make sure it is a directory. */ /* Already exists, make sure it is a directory. */
if (stat(path, &sb) != 0) { if (stat(path, &sb) != 0) {
log_warning(SLOG_SEND_MAIL, N_("unable to mkdir %s"), path); log_warning(SLOG_SEND_MAIL, N_("unable to mkdir %s"), path);
ok = false; rval = false;
break; break;
} }
if (!S_ISDIR(sb.st_mode)) { if (!S_ISDIR(sb.st_mode)) {
log_warningx(SLOG_SEND_MAIL, log_warningx(SLOG_SEND_MAIL,
N_("%s exists but is not a directory (0%o)"), N_("%s exists but is not a directory (0%o)"),
path, (unsigned int) sb.st_mode); path, (unsigned int) sb.st_mode);
ok = false; rval = false;
break; break;
} }
/* Inherit gid of parent dir for ownership. */ /* Inherit gid of parent dir for ownership. */
if (*gidp == (gid_t)-1)
parent_gid = sb.st_gid; parent_gid = sb.st_gid;
} }
*slash = '/'; *slash = '/';
} }
if (ok) {
/* Create final path component. */ /* Return parent gid if none was specified by caller. */
if (is_temp) { if (rval && *gidp == (gid_t)-1)
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, *gidp = parent_gid;
"mkdtemp %s", path); debug_return_bool(rval);
if (mkdtemp(path) == NULL) { }
log_warning(SLOG_SEND_MAIL, N_("unable to mkdir %s"), path);
/*
* Create directory and any parent directories as needed.
*/
static bool
io_mkdirs(char *path, uid_t uid, gid_t *gidp, mode_t mode, bool set_intermediate)
{
struct stat sb;
uid_t parent_uid;
gid_t parent_gid;
mode_t parent_mode;
bool ok = true;
debug_decl(io_mkdirs, SUDOERS_DEBUG_UTIL)
if (stat(path, &sb) == 0) {
if (S_ISDIR(sb.st_mode)) {
parent_gid = sb.st_gid;
} else {
log_warningx(SLOG_SEND_MAIL,
N_("%s exists but is not a directory (0%o)"),
path, (unsigned int) sb.st_mode);
ok = false; ok = false;
} else {
ignore_result(chown(path, (uid_t)-1, parent_gid));
} }
goto done;
}
/* Parent directory ownership and mode. */
if (!set_intermediate) {
parent_mode = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
parent_uid = ROOT_UID;
parent_gid = 0;
} else { } else {
parent_mode = mode;
parent_uid = uid;
parent_gid = *gidp;
}
ok = io_mkdir_parents(path, parent_uid, &parent_gid, parent_mode);
if (ok) {
/* Use group ID if specified, else parent gid. */
gid_t gid = *gidp != (gid_t)-1 ? *gidp : parent_gid;
/* Create final path component. */
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdir %s, mode 0%o", path, (unsigned int) mode); "mkdir %s, mode 0%o", path, (unsigned int) mode);
if (mkdir(path, mode) != 0 && errno != EEXIST) { if (mkdir(path, mode) != 0 && errno != EEXIST) {
log_warning(SLOG_SEND_MAIL, N_("unable to mkdir %s"), path); log_warning(SLOG_SEND_MAIL, N_("unable to mkdir %s"), path);
ok = false; ok = false;
} else { } else {
ignore_result(chown(path, (uid_t)-1, parent_gid)); ignore_result(chown(path, uid, gid));
} }
} }
done:
if (ok && *gidp == (gid_t)-1)
*gidp = parent_gid;
debug_return_bool(ok);
}
/*
* Create temporary directory and any parent directories as needed.
*/
static bool
io_mkdtemp(char *path, uid_t uid, gid_t *gidp, mode_t mode, bool set_intermediate)
{
uid_t parent_uid;
gid_t parent_gid;
mode_t parent_mode;
bool ok = true;
debug_decl(io_mkdtemp, SUDOERS_DEBUG_UTIL)
/* Parent directory ownership and mode. */
if (!set_intermediate) {
parent_mode = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
parent_uid = ROOT_UID;
parent_gid = 0;
} else {
parent_mode = mode;
parent_uid = uid;
parent_gid = *gidp;
} }
if (gidp != NULL)
ok = io_mkdir_parents(path, parent_uid, &parent_gid, parent_mode);
if (ok) {
/* Use group ID if specified, else parent gid. */
gid_t gid = *gidp != (gid_t)-1 ? *gidp : parent_gid;
/* Create final path component. */
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdtemp %s", path);
if (mkdtemp(path) == NULL) {
log_warning(SLOG_SEND_MAIL, N_("unable to mkdir %s"), path);
ok = false;
} else {
ignore_result(chown(path, uid, gid));
}
}
if (ok && *gidp == (gid_t)-1)
*gidp = parent_gid; *gidp = parent_gid;
debug_return_bool(ok); debug_return_bool(ok);
} }
@@ -195,6 +269,74 @@ cb_maxseq(const union sudo_defs_val *sd_un)
debug_return_bool(true); debug_return_bool(true);
} }
/*
* Sudoers callback for iolog_user Defaults setting.
*/
bool
cb_iolog_user(const union sudo_defs_val *sd_un)
{
struct passwd *pw;
debug_decl(cb_iolog_user, SUDOERS_DEBUG_UTIL)
if (sd_un->str != NULL) {
pw = sudo_getpwnam(sd_un->str);
if (pw != NULL) {
iolog_uid = pw->pw_uid;
} else {
log_warningx(SLOG_SEND_MAIL,
N_("unknown user: %s"), sd_un->str);
}
} else {
iolog_uid = ROOT_UID;
}
debug_return_bool(true);
}
/*
* Sudoers callback for iolog_group Defaults setting.
*/
bool
cb_iolog_group(const union sudo_defs_val *sd_un)
{
struct group *gr;
debug_decl(cb_iolog_group, SUDOERS_DEBUG_UTIL)
if (sd_un->str != NULL) {
gr = sudo_getgrnam(sd_un->str);
if (gr != NULL) {
iolog_gid = gr->gr_gid;
} else {
log_warningx(SLOG_SEND_MAIL,
N_("unknown group: %s"), sd_un->str);
}
} else {
iolog_gid = (mode_t)-1;
}
debug_return_bool(true);
}
/*
* Sudoers callback for iolog_mode Defaults setting.
*/
bool
cb_iolog_mode(const union sudo_defs_val *sd_un)
{
debug_decl(cb_iolog_mode, SUDOERS_DEBUG_UTIL)
/* Base directory mode on iolog_mode, adding in the X bit as needed */
iolog_dirmode = def_iolog_mode;
if (iolog_dirmode & (S_IRUSR|S_IWUSR))
iolog_dirmode |= S_IXUSR;
if (iolog_dirmode & (S_IRGRP|S_IWGRP))
iolog_dirmode |= S_IXGRP;
if (iolog_dirmode & (S_IROTH|S_IWOTH))
iolog_dirmode |= S_IXOTH;
debug_return_bool(true);
}
/* /*
* Read the on-disk sequence number, set sessid to the next * Read the on-disk sequence number, set sessid to the next
* number, and update the on-disk copy. * number, and update the on-disk copy.
@@ -207,7 +349,7 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
char buf[32], *ep; char buf[32], *ep;
int i, len, fd = -1; int i, len, fd = -1;
unsigned long id = 0; unsigned long id = 0;
gid_t gid; gid_t gid = iolog_gid;
ssize_t nread; ssize_t nread;
bool ret = false; bool ret = false;
char pathbuf[PATH_MAX]; char pathbuf[PATH_MAX];
@@ -216,8 +358,9 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
/* /*
* Create I/O log directory if it doesn't already exist. * Create I/O log directory if it doesn't already exist.
* Avoid modifying iolog_gid at this point.
*/ */
if (!io_mkdirs(iolog_dir, S_IRWXU, &gid, false)) if (!io_mkdirs(iolog_dir, iolog_uid, &gid, iolog_dirmode, false))
goto done; goto done;
/* /*
@@ -229,13 +372,13 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
log_warning(SLOG_SEND_MAIL, "%s/seq", pathbuf); log_warning(SLOG_SEND_MAIL, "%s/seq", pathbuf);
goto done; goto done;
} }
fd = open(pathbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); fd = open(pathbuf, O_RDWR|O_CREAT, def_iolog_mode);
if (fd == -1) { if (fd == -1) {
log_warning(SLOG_SEND_MAIL, N_("unable to open %s"), pathbuf); log_warning(SLOG_SEND_MAIL, N_("unable to open %s"), pathbuf);
goto done; goto done;
} }
sudo_lock_file(fd, SUDO_LOCK); sudo_lock_file(fd, SUDO_LOCK);
ignore_result(fchown(fd, (uid_t)-1, gid)); ignore_result(fchown(fd, iolog_uid, gid));
/* /*
* If there is no seq file in iolog_dir and a fallback dir was * If there is no seq file in iolog_dir and a fallback dir was
@@ -249,9 +392,9 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
len = snprintf(fallback, sizeof(fallback), "%s/seq", len = snprintf(fallback, sizeof(fallback), "%s/seq",
iolog_dir_fallback); iolog_dir_fallback);
if (len > 0 && (size_t)len < sizeof(fallback)) { if (len > 0 && (size_t)len < sizeof(fallback)) {
int fd2 = open(fallback, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); int fd2 = open(fallback, O_RDWR|O_CREAT, def_iolog_mode);
if (fd2 != -1) { if (fd2 != -1) {
ignore_result(fchown(fd2, (uid_t)-1, gid)); ignore_result(fchown(fd2, iolog_uid, gid));
nread = read(fd2, buf, sizeof(buf) - 1); nread = read(fd2, buf, sizeof(buf) - 1);
if (nread > 0) { if (nread > 0) {
if (buf[nread - 1] == '\n') if (buf[nread - 1] == '\n')
@@ -328,10 +471,10 @@ done:
* Returns SIZE_MAX on error. * Returns SIZE_MAX on error.
*/ */
static size_t static size_t
mkdir_iopath(const char *iolog_path, char *pathbuf, size_t pathsize, gid_t *gidp) mkdir_iopath(const char *iolog_path, char *pathbuf, size_t pathsize)
{ {
size_t len; size_t len;
bool is_temp = false; bool ok;
debug_decl(mkdir_iopath, SUDOERS_DEBUG_UTIL) debug_decl(mkdir_iopath, SUDOERS_DEBUG_UTIL)
len = strlcpy(pathbuf, iolog_path, pathsize); len = strlcpy(pathbuf, iolog_path, pathsize);
@@ -344,13 +487,14 @@ mkdir_iopath(const char *iolog_path, char *pathbuf, size_t pathsize, gid_t *gidp
/* /*
* Create path and intermediate subdirs as needed. * Create path and intermediate subdirs as needed.
* If path ends in at least 6 Xs (ala POSIX mktemp), use mkdtemp(). * If path ends in at least 6 Xs (ala POSIX mktemp), use mkdtemp().
* Sets iolog_gid (if it is not already set) as a side effect.
*/ */
if (len >= 6 && strcmp(&pathbuf[len - 6], "XXXXXX") == 0) if (len >= 6 && strcmp(&pathbuf[len - 6], "XXXXXX") == 0)
is_temp = true; ok = io_mkdtemp(pathbuf, iolog_uid, &iolog_gid, iolog_dirmode, true);
if (!io_mkdirs(pathbuf, S_IRWXU, gidp, is_temp)) else
len = (size_t)-1; ok = io_mkdirs(pathbuf, iolog_uid, &iolog_gid, iolog_dirmode, true);
debug_return_size_t(len); debug_return_size_t(ok ? len : (size_t)-1);
} }
/* /*
@@ -360,17 +504,16 @@ mkdir_iopath(const char *iolog_path, char *pathbuf, size_t pathsize, gid_t *gidp
* Stores the open file handle which has the close-on-exec flag set. * Stores the open file handle which has the close-on-exec flag set.
*/ */
static bool static bool
open_io_fd(char *pathbuf, size_t len, gid_t gid, struct io_log_file *iol, open_io_fd(char *pathbuf, size_t len, struct io_log_file *iol, bool docompress)
bool docompress)
{ {
debug_decl(open_io_fd, SUDOERS_DEBUG_UTIL) debug_decl(open_io_fd, SUDOERS_DEBUG_UTIL)
pathbuf[len] = '\0'; pathbuf[len] = '\0';
strlcat(pathbuf, iol->suffix, PATH_MAX); strlcat(pathbuf, iol->suffix, PATH_MAX);
if (iol->enabled) { if (iol->enabled) {
int fd = open(pathbuf, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR); int fd = open(pathbuf, O_CREAT|O_TRUNC|O_WRONLY, def_iolog_mode);
if (fd != -1) { if (fd != -1) {
ignore_result(fchown(fd, (uid_t)-1, gid)); ignore_result(fchown(fd, iolog_uid, iolog_gid));
(void)fcntl(fd, F_SETFD, FD_CLOEXEC); (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
#ifdef HAVE_ZLIB_H #ifdef HAVE_ZLIB_H
if (docompress) if (docompress)
@@ -575,8 +718,8 @@ iolog_deserialize_info(struct iolog_details *details, char * const user_info[],
* Write the "/log" file that contains the user and command info. * Write the "/log" file that contains the user and command info.
*/ */
static bool static bool
write_info_log(char *pathbuf, size_t len, gid_t gid, write_info_log(char *pathbuf, size_t len, struct iolog_details *details,
struct iolog_details *details, char * const argv[], struct timeval *now) char * const argv[], struct timeval *now)
{ {
char * const *av; char * const *av;
FILE *fp; FILE *fp;
@@ -586,12 +729,12 @@ write_info_log(char *pathbuf, size_t len, gid_t gid,
pathbuf[len] = '\0'; pathbuf[len] = '\0';
strlcat(pathbuf, "/log", PATH_MAX); strlcat(pathbuf, "/log", PATH_MAX);
fd = open(pathbuf, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR); fd = open(pathbuf, O_CREAT|O_TRUNC|O_WRONLY, def_iolog_mode);
if (fd == -1 || (fp = fdopen(fd, "w")) == NULL) { if (fd == -1 || (fp = fdopen(fd, "w")) == NULL) {
log_warning(SLOG_SEND_MAIL, N_("unable to create %s"), pathbuf); log_warning(SLOG_SEND_MAIL, N_("unable to create %s"), pathbuf);
debug_return_bool(false); debug_return_bool(false);
} }
ignore_result(fchown(fd, (uid_t)-1, gid)); ignore_result(fchown(fd, iolog_uid, iolog_gid));
fprintf(fp, "%lld:%s:%s:%s:%s:%d:%d\n%s\n%s", (long long)now->tv_sec, fprintf(fp, "%lld:%s:%s:%s:%s:%d:%d\n%s\n%s", (long long)now->tv_sec,
details->user ? details->user : "unknown", details->runas_pw->pw_name, details->user ? details->user : "unknown", details->runas_pw->pw_name,
@@ -624,7 +767,6 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation,
const char *cp, *plugin_path = NULL; const char *cp, *plugin_path = NULL;
size_t len; size_t len;
int i, ret = -1; int i, ret = -1;
gid_t gid;
debug_decl(sudoers_io_open, SUDOERS_DEBUG_PLUGIN) debug_decl(sudoers_io_open, SUDOERS_DEBUG_PLUGIN)
sudo_conv = conversation; sudo_conv = conversation;
@@ -682,19 +824,18 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation,
* Make local copy of I/O log path and create it, along with any * Make local copy of I/O log path and create it, along with any
* intermediate subdirs. Calls mkdtemp() if iolog_path ends in XXXXXX. * intermediate subdirs. Calls mkdtemp() if iolog_path ends in XXXXXX.
*/ */
len = mkdir_iopath(iolog_details.iolog_path, pathbuf, sizeof(pathbuf), len = mkdir_iopath(iolog_details.iolog_path, pathbuf, sizeof(pathbuf));
&gid);
if (len >= sizeof(pathbuf)) if (len >= sizeof(pathbuf))
goto done; goto done;
/* Write log file with user and command details. */ /* Write log file with user and command details. */
if (gettimeofday(&last_time, NULL) == -1) if (gettimeofday(&last_time, NULL) == -1)
goto done; goto done;
write_info_log(pathbuf, len, gid, &iolog_details, argv, &last_time); write_info_log(pathbuf, len, &iolog_details, argv, &last_time);
/* Create the timing and I/O log files. */ /* Create the timing and I/O log files. */
for (i = 0; i < IOFD_MAX; i++) { for (i = 0; i < IOFD_MAX; i++) {
if (!open_io_fd(pathbuf, len, gid, &io_log_files[i], iolog_compress)) if (!open_io_fd(pathbuf, len, &io_log_files[i], iolog_compress))
goto done; goto done;
} }

View File

@@ -723,6 +723,15 @@ init_vars(char * const envp[])
/* Set maxseq callback. */ /* Set maxseq callback. */
sudo_defs_table[I_MAXSEQ].callback = cb_maxseq; sudo_defs_table[I_MAXSEQ].callback = cb_maxseq;
/* Set iolog_user callback. */
sudo_defs_table[I_IOLOG_USER].callback = cb_iolog_user;
/* Set iolog_group callback. */
sudo_defs_table[I_IOLOG_GROUP].callback = cb_iolog_group;
/* Set iolog_mode callback. */
sudo_defs_table[I_IOLOG_MODE].callback = cb_iolog_mode;
/* It is now safe to use log_warningx() and set_perms() */ /* It is now safe to use log_warningx() and set_perms() */
if (unknown_user) { if (unknown_user) {
log_warningx(SLOG_SEND_MAIL, N_("unknown uid: %u"), log_warningx(SLOG_SEND_MAIL, N_("unknown uid: %u"),

View File

@@ -328,6 +328,9 @@ bool get_boottime(struct timespec *);
/* iolog.c */ /* iolog.c */
bool io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7]); bool io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7]);
bool cb_maxseq(const union sudo_defs_val *sd_un); bool cb_maxseq(const union sudo_defs_val *sd_un);
bool cb_iolog_user(const union sudo_defs_val *sd_un);
bool cb_iolog_group(const union sudo_defs_val *sd_un);
bool cb_iolog_mode(const union sudo_defs_val *sd_un);
/* iolog_path.c */ /* iolog_path.c */
char *expand_iolog_path(const char *prefix, const char *dir, const char *file, char *expand_iolog_path(const char *prefix, const char *dir, const char *file,