Use the expanded io log dir when updating the sequence number.
Includes a workaround for older versions of sudo where the sequence number was stored in the unexpanded io log dir.
This commit is contained in:
@@ -135,7 +135,7 @@ mkdir_parents(char *path)
|
|||||||
* Uses file locking to avoid sequence number collisions.
|
* Uses file locking to avoid sequence number collisions.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
io_nextid(char *iolog_dir, char sessid[7])
|
io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
|
||||||
{
|
{
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
char buf[32], *ep;
|
char buf[32], *ep;
|
||||||
@@ -172,14 +172,41 @@ io_nextid(char *iolog_dir, char sessid[7])
|
|||||||
log_fatal(USE_ERRNO, _("unable to open %s"), pathbuf);
|
log_fatal(USE_ERRNO, _("unable to open %s"), pathbuf);
|
||||||
lock_file(fd, SUDO_LOCK);
|
lock_file(fd, SUDO_LOCK);
|
||||||
|
|
||||||
/* Read seq number (base 36). */
|
/*
|
||||||
nread = read(fd, buf, sizeof(buf));
|
* If there is no seq file in iolog_dir and a fallback dir was
|
||||||
if (nread != 0) {
|
* specified, look for seq in the fallback dir. This is to work
|
||||||
if (nread == -1)
|
* around a bug in sudo 1.8.5 and older where iolog_dir was not
|
||||||
log_fatal(USE_ERRNO, _("unable to read %s"), pathbuf);
|
* expanded before the sequence number was updated.
|
||||||
id = strtoul(buf, &ep, 36);
|
*/
|
||||||
if (buf == ep || id >= SESSID_MAX)
|
if (iolog_dir_fallback != NULL && fstat(fd, &sb) == 0 && sb.st_size == 0) {
|
||||||
log_fatal(0, _("invalid sequence number %s"), pathbuf);
|
char fallback[PATH_MAX];
|
||||||
|
|
||||||
|
len = snprintf(fallback, sizeof(fallback), "%s/seq",
|
||||||
|
iolog_dir_fallback);
|
||||||
|
if (len > 0 && len < sizeof(fallback)) {
|
||||||
|
int fd2 = open(fallback, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
|
||||||
|
if (fd2 != -1) {
|
||||||
|
nread = read(fd2, buf, sizeof(buf));
|
||||||
|
if (nread > 0) {
|
||||||
|
id = strtoul(buf, &ep, 36);
|
||||||
|
if (buf == ep || id >= SESSID_MAX)
|
||||||
|
id = 0;
|
||||||
|
}
|
||||||
|
close(fd2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read current seq number (base 36). */
|
||||||
|
if (id == 0) {
|
||||||
|
nread = read(fd, buf, sizeof(buf));
|
||||||
|
if (nread != 0) {
|
||||||
|
if (nread == -1)
|
||||||
|
log_fatal(USE_ERRNO, _("unable to read %s"), pathbuf);
|
||||||
|
id = strtoul(buf, &ep, 36);
|
||||||
|
if (buf == ep || id >= SESSID_MAX)
|
||||||
|
log_fatal(0, _("invalid sequence number %s"), pathbuf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
id++;
|
id++;
|
||||||
|
|
||||||
@@ -476,7 +503,7 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation,
|
|||||||
/* Get next session ID and convert it into a path. */
|
/* Get next session ID and convert it into a path. */
|
||||||
tofree = emalloc(sizeof(_PATH_SUDO_IO_LOGDIR) + sizeof(sessid) + 2);
|
tofree = emalloc(sizeof(_PATH_SUDO_IO_LOGDIR) + sizeof(sessid) + 2);
|
||||||
memcpy(tofree, _PATH_SUDO_IO_LOGDIR, sizeof(_PATH_SUDO_IO_LOGDIR));
|
memcpy(tofree, _PATH_SUDO_IO_LOGDIR, sizeof(_PATH_SUDO_IO_LOGDIR));
|
||||||
io_nextid(tofree, sessid);
|
io_nextid(tofree, NULL, sessid);
|
||||||
snprintf(tofree + sizeof(_PATH_SUDO_IO_LOGDIR), sizeof(sessid) + 2,
|
snprintf(tofree + sizeof(_PATH_SUDO_IO_LOGDIR), sizeof(sessid) + 2,
|
||||||
"%c%c/%c%c/%c%c", sessid[0], sessid[1], sessid[2], sessid[3],
|
"%c%c/%c%c/%c%c", sessid[0], sessid[1], sessid[2], sessid[3],
|
||||||
sessid[4], sessid[5]);
|
sessid[4], sessid[5]);
|
||||||
|
@@ -46,18 +46,19 @@
|
|||||||
|
|
||||||
struct path_escape {
|
struct path_escape {
|
||||||
const char *name;
|
const char *name;
|
||||||
size_t (*copy_fn)(char *, size_t);
|
size_t (*copy_fn)(char *, size_t, char *);
|
||||||
};
|
};
|
||||||
|
|
||||||
static size_t fill_seq(char *, size_t);
|
static size_t fill_seq(char *, size_t, char *);
|
||||||
static size_t fill_user(char *, size_t);
|
static size_t fill_user(char *, size_t, char *);
|
||||||
static size_t fill_group(char *, size_t);
|
static size_t fill_group(char *, size_t, char *);
|
||||||
static size_t fill_runas_user(char *, size_t);
|
static size_t fill_runas_user(char *, size_t, char *);
|
||||||
static size_t fill_runas_group(char *, size_t);
|
static size_t fill_runas_group(char *, size_t, char *);
|
||||||
static size_t fill_hostname(char *, size_t);
|
static size_t fill_hostname(char *, size_t, char *);
|
||||||
static size_t fill_command(char *, size_t);
|
static size_t fill_command(char *, size_t, char *);
|
||||||
|
|
||||||
static struct path_escape escapes[] = {
|
/* Note: "seq" must be first in the list. */
|
||||||
|
static struct path_escape io_path_escapes[] = {
|
||||||
{ "seq", fill_seq },
|
{ "seq", fill_seq },
|
||||||
{ "user", fill_user },
|
{ "user", fill_user },
|
||||||
{ "group", fill_group },
|
{ "group", fill_group },
|
||||||
@@ -69,14 +70,14 @@ static struct path_escape escapes[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
fill_seq(char *str, size_t strsize)
|
fill_seq(char *str, size_t strsize, char *logdir)
|
||||||
{
|
{
|
||||||
static char sessid[7];
|
static char sessid[7];
|
||||||
int len;
|
int len;
|
||||||
debug_decl(sudoers_io_version, SUDO_DEBUG_UTIL)
|
debug_decl(sudoers_io_version, SUDO_DEBUG_UTIL)
|
||||||
|
|
||||||
if (sessid[0] == '\0')
|
if (sessid[0] == '\0')
|
||||||
io_nextid(def_iolog_dir, sessid);
|
io_nextid(logdir, def_iolog_dir, sessid);
|
||||||
|
|
||||||
/* Path is of the form /var/log/sudo-io/00/00/01. */
|
/* Path is of the form /var/log/sudo-io/00/00/01. */
|
||||||
len = snprintf(str, strsize, "%c%c/%c%c/%c%c", sessid[0],
|
len = snprintf(str, strsize, "%c%c/%c%c/%c%c", sessid[0],
|
||||||
@@ -87,14 +88,14 @@ fill_seq(char *str, size_t strsize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
fill_user(char *str, size_t strsize)
|
fill_user(char *str, size_t strsize, char *unused)
|
||||||
{
|
{
|
||||||
debug_decl(fill_user, SUDO_DEBUG_UTIL)
|
debug_decl(fill_user, SUDO_DEBUG_UTIL)
|
||||||
debug_return_size_t(strlcpy(str, user_name, strsize));
|
debug_return_size_t(strlcpy(str, user_name, strsize));
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
fill_group(char *str, size_t strsize)
|
fill_group(char *str, size_t strsize, char *unused)
|
||||||
{
|
{
|
||||||
struct group *grp;
|
struct group *grp;
|
||||||
size_t len;
|
size_t len;
|
||||||
@@ -112,14 +113,14 @@ fill_group(char *str, size_t strsize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
fill_runas_user(char *str, size_t strsize)
|
fill_runas_user(char *str, size_t strsize, char *unused)
|
||||||
{
|
{
|
||||||
debug_decl(fill_runas_user, SUDO_DEBUG_UTIL)
|
debug_decl(fill_runas_user, SUDO_DEBUG_UTIL)
|
||||||
debug_return_size_t(strlcpy(str, runas_pw->pw_name, strsize));
|
debug_return_size_t(strlcpy(str, runas_pw->pw_name, strsize));
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
fill_runas_group(char *str, size_t strsize)
|
fill_runas_group(char *str, size_t strsize, char *unused)
|
||||||
{
|
{
|
||||||
struct group *grp;
|
struct group *grp;
|
||||||
size_t len;
|
size_t len;
|
||||||
@@ -141,14 +142,14 @@ fill_runas_group(char *str, size_t strsize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
fill_hostname(char *str, size_t strsize)
|
fill_hostname(char *str, size_t strsize, char *unused)
|
||||||
{
|
{
|
||||||
debug_decl(fill_hostname, SUDO_DEBUG_UTIL)
|
debug_decl(fill_hostname, SUDO_DEBUG_UTIL)
|
||||||
debug_return_size_t(strlcpy(str, user_shost, strsize));
|
debug_return_size_t(strlcpy(str, user_shost, strsize));
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
fill_command(char *str, size_t strsize)
|
fill_command(char *str, size_t strsize, char *unused)
|
||||||
{
|
{
|
||||||
debug_decl(fill_command, SUDO_DEBUG_UTIL)
|
debug_decl(fill_command, SUDO_DEBUG_UTIL)
|
||||||
debug_return_size_t(strlcpy(str, user_base, strsize));
|
debug_return_size_t(strlcpy(str, user_base, strsize));
|
||||||
@@ -165,7 +166,9 @@ expand_iolog_path(const char *prefix, const char *dir, const char *file,
|
|||||||
{
|
{
|
||||||
size_t len, prelen = 0;
|
size_t len, prelen = 0;
|
||||||
char *dst, *dst0, *path, *pathend, tmpbuf[PATH_MAX];
|
char *dst, *dst0, *path, *pathend, tmpbuf[PATH_MAX];
|
||||||
|
char *slash = NULL;
|
||||||
const char *endbrace, *src = dir;
|
const char *endbrace, *src = dir;
|
||||||
|
static struct path_escape *escapes;
|
||||||
int pass;
|
int pass;
|
||||||
bool strfit;
|
bool strfit;
|
||||||
debug_decl(expand_iolog_path, SUDO_DEBUG_UTIL)
|
debug_decl(expand_iolog_path, SUDO_DEBUG_UTIL)
|
||||||
@@ -193,17 +196,20 @@ expand_iolog_path(const char *prefix, const char *dir, const char *file,
|
|||||||
switch (pass) {
|
switch (pass) {
|
||||||
case 0:
|
case 0:
|
||||||
src = dir;
|
src = dir;
|
||||||
|
escapes = io_path_escapes + 1; /* skip "${seq}" */
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
/* Trim trailing slashes from dir component. */
|
/* Trim trailing slashes from dir component. */
|
||||||
while (dst - path - 1 > prelen && dst[-1] == '/')
|
while (dst - path - 1 > prelen && dst[-1] == '/')
|
||||||
dst--;
|
dst--;
|
||||||
if (slashp)
|
/* The NUL will be replaced with a '/' at the end. */
|
||||||
*slashp = dst;
|
if (dst + 1 >= pathend)
|
||||||
src = "/";
|
goto bad;
|
||||||
break;
|
slash = dst++;
|
||||||
|
continue;
|
||||||
case 2:
|
case 2:
|
||||||
src = file;
|
src = file;
|
||||||
|
escapes = io_path_escapes;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dst0 = dst;
|
dst0 = dst;
|
||||||
@@ -220,7 +226,8 @@ expand_iolog_path(const char *prefix, const char *dir, const char *file,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (esc->name != NULL) {
|
if (esc->name != NULL) {
|
||||||
len = esc->copy_fn(dst, (size_t)(pathend - dst));
|
len = esc->copy_fn(dst, (size_t)(pathend - dst),
|
||||||
|
path + prelen);
|
||||||
if (len >= (size_t)(pathend - dst))
|
if (len >= (size_t)(pathend - dst))
|
||||||
goto bad;
|
goto bad;
|
||||||
dst += len;
|
dst += len;
|
||||||
@@ -275,6 +282,9 @@ expand_iolog_path(const char *prefix, const char *dir, const char *file,
|
|||||||
*dst = '\0';
|
*dst = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (slashp)
|
||||||
|
*slashp = slash;
|
||||||
|
*slash = '/';
|
||||||
|
|
||||||
debug_return_str(path);
|
debug_return_str(path);
|
||||||
bad:
|
bad:
|
||||||
|
@@ -200,7 +200,7 @@ main(int argc, char *argv[])
|
|||||||
exit(errors);
|
exit(errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
void io_nextid(char *iolog_dir, char id[7])
|
void io_nextid(char *iolog_dir, char *fallback, char id[7])
|
||||||
{
|
{
|
||||||
memcpy(id, sessid, sizeof(sessid));
|
memcpy(id, sessid, sizeof(sessid));
|
||||||
}
|
}
|
||||||
|
@@ -296,7 +296,7 @@ int atobool(const char *str);
|
|||||||
int get_boottime(struct timeval *);
|
int get_boottime(struct timeval *);
|
||||||
|
|
||||||
/* iolog.c */
|
/* iolog.c */
|
||||||
void io_nextid(char *iolog_dir, char sessid[7]);
|
void io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7]);
|
||||||
|
|
||||||
/* 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,
|
||||||
|
Reference in New Issue
Block a user