Make the I/O log file/dir permissions and owner configurable.
This commit is contained in:
@@ -1543,6 +1543,30 @@ SSUUDDOOEERRSS OOPPTTIIOONNSS
|
||||
will be truncated and overwritten unless _i_o_l_o_g___f_i_l_e
|
||||
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
|
||||
The directory in which ssuuddoo stores per-user lecture
|
||||
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
|
||||
complete details.
|
||||
|
||||
Sudo 1.8.18 October 19, 2016 Sudo 1.8.18
|
||||
Sudo 1.8.19 October 29, 2016 Sudo 1.8.19
|
||||
|
@@ -21,7 +21,7 @@
|
||||
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
.\" 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
|
||||
.if n .ad l
|
||||
.SH "NAME"
|
||||
@@ -3188,6 +3188,31 @@ ends in six or
|
||||
more
|
||||
\fRX\fRs.
|
||||
.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
|
||||
The directory in which
|
||||
\fBsudo\fR
|
||||
|
@@ -19,7 +19,7 @@
|
||||
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
.\"
|
||||
.Dd October 19, 2016
|
||||
.Dd October 29, 2016
|
||||
.Dt SUDOERS @mansectform@
|
||||
.Os Sudo @PACKAGE_VERSION@
|
||||
.Sh NAME
|
||||
@@ -2988,6 +2988,28 @@ overwritten unless
|
||||
ends in six or
|
||||
more
|
||||
.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
|
||||
The directory in which
|
||||
.Nm sudo
|
||||
|
@@ -422,6 +422,18 @@ struct sudo_defs_types sudo_defs_table[] = {
|
||||
"syslog_maxlen", T_UINT,
|
||||
N_("Log entries larger than this value will be split into multiple syslog messages"),
|
||||
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
|
||||
}
|
||||
|
@@ -198,6 +198,12 @@
|
||||
#define def_match_group_by_gid (sudo_defs_table[I_MATCH_GROUP_BY_GID].sd_un.flag)
|
||||
#define I_SYSLOG_MAXLEN 99
|
||||
#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 {
|
||||
never,
|
||||
|
@@ -313,3 +313,12 @@ match_group_by_gid
|
||||
syslog_maxlen
|
||||
T_UINT
|
||||
"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"
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_STRING_H
|
||||
@@ -493,6 +494,7 @@ init_defaults(void)
|
||||
#endif
|
||||
def_netgroup_tuple = false;
|
||||
def_sudoedit_checkdir = true;
|
||||
def_iolog_mode = S_IRUSR|S_IWUSR;
|
||||
|
||||
/* Syslog options need special care since they both strings and ints */
|
||||
#if (LOGGING & SLOG_SYSLOG)
|
||||
|
@@ -71,89 +71,163 @@ static bool iolog_compress = false;
|
||||
static bool warned = false;
|
||||
static struct timeval last_time;
|
||||
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. */
|
||||
extern __dso_public struct io_plugin sudoers_io;
|
||||
|
||||
/*
|
||||
* Create path and any parent directories as needed.
|
||||
* If is_temp is set, use mkdtemp() for the final directory.
|
||||
*/
|
||||
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;
|
||||
gid_t parent_gid = 0;
|
||||
gid_t parent_gid;
|
||||
char *slash = path;
|
||||
bool ok = true;
|
||||
debug_decl(io_mkdirs, 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);
|
||||
}
|
||||
bool rval = true;
|
||||
debug_decl(io_mkdir_parents, SUDOERS_DEBUG_UTIL)
|
||||
|
||||
/* Create parent directories as needed. */
|
||||
parent_gid = *gidp != (gid_t)-1 ? *gidp : 0;
|
||||
while ((slash = strchr(slash + 1, '/')) != NULL) {
|
||||
*slash = '\0';
|
||||
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) {
|
||||
ignore_result(chown(path, (uid_t)-1, parent_gid));
|
||||
ignore_result(chown(path, uid, parent_gid));
|
||||
} else {
|
||||
if (errno != EEXIST) {
|
||||
log_warning(SLOG_SEND_MAIL, N_("unable to mkdir %s"), path);
|
||||
ok = false;
|
||||
rval = false;
|
||||
break;
|
||||
}
|
||||
/* Already exists, make sure it is a directory. */
|
||||
if (stat(path, &sb) != 0) {
|
||||
log_warning(SLOG_SEND_MAIL, N_("unable to mkdir %s"), path);
|
||||
ok = false;
|
||||
rval = false;
|
||||
break;
|
||||
}
|
||||
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;
|
||||
rval = false;
|
||||
break;
|
||||
}
|
||||
/* Inherit gid of parent dir for ownership. */
|
||||
parent_gid = sb.st_gid;
|
||||
if (*gidp == (gid_t)-1)
|
||||
parent_gid = sb.st_gid;
|
||||
}
|
||||
*slash = '/';
|
||||
}
|
||||
if (ok) {
|
||||
/* Create final path component. */
|
||||
if (is_temp) {
|
||||
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_t)-1, parent_gid));
|
||||
}
|
||||
|
||||
/* Return parent gid if none was specified by caller. */
|
||||
if (rval && *gidp == (gid_t)-1)
|
||||
*gidp = parent_gid;
|
||||
debug_return_bool(rval);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 {
|
||||
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
|
||||
"mkdir %s, mode 0%o", path, (unsigned int) mode);
|
||||
if (mkdir(path, mode) != 0 && errno != EEXIST) {
|
||||
log_warning(SLOG_SEND_MAIL, N_("unable to mkdir %s"), path);
|
||||
ok = false;
|
||||
} else {
|
||||
ignore_result(chown(path, (uid_t)-1, parent_gid));
|
||||
}
|
||||
log_warningx(SLOG_SEND_MAIL,
|
||||
N_("%s exists but is not a directory (0%o)"),
|
||||
path, (unsigned int) sb.st_mode);
|
||||
ok = false;
|
||||
}
|
||||
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 {
|
||||
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,
|
||||
"mkdir %s, mode 0%o", path, (unsigned int) mode);
|
||||
if (mkdir(path, mode) != 0 && errno != EEXIST) {
|
||||
log_warning(SLOG_SEND_MAIL, N_("unable to mkdir %s"), path);
|
||||
ok = false;
|
||||
} else {
|
||||
ignore_result(chown(path, uid, gid));
|
||||
}
|
||||
}
|
||||
if (gidp != NULL)
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
debug_return_bool(ok);
|
||||
}
|
||||
@@ -195,6 +269,74 @@ cb_maxseq(const union sudo_defs_val *sd_un)
|
||||
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
|
||||
* 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;
|
||||
int i, len, fd = -1;
|
||||
unsigned long id = 0;
|
||||
gid_t gid;
|
||||
gid_t gid = iolog_gid;
|
||||
ssize_t nread;
|
||||
bool ret = false;
|
||||
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.
|
||||
* 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;
|
||||
|
||||
/*
|
||||
@@ -229,13 +372,13 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
|
||||
log_warning(SLOG_SEND_MAIL, "%s/seq", pathbuf);
|
||||
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) {
|
||||
log_warning(SLOG_SEND_MAIL, N_("unable to open %s"), pathbuf);
|
||||
goto done;
|
||||
}
|
||||
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
|
||||
@@ -249,9 +392,9 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
|
||||
len = snprintf(fallback, sizeof(fallback), "%s/seq",
|
||||
iolog_dir_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) {
|
||||
ignore_result(fchown(fd2, (uid_t)-1, gid));
|
||||
ignore_result(fchown(fd2, iolog_uid, gid));
|
||||
nread = read(fd2, buf, sizeof(buf) - 1);
|
||||
if (nread > 0) {
|
||||
if (buf[nread - 1] == '\n')
|
||||
@@ -328,10 +471,10 @@ done:
|
||||
* Returns SIZE_MAX on error.
|
||||
*/
|
||||
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;
|
||||
bool is_temp = false;
|
||||
bool ok;
|
||||
debug_decl(mkdir_iopath, SUDOERS_DEBUG_UTIL)
|
||||
|
||||
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.
|
||||
* 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)
|
||||
is_temp = true;
|
||||
if (!io_mkdirs(pathbuf, S_IRWXU, gidp, is_temp))
|
||||
len = (size_t)-1;
|
||||
ok = io_mkdtemp(pathbuf, iolog_uid, &iolog_gid, iolog_dirmode, true);
|
||||
else
|
||||
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.
|
||||
*/
|
||||
static bool
|
||||
open_io_fd(char *pathbuf, size_t len, gid_t gid, struct io_log_file *iol,
|
||||
bool docompress)
|
||||
open_io_fd(char *pathbuf, size_t len, struct io_log_file *iol, bool docompress)
|
||||
{
|
||||
debug_decl(open_io_fd, SUDOERS_DEBUG_UTIL)
|
||||
|
||||
pathbuf[len] = '\0';
|
||||
strlcat(pathbuf, iol->suffix, PATH_MAX);
|
||||
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) {
|
||||
ignore_result(fchown(fd, (uid_t)-1, gid));
|
||||
ignore_result(fchown(fd, iolog_uid, iolog_gid));
|
||||
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
#ifdef HAVE_ZLIB_H
|
||||
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.
|
||||
*/
|
||||
static bool
|
||||
write_info_log(char *pathbuf, size_t len, gid_t gid,
|
||||
struct iolog_details *details, char * const argv[], struct timeval *now)
|
||||
write_info_log(char *pathbuf, size_t len, struct iolog_details *details,
|
||||
char * const argv[], struct timeval *now)
|
||||
{
|
||||
char * const *av;
|
||||
FILE *fp;
|
||||
@@ -586,12 +729,12 @@ write_info_log(char *pathbuf, size_t len, gid_t gid,
|
||||
|
||||
pathbuf[len] = '\0';
|
||||
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) {
|
||||
log_warning(SLOG_SEND_MAIL, N_("unable to create %s"), pathbuf);
|
||||
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,
|
||||
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;
|
||||
size_t len;
|
||||
int i, ret = -1;
|
||||
gid_t gid;
|
||||
debug_decl(sudoers_io_open, SUDOERS_DEBUG_PLUGIN)
|
||||
|
||||
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
|
||||
* intermediate subdirs. Calls mkdtemp() if iolog_path ends in XXXXXX.
|
||||
*/
|
||||
len = mkdir_iopath(iolog_details.iolog_path, pathbuf, sizeof(pathbuf),
|
||||
&gid);
|
||||
len = mkdir_iopath(iolog_details.iolog_path, pathbuf, sizeof(pathbuf));
|
||||
if (len >= sizeof(pathbuf))
|
||||
goto done;
|
||||
|
||||
/* Write log file with user and command details. */
|
||||
if (gettimeofday(&last_time, NULL) == -1)
|
||||
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. */
|
||||
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;
|
||||
}
|
||||
|
||||
|
@@ -723,6 +723,15 @@ init_vars(char * const envp[])
|
||||
/* Set maxseq callback. */
|
||||
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() */
|
||||
if (unknown_user) {
|
||||
log_warningx(SLOG_SEND_MAIL, N_("unknown uid: %u"),
|
||||
|
@@ -328,6 +328,9 @@ bool get_boottime(struct timespec *);
|
||||
/* iolog.c */
|
||||
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_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 */
|
||||
char *expand_iolog_path(const char *prefix, const char *dir, const char *file,
|
||||
|
Reference in New Issue
Block a user