Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 49 additions & 2 deletions lib/iolog/iolog_path.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,39 @@
#include <sudo_iolog.h>
#include <sudo_util.h>

/*
* Double any '%' characters in the first len bytes of str so they
* are not interpreted as escapes when the path is expanded further.
* Returns the new length or (size_t)-1 if it would not fit in size.
*/
static size_t
escape_percent(char *str, size_t len, size_t size)
{
size_t i, n, nesc = 0;
debug_decl(escape_percent, SUDO_DEBUG_UTIL);

for (i = 0; i < len; i++) {
if (str[i] == '%')
nesc++;
}
if (nesc == 0)
debug_return_size_t(len);
if (len + nesc >= size)
debug_return_size_t((size_t)-1);

/* Shift right from the end, duplicating each '%'. */
for (i = len, n = nesc; n > 0; ) {
if (i-- == 0)
debug_return_size_t((size_t)-1);
str[i + n] = str[i];
if (str[i] == '%') {
n--;
str[i + n] = '%';
}
}
debug_return_size_t(len + nesc);
}

/*
* Expand any escape sequences in inpath, returning the expanded path.
*/
Expand Down Expand Up @@ -72,14 +105,20 @@ expand_iolog_path(const char *inpath, char *path, size_t pathlen,
closure);
if (len >= (size_t)(pathend - dst))
goto bad;
/* The value may contain '%', treat it as a literal. */
len = escape_percent(dst, len, (size_t)(pathend - dst));
if (len == (size_t)-1)
goto bad;
dst += len;
src = endbrace;
continue;
}
}
} else if (src[1] == '%') {
/* Collapse %% -> % */
src++;
/* Copy %% as-is, it is collapsed after expansion. */
if (dst + 1 >= pathend)
goto bad;
*dst++ = *src++;
} else {
/* May need strftime() */
strfit = true;
Expand Down Expand Up @@ -117,6 +156,14 @@ expand_iolog_path(const char *inpath, char *path, size_t pathlen,
memcpy(path, tmpbuf, len);
dst = path + len;
*dst = '\0';
} else {
/* No strftime() needed, collapse %% -> % ourselves. */
for (src = dst = path; *src != '\0'; src++) {
if (src[0] == '%' && src[1] == '%')
src++;
*dst++ = *src;
}
*dst = '\0';
}

debug_return_bool(true);
Expand Down
36 changes: 36 additions & 0 deletions lib/iolog/regress/iolog_path/data
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,39 @@ su

nobody/root/su

000001
%D
nogroup
root
wheel
somehost
x%Hy
/var/log/sudo-io/%{user}/%Y
%{command}_%Y%m%d
/var/log/sudo-io/%%D/%Y
x%%Hy_%Y%m%d

000001
nobody
nogroup
root
wheel
somehost
su
/var/log/sudo-io/%%Y_%Y
%{seq}
/var/log/sudo-io/%%Y_%Y
00/00/01

000001
50%
nogroup
root
wheel
somehost
su
/var/log/sudo-io/%{user}
%{seq}
/var/log/sudo-io/50%%
00/00/01

Loading