Replace '/' with '_' in paths using the user, group or host name.

This commit is contained in:
Todd C. Miller
2023-09-20 09:00:27 -06:00
parent 7363ad7b32
commit d9da92951a
5 changed files with 107 additions and 19 deletions

View File

@@ -2483,6 +2483,11 @@ will cause
\fBsudo\fR
to include the file
\fI/etc/sudoers.xerxes\fR.
Any path name separator characters
(\(oq/\(cq)
present in the host name will be replaced with an underbar
(\(oq_\(cq)
during expansion.
.PP
The
\fI@includedir\fR
@@ -4654,6 +4659,12 @@ To include a literal
character, the string
\(oq%%\(cq
should be used.
.sp
Any path name separator characters
(\(oq/\(cq)
present in the user, group or host name will be replaced with an underbar
(\(oq_\(cq)
during expansion.
.RE
.TP 18n
iolog_file

View File

@@ -2353,6 +2353,11 @@ will cause
.Nm sudo
to include the file
.Pa /etc/sudoers.xerxes .
Any path name separator characters
.Pq Ql /
present in the host name will be replaced with an underbar
.Pq Ql _
during expansion.
.Pp
The
.Em @includedir
@@ -4400,6 +4405,12 @@ To include a literal
character, the string
.Ql %%
should be used.
.Pp
Any path name separator characters
.Pq Ql /
present in the user, group or host name will be replaced with an underbar
.Pq Ql _
during expansion.
.It iolog_file
The path name, relative to
.Em iolog_dir ,

View File

@@ -33,6 +33,32 @@
#include "sudoers.h"
#include "sudo_iolog.h"
/*
* Like strlcpy(3) but replaces '/' with '_'.
*/
static size_t
strlcpy_no_slash(char *dst, const char *src, size_t size)
{
size_t len = 0;
char ch;
debug_decl(strlcpy_no_slash, SUDOERS_DEBUG_UTIL);
while ((ch = *src++) != '\0') {
if (size > 1) {
/* Replace '/' with '_' */
if (ch == '/')
ch = '_';
*dst++ = ch;
size--;
}
len++;
}
if (size > 0)
*dst = '\0';
debug_return_size_t(len);
}
static size_t
fill_seq(char *str, size_t strsize, void *v)
{
@@ -64,7 +90,7 @@ fill_user(char *str, size_t strsize, void *v)
{
struct sudoers_context *ctx = v;
debug_decl(fill_user, SUDOERS_DEBUG_UTIL);
debug_return_size_t(strlcpy(str, ctx->user.name, strsize));
debug_return_size_t(strlcpy_no_slash(str, ctx->user.name, strsize));
}
static size_t
@@ -76,7 +102,7 @@ fill_group(char *str, size_t strsize, void *v)
debug_decl(fill_group, SUDOERS_DEBUG_UTIL);
if ((grp = sudo_getgrgid(ctx->user.gid)) != NULL) {
len = strlcpy(str, grp->gr_name, strsize);
len = strlcpy_no_slash(str, grp->gr_name, strsize);
sudo_gr_delref(grp);
} else {
len = (size_t)snprintf(str, strsize, "#%u", (unsigned int)ctx->user.gid);
@@ -89,7 +115,7 @@ fill_runas_user(char *str, size_t strsize, void *v)
{
struct sudoers_context *ctx = v;
debug_decl(fill_runas_user, SUDOERS_DEBUG_UTIL);
debug_return_size_t(strlcpy(str, ctx->runas.pw->pw_name, strsize));
debug_return_size_t(strlcpy_no_slash(str, ctx->runas.pw->pw_name, strsize));
}
static size_t
@@ -101,10 +127,10 @@ fill_runas_group(char *str, size_t strsize, void *v)
debug_decl(fill_runas_group, SUDOERS_DEBUG_UTIL);
if (ctx->runas.gr != NULL) {
len = strlcpy(str, ctx->runas.gr->gr_name, strsize);
len = strlcpy_no_slash(str, ctx->runas.gr->gr_name, strsize);
} else {
if ((grp = sudo_getgrgid(ctx->runas.pw->pw_gid)) != NULL) {
len = strlcpy(str, grp->gr_name, strsize);
len = strlcpy_no_slash(str, grp->gr_name, strsize);
sudo_gr_delref(grp);
} else {
len = (size_t)snprintf(str, strsize, "#%u",
@@ -119,7 +145,7 @@ fill_hostname(char *str, size_t strsize, void *v)
{
struct sudoers_context *ctx = v;
debug_decl(fill_hostname, SUDOERS_DEBUG_UTIL);
debug_return_size_t(strlcpy(str, ctx->user.shost, strsize));
debug_return_size_t(strlcpy_no_slash(str, ctx->user.shost, strsize));
}
static size_t
@@ -127,7 +153,7 @@ fill_command(char *str, size_t strsize, void *v)
{
struct sudoers_context *ctx = v;
debug_decl(fill_command, SUDOERS_DEBUG_UTIL);
debug_return_size_t(strlcpy(str, ctx->user.cmnd_base, strsize));
debug_return_size_t(strlcpy_no_slash(str, ctx->user.cmnd_base, strsize));
}
/* Note: "seq" must be first in the list. */

View File

@@ -5938,8 +5938,8 @@ expand_include(const char *src, const char *host)
{
const char *path = sudoers_search_path ? sudoers_search_path : sudoers;
const char *path_end = path + strlen(path);
char *dst, *dst0 = NULL, *dynamic_host = NULL;
const char *cp, *ep;
char *dst0, *dst;
size_t dst_size, src_len;
size_t nhost = 0;
debug_decl(expand_include, SUDOERS_DEBUG_PARSER);
@@ -5965,18 +5965,35 @@ expand_include(const char *src, const char *host)
cp++;
}
/* Check for a path separator in the host name, replace with '_'. */
if (nhost != 0 && strchr(host, '/') != NULL) {
dynamic_host = malloc(strlen(host) + 1);
if (dynamic_host == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
goto bad;
}
for (dst = dynamic_host; *host != '\0'; host++) {
if (*host == '/') {
*dst++ = '_';
continue;
}
*dst++ = *host;
}
*dst = '\0';
host = dynamic_host;
}
if (*src == '/') {
/* Fully-qualified path, make a copy and expand %h escapes. */
dst_size = src_len + (nhost * strlen(host)) - (nhost * 2) + 1;
dst0 = sudo_rcstr_alloc(dst_size - 1);
if (dst0 == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
sudoerserror(NULL);
debug_return_str(NULL);
goto bad;
}
if (strlcpy_expand_host(dst0, src, host, dst_size) >= dst_size)
goto oflow;
debug_return_str(dst0);
goto done;
}
/*
@@ -5999,8 +6016,7 @@ expand_include(const char *src, const char *host)
dst = dst0 = sudo_rcstr_alloc(dst_size - 1);
if (dst0 == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
sudoerserror(NULL);
debug_return_str(NULL);
goto bad;
}
for (cp = sudo_strsplit(path, path_end, ":", &ep); cp != NULL;
cp = sudo_strsplit(NULL, path_end, ":", &ep)) {
@@ -6032,10 +6048,14 @@ expand_include(const char *src, const char *host)
}
*dst = '\0';
done:
free(dynamic_host);
debug_return_str(dst0);
oflow:
sudo_warnx(U_("internal error, %s overflow"), __func__);
bad:
sudoerserror(NULL);
free(dynamic_host);
free(dst0);
debug_return_str(NULL);
}

View File

@@ -1159,8 +1159,8 @@ expand_include(const char *src, const char *host)
{
const char *path = sudoers_search_path ? sudoers_search_path : sudoers;
const char *path_end = path + strlen(path);
char *dst, *dst0 = NULL, *dynamic_host = NULL;
const char *cp, *ep;
char *dst0, *dst;
size_t dst_size, src_len;
size_t nhost = 0;
debug_decl(expand_include, SUDOERS_DEBUG_PARSER);
@@ -1186,18 +1186,35 @@ expand_include(const char *src, const char *host)
cp++;
}
/* Check for a path separator in the host name, replace with '_'. */
if (nhost != 0 && strchr(host, '/') != NULL) {
dynamic_host = malloc(strlen(host) + 1);
if (dynamic_host == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
goto bad;
}
for (dst = dynamic_host; *host != '\0'; host++) {
if (*host == '/') {
*dst++ = '_';
continue;
}
*dst++ = *host;
}
*dst = '\0';
host = dynamic_host;
}
if (*src == '/') {
/* Fully-qualified path, make a copy and expand %h escapes. */
dst_size = src_len + (nhost * strlen(host)) - (nhost * 2) + 1;
dst0 = sudo_rcstr_alloc(dst_size - 1);
if (dst0 == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
sudoerserror(NULL);
debug_return_str(NULL);
goto bad;
}
if (strlcpy_expand_host(dst0, src, host, dst_size) >= dst_size)
goto oflow;
debug_return_str(dst0);
goto done;
}
/*
@@ -1220,8 +1237,7 @@ expand_include(const char *src, const char *host)
dst = dst0 = sudo_rcstr_alloc(dst_size - 1);
if (dst0 == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
sudoerserror(NULL);
debug_return_str(NULL);
goto bad;
}
for (cp = sudo_strsplit(path, path_end, ":", &ep); cp != NULL;
cp = sudo_strsplit(NULL, path_end, ":", &ep)) {
@@ -1253,10 +1269,14 @@ expand_include(const char *src, const char *host)
}
*dst = '\0';
done:
free(dynamic_host);
debug_return_str(dst0);
oflow:
sudo_warnx(U_("internal error, %s overflow"), __func__);
bad:
sudoerserror(NULL);
free(dynamic_host);
free(dst0);
debug_return_str(NULL);
}