version 1.1.1.4, 2013/07/22 10:46:12
|
version 1.1.1.6, 2014/06/15 16:12:54
|
Line 91
|
Line 91
|
#include "sha2.h" |
#include "sha2.h" |
#include <gram.h> |
#include <gram.h> |
|
|
static struct member_list 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. |
Line 110 static bool command_matches_normal(char *, char *, str
|
Line 110 static bool command_matches_normal(char *, char *, str
|
* 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; |
int rval, matched = UNSPEC; |
int rval, matched = UNSPEC; |
debug_decl(userlist_matches, SUDO_DEBUG_MATCH) |
debug_decl(userlist_matches, SUDO_DEBUG_MATCH) |
|
|
tq_foreach_rev(list, m) { | TAILQ_FOREACH_REVERSE(m, list, member_list, entries) { |
switch (m->type) { |
switch (m->type) { |
case ALL: |
case ALL: |
matched = !m->negated; |
matched = !m->negated; |
Line 156 userlist_matches(struct passwd *pw, struct member_list
|
Line 156 userlist_matches(struct passwd *pw, struct member_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; |
Line 169 runaslist_matches(struct member_list *user_list,
|
Line 169 runaslist_matches(struct member_list *user_list,
|
|
|
if (runas_pw != NULL) { |
if (runas_pw != NULL) { |
/* If no runas user or runas group listed in sudoers, use default. */ |
/* If no runas user or runas group listed in sudoers, use default. */ |
if (tq_empty(user_list) && tq_empty(group_list)) | if (user_list == NULL && group_list == NULL) |
debug_return_int(userpw_matches(def_runas_default, runas_pw->pw_name, runas_pw)); |
debug_return_int(userpw_matches(def_runas_default, runas_pw->pw_name, runas_pw)); |
|
|
tq_foreach_rev(user_list, m) { | if (user_list != NULL) { |
switch (m->type) { | TAILQ_FOREACH_REVERSE(m, user_list, member_list, entries) { |
case ALL: | switch (m->type) { |
user_matched = !m->negated; | case ALL: |
break; | |
case NETGROUP: | |
if (netgr_matches(m->name, NULL, NULL, runas_pw->pw_name)) | |
user_matched = !m->negated; |
user_matched = !m->negated; |
break; |
|
case USERGROUP: |
|
if (usergr_matches(m->name, runas_pw->pw_name, runas_pw)) |
|
user_matched = !m->negated; |
|
break; |
|
case ALIAS: |
|
if ((a = alias_get(m->name, RUNASALIAS)) != NULL) { |
|
rval = runaslist_matches(&a->members, &empty, |
|
matching_user, NULL); |
|
if (rval != UNSPEC) |
|
user_matched = m->negated ? !rval : rval; |
|
alias_put(a); |
|
break; |
break; |
} | case NETGROUP: |
/* FALLTHROUGH */ | if (netgr_matches(m->name, NULL, NULL, runas_pw->pw_name)) |
case WORD: | user_matched = !m->negated; |
if (userpw_matches(m->name, runas_pw->pw_name, runas_pw)) | break; |
user_matched = !m->negated; | case USERGROUP: |
| if (usergr_matches(m->name, runas_pw->pw_name, runas_pw)) |
| user_matched = !m->negated; |
| break; |
| case ALIAS: |
| if ((a = alias_get(m->name, RUNASALIAS)) != NULL) { |
| rval = runaslist_matches(&a->members, &empty, |
| matching_user, NULL); |
| if (rval != UNSPEC) |
| user_matched = m->negated ? !rval : rval; |
| alias_put(a); |
| break; |
| } |
| /* FALLTHROUGH */ |
| case WORD: |
| if (userpw_matches(m->name, runas_pw->pw_name, runas_pw)) |
| user_matched = !m->negated; |
| break; |
| case MYSELF: |
| if (!ISSET(sudo_user.flags, RUNAS_USER_SPECIFIED) || |
| strcmp(user_name, runas_pw->pw_name) == 0) |
| user_matched = !m->negated; |
| break; |
| } |
| if (user_matched != UNSPEC) { |
| if (matching_user != NULL && m->type != ALIAS) |
| *matching_user = m; |
break; |
break; |
case MYSELF: | } |
if (!ISSET(sudo_user.flags, RUNAS_USER_SPECIFIED) || | |
strcmp(user_name, runas_pw->pw_name) == 0) | |
user_matched = !m->negated; | |
break; | |
} |
} |
if (user_matched != UNSPEC) { |
|
if (matching_user != NULL && m->type != ALIAS) |
|
*matching_user = m; |
|
break; |
|
} |
|
} |
} |
} |
} |
|
|
Line 218 runaslist_matches(struct member_list *user_list,
|
Line 220 runaslist_matches(struct member_list *user_list,
|
if (runas_pw == NULL || strcmp(runas_pw->pw_name, user_name) == 0) |
if (runas_pw == NULL || strcmp(runas_pw->pw_name, user_name) == 0) |
user_matched = ALLOW; /* only changing group */ |
user_matched = ALLOW; /* only changing group */ |
} |
} |
tq_foreach_rev(group_list, m) { | if (group_list != NULL) { |
switch (m->type) { | TAILQ_FOREACH_REVERSE(m, group_list, member_list, entries) { |
case ALL: | switch (m->type) { |
group_matched = !m->negated; | case ALL: |
break; | |
case ALIAS: | |
if ((a = alias_get(m->name, RUNASALIAS)) != NULL) { | |
rval = runaslist_matches(&empty, &a->members, | |
NULL, matching_group); | |
if (rval != UNSPEC) | |
group_matched = m->negated ? !rval : rval; | |
alias_put(a); | |
break; | |
} | |
/* FALLTHROUGH */ | |
case WORD: | |
if (group_matches(m->name, runas_gr)) | |
group_matched = !m->negated; |
group_matched = !m->negated; |
|
break; |
|
case ALIAS: |
|
if ((a = alias_get(m->name, RUNASALIAS)) != NULL) { |
|
rval = runaslist_matches(&empty, &a->members, |
|
NULL, matching_group); |
|
if (rval != UNSPEC) |
|
group_matched = m->negated ? !rval : rval; |
|
alias_put(a); |
|
break; |
|
} |
|
/* FALLTHROUGH */ |
|
case WORD: |
|
if (group_matches(m->name, runas_gr)) |
|
group_matched = !m->negated; |
|
break; |
|
} |
|
if (group_matched != UNSPEC) { |
|
if (matching_group != NULL && m->type != ALIAS) |
|
*matching_group = m; |
break; |
break; |
|
} |
} |
} |
if (group_matched != UNSPEC) { |
|
if (matching_group != NULL && m->type != ALIAS) |
|
*matching_group = m; |
|
break; |
|
} |
|
} |
} |
if (group_matched == UNSPEC) { |
if (group_matched == UNSPEC) { |
if (runas_pw != NULL && runas_pw->pw_gid == runas_gr->gr_gid) |
if (runas_pw != NULL && runas_pw->pw_gid == runas_gr->gr_gid) |
Line 262 runaslist_matches(struct member_list *user_list,
|
Line 266 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; |
int rval, matched = UNSPEC; |
int rval, matched = UNSPEC; |
debug_decl(hostlist_matches, SUDO_DEBUG_MATCH) |
debug_decl(hostlist_matches, SUDO_DEBUG_MATCH) |
|
|
tq_foreach_rev(list, m) { | TAILQ_FOREACH_REVERSE(m, list, member_list, entries) { |
switch (m->type) { |
switch (m->type) { |
case ALL: |
case ALL: |
matched = !m->negated; |
matched = !m->negated; |
break; |
break; |
case NETGROUP: |
case NETGROUP: |
if (netgr_matches(m->name, user_host, user_shost, NULL)) | if (netgr_matches(m->name, user_runhost, user_srunhost, NULL)) |
matched = !m->negated; |
matched = !m->negated; |
break; |
break; |
case NTWKADDR: |
case NTWKADDR: |
Line 292 hostlist_matches(struct member_list *list)
|
Line 296 hostlist_matches(struct member_list *list)
|
} |
} |
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
case WORD: |
case WORD: |
if (hostname_matches(user_shost, user_host, m->name)) | if (hostname_matches(user_srunhost, user_runhost, m->name)) |
matched = !m->negated; |
matched = !m->negated; |
break; |
break; |
} |
} |
Line 307 hostlist_matches(struct member_list *list)
|
Line 311 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; |
debug_decl(cmndlist_matches, SUDO_DEBUG_MATCH) |
debug_decl(cmndlist_matches, SUDO_DEBUG_MATCH) |
|
|
tq_foreach_rev(list, m) { | TAILQ_FOREACH_REVERSE(m, list, member_list, entries) { |
matched = cmnd_matches(m); |
matched = cmnd_matches(m); |
if (matched != UNSPEC) |
if (matched != UNSPEC) |
break; |
break; |
Line 326 cmndlist_matches(struct member_list *list)
|
Line 330 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; |
Line 355 cmnd_matches(struct member *m)
|
Line 359 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) |
Line 386 command_args_match(char *sudoers_cmnd, char *sudoers_a
|
Line 390 command_args_match(char *sudoers_cmnd, char *sudoers_a
|
* 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 */ |
Line 398 command_matches(char *sudoers_cmnd, char *sudoers_args
|
Line 403 command_matches(char *sudoers_cmnd, char *sudoers_args
|
* 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)) { |
Line 415 command_matches(char *sudoers_cmnd, char *sudoers_args
|
Line 419 command_matches(char *sudoers_cmnd, char *sudoers_args
|
* 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) |
|
|
Line 450 command_matches_fnmatch(char *sudoers_cmnd, char *sudo
|
Line 463 command_matches_fnmatch(char *sudoers_cmnd, char *sudo
|
|
|
#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; |
Line 523 command_matches_glob(char *sudoers_cmnd, char *sudoers
|
Line 536 command_matches_glob(char *sudoers_cmnd, char *sudoers
|
|
|
#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) |
Line 582 static struct digest_function {
|
Line 595 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]; |
Line 601 digest_matches(char *file, struct sudo_digest *sd)
|
Line 614 digest_matches(char *file, struct sudo_digest *sd)
|
} |
} |
} |
} |
if (func == NULL) { |
if (func == NULL) { |
warningx(_("unsupported digest type %d for %s"), sd->digest_type, file); | warningx(U_("unsupported digest type %d for %s"), sd->digest_type, file); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
if (strlen(sd->digest_str) == func->digest_len * 2) { |
if (strlen(sd->digest_str) == func->digest_len * 2) { |
Line 631 digest_matches(char *file, struct sudo_digest *sd)
|
Line 644 digest_matches(char *file, struct sudo_digest *sd)
|
func->update(&ctx, buf, nread); |
func->update(&ctx, buf, nread); |
} |
} |
if (ferror(fp)) { |
if (ferror(fp)) { |
warningx(_("%s: read error"), file); | warningx(U_("%s: read error"), file); |
fclose(fp); |
fclose(fp); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
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(_("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); |
debug_return_bool(false); |
debug_return_bool(false); |
} |
} |
|
|
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) |
|
|
Line 696 command_matches_normal(char *sudoers_cmnd, char *sudoe
|
Line 714 command_matches_normal(char *sudoers_cmnd, char *sudoe
|
* 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); |
Line 706 command_matches_dir(char *sudoers_dir, size_t dlen)
|
Line 724 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; |
Line 753 command_matches_dir(char *sudoers_dir, size_t dlen)
|
Line 771 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; |
|
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_t uid = (uid_t) atoi(sudoers_user + 1); | uid = (uid_t) atoid(sudoers_user + 1, NULL, NULL, &errstr); |
if (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; |
|
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_t gid = (gid_t) atoi(sudoers_group + 1); | gid = (gid_t) atoid(sudoers_group + 1, NULL, NULL, &errstr); |
if (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); |
Line 826 usergr_matches(char *group, char *user, struct passwd
|
Line 868 usergr_matches(char *group, char *user, struct passwd
|
|
|
/* 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; |
} |
} |
|
|
Line 846 done:
|
Line 891 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); |
} |
} |
|
|
Line 880 sudo_getdomainname(void)
|
Line 927 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) |
|
|
|
if (!def_use_netgroups) { |
|
sudo_debug_printf(SUDO_DEBUG_INFO, "netgroups are disabled"); |
|
debug_return_bool(false); |
|
} |
|
|
#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) { |
Line 906 netgr_matches(char *netgr, char *lhost, char *shost, c
|
Line 960 netgr_matches(char *netgr, char *lhost, char *shost, c
|
} |
} |
|
|
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); |
} |
} |