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:
Todd C. Miller
2012-06-15 12:33:12 -04:00
parent 85c6078659
commit 203abd98b9
4 changed files with 71 additions and 34 deletions

View File

@@ -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]);

View File

@@ -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:

View File

@@ -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));
} }

View File

@@ -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,