version 1.1.1.2, 2012/05/29 12:26:49
|
version 1.1.1.3, 2012/10/09 09:29:52
|
Line 145 sudoers_policy_open(unsigned int version, sudo_conv_t
|
Line 145 sudoers_policy_open(unsigned int version, sudo_conv_t
|
volatile int sources = 0; |
volatile int sources = 0; |
sigaction_t sa; |
sigaction_t sa; |
struct sudo_nss *nss; |
struct sudo_nss *nss; |
|
struct sudo_nss *nss_next; |
debug_decl(sudoers_policy_open, SUDO_DEBUG_PLUGIN) |
debug_decl(sudoers_policy_open, SUDO_DEBUG_PLUGIN) |
|
|
sudo_version = version; |
sudo_version = version; |
Line 201 sudoers_policy_open(unsigned int version, sudo_conv_t
|
Line 202 sudoers_policy_open(unsigned int version, sudo_conv_t
|
set_perms(PERM_ROOT); |
set_perms(PERM_ROOT); |
|
|
/* Open and parse sudoers, set global defaults */ |
/* Open and parse sudoers, set global defaults */ |
tq_foreach_fwd(snl, nss) { | for (nss = snl->first; nss != NULL; nss = nss_next) { |
if (nss->open(nss) == 0 && nss->parse(nss) == 0) { | nss_next = nss->next; |
sources++; | if (nss->open(nss) == 0 && nss->parse(nss) == 0) { |
if (nss->setdefs(nss) != 0) | sources++; |
log_error(NO_STDERR, _("problem with defaults entries")); | if (nss->setdefs(nss) != 0) |
} | log_error(NO_STDERR, _("problem with defaults entries")); |
| } else { |
| tq_remove(snl, nss); |
| } |
} |
} |
if (sources == 0) { |
if (sources == 0) { |
warningx(_("no valid sudoers sources found, quitting")); |
warningx(_("no valid sudoers sources found, quitting")); |
Line 268 sudoers_policy_close(int exit_status, int error_code)
|
Line 272 sudoers_policy_close(int exit_status, int error_code)
|
(void)sudo_auth_end_session(runas_pw); |
(void)sudo_auth_end_session(runas_pw); |
|
|
/* Free remaining references to password and group entries. */ |
/* Free remaining references to password and group entries. */ |
pw_delref(sudo_user.pw); | sudo_pw_delref(sudo_user.pw); |
pw_delref(runas_pw); | sudo_user.pw = NULL; |
if (runas_gr != NULL) | sudo_pw_delref(runas_pw); |
gr_delref(runas_gr); | runas_pw = NULL; |
if (user_group_list != NULL) | if (runas_gr != NULL) { |
grlist_delref(user_group_list); | sudo_gr_delref(runas_gr); |
| runas_gr = NULL; |
| } |
| if (user_group_list != NULL) { |
| sudo_grlist_delref(user_group_list); |
| user_group_list = NULL; |
| } |
| efree(user_gids); |
| user_gids = NULL; |
|
|
debug_return; |
debug_return; |
} |
} |
Line 281 sudoers_policy_close(int exit_status, int error_code)
|
Line 293 sudoers_policy_close(int exit_status, int error_code)
|
/* |
/* |
* The init_session function is called before executing the command |
* The init_session function is called before executing the command |
* and before uid/gid changes occur. |
* and before uid/gid changes occur. |
|
* Returns 1 on success, 0 on failure and -1 on error. |
*/ |
*/ |
static int |
static int |
sudoers_policy_init_session(struct passwd *pwd, char **user_env[]) |
sudoers_policy_init_session(struct passwd *pwd, char **user_env[]) |
Line 293 sudoers_policy_init_session(struct passwd *pwd, char *
|
Line 306 sudoers_policy_init_session(struct passwd *pwd, char *
|
|
|
if (sigsetjmp(error_jmp, 1)) { |
if (sigsetjmp(error_jmp, 1)) { |
/* called via error(), errorx() or log_fatal() */ |
/* called via error(), errorx() or log_fatal() */ |
return -1; | debug_return_bool(-1); |
} |
} |
|
|
debug_return_bool(sudo_auth_begin_session(pwd, user_env)); |
debug_return_bool(sudo_auth_begin_session(pwd, user_env)); |
Line 363 sudoers_policy_main(int argc, char * const argv[], int
|
Line 376 sudoers_policy_main(int argc, char * const argv[], int
|
|
|
/* Find command in path */ |
/* Find command in path */ |
cmnd_status = set_cmnd(); |
cmnd_status = set_cmnd(); |
if (cmnd_status == -1) { |
|
rval = -1; |
|
goto done; |
|
} |
|
|
|
#ifdef HAVE_SETLOCALE |
#ifdef HAVE_SETLOCALE |
if (!setlocale(LC_ALL, def_sudoers_locale)) { |
if (!setlocale(LC_ALL, def_sudoers_locale)) { |
Line 384 sudoers_policy_main(int argc, char * const argv[], int
|
Line 393 sudoers_policy_main(int argc, char * const argv[], int
|
validated = nss->lookup(nss, validated, pwflag); |
validated = nss->lookup(nss, validated, pwflag); |
|
|
if (ISSET(validated, VALIDATE_OK)) { |
if (ISSET(validated, VALIDATE_OK)) { |
/* Handle "= auth" in netsvc.conf */ | /* Handle [SUCCESS=return] */ |
if (nss->ret_if_found) |
if (nss->ret_if_found) |
break; |
break; |
} else { |
} else { |
Line 417 sudoers_policy_main(int argc, char * const argv[], int
|
Line 426 sudoers_policy_main(int argc, char * const argv[], int
|
pw = sudo_getpwnam(def_timestampowner); |
pw = sudo_getpwnam(def_timestampowner); |
if (pw != NULL) { |
if (pw != NULL) { |
timestamp_uid = pw->pw_uid; |
timestamp_uid = pw->pw_uid; |
pw_delref(pw); | sudo_pw_delref(pw); |
} else { |
} else { |
log_error(0, _("timestamp owner (%s): No such user"), |
log_error(0, _("timestamp owner (%s): No such user"), |
def_timestampowner); |
def_timestampowner); |
Line 455 sudoers_policy_main(int argc, char * const argv[], int
|
Line 464 sudoers_policy_main(int argc, char * const argv[], int
|
|
|
/* Require a password if sudoers says so. */ |
/* Require a password if sudoers says so. */ |
rval = check_user(validated, sudo_mode); |
rval = check_user(validated, sudo_mode); |
if (rval != true) | if (rval != true) { |
| if (!ISSET(validated, VALIDATE_OK)) |
| log_failure(validated, cmnd_status); |
goto done; |
goto done; |
|
} |
|
|
/* If run as root with SUDO_USER set, set sudo_user.pw to that user. */ |
/* If run as root with SUDO_USER set, set sudo_user.pw to that user. */ |
/* XXX - causes confusion when root is not listed in sudoers */ |
/* XXX - causes confusion when root is not listed in sudoers */ |
Line 466 sudoers_policy_main(int argc, char * const argv[], int
|
Line 478 sudoers_policy_main(int argc, char * const argv[], int
|
|
|
if ((pw = sudo_getpwnam(prev_user)) != NULL) { |
if ((pw = sudo_getpwnam(prev_user)) != NULL) { |
if (sudo_user.pw != NULL) |
if (sudo_user.pw != NULL) |
pw_delref(sudo_user.pw); | sudo_pw_delref(sudo_user.pw); |
sudo_user.pw = pw; |
sudo_user.pw = pw; |
} |
} |
} |
} |
Line 474 sudoers_policy_main(int argc, char * const argv[], int
|
Line 486 sudoers_policy_main(int argc, char * const argv[], int
|
|
|
/* If the user was not allowed to run the command we are done. */ |
/* If the user was not allowed to run the command we are done. */ |
if (!ISSET(validated, VALIDATE_OK)) { |
if (!ISSET(validated, VALIDATE_OK)) { |
if (ISSET(validated, FLAG_NO_USER | FLAG_NO_HOST)) { | log_failure(validated, cmnd_status); |
audit_failure(NewArgv, _("No user or host")); | |
log_denial(validated, 1); | |
} else { | |
if (def_path_info) { | |
/* | |
* We'd like to not leak path info at all here, but that can | |
* *really* confuse the users. To really close the leak we'd | |
* have to say "not allowed to run foo" even when the problem | |
* is just "no foo in path" since the user can trivially set | |
* their path to just contain a single dir. | |
*/ | |
log_denial(validated, | |
!(cmnd_status == NOT_FOUND_DOT || cmnd_status == NOT_FOUND)); | |
if (cmnd_status == NOT_FOUND) | |
warningx(_("%s: command not found"), user_cmnd); | |
else if (cmnd_status == NOT_FOUND_DOT) | |
warningx(_("ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run."), user_cmnd, user_cmnd, user_cmnd); | |
} else { | |
/* Just tell the user they are not allowed to run foo. */ | |
log_denial(validated, 1); | |
} | |
audit_failure(NewArgv, _("validation failure")); | |
} | |
goto bad; |
goto bad; |
} |
} |
|
|
Line 664 sudoers_policy_main(int argc, char * const argv[], int
|
Line 653 sudoers_policy_main(int argc, char * const argv[], int
|
gid_t egid; |
gid_t egid; |
size_t glsize; |
size_t glsize; |
char *cp, *gid_list; |
char *cp, *gid_list; |
struct group_list *grlist = get_group_list(runas_pw); | struct group_list *grlist = sudo_get_grlist(runas_pw); |
|
|
/* We reserve an extra spot in the list for the effective gid. */ |
/* We reserve an extra spot in the list for the effective gid. */ |
glsize = sizeof("runas_groups=") - 1 + |
glsize = sizeof("runas_groups=") - 1 + |
Line 678 sudoers_policy_main(int argc, char * const argv[], int
|
Line 667 sudoers_policy_main(int argc, char * const argv[], int
|
(unsigned int)runas_pw->pw_gid; |
(unsigned int)runas_pw->pw_gid; |
len = snprintf(cp, glsize - (cp - gid_list), "%u", egid); |
len = snprintf(cp, glsize - (cp - gid_list), "%u", egid); |
if (len < 0 || len >= glsize - (cp - gid_list)) |
if (len < 0 || len >= glsize - (cp - gid_list)) |
errorx(1, _("internal error, runas_groups overflow")); | errorx(1, _("internal error, %s overflow"), "runas_groups"); |
cp += len; |
cp += len; |
for (i = 0; i < grlist->ngids; i++) { |
for (i = 0; i < grlist->ngids; i++) { |
if (grlist->gids[i] != egid) { |
if (grlist->gids[i] != egid) { |
len = snprintf(cp, glsize - (cp - gid_list), ",%u", |
len = snprintf(cp, glsize - (cp - gid_list), ",%u", |
(unsigned int) grlist->gids[i]); |
(unsigned int) grlist->gids[i]); |
if (len < 0 || len >= glsize - (cp - gid_list)) |
if (len < 0 || len >= glsize - (cp - gid_list)) |
errorx(1, _("internal error, runas_groups overflow")); | errorx(1, _("internal error, %s overflow"), "runas_groups"); |
cp += len; |
cp += len; |
} |
} |
} |
} |
command_info[info_len++] = gid_list; |
command_info[info_len++] = gid_list; |
grlist_delref(grlist); | sudo_grlist_delref(grlist); |
} |
} |
if (def_closefrom >= 0) |
if (def_closefrom >= 0) |
easprintf(&command_info[info_len++], "closefrom=%d", def_closefrom); |
easprintf(&command_info[info_len++], "closefrom=%d", def_closefrom); |
Line 712 sudoers_policy_main(int argc, char * const argv[], int
|
Line 701 sudoers_policy_main(int argc, char * const argv[], int
|
if (user_type != NULL) |
if (user_type != NULL) |
command_info[info_len++] = fmt_string("selinux_type", user_type); |
command_info[info_len++] = fmt_string("selinux_type", user_type); |
#endif /* HAVE_SELINUX */ |
#endif /* HAVE_SELINUX */ |
|
#ifdef HAVE_PRIV_SET |
|
if (runas_privs != NULL) |
|
command_info[info_len++] = fmt_string("runas_privs", runas_privs); |
|
if (runas_limitprivs != NULL) |
|
command_info[info_len++] = fmt_string("runas_limitprivs", runas_limitprivs); |
|
#endif /* HAVE_SELINUX */ |
|
|
/* Must audit before uid change. */ |
/* Must audit before uid change. */ |
audit_success(NewArgv); |
audit_success(NewArgv); |
Line 800 sudoers_policy_list(int argc, char * const argv[], int
|
Line 795 sudoers_policy_list(int argc, char * const argv[], int
|
} |
} |
rval = sudoers_policy_main(argc, argv, I_LISTPW, NULL, NULL, NULL, NULL); |
rval = sudoers_policy_main(argc, argv, I_LISTPW, NULL, NULL, NULL, NULL); |
if (list_user) { |
if (list_user) { |
pw_delref(list_pw); | sudo_pw_delref(list_pw); |
list_pw = NULL; |
list_pw = NULL; |
} |
} |
|
|
Line 865 init_vars(char * const envp[])
|
Line 860 init_vars(char * const envp[])
|
* Get group list. |
* Get group list. |
*/ |
*/ |
if (user_group_list == NULL) |
if (user_group_list == NULL) |
user_group_list = get_group_list(sudo_user.pw); | user_group_list = sudo_get_grlist(sudo_user.pw); |
|
|
/* Set runas callback. */ |
/* Set runas callback. */ |
sudo_defs_table[I_RUNAS_DEFAULT].callback = cb_runas_default; |
sudo_defs_table[I_RUNAS_DEFAULT].callback = cb_runas_default; |
Line 938 set_cmnd(void)
|
Line 933 set_cmnd(void)
|
for (to = user_args, av = NewArgv + 1; *av; av++) { |
for (to = user_args, av = NewArgv + 1; *av; av++) { |
n = strlcpy(to, *av, size - (to - user_args)); |
n = strlcpy(to, *av, size - (to - user_args)); |
if (n >= size - (to - user_args)) |
if (n >= size - (to - user_args)) |
errorx(1, _("internal error, set_cmnd() overflow")); | errorx(1, _("internal error, %s overflow"), "set_cmnd()"); |
to += n; |
to += n; |
*to++ = ' '; |
*to++ = ' '; |
} |
} |
Line 975 open_sudoers(const char *sudoers, bool doedit, bool *k
|
Line 970 open_sudoers(const char *sudoers, bool doedit, bool *k
|
|
|
switch (sudo_secure_file(sudoers, sudoers_uid, sudoers_gid, &sb)) { |
switch (sudo_secure_file(sudoers, sudoers_uid, sudoers_gid, &sb)) { |
case SUDO_PATH_SECURE: |
case SUDO_PATH_SECURE: |
|
/* |
|
* If we are expecting sudoers to be group readable but |
|
* it is not, we must open the file as root, not uid 1. |
|
*/ |
|
if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP)) { |
|
if ((sb.st_mode & S_IRGRP) == 0) { |
|
restore_perms(); |
|
set_perms(PERM_ROOT); |
|
} |
|
} |
|
/* |
|
* Open sudoers and make sure we can read it so we can present |
|
* the user with a reasonable error message (unlike the lexer). |
|
*/ |
if ((fp = fopen(sudoers, "r")) == NULL) { |
if ((fp = fopen(sudoers, "r")) == NULL) { |
log_error(USE_ERRNO, _("unable to open %s"), sudoers); |
log_error(USE_ERRNO, _("unable to open %s"), sudoers); |
} else { |
} else { |
/* |
|
* Make sure we can actually read sudoers so we can present the |
|
* user with a reasonable error message (unlike the lexer). |
|
*/ |
|
if (sb.st_size != 0 && fgetc(fp) == EOF) { |
if (sb.st_size != 0 && fgetc(fp) == EOF) { |
log_error(USE_ERRNO, _("unable to read %s"), |
log_error(USE_ERRNO, _("unable to read %s"), |
sudoers); |
sudoers); |
Line 1067 set_loginclass(struct passwd *pw)
|
Line 1072 set_loginclass(struct passwd *pw)
|
} |
} |
#endif /* HAVE_LOGIN_CAP_H */ |
#endif /* HAVE_LOGIN_CAP_H */ |
|
|
|
#ifndef AI_FQDN |
|
# define AI_FQDN AI_CANONNAME |
|
#endif |
|
|
/* |
/* |
* Look up the fully qualified domain name and set user_host and user_shost. |
* Look up the fully qualified domain name and set user_host and user_shost. |
|
* Use AI_FQDN if available since "canonical" is not always the same as fqdn. |
*/ |
*/ |
void |
void |
set_fqdn(void) |
set_fqdn(void) |
Line 1079 set_fqdn(void)
|
Line 1089 set_fqdn(void)
|
|
|
zero_bytes(&hint, sizeof(hint)); |
zero_bytes(&hint, sizeof(hint)); |
hint.ai_family = PF_UNSPEC; |
hint.ai_family = PF_UNSPEC; |
hint.ai_flags = AI_CANONNAME; | hint.ai_flags = AI_FQDN; |
if (getaddrinfo(user_host, NULL, &hint, &res0) != 0) { |
if (getaddrinfo(user_host, NULL, &hint, &res0) != 0) { |
log_error(MSG_ONLY, _("unable to resolve host %s"), user_host); |
log_error(MSG_ONLY, _("unable to resolve host %s"), user_host); |
} else { |
} else { |
Line 1088 set_fqdn(void)
|
Line 1098 set_fqdn(void)
|
efree(user_host); |
efree(user_host); |
user_host = estrdup(res0->ai_canonname); |
user_host = estrdup(res0->ai_canonname); |
freeaddrinfo(res0); |
freeaddrinfo(res0); |
|
if ((p = strchr(user_host, '.')) != NULL) |
|
user_shost = estrndup(user_host, (size_t)(p - user_host)); |
|
else |
|
user_shost = user_host; |
} |
} |
if ((p = strchr(user_host, '.')) != NULL) |
|
user_shost = estrndup(user_host, (size_t)(p - user_host)); |
|
else |
|
user_shost = user_host; |
|
debug_return; |
debug_return; |
} |
} |
|
|
Line 1106 set_runaspw(const char *user)
|
Line 1116 set_runaspw(const char *user)
|
debug_decl(set_runaspw, SUDO_DEBUG_PLUGIN) |
debug_decl(set_runaspw, SUDO_DEBUG_PLUGIN) |
|
|
if (runas_pw != NULL) |
if (runas_pw != NULL) |
pw_delref(runas_pw); | sudo_pw_delref(runas_pw); |
if (*user == '#') { |
if (*user == '#') { |
if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL) |
if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL) |
runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0); |
runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0); |
Line 1127 set_runasgr(const char *group)
|
Line 1137 set_runasgr(const char *group)
|
debug_decl(set_runasgr, SUDO_DEBUG_PLUGIN) |
debug_decl(set_runasgr, SUDO_DEBUG_PLUGIN) |
|
|
if (runas_gr != NULL) |
if (runas_gr != NULL) |
gr_delref(runas_gr); | sudo_gr_delref(runas_gr); |
if (*group == '#') { |
if (*group == '#') { |
if ((runas_gr = sudo_getgrgid(atoi(group + 1))) == NULL) |
if ((runas_gr = sudo_getgrgid(atoi(group + 1))) == NULL) |
runas_gr = sudo_fakegrnam(group); |
runas_gr = sudo_fakegrnam(group); |
Line 1254 deserialize_info(char * const args[], char * const set
|
Line 1264 deserialize_info(char * const args[], char * const set
|
} |
} |
if (MATCHES(*cur, "runas_user=")) { |
if (MATCHES(*cur, "runas_user=")) { |
runas_user = *cur + sizeof("runas_user=") - 1; |
runas_user = *cur + sizeof("runas_user=") - 1; |
|
sudo_user.flags |= RUNAS_USER_SPECIFIED; |
continue; |
continue; |
} |
} |
if (MATCHES(*cur, "runas_group=")) { |
if (MATCHES(*cur, "runas_group=")) { |
runas_group = *cur + sizeof("runas_group=") - 1; |
runas_group = *cur + sizeof("runas_group=") - 1; |
|
sudo_user.flags |= RUNAS_GROUP_SPECIFIED; |
continue; |
continue; |
} |
} |
if (MATCHES(*cur, "prompt=")) { |
if (MATCHES(*cur, "prompt=")) { |
Line 1317 deserialize_info(char * const args[], char * const set
|
Line 1329 deserialize_info(char * const args[], char * const set
|
def_use_loginclass = true; |
def_use_loginclass = true; |
continue; |
continue; |
} |
} |
|
#ifdef HAVE_PRIV_SET |
|
if (MATCHES(*cur, "runas_privs=")) { |
|
def_privs = *cur + sizeof("runas_privs=") - 1; |
|
continue; |
|
} |
|
if (MATCHES(*cur, "runas_limitprivs=")) { |
|
def_limitprivs = *cur + sizeof("runas_limitprivs=") - 1; |
|
continue; |
|
} |
|
#endif /* HAVE_PRIV_SET */ |
#ifdef HAVE_SELINUX |
#ifdef HAVE_SELINUX |
if (MATCHES(*cur, "selinux_role=")) { |
if (MATCHES(*cur, "selinux_role=")) { |
user_role = *cur + sizeof("selinux_role=") - 1; |
user_role = *cur + sizeof("selinux_role=") - 1; |
Line 1420 deserialize_info(char * const args[], char * const set
|
Line 1442 deserialize_info(char * const args[], char * const set
|
break; |
break; |
cp++; /* skip over comma */ |
cp++; /* skip over comma */ |
} |
} |
set_group_list(user_name, gids, ngids); | user_gids = gids; |
efree(gids); | user_ngids = ngids; |
} |
} |
|
|
/* Setup debugging if indicated. */ |
/* Setup debugging if indicated. */ |
Line 1586 sudoers_policy_register_hooks(int version, int (*regis
|
Line 1608 sudoers_policy_register_hooks(int version, int (*regis
|
register_hook(&hook); |
register_hook(&hook); |
} |
} |
|
|
struct policy_plugin sudoers_policy = { | __dso_public struct policy_plugin sudoers_policy = { |
SUDO_POLICY_PLUGIN, |
SUDO_POLICY_PLUGIN, |
SUDO_API_VERSION, |
SUDO_API_VERSION, |
sudoers_policy_open, |
sudoers_policy_open, |