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/pwrite.c
|
||||
lib/util/rcstr.c
|
||||
lib/util/regex.c
|
||||
lib/util/reallocarray.c
|
||||
lib/util/regress/corpus/seed/sudo_conf/sudo.conf.1
|
||||
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
|
||||
.\" 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
|
||||
.if n .ad l
|
||||
.SH "NAME"
|
||||
@@ -641,6 +641,9 @@ One or more POSIX extended regular expressions used to
|
||||
match password prompts in the terminal output when
|
||||
\fIlog_passwords\fR
|
||||
is disabled.
|
||||
As an extension, if the regular expression begins with
|
||||
\(lq(?i)\(rq,
|
||||
it will be matched in a case-insensitive manner.
|
||||
Multiple
|
||||
\fIpassprompt_regex\fR
|
||||
settings may be specified.
|
||||
|
@@ -15,7 +15,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd February 10, 2022
|
||||
.Dd February 11, 2022
|
||||
.Dt SUDO_LOGSRVD.CONF @mansectform@
|
||||
.Os Sudo @PACKAGE_VERSION@
|
||||
.Sh NAME
|
||||
@@ -571,6 +571,9 @@ One or more POSIX extended regular expressions used to
|
||||
match password prompts in the terminal output when
|
||||
.Em log_passwords
|
||||
is disabled.
|
||||
As an extension, if the regular expression begins with
|
||||
.Dq (?i) ,
|
||||
it will be matched in a case-insensitive manner.
|
||||
Multiple
|
||||
.Em passprompt_regex
|
||||
settings may be specified.
|
||||
|
@@ -25,7 +25,7 @@
|
||||
.nr BA @BAMAN@
|
||||
.nr LC @LCMAN@
|
||||
.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
|
||||
.if n .ad l
|
||||
.SH "NAME"
|
||||
@@ -5424,6 +5424,9 @@ This setting is only supported by version 1.9.0 or higher.
|
||||
passprompt_regex
|
||||
A list of POSIX extended regular expressions used to
|
||||
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
|
||||
\fIlog_passwords\fR
|
||||
has been disabled.
|
||||
|
@@ -24,7 +24,7 @@
|
||||
.nr BA @BAMAN@
|
||||
.nr LC @LCMAN@
|
||||
.nr PS @PSMAN@
|
||||
.Dd February 10, 2022
|
||||
.Dd February 11, 2022
|
||||
.Dt SUDOERS @mansectform@
|
||||
.Os Sudo @PACKAGE_VERSION@
|
||||
.Sh NAME
|
||||
@@ -5062,6 +5062,9 @@ This setting is only supported by version 1.9.0 or higher.
|
||||
.It passprompt_regex
|
||||
A list of POSIX extended regular expressions used to
|
||||
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
|
||||
.Em log_passwords
|
||||
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 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 */
|
||||
sudo_dso_public unsigned int sudo_pow2_roundup_v1(unsigned int len);
|
||||
#define sudo_pow2_roundup(_a) sudo_pow2_roundup_v1((_a))
|
||||
|
@@ -41,6 +41,7 @@
|
||||
#include "sudo_gettext.h"
|
||||
#include "sudo_iolog.h"
|
||||
#include "sudo_queue.h"
|
||||
#include "sudo_util.h"
|
||||
|
||||
struct pwfilt_regex {
|
||||
TAILQ_ENTRY(pwfilt_regex) entries;
|
||||
@@ -110,51 +111,6 @@ iolog_pwfilt_free(void *vhandle)
|
||||
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.
|
||||
*/
|
||||
@@ -163,22 +119,19 @@ iolog_pwfilt_add(void *vhandle, const char *pattern)
|
||||
{
|
||||
struct pwfilt_handle *handle = vhandle;
|
||||
struct pwfilt_regex *filt;
|
||||
char errbuf[1024];
|
||||
int errcode;
|
||||
const char *errstr;
|
||||
debug_decl(iolog_pwfilt_add, SUDO_DEBUG_UTIL);
|
||||
|
||||
filt = malloc(sizeof(*filt));
|
||||
if (filt == NULL)
|
||||
goto oom;
|
||||
filt->pattern = dup_pattern(pattern);
|
||||
filt->pattern = strdup(pattern);
|
||||
if (filt->pattern == NULL)
|
||||
goto oom;
|
||||
|
||||
errcode = regcomp(&filt->regex, filt->pattern, REG_EXTENDED|REG_NOSUB);
|
||||
if (errcode != 0) {
|
||||
regerror(errcode, &filt->regex, errbuf, sizeof(errbuf));
|
||||
if (!sudo_regex_compile(&filt->regex, filt->pattern, &errstr)) {
|
||||
sudo_warnx(U_("invalid regular expression \"%s\": %s"),
|
||||
pattern, errbuf);
|
||||
pattern, U_(errstr));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# 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
|
||||
# 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 \
|
||||
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 \
|
||||
roundup.lo secure_path.lo setgroups.lo strsplit.lo strtobool.lo \
|
||||
strtoid.lo strtomode.lo strtonum.lo sudo_conf.lo \
|
||||
logfac.lo logpri.lo mkdir_parents.lo parseln.lo progname.lo rcstr.lo \
|
||||
regex.lo roundup.lo secure_path.lo setgroups.lo strsplit.lo \
|
||||
strtobool.lo strtoid.lo strtomode.lo strtonum.lo sudo_conf.lo \
|
||||
sudo_debug.lo sudo_dso.lo term.lo ttyname_dev.lo \
|
||||
ttysize.lo uuid.lo @COMMON_OBJS@ @LTLIBOBJS@
|
||||
|
||||
@@ -1212,6 +1212,16 @@ reallocarray.i: $(srcdir)/reallocarray.c $(incdir)/sudo_compat.h \
|
||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||
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 $@
|
||||
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 \
|
||||
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.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_delref
|
||||
sudo_rcstr_dup
|
||||
sudo_regex_compile_v1
|
||||
sudo_secure_dir_v1
|
||||
sudo_secure_file_v1
|
||||
sudo_setgroups_v1
|
||||
|
@@ -36,7 +36,6 @@
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <regex.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "sudoers.h"
|
||||
@@ -1287,22 +1286,17 @@ bool
|
||||
cb_passprompt_regex(const union sudo_defs_val *sd_un, int op)
|
||||
{
|
||||
struct list_member *lm;
|
||||
int errcode;
|
||||
char errbuf[1024];
|
||||
regex_t re;
|
||||
const char *errstr;
|
||||
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) {
|
||||
SLIST_FOREACH(lm, &sd_un->list, entries) {
|
||||
errcode = regcomp(&re, lm->value, REG_EXTENDED|REG_NOSUB);
|
||||
if (errcode != 0) {
|
||||
regerror(errcode, &re, errbuf, sizeof(errbuf));
|
||||
if (!sudo_regex_compile(NULL, lm->value, &errstr)) {
|
||||
sudo_warnx(U_("invalid regular expression \"%s\": %s"),
|
||||
lm->value, errbuf);
|
||||
lm->value, U_(errstr));
|
||||
debug_return_bool(false);
|
||||
}
|
||||
regfree(&re);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -60,36 +60,20 @@
|
||||
static bool
|
||||
regex_matches(const char *pattern, const char *str)
|
||||
{
|
||||
int errcode, cflags = REG_EXTENDED|REG_NOSUB;
|
||||
char *copy = NULL;
|
||||
const char *errstr;
|
||||
int errcode;
|
||||
regex_t re;
|
||||
debug_decl(regex_matches, SUDOERS_DEBUG_MATCH);
|
||||
|
||||
/* 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"));
|
||||
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));
|
||||
if (!sudo_regex_compile(&re, pattern, &errstr)) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"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);
|
||||
}
|
||||
|
@@ -1,3 +1,6 @@
|
||||
# Test passprompt_regex
|
||||
Defaults passprompt_regex="(?i)password: *"
|
||||
|
||||
# Test simple command with regex args
|
||||
user ALL = /bin/ls ^/etc/(hosts|motd|issue)$
|
||||
|
||||
|
@@ -1,4 +1,17 @@
|
||||
{
|
||||
"Defaults": [
|
||||
{
|
||||
"Options": [
|
||||
{
|
||||
"operation": "list_assign",
|
||||
"passprompt_regex": [
|
||||
"(?i)password:",
|
||||
"*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"User_Specs": [
|
||||
{
|
||||
"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
|
||||
objectClass: top
|
||||
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,
|
||||
# user_8, user_9, user_10, user_11
|
||||
user ALL = /bin/ls ^/etc/(hosts|motd|issue)$, /usr/bin/c*\
|
||||
|
@@ -1,5 +1,7 @@
|
||||
Parses OK
|
||||
|
||||
Defaults passprompt_regex="(?i)password: *"
|
||||
|
||||
user ALL = /bin/ls ^/etc/(hosts|motd|issue)$
|
||||
user ALL = /usr/bin/c* ^/etc/(hosts|motd|issue)$
|
||||
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
|
||||
|
||||
|
@@ -1195,6 +1195,7 @@ parse_expr(struct search_node_list *head, char *argv[], bool sub_expr)
|
||||
bool or = false, not = false;
|
||||
struct search_node *sn;
|
||||
char type, **av;
|
||||
const char *errstr;
|
||||
debug_decl(parse_expr, SUDO_DEBUG_UTIL);
|
||||
|
||||
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)
|
||||
sudo_fatalx(U_("%s requires an argument"), av[-1]);
|
||||
if (type == ST_PATTERN) {
|
||||
if (regcomp(&sn->u.cmdre, *av, REG_EXTENDED|REG_NOSUB) != 0)
|
||||
sudo_fatalx(U_("invalid regular expression: %s"), *av);
|
||||
if (!sudo_regex_compile(&sn->u.cmdre, *av, &errstr)) {
|
||||
sudo_fatalx(U_("invalid regular expression \"%s\": %s"),
|
||||
*av, U_(errstr));
|
||||
}
|
||||
} else if (type == ST_TODATE || type == ST_FROMDATE) {
|
||||
sn->u.tstamp.tv_sec = get_date(*av);
|
||||
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)
|
||||
{
|
||||
regex_t rebuf, *re = NULL;
|
||||
const char *errstr;
|
||||
debug_decl(list_sessions, SUDO_DEBUG_UTIL);
|
||||
|
||||
/* Parse search expression if present */
|
||||
@@ -1550,8 +1554,10 @@ list_sessions(int argc, char **argv, const char *pattern, const char *user,
|
||||
/* optional regex */
|
||||
if (pattern) {
|
||||
re = &rebuf;
|
||||
if (regcomp(re, pattern, REG_EXTENDED|REG_NOSUB) != 0)
|
||||
sudo_fatalx(U_("invalid regular expression: %s"), pattern);
|
||||
if (!sudo_regex_compile(re, pattern, &errstr)) {
|
||||
sudo_fatalx(U_("invalid regular expression \"%s\": %s"),
|
||||
pattern, U_(errstr));
|
||||
}
|
||||
}
|
||||
|
||||
debug_return_int(find_sessions(session_dir, re, user, tty));
|
||||
|
@@ -3083,7 +3083,7 @@ char *sudoerstext;
|
||||
|
||||
int sudolineno; /* current sudoers line number. */
|
||||
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. */
|
||||
|
||||
/* Default sudoers path, mode and owner (may be set via sudo.conf) */
|
||||
@@ -3648,7 +3648,7 @@ YY_RULE_SETUP
|
||||
BEGIN INITIAL;
|
||||
continued = false;
|
||||
if (sudoers_strict) {
|
||||
if (!regex_valid(sudoerstext, &sudoers_errstr)) {
|
||||
if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) {
|
||||
LEXTRACE("ERROR ");
|
||||
return ERROR;
|
||||
}
|
||||
@@ -4283,7 +4283,7 @@ YY_RULE_SETUP
|
||||
#line 774 "toke.l"
|
||||
{
|
||||
if (sudoers_strict) {
|
||||
if (!regex_valid(sudoerstext, &sudoers_errstr)) {
|
||||
if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) {
|
||||
LEXTRACE("ERROR ");
|
||||
return ERROR;
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@ struct sudolinebuf {
|
||||
size_t toke_start; /* starting 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;
|
||||
|
||||
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(const char *, size_t);
|
||||
bool ipv6_valid(const char *s);
|
||||
bool regex_valid(const char *pattern, char **errstr);
|
||||
int sudoers_trace_print(const char *);
|
||||
void sudoerserrorf(const char *, ...) __printf0like(1, 2);
|
||||
void sudoerserror(const char *);
|
||||
|
@@ -55,7 +55,7 @@
|
||||
|
||||
int sudolineno; /* current sudoers line number. */
|
||||
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. */
|
||||
|
||||
/* Default sudoers path, mode and owner (may be set via sudo.conf) */
|
||||
@@ -297,7 +297,7 @@ DEFVAR [a-z_]+
|
||||
BEGIN INITIAL;
|
||||
continued = false;
|
||||
if (sudoers_strict) {
|
||||
if (!regex_valid(sudoerstext, &sudoers_errstr)) {
|
||||
if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) {
|
||||
LEXTRACE("ERROR ");
|
||||
return ERROR;
|
||||
}
|
||||
@@ -773,7 +773,7 @@ sudoedit {
|
||||
|
||||
{REGEX} {
|
||||
if (sudoers_strict) {
|
||||
if (!regex_valid(sudoerstext, &sudoers_errstr)) {
|
||||
if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) {
|
||||
LEXTRACE("ERROR ");
|
||||
return ERROR;
|
||||
}
|
||||
|
@@ -39,7 +39,6 @@
|
||||
|
||||
static unsigned int arg_len = 0;
|
||||
static unsigned int arg_size = 0;
|
||||
static char errbuf[1024];
|
||||
|
||||
/*
|
||||
* Copy the string and collapse any escaped characters.
|
||||
@@ -247,36 +246,3 @@ ipv6_valid(const char *s)
|
||||
|
||||
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