mirror of
https://github.com/sudo-project/sudo.git
synced 2025-09-01 06:45:10 +00:00
Allow sudoers to specify the iolog file in addition to the iolog dir.
Add escape sequence support to iolog file and dir: sequence number, user, group, runas_user, runas_group, hostname and command in addition to any escape sequence recognized by strftime(3).
This commit is contained in:
@@ -103,8 +103,9 @@ LIBSUDOERS_OBJS = alias.lo audit.lo defaults.lo gram.lo match.lo pwutil.lo \
|
|||||||
timestr.lo toke.lo redblack.lo
|
timestr.lo toke.lo redblack.lo
|
||||||
|
|
||||||
SUDOERS_OBJS = $(AUTH_OBJS) boottime.lo check.lo env.lo goodpath.lo \
|
SUDOERS_OBJS = $(AUTH_OBJS) boottime.lo check.lo env.lo goodpath.lo \
|
||||||
group_plugin.lo find_path.lo interfaces.lo logging.lo parse.lo \
|
group_plugin.lo find_path.lo interfaces.lo logging.lo \
|
||||||
set_perms.lo sudoers.lo sudo_nss.lo iolog.lo @SUDOERS_OBJS@
|
parse.lo set_perms.lo sudoers.lo sudo_nss.lo iolog.lo \
|
||||||
|
iolog_path.lo @SUDOERS_OBJS@
|
||||||
|
|
||||||
VISUDO_OBJS = visudo.o goodpath.o find_path.o error.o
|
VISUDO_OBJS = visudo.o goodpath.o find_path.o error.o
|
||||||
|
|
||||||
@@ -221,6 +222,8 @@ interfaces.lo: $(srcdir)/interfaces.c $(SUDODEP) $(srcdir)/interfaces.h
|
|||||||
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/interfaces.c
|
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/interfaces.c
|
||||||
iolog.lo: $(srcdir)/iolog.c $(SUDODEP)
|
iolog.lo: $(srcdir)/iolog.c $(SUDODEP)
|
||||||
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/iolog.c
|
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/iolog.c
|
||||||
|
iolog_path.lo: $(srcdir)/iolog_path.c $(SUDODEP)
|
||||||
|
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/iolog_path.c
|
||||||
ldap.lo: $(srcdir)/ldap.c $(SUDODEP) $(srcdir)/parse.h $(incdir)/list.h
|
ldap.lo: $(srcdir)/ldap.c $(SUDODEP) $(srcdir)/parse.h $(incdir)/list.h
|
||||||
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/ldap.c
|
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/ldap.c
|
||||||
linux_audit.lo: $(srcdir)/linux_audit.c $(SUDODEP) $(srcdir)/linux_audit.h
|
linux_audit.lo: $(srcdir)/linux_audit.c $(SUDODEP) $(srcdir)/linux_audit.h
|
||||||
|
@@ -334,6 +334,10 @@ struct sudo_defs_types sudo_defs_table[] = {
|
|||||||
"iolog_dir", T_STR|T_PATH,
|
"iolog_dir", T_STR|T_PATH,
|
||||||
"Directory in which to store input/output logs",
|
"Directory in which to store input/output logs",
|
||||||
NULL,
|
NULL,
|
||||||
|
}, {
|
||||||
|
"iolog_file", T_STR,
|
||||||
|
"File in which to store the input/output log",
|
||||||
|
NULL,
|
||||||
}, {
|
}, {
|
||||||
NULL, 0, NULL
|
NULL, 0, NULL
|
||||||
}
|
}
|
||||||
|
@@ -154,6 +154,8 @@
|
|||||||
#define I_GROUP_PLUGIN 76
|
#define I_GROUP_PLUGIN 76
|
||||||
#define def_iolog_dir (sudo_defs_table[77].sd_un.str)
|
#define def_iolog_dir (sudo_defs_table[77].sd_un.str)
|
||||||
#define I_IOLOG_DIR 77
|
#define I_IOLOG_DIR 77
|
||||||
|
#define def_iolog_file (sudo_defs_table[78].sd_un.str)
|
||||||
|
#define I_IOLOG_FILE 78
|
||||||
|
|
||||||
enum def_tupple {
|
enum def_tupple {
|
||||||
never,
|
never,
|
||||||
|
@@ -247,3 +247,6 @@ group_plugin
|
|||||||
iolog_dir
|
iolog_dir
|
||||||
T_STR|T_PATH
|
T_STR|T_PATH
|
||||||
"Directory in which to store input/output logs"
|
"Directory in which to store input/output logs"
|
||||||
|
iolog_file
|
||||||
|
T_STR
|
||||||
|
"File in which to store the input/output log"
|
||||||
|
@@ -443,7 +443,8 @@ init_defaults(void)
|
|||||||
#ifdef UMASK_OVERRIDE
|
#ifdef UMASK_OVERRIDE
|
||||||
def_umask_override = TRUE;
|
def_umask_override = TRUE;
|
||||||
#endif
|
#endif
|
||||||
def_iolog_dir = _PATH_SUDO_IO_LOGDIR;
|
def_iolog_file = estrdup("%{seq}");
|
||||||
|
def_iolog_dir = estrdup(_PATH_SUDO_IO_LOGDIR);
|
||||||
def_sudoers_locale = estrdup("C");
|
def_sudoers_locale = estrdup("C");
|
||||||
def_env_reset = TRUE;
|
def_env_reset = TRUE;
|
||||||
def_set_logname = TRUE;
|
def_set_logname = TRUE;
|
||||||
|
@@ -84,6 +84,26 @@ static struct timeval last_time;
|
|||||||
static union io_fd io_fds[IOFD_MAX];
|
static union io_fd io_fds[IOFD_MAX];
|
||||||
extern struct io_plugin sudoers_io;
|
extern struct io_plugin sudoers_io;
|
||||||
|
|
||||||
|
static void
|
||||||
|
mkdir_parents(char *path)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
char *slash = path;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if ((slash = strchr(slash + 1, '/')) == NULL)
|
||||||
|
break;
|
||||||
|
*slash = '\0';
|
||||||
|
if (stat(path, &sb) != 0) {
|
||||||
|
if (mkdir(path, S_IRWXU) != 0)
|
||||||
|
log_error(USE_ERRNO, "Can't mkdir %s", path);
|
||||||
|
} else if (!S_ISDIR(sb.st_mode)) {
|
||||||
|
log_error(0, "%s: %s", path, strerror(ENOTDIR));
|
||||||
|
}
|
||||||
|
*slash = '/';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
io_nextid(void)
|
io_nextid(void)
|
||||||
{
|
{
|
||||||
@@ -98,6 +118,7 @@ io_nextid(void)
|
|||||||
/*
|
/*
|
||||||
* Create I/O log directory if it doesn't already exist.
|
* Create I/O log directory if it doesn't already exist.
|
||||||
*/
|
*/
|
||||||
|
mkdir_parents(def_iolog_dir);
|
||||||
if (stat(def_iolog_dir, &sb) != 0) {
|
if (stat(def_iolog_dir, &sb) != 0) {
|
||||||
if (mkdir(def_iolog_dir, S_IRWXU) != 0)
|
if (mkdir(def_iolog_dir, S_IRWXU) != 0)
|
||||||
log_error(USE_ERRNO, "Can't mkdir %s", def_iolog_dir);
|
log_error(USE_ERRNO, "Can't mkdir %s", def_iolog_dir);
|
||||||
@@ -152,72 +173,36 @@ io_nextid(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
build_idpath(const char *iolog_dir, const char *sessid, char *pathbuf, size_t pathsize)
|
build_iopath(const char *iolog_dir, const char *iolog_file, char *pathbuf,
|
||||||
|
size_t pathsize)
|
||||||
{
|
{
|
||||||
struct stat sb;
|
int dirlen, filelen, len;
|
||||||
char *cp;
|
|
||||||
int i, len;
|
|
||||||
|
|
||||||
if (sessid[0] == '\0')
|
/* Trim extraneous slashes. */
|
||||||
log_error(0, "tried to build a session id path without a session id");
|
dirlen = strlen(iolog_dir);
|
||||||
|
while (dirlen > 1 && iolog_dir[dirlen - 1] == '/')
|
||||||
|
dirlen--;
|
||||||
|
while (*iolog_file == '/')
|
||||||
|
iolog_file++;
|
||||||
|
filelen = strlen(iolog_file);
|
||||||
|
while (filelen > 1 && iolog_file[filelen - 1] == '/')
|
||||||
|
filelen--;
|
||||||
|
|
||||||
/* Check whether or not we have a real session ID. */
|
if (*iolog_dir != '/' || *iolog_file == '\0')
|
||||||
for (i = 0; i < 6; i++) {
|
log_error(0, "invalid I/O log path: %s/%s", iolog_dir, iolog_file);
|
||||||
switch (sessid[i]) {
|
|
||||||
case '0': case '1': case '2': case '3': case '4': case '5':
|
len = snprintf(pathbuf, pathsize, "%.*s/%.*s", dirlen, iolog_dir,
|
||||||
case '6': case '7': case '8': case '9': case 'A': case 'B':
|
filelen, iolog_file);
|
||||||
case 'C': case 'D': case 'E': case 'F': case 'G': case 'H':
|
if (len <= 0 && len >= pathsize) {
|
||||||
case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
|
errno = ENAMETOOLONG;
|
||||||
case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T':
|
log_error(USE_ERRNO, "%.*s/%.*s", dirlen, iolog_dir,
|
||||||
case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
|
filelen, iolog_file);
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto checked;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
checked:
|
|
||||||
if (i == 6 && sessid[6] == '\0') {
|
|
||||||
/* Path is of the form /var/log/sudo-io/00/00/01. */
|
|
||||||
len = snprintf(pathbuf, pathsize, "%s/%c%c/%c%c/%c%c", iolog_dir,
|
|
||||||
sessid[0], sessid[1], sessid[2], sessid[3], sessid[4], sessid[5]);
|
|
||||||
if (len <= 0 && len >= pathsize) {
|
|
||||||
errno = ENAMETOOLONG;
|
|
||||||
log_error(USE_ERRNO, "%s/%s", iolog_dir, sessid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the intermediate subdirs as needed. */
|
/* Create path and intermediate subdirs as needed. */
|
||||||
for (i = 6; i > 0; i -= 3) {
|
mkdir_parents(pathbuf);
|
||||||
pathbuf[len - i] = '\0';
|
if (mkdtemp(pathbuf) == NULL)
|
||||||
if (stat(pathbuf, &sb) != 0) {
|
log_error(USE_ERRNO, "Can't create %s", pathbuf);
|
||||||
if (mkdir(pathbuf, S_IRWXU) != 0)
|
|
||||||
log_error(USE_ERRNO, "Can't mkdir %s", pathbuf);
|
|
||||||
} else if (!S_ISDIR(sb.st_mode)) {
|
|
||||||
log_error(0, "%s: %s", pathbuf, strerror(ENOTDIR));
|
|
||||||
}
|
|
||||||
pathbuf[len - i] = '/';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Not a session ID, just append dir + file. */
|
|
||||||
len = snprintf(pathbuf, pathsize, "%s/%s", iolog_dir, sessid);
|
|
||||||
if (len <= 0 && len >= pathsize) {
|
|
||||||
errno = ENAMETOOLONG;
|
|
||||||
log_error(USE_ERRNO, "%s/%s", iolog_dir, sessid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the intermediate subdirs as needed. */
|
|
||||||
cp = &pathbuf[strlen(iolog_dir)];
|
|
||||||
do {
|
|
||||||
*cp = '\0';
|
|
||||||
if (stat(pathbuf, &sb) != 0) {
|
|
||||||
if (mkdir(pathbuf, S_IRWXU) != 0)
|
|
||||||
log_error(USE_ERRNO, "Can't mkdir %s", pathbuf);
|
|
||||||
} else if (!S_ISDIR(sb.st_mode)) {
|
|
||||||
log_error(0, "%s: %s", pathbuf, strerror(ENOTDIR));
|
|
||||||
}
|
|
||||||
*cp++ = '/';
|
|
||||||
cp = strchr(cp, '/');
|
|
||||||
} while (cp != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(len);
|
return(len);
|
||||||
}
|
}
|
||||||
@@ -272,8 +257,8 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation,
|
|||||||
/*
|
/*
|
||||||
* Pull iolog settings out of command_info, if any.
|
* Pull iolog settings out of command_info, if any.
|
||||||
*/
|
*/
|
||||||
iolog_dir = def_iolog_dir;
|
iolog_dir = _PATH_SUDO_IO_LOGDIR; /* XXX */
|
||||||
iolog_file = sudo_user.sessid;
|
iolog_file = sudo_user.sessid; /* XXX */
|
||||||
iolog_stdin = iolog_ttyin = def_log_input;
|
iolog_stdin = iolog_ttyin = def_log_input;
|
||||||
iolog_stdout = iolog_stderr = iolog_ttyout = def_log_output;
|
iolog_stdout = iolog_stderr = iolog_ttyout = def_log_output;
|
||||||
for (cur = command_info; *cur != NULL; cur++) {
|
for (cur = command_info; *cur != NULL; cur++) {
|
||||||
@@ -319,20 +304,17 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* If no I/O log file defined there is nothing to do. */
|
/* If no I/O log file defined there is nothing to do. */
|
||||||
if (iolog_file == NULL)
|
if (iolog_file == NULL || iolog_dir == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Build a path containing the session ID split into two-digit subdirs,
|
* Build a path from I/O file and dir, creating intermediate subdirs
|
||||||
* so ID 000001 becomes /var/log/sudo-io/00/00/01.
|
* and calling mkdtemp() on the result.
|
||||||
*/
|
*/
|
||||||
len = build_idpath(iolog_dir, iolog_file, pathbuf, sizeof(pathbuf));
|
len = build_iopath(iolog_dir, iolog_file, pathbuf, sizeof(pathbuf));
|
||||||
if (len == -1)
|
if (len < 0 || len >= sizeof(pathbuf))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (mkdir(pathbuf, S_IRUSR|S_IWUSR|S_IXUSR) != 0)
|
|
||||||
log_error(USE_ERRNO, "Can't mkdir %s", pathbuf);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We create 7 files: a log file, a timing file and 5 for input/output.
|
* We create 7 files: a log file, a timing file and 5 for input/output.
|
||||||
*/
|
*/
|
||||||
|
229
plugins/sudoers/iolog_path.c
Normal file
229
plugins/sudoers/iolog_path.c
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef STDC_HEADERS
|
||||||
|
# include <stdlib.h>
|
||||||
|
# include <stddef.h>
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_STDLIB_H
|
||||||
|
# include <stdlib.h>
|
||||||
|
# endif
|
||||||
|
#endif /* STDC_HEADERS */
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
|
||||||
|
# include <memory.h>
|
||||||
|
# endif
|
||||||
|
# include <string.h>
|
||||||
|
#endif /* HAVE_STRING_H */
|
||||||
|
#ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
#endif /* HAVE_STRINGS_H */
|
||||||
|
#ifdef HAVE_SETLOCALE
|
||||||
|
# include <locale.h>
|
||||||
|
#endif
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <grp.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "sudoers.h"
|
||||||
|
|
||||||
|
struct path_escape {
|
||||||
|
const char *name;
|
||||||
|
size_t (*copy_fn)(char *, size_t);
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t fill_seq(char *, size_t);
|
||||||
|
static size_t fill_user(char *, size_t);
|
||||||
|
static size_t fill_group(char *, size_t);
|
||||||
|
static size_t fill_runas_user(char *, size_t);
|
||||||
|
static size_t fill_runas_group(char *, size_t);
|
||||||
|
static size_t fill_hostname(char *, size_t);
|
||||||
|
static size_t fill_command(char *, size_t);
|
||||||
|
|
||||||
|
static struct path_escape escapes[] = {
|
||||||
|
{ "seq", fill_seq },
|
||||||
|
{ "user", fill_user },
|
||||||
|
{ "group", fill_group },
|
||||||
|
{ "runas_user", fill_runas_user },
|
||||||
|
{ "runas_group", fill_runas_group },
|
||||||
|
{ "hostname", fill_hostname },
|
||||||
|
{ "command", fill_command },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
fill_seq(char *str, size_t strsize)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
/* Path is of the form /var/log/sudo-io/00/00/01. */
|
||||||
|
len = snprintf(str, strsize, "%c%c/%c%c/%c%c", sudo_user.sessid[0],
|
||||||
|
sudo_user.sessid[1], sudo_user.sessid[2], sudo_user.sessid[3],
|
||||||
|
sudo_user.sessid[4], sudo_user.sessid[5]);
|
||||||
|
if (len < 0)
|
||||||
|
return strsize; /* handle non-standard snprintf() */
|
||||||
|
return (size_t)len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
fill_user(char *str, size_t strsize)
|
||||||
|
{
|
||||||
|
return strlcpy(str, user_name, strsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
fill_group(char *str, size_t strsize)
|
||||||
|
{
|
||||||
|
struct group *grp;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if ((grp = sudo_getgrgid(user_gid)) != NULL) {
|
||||||
|
len = strlcpy(str, grp->gr_name, strsize);
|
||||||
|
gr_delref(grp);
|
||||||
|
} else {
|
||||||
|
len = strlen(str);
|
||||||
|
len = snprintf(str + len, strsize - len, "#%u",
|
||||||
|
(unsigned int) user_gid);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
fill_runas_user(char *str, size_t strsize)
|
||||||
|
{
|
||||||
|
return strlcpy(str, runas_pw->pw_name, strsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
fill_runas_group(char *str, size_t strsize)
|
||||||
|
{
|
||||||
|
struct group *grp;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (runas_gr != NULL) {
|
||||||
|
len = strlcpy(str, runas_gr->gr_name, strsize);
|
||||||
|
} else {
|
||||||
|
if ((grp = sudo_getgrgid(runas_pw->pw_gid)) != NULL) {
|
||||||
|
len = strlcpy(str, grp->gr_name, strsize);
|
||||||
|
gr_delref(grp);
|
||||||
|
} else {
|
||||||
|
len = strlen(str);
|
||||||
|
len = snprintf(str + len, strsize - len, "#%u",
|
||||||
|
(unsigned int) runas_pw->pw_gid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
fill_hostname(char *str, size_t strsize)
|
||||||
|
{
|
||||||
|
return strlcpy(str, user_shost, strsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
fill_command(char *str, size_t strsize)
|
||||||
|
{
|
||||||
|
return strlcpy(str, user_base, strsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
expand_iolog_path(const char *prefix, const char *opath)
|
||||||
|
{
|
||||||
|
size_t plen = 0, psize = 1024;
|
||||||
|
char *path, *dst;
|
||||||
|
const char *src, *ep;
|
||||||
|
int strfit = FALSE;
|
||||||
|
|
||||||
|
/* Copy opath -> path, expanding any escape sequences. */
|
||||||
|
dst = path = emalloc(psize);
|
||||||
|
*path = '\0';
|
||||||
|
|
||||||
|
if (prefix != NULL) {
|
||||||
|
plen = strlcpy(path, prefix, psize);
|
||||||
|
dst += plen;
|
||||||
|
}
|
||||||
|
for (src = opath; *src != '\0'; src++) {
|
||||||
|
if (src[0] == '%') {
|
||||||
|
if (src[1] == '{') {
|
||||||
|
ep = strchr(src + 2, '}');
|
||||||
|
if (ep != NULL) {
|
||||||
|
struct path_escape *esc;
|
||||||
|
size_t len = (size_t)(ep - src - 2);
|
||||||
|
for (esc = escapes; esc->name != NULL; esc++) {
|
||||||
|
if (strncmp(src + 2, esc->name, len) == 0 &&
|
||||||
|
esc->name[len] == '\0')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
len = esc->copy_fn(dst, psize - (dst - path));
|
||||||
|
if (len < psize - (dst - path))
|
||||||
|
break;
|
||||||
|
path = erealloc3(path, 2, psize);
|
||||||
|
psize *= 2;
|
||||||
|
dst = path + plen;
|
||||||
|
}
|
||||||
|
dst += len;
|
||||||
|
src = ep;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* May need strftime() */
|
||||||
|
strfit = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Need at least 2 chars, including the NUL terminator. */
|
||||||
|
if (plen + 2 >= psize) {
|
||||||
|
path = erealloc3(path, 2, psize);
|
||||||
|
psize *= 2;
|
||||||
|
dst = path + plen;
|
||||||
|
}
|
||||||
|
*dst++ = *src;
|
||||||
|
}
|
||||||
|
*dst = '\0';
|
||||||
|
|
||||||
|
if (strfit) {
|
||||||
|
time_t now;
|
||||||
|
struct tm *timeptr;
|
||||||
|
char *buf = NULL;
|
||||||
|
|
||||||
|
time(&now);
|
||||||
|
timeptr = localtime(&now);
|
||||||
|
|
||||||
|
#ifdef HAVE_SETLOCALE
|
||||||
|
if (!setlocale(LC_ALL, def_sudoers_locale)) {
|
||||||
|
warningx("unable to set locale to \"%s\", using \"C\"",
|
||||||
|
def_sudoers_locale);
|
||||||
|
setlocale(LC_ALL, "C");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* Double the size of the buffer until it is big enough to expand. */
|
||||||
|
do {
|
||||||
|
psize * 2;
|
||||||
|
buf = erealloc(buf, psize);
|
||||||
|
buf[psize - 1] = '\0';
|
||||||
|
} while (!strftime(buf, psize, path, timeptr) || buf[psize - 1] != '\0');
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
efree(path);
|
||||||
|
path = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
@@ -32,7 +32,7 @@
|
|||||||
static void _warning(int, const char *, va_list);
|
static void _warning(int, const char *, va_list);
|
||||||
void plugin_cleanup(int);
|
void plugin_cleanup(int);
|
||||||
|
|
||||||
extern sigjmp_buf error_jmp;
|
sigjmp_buf error_jmp;
|
||||||
|
|
||||||
extern sudo_conv_t sudo_conv;
|
extern sudo_conv_t sudo_conv;
|
||||||
|
|
||||||
|
@@ -135,8 +135,8 @@ static struct sudo_nss_list *snl;
|
|||||||
int NewArgc;
|
int NewArgc;
|
||||||
char **NewArgv;
|
char **NewArgv;
|
||||||
|
|
||||||
/* error.c */
|
/* plugin_error.c */
|
||||||
sigjmp_buf error_jmp;
|
extern sigjmp_buf error_jmp;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sudoers_policy_open(unsigned int version, sudo_conv_t conversation,
|
sudoers_policy_open(unsigned int version, sudo_conv_t conversation,
|
||||||
@@ -500,9 +500,13 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ISSET(sudo_mode, (MODE_RUN | MODE_EDIT)) && (def_log_input || def_log_output)) {
|
if (ISSET(sudo_mode, (MODE_RUN | MODE_EDIT)) && (def_log_input || def_log_output)) {
|
||||||
io_nextid();
|
if (def_iolog_file) {
|
||||||
command_info[info_len++] = fmt_string("iolog_dir", def_iolog_dir);
|
if (strstr(def_iolog_file, "%{seq}") != NULL) /* XXX - inline? */
|
||||||
command_info[info_len++] = fmt_string("iolog_file", sudo_user.sessid);
|
io_nextid();
|
||||||
|
command_info[info_len++] = expand_iolog_path("iolog_file=", def_iolog_file);
|
||||||
|
}
|
||||||
|
if (def_iolog_dir)
|
||||||
|
command_info[info_len++] = expand_iolog_path("iolog_dir=", def_iolog_dir);
|
||||||
if (def_log_input) {
|
if (def_log_input) {
|
||||||
command_info[info_len++] = estrdup("iolog_stdin=true");
|
command_info[info_len++] = estrdup("iolog_stdin=true");
|
||||||
command_info[info_len++] = estrdup("iolog_ttyin=true");
|
command_info[info_len++] = estrdup("iolog_ttyin=true");
|
||||||
|
@@ -285,6 +285,9 @@ int get_boottime(struct timeval *);
|
|||||||
/* iolog.c */
|
/* iolog.c */
|
||||||
void io_nextid(void);
|
void io_nextid(void);
|
||||||
|
|
||||||
|
/* iolog_path.c */
|
||||||
|
char *expand_iolog_path(const char *prefix, const char *opath);
|
||||||
|
|
||||||
/* env.c */
|
/* env.c */
|
||||||
char **env_get(void);
|
char **env_get(void);
|
||||||
void env_init(char * const envp[]);
|
void env_init(char * const envp[]);
|
||||||
|
Reference in New Issue
Block a user