Add helper function to compile a regex that supports (?i).
This commit is contained in:
1
MANIFEST
1
MANIFEST
@@ -245,6 +245,7 @@ lib/util/progname.c
|
|||||||
lib/util/pw_dup.c
|
lib/util/pw_dup.c
|
||||||
lib/util/pwrite.c
|
lib/util/pwrite.c
|
||||||
lib/util/rcstr.c
|
lib/util/rcstr.c
|
||||||
|
lib/util/regex.c
|
||||||
lib/util/reallocarray.c
|
lib/util/reallocarray.c
|
||||||
lib/util/regress/corpus/seed/sudo_conf/sudo.conf.1
|
lib/util/regress/corpus/seed/sudo_conf/sudo.conf.1
|
||||||
lib/util/regress/corpus/seed/sudo_conf/sudo.conf.2
|
lib/util/regress/corpus/seed/sudo_conf/sudo.conf.2
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
.\"
|
.\"
|
||||||
.TH "SUDO_LOGSRVD.CONF" "@mansectform@" "February 10, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
|
.TH "SUDO_LOGSRVD.CONF" "@mansectform@" "February 11, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
|
||||||
.nh
|
.nh
|
||||||
.if n .ad l
|
.if n .ad l
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
@@ -641,6 +641,9 @@ One or more POSIX extended regular expressions used to
|
|||||||
match password prompts in the terminal output when
|
match password prompts in the terminal output when
|
||||||
\fIlog_passwords\fR
|
\fIlog_passwords\fR
|
||||||
is disabled.
|
is disabled.
|
||||||
|
As an extension, if the regular expression begins with
|
||||||
|
\(lq(?i)\(rq,
|
||||||
|
it will be matched in a case-insensitive manner.
|
||||||
Multiple
|
Multiple
|
||||||
\fIpassprompt_regex\fR
|
\fIpassprompt_regex\fR
|
||||||
settings may be specified.
|
settings may be specified.
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
.\"
|
.\"
|
||||||
.Dd February 10, 2022
|
.Dd February 11, 2022
|
||||||
.Dt SUDO_LOGSRVD.CONF @mansectform@
|
.Dt SUDO_LOGSRVD.CONF @mansectform@
|
||||||
.Os Sudo @PACKAGE_VERSION@
|
.Os Sudo @PACKAGE_VERSION@
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -571,6 +571,9 @@ One or more POSIX extended regular expressions used to
|
|||||||
match password prompts in the terminal output when
|
match password prompts in the terminal output when
|
||||||
.Em log_passwords
|
.Em log_passwords
|
||||||
is disabled.
|
is disabled.
|
||||||
|
As an extension, if the regular expression begins with
|
||||||
|
.Dq (?i) ,
|
||||||
|
it will be matched in a case-insensitive manner.
|
||||||
Multiple
|
Multiple
|
||||||
.Em passprompt_regex
|
.Em passprompt_regex
|
||||||
settings may be specified.
|
settings may be specified.
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
.nr BA @BAMAN@
|
.nr BA @BAMAN@
|
||||||
.nr LC @LCMAN@
|
.nr LC @LCMAN@
|
||||||
.nr PS @PSMAN@
|
.nr PS @PSMAN@
|
||||||
.TH "SUDOERS" "@mansectform@" "February 10, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
|
.TH "SUDOERS" "@mansectform@" "February 11, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
|
||||||
.nh
|
.nh
|
||||||
.if n .ad l
|
.if n .ad l
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
@@ -5424,6 +5424,9 @@ This setting is only supported by version 1.9.0 or higher.
|
|||||||
passprompt_regex
|
passprompt_regex
|
||||||
A list of POSIX extended regular expressions used to
|
A list of POSIX extended regular expressions used to
|
||||||
match password prompts in the terminal output.
|
match password prompts in the terminal output.
|
||||||
|
As an extension, if the regular expression begins with
|
||||||
|
\(lq(?i)\(rq,
|
||||||
|
it will be matched in a case-insensitive manner.
|
||||||
This option is only used when
|
This option is only used when
|
||||||
\fIlog_passwords\fR
|
\fIlog_passwords\fR
|
||||||
has been disabled.
|
has been disabled.
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
.nr BA @BAMAN@
|
.nr BA @BAMAN@
|
||||||
.nr LC @LCMAN@
|
.nr LC @LCMAN@
|
||||||
.nr PS @PSMAN@
|
.nr PS @PSMAN@
|
||||||
.Dd February 10, 2022
|
.Dd February 11, 2022
|
||||||
.Dt SUDOERS @mansectform@
|
.Dt SUDOERS @mansectform@
|
||||||
.Os Sudo @PACKAGE_VERSION@
|
.Os Sudo @PACKAGE_VERSION@
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -5062,6 +5062,9 @@ This setting is only supported by version 1.9.0 or higher.
|
|||||||
.It passprompt_regex
|
.It passprompt_regex
|
||||||
A list of POSIX extended regular expressions used to
|
A list of POSIX extended regular expressions used to
|
||||||
match password prompts in the terminal output.
|
match password prompts in the terminal output.
|
||||||
|
As an extension, if the regular expression begins with
|
||||||
|
.Dq (?i) ,
|
||||||
|
it will be matched in a case-insensitive manner.
|
||||||
This option is only used when
|
This option is only used when
|
||||||
.Em log_passwords
|
.Em log_passwords
|
||||||
has been disabled.
|
has been disabled.
|
||||||
|
@@ -256,6 +256,10 @@ sudo_dso_public char *sudo_rcstr_alloc(size_t len);
|
|||||||
sudo_dso_public char *sudo_rcstr_addref(const char *s);
|
sudo_dso_public char *sudo_rcstr_addref(const char *s);
|
||||||
sudo_dso_public void sudo_rcstr_delref(const char *s);
|
sudo_dso_public void sudo_rcstr_delref(const char *s);
|
||||||
|
|
||||||
|
/* regex.c */
|
||||||
|
sudo_dso_public bool sudo_regex_compile_v1(void *v, const char *pattern, const char **errstr);
|
||||||
|
#define sudo_regex_compile(_a, _b, _c) sudo_regex_compile_v1((_a), (_b), (_c))
|
||||||
|
|
||||||
/* roundup.c */
|
/* roundup.c */
|
||||||
sudo_dso_public unsigned int sudo_pow2_roundup_v1(unsigned int len);
|
sudo_dso_public unsigned int sudo_pow2_roundup_v1(unsigned int len);
|
||||||
#define sudo_pow2_roundup(_a) sudo_pow2_roundup_v1((_a))
|
#define sudo_pow2_roundup(_a) sudo_pow2_roundup_v1((_a))
|
||||||
|
@@ -41,6 +41,7 @@
|
|||||||
#include "sudo_gettext.h"
|
#include "sudo_gettext.h"
|
||||||
#include "sudo_iolog.h"
|
#include "sudo_iolog.h"
|
||||||
#include "sudo_queue.h"
|
#include "sudo_queue.h"
|
||||||
|
#include "sudo_util.h"
|
||||||
|
|
||||||
struct pwfilt_regex {
|
struct pwfilt_regex {
|
||||||
TAILQ_ENTRY(pwfilt_regex) entries;
|
TAILQ_ENTRY(pwfilt_regex) entries;
|
||||||
@@ -110,51 +111,6 @@ iolog_pwfilt_free(void *vhandle)
|
|||||||
debug_return;
|
debug_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Like strdup but collapses repeated '?', '*' and '+' ops in a regex.
|
|
||||||
* Glibc regcomp() has a bug where it uses excessive memory for repeated
|
|
||||||
* '+' ops. Collapse them to avoid running the fuzzer out of memory.
|
|
||||||
*/
|
|
||||||
static char *
|
|
||||||
dup_pattern(const char *src)
|
|
||||||
{
|
|
||||||
char *dst, *ret;
|
|
||||||
char ch, prev = '\0';
|
|
||||||
size_t len;
|
|
||||||
debug_decl(dup_pattern, SUDO_DEBUG_UTIL);
|
|
||||||
|
|
||||||
len = strlen(src);
|
|
||||||
ret = malloc(len + 1);
|
|
||||||
if (ret == NULL)
|
|
||||||
debug_return_ptr(NULL);
|
|
||||||
|
|
||||||
dst = ret;
|
|
||||||
while ((ch = *src++) != '\0') {
|
|
||||||
switch (ch) {
|
|
||||||
case '\\':
|
|
||||||
if (*src != '\0') {
|
|
||||||
*dst++ = '\\';
|
|
||||||
*dst++ = *src++;
|
|
||||||
prev = '\0';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '?':
|
|
||||||
case '*':
|
|
||||||
case '+':
|
|
||||||
if (ch == prev) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*dst++ = ch;
|
|
||||||
prev = ch;
|
|
||||||
}
|
|
||||||
*dst = '\0';
|
|
||||||
|
|
||||||
debug_return_ptr(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a pattern to the password filter list.
|
* Add a pattern to the password filter list.
|
||||||
*/
|
*/
|
||||||
@@ -163,22 +119,19 @@ iolog_pwfilt_add(void *vhandle, const char *pattern)
|
|||||||
{
|
{
|
||||||
struct pwfilt_handle *handle = vhandle;
|
struct pwfilt_handle *handle = vhandle;
|
||||||
struct pwfilt_regex *filt;
|
struct pwfilt_regex *filt;
|
||||||
char errbuf[1024];
|
const char *errstr;
|
||||||
int errcode;
|
|
||||||
debug_decl(iolog_pwfilt_add, SUDO_DEBUG_UTIL);
|
debug_decl(iolog_pwfilt_add, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
filt = malloc(sizeof(*filt));
|
filt = malloc(sizeof(*filt));
|
||||||
if (filt == NULL)
|
if (filt == NULL)
|
||||||
goto oom;
|
goto oom;
|
||||||
filt->pattern = dup_pattern(pattern);
|
filt->pattern = strdup(pattern);
|
||||||
if (filt->pattern == NULL)
|
if (filt->pattern == NULL)
|
||||||
goto oom;
|
goto oom;
|
||||||
|
|
||||||
errcode = regcomp(&filt->regex, filt->pattern, REG_EXTENDED|REG_NOSUB);
|
if (!sudo_regex_compile(&filt->regex, filt->pattern, &errstr)) {
|
||||||
if (errcode != 0) {
|
|
||||||
regerror(errcode, &filt->regex, errbuf, sizeof(errbuf));
|
|
||||||
sudo_warnx(U_("invalid regular expression \"%s\": %s"),
|
sudo_warnx(U_("invalid regular expression \"%s\": %s"),
|
||||||
pattern, errbuf);
|
pattern, U_(errstr));
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# SPDX-License-Identifier: ISC
|
# SPDX-License-Identifier: ISC
|
||||||
#
|
#
|
||||||
# Copyright (c) 2011-2021 Todd C. Miller <Todd.Miller@sudo.ws>
|
# Copyright (c) 2011-2022 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and distribute this software for any
|
# Permission to use, copy, modify, and distribute this software for any
|
||||||
# purpose with or without fee is hereby granted, provided that the above
|
# purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -140,9 +140,9 @@ SHELL = @SHELL@
|
|||||||
|
|
||||||
LTOBJS = basename.lo @DIGEST@ event.lo fatal.lo key_val.lo gethostname.lo \
|
LTOBJS = basename.lo @DIGEST@ event.lo fatal.lo key_val.lo gethostname.lo \
|
||||||
gettime.lo getgrouplist.lo gidlist.lo json.lo lbuf.lo locking.lo \
|
gettime.lo getgrouplist.lo gidlist.lo json.lo lbuf.lo locking.lo \
|
||||||
logfac.lo logpri.lo mkdir_parents.lo parseln.lo progname.lo rcstr.lo \
|
logfac.lo logpri.lo mkdir_parents.lo parseln.lo progname.lo rcstr.lo \
|
||||||
roundup.lo secure_path.lo setgroups.lo strsplit.lo strtobool.lo \
|
regex.lo roundup.lo secure_path.lo setgroups.lo strsplit.lo \
|
||||||
strtoid.lo strtomode.lo strtonum.lo sudo_conf.lo \
|
strtobool.lo strtoid.lo strtomode.lo strtonum.lo sudo_conf.lo \
|
||||||
sudo_debug.lo sudo_dso.lo term.lo ttyname_dev.lo \
|
sudo_debug.lo sudo_dso.lo term.lo ttyname_dev.lo \
|
||||||
ttysize.lo uuid.lo @COMMON_OBJS@ @LTLIBOBJS@
|
ttysize.lo uuid.lo @COMMON_OBJS@ @LTLIBOBJS@
|
||||||
|
|
||||||
@@ -1212,6 +1212,16 @@ reallocarray.i: $(srcdir)/reallocarray.c $(incdir)/sudo_compat.h \
|
|||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
reallocarray.plog: reallocarray.i
|
reallocarray.plog: reallocarray.i
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/reallocarray.c --i-file $< --output-file $@
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/reallocarray.c --i-file $< --output-file $@
|
||||||
|
regex.lo: $(srcdir)/regex.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
||||||
|
$(incdir)/sudo_debug.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/regex.c
|
||||||
|
regex.i: $(srcdir)/regex.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
||||||
|
$(incdir)/sudo_debug.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
regex.plog: regex.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regex.c --i-file $< --output-file $@
|
||||||
roundup.lo: $(srcdir)/roundup.c $(incdir)/compat/stdbool.h \
|
roundup.lo: $(srcdir)/roundup.c $(incdir)/compat/stdbool.h \
|
||||||
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
|
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
|
||||||
|
131
lib/util/regex.c
Normal file
131
lib/util/regex.c
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <regex.h>
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_util.h"
|
||||||
|
#include "sudo_gettext.h"
|
||||||
|
|
||||||
|
static char errbuf[1024];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like strdup but collapses repeated '?', '*' and '+' ops in a regex.
|
||||||
|
* Glibc regcomp() has a bug where it uses excessive memory for repeated
|
||||||
|
* '+' ops. Collapse them to avoid running the fuzzer out of memory.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
dup_pattern(const char *src)
|
||||||
|
{
|
||||||
|
char *dst, *ret;
|
||||||
|
char ch, prev = '\0';
|
||||||
|
size_t len;
|
||||||
|
debug_decl(dup_pattern, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
len = strlen(src);
|
||||||
|
ret = malloc(len + 1);
|
||||||
|
if (ret == NULL)
|
||||||
|
debug_return_ptr(NULL);
|
||||||
|
|
||||||
|
dst = ret;
|
||||||
|
while ((ch = *src++) != '\0') {
|
||||||
|
switch (ch) {
|
||||||
|
case '\\':
|
||||||
|
if (*src != '\0') {
|
||||||
|
*dst++ = '\\';
|
||||||
|
*dst++ = *src++;
|
||||||
|
prev = '\0';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
case '*':
|
||||||
|
case '+':
|
||||||
|
if (ch == prev) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*dst++ = ch;
|
||||||
|
prev = ch;
|
||||||
|
}
|
||||||
|
*dst = '\0';
|
||||||
|
|
||||||
|
debug_return_ptr(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrapper around regcomp() that handles a regex starting with (?i).
|
||||||
|
* Avoid using regex_t in the function args so we don't need to
|
||||||
|
* include regex.h everywhere.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
sudo_regex_compile_v1(void *v, const char *pattern, const char **errstr)
|
||||||
|
{
|
||||||
|
int errcode, cflags = REG_EXTENDED|REG_NOSUB;
|
||||||
|
regex_t *preg;
|
||||||
|
char *copy = NULL;
|
||||||
|
const char *cp;
|
||||||
|
regex_t rebuf;
|
||||||
|
debug_decl(regex_compile, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
/* Some callers just want to check the validity of the pattern. */
|
||||||
|
preg = v ? v : &rebuf;
|
||||||
|
|
||||||
|
/* Check for (?i) to enable case-insensitive matching. */
|
||||||
|
cp = pattern[0] == '^' ? pattern + 1 : pattern;
|
||||||
|
if (strncmp(cp, "(?i)", 4) == 0) {
|
||||||
|
cflags |= REG_ICASE;
|
||||||
|
copy = dup_pattern(pattern + 4);
|
||||||
|
if (copy == NULL) {
|
||||||
|
*errstr = N_("unable to allocate memory");
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
if (pattern[0] == '^')
|
||||||
|
copy[0] = '^';
|
||||||
|
} else {
|
||||||
|
copy = dup_pattern(pattern);
|
||||||
|
if (copy == NULL) {
|
||||||
|
*errstr = N_("unable to allocate memory");
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errcode = regcomp(preg, copy, cflags);
|
||||||
|
if (errcode == 0) {
|
||||||
|
if (preg == &rebuf)
|
||||||
|
regfree(&rebuf);
|
||||||
|
} else {
|
||||||
|
regerror(errcode, preg, errbuf, sizeof(errbuf));
|
||||||
|
*errstr = errbuf;
|
||||||
|
}
|
||||||
|
free(copy);
|
||||||
|
|
||||||
|
debug_return_bool(errcode == 0);
|
||||||
|
}
|
@@ -119,6 +119,7 @@ sudo_rcstr_addref
|
|||||||
sudo_rcstr_alloc
|
sudo_rcstr_alloc
|
||||||
sudo_rcstr_delref
|
sudo_rcstr_delref
|
||||||
sudo_rcstr_dup
|
sudo_rcstr_dup
|
||||||
|
sudo_regex_compile_v1
|
||||||
sudo_secure_dir_v1
|
sudo_secure_dir_v1
|
||||||
sudo_secure_file_v1
|
sudo_secure_file_v1
|
||||||
sudo_setgroups_v1
|
sudo_setgroups_v1
|
||||||
|
@@ -36,7 +36,6 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <regex.h>
|
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
|
||||||
#include "sudoers.h"
|
#include "sudoers.h"
|
||||||
@@ -1287,22 +1286,17 @@ bool
|
|||||||
cb_passprompt_regex(const union sudo_defs_val *sd_un, int op)
|
cb_passprompt_regex(const union sudo_defs_val *sd_un, int op)
|
||||||
{
|
{
|
||||||
struct list_member *lm;
|
struct list_member *lm;
|
||||||
int errcode;
|
const char *errstr;
|
||||||
char errbuf[1024];
|
|
||||||
regex_t re;
|
|
||||||
debug_decl(cb_passprompt_regex, SUDOERS_DEBUG_DEFAULTS);
|
debug_decl(cb_passprompt_regex, SUDOERS_DEBUG_DEFAULTS);
|
||||||
|
|
||||||
/* If adding one or more regexps, validate them with regcomp(). */
|
/* If adding one or more regexps, make sure they are valid. */
|
||||||
if (op == '+' || op == true) {
|
if (op == '+' || op == true) {
|
||||||
SLIST_FOREACH(lm, &sd_un->list, entries) {
|
SLIST_FOREACH(lm, &sd_un->list, entries) {
|
||||||
errcode = regcomp(&re, lm->value, REG_EXTENDED|REG_NOSUB);
|
if (!sudo_regex_compile(NULL, lm->value, &errstr)) {
|
||||||
if (errcode != 0) {
|
|
||||||
regerror(errcode, &re, errbuf, sizeof(errbuf));
|
|
||||||
sudo_warnx(U_("invalid regular expression \"%s\": %s"),
|
sudo_warnx(U_("invalid regular expression \"%s\": %s"),
|
||||||
lm->value, errbuf);
|
lm->value, U_(errstr));
|
||||||
debug_return_bool(false);
|
debug_return_bool(false);
|
||||||
}
|
}
|
||||||
regfree(&re);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -60,36 +60,20 @@
|
|||||||
static bool
|
static bool
|
||||||
regex_matches(const char *pattern, const char *str)
|
regex_matches(const char *pattern, const char *str)
|
||||||
{
|
{
|
||||||
int errcode, cflags = REG_EXTENDED|REG_NOSUB;
|
const char *errstr;
|
||||||
char *copy = NULL;
|
int errcode;
|
||||||
regex_t re;
|
regex_t re;
|
||||||
debug_decl(regex_matches, SUDOERS_DEBUG_MATCH);
|
debug_decl(regex_matches, SUDOERS_DEBUG_MATCH);
|
||||||
|
|
||||||
/* Check for (?i) to enable case-insensitive matching. */
|
if (!sudo_regex_compile(&re, pattern, &errstr)) {
|
||||||
if (strncmp(pattern, "^(?i)", 5) == 0) {
|
|
||||||
cflags |= REG_ICASE;
|
|
||||||
copy = strdup(pattern + 4);
|
|
||||||
if (copy == NULL) {
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
copy[0] = '^';
|
|
||||||
pattern = copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
errcode = regcomp(&re, pattern, cflags);
|
|
||||||
if (errcode == 0) {
|
|
||||||
errcode = regexec(&re, str, 0, NULL, 0);
|
|
||||||
regfree(&re);
|
|
||||||
} else {
|
|
||||||
char errbuf[1024];
|
|
||||||
|
|
||||||
regerror(errcode, &re, errbuf, sizeof(errbuf));
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||||
"unable to compile regular expression \"%s\": %s",
|
"unable to compile regular expression \"%s\": %s",
|
||||||
pattern, errbuf);
|
pattern, errstr);
|
||||||
|
debug_return_bool(false);
|
||||||
}
|
}
|
||||||
free(copy);
|
|
||||||
|
errcode = regexec(&re, str, 0, NULL, 0);
|
||||||
|
regfree(&re);
|
||||||
|
|
||||||
debug_return_bool(errcode == 0);
|
debug_return_bool(errcode == 0);
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,6 @@
|
|||||||
|
# Test passprompt_regex
|
||||||
|
Defaults passprompt_regex="(?i)password: *"
|
||||||
|
|
||||||
# Test simple command with regex args
|
# Test simple command with regex args
|
||||||
user ALL = /bin/ls ^/etc/(hosts|motd|issue)$
|
user ALL = /bin/ls ^/etc/(hosts|motd|issue)$
|
||||||
|
|
||||||
|
@@ -1,4 +1,17 @@
|
|||||||
{
|
{
|
||||||
|
"Defaults": [
|
||||||
|
{
|
||||||
|
"Options": [
|
||||||
|
{
|
||||||
|
"operation": "list_assign",
|
||||||
|
"passprompt_regex": [
|
||||||
|
"(?i)password:",
|
||||||
|
"*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"User_Specs": [
|
"User_Specs": [
|
||||||
{
|
{
|
||||||
"User_List": [
|
"User_List": [
|
||||||
|
@@ -1,3 +1,10 @@
|
|||||||
|
dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws
|
||||||
|
objectClass: top
|
||||||
|
objectClass: sudoRole
|
||||||
|
cn: defaults
|
||||||
|
description: Default sudoOption's go here
|
||||||
|
sudoOption: passprompt_regex=(?i)password: *
|
||||||
|
|
||||||
dn: cn=user,ou=SUDOers,dc=sudo,dc=ws
|
dn: cn=user,ou=SUDOers,dc=sudo,dc=ws
|
||||||
objectClass: top
|
objectClass: top
|
||||||
objectClass: sudoRole
|
objectClass: sudoRole
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
Defaults passprompt_regex="(?i)password: *"
|
||||||
|
|
||||||
# sudoRole user, user_1, user_2, user_3, user_4, user_5, user_6, user_7,
|
# sudoRole user, user_1, user_2, user_3, user_4, user_5, user_6, user_7,
|
||||||
# user_8, user_9, user_10, user_11
|
# user_8, user_9, user_10, user_11
|
||||||
user ALL = /bin/ls ^/etc/(hosts|motd|issue)$, /usr/bin/c*\
|
user ALL = /bin/ls ^/etc/(hosts|motd|issue)$, /usr/bin/c*\
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
Parses OK
|
Parses OK
|
||||||
|
|
||||||
|
Defaults passprompt_regex="(?i)password: *"
|
||||||
|
|
||||||
user ALL = /bin/ls ^/etc/(hosts|motd|issue)$
|
user ALL = /bin/ls ^/etc/(hosts|motd|issue)$
|
||||||
user ALL = /usr/bin/c* ^/etc/(hosts|motd|issue)$
|
user ALL = /usr/bin/c* ^/etc/(hosts|motd|issue)$
|
||||||
user ALL = ^/usr/bin/(who|w|id|whoami)$
|
user ALL = ^/usr/bin/(who|w|id|whoami)$
|
||||||
|
@@ -1,3 +1,6 @@
|
|||||||
|
#
|
||||||
|
DEFAULTS DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4)
|
||||||
|
|
||||||
#
|
#
|
||||||
WORD(6) ALL = COMMAND ARG REGEX
|
WORD(6) ALL = COMMAND ARG REGEX
|
||||||
|
|
||||||
|
@@ -1195,6 +1195,7 @@ parse_expr(struct search_node_list *head, char *argv[], bool sub_expr)
|
|||||||
bool or = false, not = false;
|
bool or = false, not = false;
|
||||||
struct search_node *sn;
|
struct search_node *sn;
|
||||||
char type, **av;
|
char type, **av;
|
||||||
|
const char *errstr;
|
||||||
debug_decl(parse_expr, SUDO_DEBUG_UTIL);
|
debug_decl(parse_expr, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
for (av = argv; *av != NULL; av++) {
|
for (av = argv; *av != NULL; av++) {
|
||||||
@@ -1288,8 +1289,10 @@ parse_expr(struct search_node_list *head, char *argv[], bool sub_expr)
|
|||||||
if (*(++av) == NULL)
|
if (*(++av) == NULL)
|
||||||
sudo_fatalx(U_("%s requires an argument"), av[-1]);
|
sudo_fatalx(U_("%s requires an argument"), av[-1]);
|
||||||
if (type == ST_PATTERN) {
|
if (type == ST_PATTERN) {
|
||||||
if (regcomp(&sn->u.cmdre, *av, REG_EXTENDED|REG_NOSUB) != 0)
|
if (!sudo_regex_compile(&sn->u.cmdre, *av, &errstr)) {
|
||||||
sudo_fatalx(U_("invalid regular expression: %s"), *av);
|
sudo_fatalx(U_("invalid regular expression \"%s\": %s"),
|
||||||
|
*av, U_(errstr));
|
||||||
|
}
|
||||||
} else if (type == ST_TODATE || type == ST_FROMDATE) {
|
} else if (type == ST_TODATE || type == ST_FROMDATE) {
|
||||||
sn->u.tstamp.tv_sec = get_date(*av);
|
sn->u.tstamp.tv_sec = get_date(*av);
|
||||||
sn->u.tstamp.tv_nsec = 0;
|
sn->u.tstamp.tv_nsec = 0;
|
||||||
@@ -1542,6 +1545,7 @@ list_sessions(int argc, char **argv, const char *pattern, const char *user,
|
|||||||
const char *tty)
|
const char *tty)
|
||||||
{
|
{
|
||||||
regex_t rebuf, *re = NULL;
|
regex_t rebuf, *re = NULL;
|
||||||
|
const char *errstr;
|
||||||
debug_decl(list_sessions, SUDO_DEBUG_UTIL);
|
debug_decl(list_sessions, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
/* Parse search expression if present */
|
/* Parse search expression if present */
|
||||||
@@ -1550,8 +1554,10 @@ list_sessions(int argc, char **argv, const char *pattern, const char *user,
|
|||||||
/* optional regex */
|
/* optional regex */
|
||||||
if (pattern) {
|
if (pattern) {
|
||||||
re = &rebuf;
|
re = &rebuf;
|
||||||
if (regcomp(re, pattern, REG_EXTENDED|REG_NOSUB) != 0)
|
if (!sudo_regex_compile(re, pattern, &errstr)) {
|
||||||
sudo_fatalx(U_("invalid regular expression: %s"), pattern);
|
sudo_fatalx(U_("invalid regular expression \"%s\": %s"),
|
||||||
|
pattern, U_(errstr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_return_int(find_sessions(session_dir, re, user, tty));
|
debug_return_int(find_sessions(session_dir, re, user, tty));
|
||||||
|
@@ -3083,7 +3083,7 @@ char *sudoerstext;
|
|||||||
|
|
||||||
int sudolineno; /* current sudoers line number. */
|
int sudolineno; /* current sudoers line number. */
|
||||||
char *sudoers; /* sudoers file being parsed. */
|
char *sudoers; /* sudoers file being parsed. */
|
||||||
char *sudoers_errstr; /* description of last error from lexer. */
|
const char *sudoers_errstr; /* description of last error from lexer. */
|
||||||
struct sudolinebuf sudolinebuf; /* sudoers line being parsed. */
|
struct sudolinebuf sudolinebuf; /* sudoers line being parsed. */
|
||||||
|
|
||||||
/* Default sudoers path, mode and owner (may be set via sudo.conf) */
|
/* Default sudoers path, mode and owner (may be set via sudo.conf) */
|
||||||
@@ -3648,7 +3648,7 @@ YY_RULE_SETUP
|
|||||||
BEGIN INITIAL;
|
BEGIN INITIAL;
|
||||||
continued = false;
|
continued = false;
|
||||||
if (sudoers_strict) {
|
if (sudoers_strict) {
|
||||||
if (!regex_valid(sudoerstext, &sudoers_errstr)) {
|
if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) {
|
||||||
LEXTRACE("ERROR ");
|
LEXTRACE("ERROR ");
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
@@ -4283,7 +4283,7 @@ YY_RULE_SETUP
|
|||||||
#line 774 "toke.l"
|
#line 774 "toke.l"
|
||||||
{
|
{
|
||||||
if (sudoers_strict) {
|
if (sudoers_strict) {
|
||||||
if (!regex_valid(sudoerstext, &sudoers_errstr)) {
|
if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) {
|
||||||
LEXTRACE("ERROR ");
|
LEXTRACE("ERROR ");
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
@@ -27,7 +27,7 @@ struct sudolinebuf {
|
|||||||
size_t toke_start; /* starting column of current token */
|
size_t toke_start; /* starting column of current token */
|
||||||
size_t toke_end; /* ending column of current token */
|
size_t toke_end; /* ending column of current token */
|
||||||
};
|
};
|
||||||
extern char *sudoers_errstr;
|
extern const char *sudoers_errstr;
|
||||||
extern struct sudolinebuf sudolinebuf;
|
extern struct sudolinebuf sudolinebuf;
|
||||||
|
|
||||||
bool append(const char *, size_t);
|
bool append(const char *, size_t);
|
||||||
@@ -35,7 +35,6 @@ bool fill_args(const char *, size_t, int);
|
|||||||
bool fill_cmnd(const char *, size_t);
|
bool fill_cmnd(const char *, size_t);
|
||||||
bool fill(const char *, size_t);
|
bool fill(const char *, size_t);
|
||||||
bool ipv6_valid(const char *s);
|
bool ipv6_valid(const char *s);
|
||||||
bool regex_valid(const char *pattern, char **errstr);
|
|
||||||
int sudoers_trace_print(const char *);
|
int sudoers_trace_print(const char *);
|
||||||
void sudoerserrorf(const char *, ...) __printf0like(1, 2);
|
void sudoerserrorf(const char *, ...) __printf0like(1, 2);
|
||||||
void sudoerserror(const char *);
|
void sudoerserror(const char *);
|
||||||
|
@@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
int sudolineno; /* current sudoers line number. */
|
int sudolineno; /* current sudoers line number. */
|
||||||
char *sudoers; /* sudoers file being parsed. */
|
char *sudoers; /* sudoers file being parsed. */
|
||||||
char *sudoers_errstr; /* description of last error from lexer. */
|
const char *sudoers_errstr; /* description of last error from lexer. */
|
||||||
struct sudolinebuf sudolinebuf; /* sudoers line being parsed. */
|
struct sudolinebuf sudolinebuf; /* sudoers line being parsed. */
|
||||||
|
|
||||||
/* Default sudoers path, mode and owner (may be set via sudo.conf) */
|
/* Default sudoers path, mode and owner (may be set via sudo.conf) */
|
||||||
@@ -297,7 +297,7 @@ DEFVAR [a-z_]+
|
|||||||
BEGIN INITIAL;
|
BEGIN INITIAL;
|
||||||
continued = false;
|
continued = false;
|
||||||
if (sudoers_strict) {
|
if (sudoers_strict) {
|
||||||
if (!regex_valid(sudoerstext, &sudoers_errstr)) {
|
if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) {
|
||||||
LEXTRACE("ERROR ");
|
LEXTRACE("ERROR ");
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
@@ -773,7 +773,7 @@ sudoedit {
|
|||||||
|
|
||||||
{REGEX} {
|
{REGEX} {
|
||||||
if (sudoers_strict) {
|
if (sudoers_strict) {
|
||||||
if (!regex_valid(sudoerstext, &sudoers_errstr)) {
|
if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) {
|
||||||
LEXTRACE("ERROR ");
|
LEXTRACE("ERROR ");
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
@@ -39,7 +39,6 @@
|
|||||||
|
|
||||||
static unsigned int arg_len = 0;
|
static unsigned int arg_len = 0;
|
||||||
static unsigned int arg_size = 0;
|
static unsigned int arg_size = 0;
|
||||||
static char errbuf[1024];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy the string and collapse any escaped characters.
|
* Copy the string and collapse any escaped characters.
|
||||||
@@ -247,36 +246,3 @@ ipv6_valid(const char *s)
|
|||||||
|
|
||||||
debug_return_bool(nmatch <= 1);
|
debug_return_bool(nmatch <= 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
regex_valid(const char *pattern, char **errstr)
|
|
||||||
{
|
|
||||||
int errcode, cflags = REG_EXTENDED|REG_NOSUB;
|
|
||||||
char *copy = NULL;
|
|
||||||
regex_t re;
|
|
||||||
debug_decl(regex_valid, SUDOERS_DEBUG_PARSER);
|
|
||||||
|
|
||||||
/* Check for (?i) to enable case-insensitive matching. */
|
|
||||||
if (strncmp(pattern, "^(?i)", 5) == 0) {
|
|
||||||
cflags |= REG_ICASE;
|
|
||||||
copy = strdup(pattern + 4);
|
|
||||||
if (copy == NULL) {
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
sudoerserror(NULL);
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
copy[0] = '^';
|
|
||||||
pattern = copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
errcode = regcomp(&re, pattern, cflags);
|
|
||||||
if (errcode == 0) {
|
|
||||||
regfree(&re);
|
|
||||||
} else {
|
|
||||||
regerror(errcode, &re, errbuf, sizeof(errbuf));
|
|
||||||
*errstr = errbuf;
|
|
||||||
}
|
|
||||||
free(copy);
|
|
||||||
|
|
||||||
debug_return_bool(errcode == 0);
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user