Better match debugging.

Sprinkle const in match functions.
This commit is contained in:
Todd C. Miller
2013-12-05 14:34:56 -07:00
parent 1739350e20
commit 2508da6f68
7 changed files with 137 additions and 89 deletions

View File

@@ -93,12 +93,12 @@
static struct member_list empty = TAILQ_HEAD_INITIALIZER(empty);
static bool command_matches_dir(char *, size_t);
static bool command_matches_dir(const char *sudoers_dir, size_t dlen);
#ifndef SUDOERS_NAME_MATCH
static bool command_matches_glob(char *, char *);
static bool command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args);
#endif
static bool command_matches_fnmatch(char *, char *);
static bool command_matches_normal(char *, char *, struct sudo_digest *);
static bool command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args);
static bool command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const struct sudo_digest *digest);
/*
* Returns true if string 's' contains meta characters.
@@ -110,7 +110,7 @@ static bool command_matches_normal(char *, char *, struct sudo_digest *);
* Returns ALLOW, DENY or UNSPEC.
*/
int
userlist_matches(struct passwd *pw, struct member_list *list)
userlist_matches(const struct passwd *pw, const struct member_list *list)
{
struct member *m;
struct alias *a;
@@ -156,8 +156,8 @@ userlist_matches(struct passwd *pw, struct member_list *list)
* Returns ALLOW, DENY or UNSPEC.
*/
int
runaslist_matches(struct member_list *user_list,
struct member_list *group_list, struct member **matching_user,
runaslist_matches(const struct member_list *user_list,
const struct member_list *group_list, struct member **matching_user,
struct member **matching_group)
{
struct member *m;
@@ -266,7 +266,7 @@ runaslist_matches(struct member_list *user_list,
* Returns ALLOW, DENY or UNSPEC.
*/
int
hostlist_matches(struct member_list *list)
hostlist_matches(const struct member_list *list)
{
struct member *m;
struct alias *a;
@@ -311,7 +311,7 @@ hostlist_matches(struct member_list *list)
* Returns ALLOW, DENY or UNSPEC.
*/
int
cmndlist_matches(struct member_list *list)
cmndlist_matches(const struct member_list *list)
{
struct member *m;
int matched = UNSPEC;
@@ -330,7 +330,7 @@ cmndlist_matches(struct member_list *list)
* Returns ALLOW, DENY or UNSPEC.
*/
int
cmnd_matches(struct member *m)
cmnd_matches(const struct member *m)
{
struct alias *a;
struct sudo_command *c;
@@ -359,7 +359,7 @@ cmnd_matches(struct member *m)
}
static bool
command_args_match(char *sudoers_cmnd, char *sudoers_args)
command_args_match(const char *sudoers_cmnd, const char *sudoers_args)
{
int flags = 0;
debug_decl(command_args_match, SUDO_DEBUG_MATCH)
@@ -390,8 +390,9 @@ command_args_match(char *sudoers_cmnd, char *sudoers_args)
* otherwise, return true if user_cmnd names one of the inodes in path.
*/
bool
command_matches(char *sudoers_cmnd, char *sudoers_args, struct sudo_digest *digest)
command_matches(const char *sudoers_cmnd, const char *sudoers_args, const struct sudo_digest *digest)
{
bool rc = false;
debug_decl(command_matches, SUDO_DEBUG_MATCH)
/* Check for pseudo-commands */
@@ -402,15 +403,14 @@ command_matches(char *sudoers_cmnd, char *sudoers_args, struct sudo_digest *dige
* b) there are no args on command line and none req by sudoers OR
* c) there are args in sudoers and on command line and they match
*/
if (strcmp(sudoers_cmnd, "sudoedit") != 0 ||
strcmp(user_cmnd, "sudoedit") != 0)
debug_return_bool(false);
if (command_args_match(sudoers_cmnd, sudoers_args)) {
if (strcmp(sudoers_cmnd, "sudoedit") == 0 &&
strcmp(user_cmnd, "sudoedit") == 0 &&
command_args_match(sudoers_cmnd, sudoers_args)) {
efree(safe_cmnd);
safe_cmnd = estrdup(sudoers_cmnd);
debug_return_bool(true);
} else
debug_return_bool(false);
rc = true;
}
goto done;
}
if (has_meta(sudoers_cmnd)) {
@@ -419,18 +419,27 @@ command_matches(char *sudoers_cmnd, char *sudoers_args, struct sudo_digest *dige
* use glob(3) and/or fnmatch(3) to do the matching.
*/
#ifdef SUDOERS_NAME_MATCH
debug_return_bool(command_matches_fnmatch(sudoers_cmnd, sudoers_args));
rc = command_matches_fnmatch(sudoers_cmnd, sudoers_args);
#else
if (def_fast_glob)
debug_return_bool(command_matches_fnmatch(sudoers_cmnd, sudoers_args));
debug_return_bool(command_matches_glob(sudoers_cmnd, sudoers_args));
rc = command_matches_fnmatch(sudoers_cmnd, sudoers_args);
else
rc = command_matches_glob(sudoers_cmnd, sudoers_args);
#endif
} else {
rc = command_matches_normal(sudoers_cmnd, sudoers_args, digest);
}
debug_return_bool(command_matches_normal(sudoers_cmnd, sudoers_args, digest));
done:
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"user command \"%s%s%s\" matches sudoers command \"%s%s%s\": %s",
user_cmnd, user_args ? " " : "", user_args ? user_args : "",
sudoers_cmnd, sudoers_args ? " " : "", sudoers_args ? sudoers_args : "",
rc ? "true" : "false");
debug_return_bool(rc);
}
static bool
command_matches_fnmatch(char *sudoers_cmnd, char *sudoers_args)
command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args)
{
debug_decl(command_matches_fnmatch, SUDO_DEBUG_MATCH)
@@ -454,7 +463,7 @@ command_matches_fnmatch(char *sudoers_cmnd, char *sudoers_args)
#ifndef SUDOERS_NAME_MATCH
static bool
command_matches_glob(char *sudoers_cmnd, char *sudoers_args)
command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args)
{
struct stat sudoers_stat;
size_t dlen;
@@ -527,7 +536,7 @@ command_matches_glob(char *sudoers_cmnd, char *sudoers_args)
#ifdef SUDOERS_NAME_MATCH
static bool
command_matches_normal(char *sudoers_cmnd, char *sudoers_args, struct sudo_digest *digest)
command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const struct sudo_digest *digest)
{
size_t dlen;
debug_decl(command_matches_normal, SUDO_DEBUG_MATCH)
@@ -586,7 +595,7 @@ static struct digest_function {
};
static bool
digest_matches(char *file, struct sudo_digest *sd)
digest_matches(const char *file, const struct sudo_digest *sd)
{
unsigned char file_digest[SHA512_DIGEST_LENGTH];
unsigned char sudoers_digest[SHA512_DIGEST_LENGTH];
@@ -642,7 +651,12 @@ digest_matches(char *file, struct sudo_digest *sd)
fclose(fp);
func->final(file_digest, &ctx);
debug_return_bool(memcmp(file_digest, sudoers_digest, func->digest_len) == 0);
if (memcmp(file_digest, sudoers_digest, func->digest_len) == 0)
debug_return_bool(true);
sudo_debug_printf(SUDO_DEBUG_DIAG|SUDO_DEBUG_LINENO,
"%s digest mismatch for %s, expecting %s",
func->digest_name, file, sd->digest_str);
debug_return_bool(false);
bad_format:
warningx(U_("digest for %s (%s) is not in %s form"), file,
sd->digest_str, func->digest_name);
@@ -650,10 +664,10 @@ bad_format:
}
static bool
command_matches_normal(char *sudoers_cmnd, char *sudoers_args, struct sudo_digest *digest)
command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const struct sudo_digest *digest)
{
struct stat sudoers_stat;
char *base;
const char *base;
size_t dlen;
debug_decl(command_matches_normal, SUDO_DEBUG_MATCH)
@@ -700,7 +714,7 @@ command_matches_normal(char *sudoers_cmnd, char *sudoers_args, struct sudo_diges
* Note that sudoers_dir include the trailing '/'
*/
static bool
command_matches_dir(char *sudoers_dir, size_t dlen)
command_matches_dir(const char *sudoers_dir, size_t dlen)
{
debug_decl(command_matches_dir, SUDO_DEBUG_MATCH)
debug_return_bool(strncmp(user_cmnd, sudoers_dir, dlen) == 0);
@@ -710,7 +724,7 @@ command_matches_dir(char *sudoers_dir, size_t dlen)
* Return true if user_cmnd names one of the inodes in dir, else false.
*/
static bool
command_matches_dir(char *sudoers_dir, size_t dlen)
command_matches_dir(const char *sudoers_dir, size_t dlen)
{
struct stat sudoers_stat;
struct dirent *dent;
@@ -757,21 +771,22 @@ command_matches_dir(char *sudoers_dir, size_t dlen)
* Returns true if the hostname matches the pattern, else false
*/
bool
hostname_matches(char *shost, char *lhost, char *pattern)
hostname_matches(const char *shost, const char *lhost, const char *pattern)
{
debug_decl(hostname_matches, SUDO_DEBUG_MATCH)
const char *host;
bool rc;
host = strchr(pattern, '.') != NULL ? lhost : shost;
if (has_meta(pattern)) {
if (strchr(pattern, '.'))
debug_return_bool(!fnmatch(pattern, lhost, FNM_CASEFOLD));
else
debug_return_bool(!fnmatch(pattern, shost, FNM_CASEFOLD));
rc = !fnmatch(pattern, host, FNM_CASEFOLD);
} else {
if (strchr(pattern, '.'))
debug_return_bool(!strcasecmp(lhost, pattern));
else
debug_return_bool(!strcasecmp(shost, pattern));
rc = !strcasecmp(host, pattern);
}
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"host %s matches sudoers pattern %s: %s",
host, pattern, rc ? "true" : "false");
debug_return_bool(rc);
}
/*
@@ -779,18 +794,26 @@ hostname_matches(char *shost, char *lhost, char *pattern)
* else returns false.
*/
bool
userpw_matches(char *sudoers_user, char *user, struct passwd *pw)
userpw_matches(const char *sudoers_user, const char *user, const struct passwd *pw)
{
const char *errstr;
uid_t uid;
bool rc;
debug_decl(userpw_matches, SUDO_DEBUG_MATCH)
if (pw != NULL && *sudoers_user == '#') {
uid = (uid_t) atoid(sudoers_user + 1, NULL, NULL, &errstr);
if (errstr != NULL && uid == pw->pw_uid)
debug_return_bool(true);
if (errstr != NULL && uid == pw->pw_uid) {
rc = true;
goto done;
}
debug_return_bool(strcmp(sudoers_user, user) == 0);
}
rc = strcmp(sudoers_user, user) == 0;
done:
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"user %s matches sudoers user %s: %s",
user, sudoers_user, rc ? "true" : "false");
debug_return_bool(rc);
}
/*
@@ -798,18 +821,26 @@ userpw_matches(char *sudoers_user, char *user, struct passwd *pw)
* else returns false.
*/
bool
group_matches(char *sudoers_group, struct group *gr)
group_matches(const char *sudoers_group, const struct group *gr)
{
const char *errstr;
gid_t gid;
bool rc;
debug_decl(group_matches, SUDO_DEBUG_MATCH)
if (*sudoers_group == '#') {
gid = (gid_t) atoid(sudoers_group + 1, NULL, NULL, &errstr);
if (errstr != NULL && gid == gr->gr_gid)
debug_return_bool(true);
if (errstr != NULL && gid == gr->gr_gid) {
rc = true;
goto done;
}
debug_return_bool(strcmp(gr->gr_name, sudoers_group) == 0);
}
rc = strcmp(gr->gr_name, sudoers_group) == 0;
done:
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"group %s matches sudoers group %s: %s",
gr->gr_name, sudoers_group, rc ? "true" : "false");
debug_return_bool(rc);
}
/*
@@ -817,15 +848,18 @@ group_matches(char *sudoers_group, struct group *gr)
* else returns false.
*/
bool
usergr_matches(char *group, char *user, struct passwd *pw)
usergr_matches(const char *group, const char *user, const struct passwd *pw)
{
int matched = false;
struct passwd *pw0 = NULL;
debug_decl(usergr_matches, SUDO_DEBUG_MATCH)
/* make sure we have a valid usergroup, sudo style */
if (*group++ != '%')
if (*group++ != '%') {
sudo_debug_printf(SUDO_DEBUG_DIAG, "user group %s has no leading '%%'",
group);
goto done;
}
if (*group == ':' && def_group_plugin) {
matched = group_plugin_query(user, group + 1, pw);
@@ -834,8 +868,11 @@ usergr_matches(char *group, char *user, struct passwd *pw)
/* look up user's primary gid in the passwd file */
if (pw == NULL) {
if ((pw0 = sudo_getpwnam(user)) == NULL)
if ((pw0 = sudo_getpwnam(user)) == NULL) {
sudo_debug_printf(SUDO_DEBUG_DIAG, "unable to find %s in passwd db",
user);
goto done;
}
pw = pw0;
}
@@ -854,6 +891,8 @@ done:
if (pw0 != NULL)
sudo_pw_delref(pw0);
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"user %s matches group %s: %s", user, group, matched ? "true" : "false");
debug_return_bool(matched);
}
@@ -888,24 +927,26 @@ sudo_getdomainname(void)
/*
* Returns true if "host" and "user" belong to the netgroup "netgr",
* else return false. Either of "host", "shost" or "user" may be NULL
* else return false. Either of "lhost", "shost" or "user" may be NULL
* in which case that argument is not checked...
*
* XXX - swap order of host & shost
*/
bool
netgr_matches(char *netgr, char *lhost, char *shost, char *user)
netgr_matches(const char *netgr, const char *lhost, const char *shost, const char *user)
{
#ifdef HAVE_INNETGR
static char *domain;
static int initialized;
#endif
bool rc = false;
debug_decl(netgr_matches, SUDO_DEBUG_MATCH)
#ifdef HAVE_INNETGR
/* make sure we have a valid netgroup, sudo style */
if (*netgr++ != '+')
if (*netgr++ != '+') {
sudo_debug_printf(SUDO_DEBUG_DIAG, "netgroup %s has no leading '+'",
netgr);
debug_return_bool(false);
}
/* get the domain name (if any) */
if (!initialized) {
@@ -914,10 +955,15 @@ netgr_matches(char *netgr, char *lhost, char *shost, char *user)
}
if (innetgr(netgr, lhost, user, domain))
debug_return_bool(true);
rc = true;
else if (lhost != shost && innetgr(netgr, shost, user, domain))
debug_return_bool(true);
rc = true;
#endif /* HAVE_INNETGR */
debug_return_bool(false);
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"netgroup %s matches (%s|%s, %s, %s): %s", netgr, lhost ? lhost : "",
shost ? shost : "", user ? user : "", domain ? domain : "",
rc ? "true" : "false");
debug_return_bool(rc);
}

View File

@@ -50,7 +50,7 @@
#include "interfaces.h"
static bool
addr_matches_if(char *n)
addr_matches_if(const char *n)
{
union sudo_in_addr_un addr;
struct interface *ifp;
@@ -100,7 +100,7 @@ addr_matches_if(char *n)
}
static bool
addr_matches_if_netmask(char *n, char *m)
addr_matches_if_netmask(const char *n, const char *m)
{
unsigned int i;
union sudo_in_addr_un addr, mask;
@@ -185,16 +185,18 @@ bool
addr_matches(char *n)
{
char *m;
bool retval;
bool rc;
debug_decl(addr_matches, SUDO_DEBUG_MATCH)
/* If there's an explicit netmask, use it. */
if ((m = strchr(n, '/'))) {
*m++ = '\0';
retval = addr_matches_if_netmask(n, m);
rc = addr_matches_if_netmask(n, m);
*(m - 1) = '/';
} else
retval = addr_matches_if(n);
rc = addr_matches_if(n);
debug_return_bool(retval);
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"IP address %s matches local host: %s", n, rc ? "true" : "false");
debug_return_bool(rc);
}

View File

@@ -200,17 +200,17 @@ void init_parser(const char *, bool);
bool addr_matches(char *n);
/* match.c */
bool command_matches(char *sudoers_cmnd, char *sudoers_args, struct sudo_digest *digest);
bool group_matches(char *sudoers_group, struct group *gr);
bool hostname_matches(char *shost, char *lhost, char *pattern);
bool netgr_matches(char *netgr, char *lhost, char *shost, char *user);
bool usergr_matches(char *group, char *user, struct passwd *pw);
bool userpw_matches(char *sudoers_user, char *user, struct passwd *pw);
int cmnd_matches(struct member *m);
int cmndlist_matches(struct member_list *list);
int hostlist_matches(struct member_list *list);
int runaslist_matches(struct member_list *user_list, struct member_list *group_list, struct member **matching_user, struct member **matching_group);
int userlist_matches(struct passwd *pw, struct member_list *list);
bool command_matches(const char *sudoers_cmnd, const char *sudoers_args, const struct sudo_digest *digest);
bool group_matches(const char *sudoers_group, const struct group *gr);
bool hostname_matches(const char *shost, const char *lhost, const char *pattern);
bool netgr_matches(const char *netgr, const char *lhost, const char *shost, const char *user);
bool usergr_matches(const char *group, const char *user, const struct passwd *pw);
bool userpw_matches(const char *sudoers_user, const char *user, const struct passwd *pw);
int cmnd_matches(const struct member *m);
int cmndlist_matches(const struct member_list *list);
int hostlist_matches(const struct member_list *list);
int runaslist_matches(const struct member_list *user_list, const struct member_list *group_list, struct member **matching_user, struct member **matching_group);
int userlist_matches(const struct passwd *pw, const struct member_list *list);
/* toke.c */
void init_lexer(void);

View File

@@ -549,7 +549,7 @@ sudo_endgrent(void)
}
struct group_list *
sudo_get_grlist(struct passwd *pw)
sudo_get_grlist(const struct passwd *pw)
{
struct cache_item key, *item;
struct rbnode *node;
@@ -604,7 +604,7 @@ sudo_set_grlist(struct passwd *pw, char * const *groups, char * const *gids)
}
bool
user_in_group(struct passwd *pw, const char *group)
user_in_group(const struct passwd *pw, const char *group)
{
struct group_list *grlist;
struct group *grp = NULL;

View File

@@ -59,7 +59,7 @@ struct cache_item_grlist {
};
struct cache_item *sudo_make_gritem(gid_t gid, const char *group);
struct cache_item *sudo_make_grlist_item(struct passwd *pw, char * const *groups, char * const *gids);
struct cache_item *sudo_make_grlist_item(const struct passwd *pw, char * const *groups, char * const *gids);
struct cache_item *sudo_make_pwitem(uid_t uid, const char *user);
#endif /* _SUDOERS_PWUTIL_H */

View File

@@ -225,7 +225,7 @@ sudo_make_gritem(gid_t gid, const char *name)
* elements. Fills in datum from user_gids or from getgrouplist(3).
*/
struct cache_item *
sudo_make_grlist_item(struct passwd *pw, char * const *unused1,
sudo_make_grlist_item(const struct passwd *pw, char * const *unused1,
char * const *unused2)
{
char *cp;

View File

@@ -292,9 +292,9 @@ __dso_public struct group *sudo_getgrgid(gid_t);
__dso_public struct group *sudo_getgrnam(const char *);
__dso_public void sudo_gr_addref(struct group *);
__dso_public void sudo_gr_delref(struct group *);
bool user_in_group(struct passwd *, const char *);
bool user_in_group(const struct passwd *, const char *);
struct group *sudo_fakegrnam(const char *);
struct group_list *sudo_get_grlist(struct passwd *pw);
struct group_list *sudo_get_grlist(const struct passwd *pw);
struct passwd *sudo_fakepwnam(const char *, gid_t);
struct passwd *sudo_mkpwent(const char *user, uid_t uid, gid_t gid, const char *home, const char *shell);
struct passwd *sudo_getpwnam(const char *);