|
|
@@ -93,12 +93,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
static struct member_list empty = TAILQ_HEAD_INITIALIZER(empty);
|
|
|
|
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
|
|
|
|
#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
|
|
|
|
#endif
|
|
|
|
static bool command_matches_fnmatch(char *, char *);
|
|
|
|
static bool command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args);
|
|
|
|
static bool command_matches_normal(char *, char *, struct sudo_digest *);
|
|
|
|
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.
|
|
|
|
* 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.
|
|
|
|
* Returns ALLOW, DENY or UNSPEC.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
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 member *m;
|
|
|
|
struct alias *a;
|
|
|
|
struct alias *a;
|
|
|
@@ -156,8 +156,8 @@ userlist_matches(struct passwd *pw, struct member_list *list)
|
|
|
|
* Returns ALLOW, DENY or UNSPEC.
|
|
|
|
* Returns ALLOW, DENY or UNSPEC.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
int
|
|
|
|
runaslist_matches(struct member_list *user_list,
|
|
|
|
runaslist_matches(const struct member_list *user_list,
|
|
|
|
struct member_list *group_list, struct member **matching_user,
|
|
|
|
const struct member_list *group_list, struct member **matching_user,
|
|
|
|
struct member **matching_group)
|
|
|
|
struct member **matching_group)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct member *m;
|
|
|
|
struct member *m;
|
|
|
@@ -266,7 +266,7 @@ runaslist_matches(struct member_list *user_list,
|
|
|
|
* Returns ALLOW, DENY or UNSPEC.
|
|
|
|
* Returns ALLOW, DENY or UNSPEC.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
int
|
|
|
|
hostlist_matches(struct member_list *list)
|
|
|
|
hostlist_matches(const struct member_list *list)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct member *m;
|
|
|
|
struct member *m;
|
|
|
|
struct alias *a;
|
|
|
|
struct alias *a;
|
|
|
@@ -311,7 +311,7 @@ hostlist_matches(struct member_list *list)
|
|
|
|
* Returns ALLOW, DENY or UNSPEC.
|
|
|
|
* Returns ALLOW, DENY or UNSPEC.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
int
|
|
|
|
cmndlist_matches(struct member_list *list)
|
|
|
|
cmndlist_matches(const struct member_list *list)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct member *m;
|
|
|
|
struct member *m;
|
|
|
|
int matched = UNSPEC;
|
|
|
|
int matched = UNSPEC;
|
|
|
@@ -330,7 +330,7 @@ cmndlist_matches(struct member_list *list)
|
|
|
|
* Returns ALLOW, DENY or UNSPEC.
|
|
|
|
* Returns ALLOW, DENY or UNSPEC.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
int
|
|
|
|
cmnd_matches(struct member *m)
|
|
|
|
cmnd_matches(const struct member *m)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct alias *a;
|
|
|
|
struct alias *a;
|
|
|
|
struct sudo_command *c;
|
|
|
|
struct sudo_command *c;
|
|
|
@@ -359,7 +359,7 @@ cmnd_matches(struct member *m)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
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;
|
|
|
|
int flags = 0;
|
|
|
|
debug_decl(command_args_match, SUDO_DEBUG_MATCH)
|
|
|
|
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.
|
|
|
|
* otherwise, return true if user_cmnd names one of the inodes in path.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
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)
|
|
|
|
debug_decl(command_matches, SUDO_DEBUG_MATCH)
|
|
|
|
|
|
|
|
|
|
|
|
/* Check for pseudo-commands */
|
|
|
|
/* 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
|
|
|
|
* 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
|
|
|
|
* c) there are args in sudoers and on command line and they match
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
if (strcmp(sudoers_cmnd, "sudoedit") != 0 ||
|
|
|
|
if (strcmp(sudoers_cmnd, "sudoedit") == 0 &&
|
|
|
|
strcmp(user_cmnd, "sudoedit") != 0)
|
|
|
|
strcmp(user_cmnd, "sudoedit") == 0 &&
|
|
|
|
debug_return_bool(false);
|
|
|
|
command_args_match(sudoers_cmnd, sudoers_args)) {
|
|
|
|
if (command_args_match(sudoers_cmnd, sudoers_args)) {
|
|
|
|
|
|
|
|
efree(safe_cmnd);
|
|
|
|
efree(safe_cmnd);
|
|
|
|
safe_cmnd = estrdup(sudoers_cmnd);
|
|
|
|
safe_cmnd = estrdup(sudoers_cmnd);
|
|
|
|
debug_return_bool(true);
|
|
|
|
rc = true;
|
|
|
|
} else
|
|
|
|
}
|
|
|
|
debug_return_bool(false);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (has_meta(sudoers_cmnd)) {
|
|
|
|
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.
|
|
|
|
* use glob(3) and/or fnmatch(3) to do the matching.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
#ifdef SUDOERS_NAME_MATCH
|
|
|
|
#ifdef SUDOERS_NAME_MATCH
|
|
|
|
debug_return_bool(command_matches_fnmatch(sudoers_cmnd, sudoers_args));
|
|
|
|
rc = command_matches_fnmatch(sudoers_cmnd, sudoers_args);
|
|
|
|
#else
|
|
|
|
#else
|
|
|
|
if (def_fast_glob)
|
|
|
|
if (def_fast_glob)
|
|
|
|
debug_return_bool(command_matches_fnmatch(sudoers_cmnd, sudoers_args));
|
|
|
|
rc = command_matches_fnmatch(sudoers_cmnd, sudoers_args);
|
|
|
|
debug_return_bool(command_matches_glob(sudoers_cmnd, sudoers_args));
|
|
|
|
else
|
|
|
|
|
|
|
|
rc = command_matches_glob(sudoers_cmnd, sudoers_args);
|
|
|
|
#endif
|
|
|
|
#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
|
|
|
|
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)
|
|
|
|
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
|
|
|
|
#ifndef SUDOERS_NAME_MATCH
|
|
|
|
static bool
|
|
|
|
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;
|
|
|
|
struct stat sudoers_stat;
|
|
|
|
size_t dlen;
|
|
|
|
size_t dlen;
|
|
|
@@ -527,7 +536,7 @@ command_matches_glob(char *sudoers_cmnd, char *sudoers_args)
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef SUDOERS_NAME_MATCH
|
|
|
|
#ifdef SUDOERS_NAME_MATCH
|
|
|
|
static bool
|
|
|
|
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;
|
|
|
|
size_t dlen;
|
|
|
|
debug_decl(command_matches_normal, SUDO_DEBUG_MATCH)
|
|
|
|
debug_decl(command_matches_normal, SUDO_DEBUG_MATCH)
|
|
|
@@ -586,7 +595,7 @@ static struct digest_function {
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
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 file_digest[SHA512_DIGEST_LENGTH];
|
|
|
|
unsigned char sudoers_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);
|
|
|
|
fclose(fp);
|
|
|
|
func->final(file_digest, &ctx);
|
|
|
|
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:
|
|
|
|
bad_format:
|
|
|
|
warningx(U_("digest for %s (%s) is not in %s form"), file,
|
|
|
|
warningx(U_("digest for %s (%s) is not in %s form"), file,
|
|
|
|
sd->digest_str, func->digest_name);
|
|
|
|
sd->digest_str, func->digest_name);
|
|
|
@@ -650,10 +664,10 @@ bad_format:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
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;
|
|
|
|
struct stat sudoers_stat;
|
|
|
|
char *base;
|
|
|
|
const char *base;
|
|
|
|
size_t dlen;
|
|
|
|
size_t dlen;
|
|
|
|
debug_decl(command_matches_normal, SUDO_DEBUG_MATCH)
|
|
|
|
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 '/'
|
|
|
|
* Note that sudoers_dir include the trailing '/'
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
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_decl(command_matches_dir, SUDO_DEBUG_MATCH)
|
|
|
|
debug_return_bool(strncmp(user_cmnd, sudoers_dir, dlen) == 0);
|
|
|
|
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.
|
|
|
|
* Return true if user_cmnd names one of the inodes in dir, else false.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
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 stat sudoers_stat;
|
|
|
|
struct dirent *dent;
|
|
|
|
struct dirent *dent;
|
|
|
@@ -757,75 +771,95 @@ command_matches_dir(char *sudoers_dir, size_t dlen)
|
|
|
|
* Returns true if the hostname matches the pattern, else false
|
|
|
|
* Returns true if the hostname matches the pattern, else false
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
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)
|
|
|
|
debug_decl(hostname_matches, SUDO_DEBUG_MATCH)
|
|
|
|
|
|
|
|
const char *host;
|
|
|
|
|
|
|
|
bool rc;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
host = strchr(pattern, '.') != NULL ? lhost : shost;
|
|
|
|
if (has_meta(pattern)) {
|
|
|
|
if (has_meta(pattern)) {
|
|
|
|
if (strchr(pattern, '.'))
|
|
|
|
rc = !fnmatch(pattern, host, FNM_CASEFOLD);
|
|
|
|
debug_return_bool(!fnmatch(pattern, lhost, FNM_CASEFOLD));
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
debug_return_bool(!fnmatch(pattern, shost, FNM_CASEFOLD));
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
if (strchr(pattern, '.'))
|
|
|
|
rc = !strcasecmp(host, pattern);
|
|
|
|
debug_return_bool(!strcasecmp(lhost, pattern));
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
debug_return_bool(!strcasecmp(shost, 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Returns true if the user/uid from sudoers matches the specified user/uid,
|
|
|
|
* Returns true if the user/uid from sudoers matches the specified user/uid,
|
|
|
|
* else returns false.
|
|
|
|
* else returns false.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
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;
|
|
|
|
const char *errstr;
|
|
|
|
uid_t uid;
|
|
|
|
uid_t uid;
|
|
|
|
|
|
|
|
bool rc;
|
|
|
|
debug_decl(userpw_matches, SUDO_DEBUG_MATCH)
|
|
|
|
debug_decl(userpw_matches, SUDO_DEBUG_MATCH)
|
|
|
|
|
|
|
|
|
|
|
|
if (pw != NULL && *sudoers_user == '#') {
|
|
|
|
if (pw != NULL && *sudoers_user == '#') {
|
|
|
|
uid = (uid_t) atoid(sudoers_user + 1, NULL, NULL, &errstr);
|
|
|
|
uid = (uid_t) atoid(sudoers_user + 1, NULL, NULL, &errstr);
|
|
|
|
if (errstr != NULL && uid == pw->pw_uid)
|
|
|
|
if (errstr != NULL && uid == pw->pw_uid) {
|
|
|
|
debug_return_bool(true);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Returns true if the group/gid from sudoers matches the specified group/gid,
|
|
|
|
* Returns true if the group/gid from sudoers matches the specified group/gid,
|
|
|
|
* else returns false.
|
|
|
|
* else returns false.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
bool
|
|
|
|
group_matches(char *sudoers_group, struct group *gr)
|
|
|
|
group_matches(const char *sudoers_group, const struct group *gr)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const char *errstr;
|
|
|
|
const char *errstr;
|
|
|
|
gid_t gid;
|
|
|
|
gid_t gid;
|
|
|
|
|
|
|
|
bool rc;
|
|
|
|
debug_decl(group_matches, SUDO_DEBUG_MATCH)
|
|
|
|
debug_decl(group_matches, SUDO_DEBUG_MATCH)
|
|
|
|
|
|
|
|
|
|
|
|
if (*sudoers_group == '#') {
|
|
|
|
if (*sudoers_group == '#') {
|
|
|
|
gid = (gid_t) atoid(sudoers_group + 1, NULL, NULL, &errstr);
|
|
|
|
gid = (gid_t) atoid(sudoers_group + 1, NULL, NULL, &errstr);
|
|
|
|
if (errstr != NULL && gid == gr->gr_gid)
|
|
|
|
if (errstr != NULL && gid == gr->gr_gid) {
|
|
|
|
debug_return_bool(true);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Returns true if the given user belongs to the named group,
|
|
|
|
* Returns true if the given user belongs to the named group,
|
|
|
|
* else returns false.
|
|
|
|
* else returns false.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
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;
|
|
|
|
int matched = false;
|
|
|
|
struct passwd *pw0 = NULL;
|
|
|
|
struct passwd *pw0 = NULL;
|
|
|
|
debug_decl(usergr_matches, SUDO_DEBUG_MATCH)
|
|
|
|
debug_decl(usergr_matches, SUDO_DEBUG_MATCH)
|
|
|
|
|
|
|
|
|
|
|
|
/* make sure we have a valid usergroup, sudo style */
|
|
|
|
/* 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;
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (*group == ':' && def_group_plugin) {
|
|
|
|
if (*group == ':' && def_group_plugin) {
|
|
|
|
matched = group_plugin_query(user, group + 1, pw);
|
|
|
|
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 */
|
|
|
|
/* look up user's primary gid in the passwd file */
|
|
|
|
if (pw == NULL) {
|
|
|
|
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;
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
}
|
|
|
|
pw = pw0;
|
|
|
|
pw = pw0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@@ -854,6 +891,8 @@ done:
|
|
|
|
if (pw0 != NULL)
|
|
|
|
if (pw0 != NULL)
|
|
|
|
sudo_pw_delref(pw0);
|
|
|
|
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);
|
|
|
|
debug_return_bool(matched);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@@ -888,24 +927,26 @@ sudo_getdomainname(void)
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Returns true if "host" and "user" belong to the netgroup "netgr",
|
|
|
|
* 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...
|
|
|
|
* in which case that argument is not checked...
|
|
|
|
*
|
|
|
|
|
|
|
|
* XXX - swap order of host & shost
|
|
|
|
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
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
|
|
|
|
#ifdef HAVE_INNETGR
|
|
|
|
static char *domain;
|
|
|
|
static char *domain;
|
|
|
|
static int initialized;
|
|
|
|
static int initialized;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
bool rc = false;
|
|
|
|
debug_decl(netgr_matches, SUDO_DEBUG_MATCH)
|
|
|
|
debug_decl(netgr_matches, SUDO_DEBUG_MATCH)
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_INNETGR
|
|
|
|
#ifdef HAVE_INNETGR
|
|
|
|
/* make sure we have a valid netgroup, sudo style */
|
|
|
|
/* 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);
|
|
|
|
debug_return_bool(false);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* get the domain name (if any) */
|
|
|
|
/* get the domain name (if any) */
|
|
|
|
if (!initialized) {
|
|
|
|
if (!initialized) {
|
|
|
@@ -914,10 +955,15 @@ netgr_matches(char *netgr, char *lhost, char *shost, char *user)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (innetgr(netgr, lhost, user, domain))
|
|
|
|
if (innetgr(netgr, lhost, user, domain))
|
|
|
|
debug_return_bool(true);
|
|
|
|
rc = true;
|
|
|
|
else if (lhost != shost && innetgr(netgr, shost, user, domain))
|
|
|
|
else if (lhost != shost && innetgr(netgr, shost, user, domain))
|
|
|
|
debug_return_bool(true);
|
|
|
|
rc = true;
|
|
|
|
#endif /* HAVE_INNETGR */
|
|
|
|
#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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|