volatile int sources = 0;
sigaction_t sa;
struct sudo_nss *nss;
+ struct sudo_nss *nss_next;
debug_decl(sudoers_policy_open, SUDO_DEBUG_PLUGIN)
sudo_version = version;
set_perms(PERM_ROOT);
/* Open and parse sudoers, set global defaults */
- tq_foreach_fwd(snl, nss) {
- if (nss->open(nss) == 0 && nss->parse(nss) == 0) {
- sources++;
- if (nss->setdefs(nss) != 0)
- log_error(NO_STDERR, _("problem with defaults entries"));
- }
+ for (nss = snl->first; nss != NULL; nss = nss_next) {
+ nss_next = nss->next;
+ if (nss->open(nss) == 0 && nss->parse(nss) == 0) {
+ sources++;
+ if (nss->setdefs(nss) != 0)
+ log_error(NO_STDERR, _("problem with defaults entries"));
+ } else {
+ tq_remove(snl, nss);
+ }
}
if (sources == 0) {
warningx(_("no valid sudoers sources found, quitting"));
(void)sudo_auth_end_session(runas_pw);
/* Free remaining references to password and group entries. */
- pw_delref(sudo_user.pw);
- pw_delref(runas_pw);
- if (runas_gr != NULL)
- gr_delref(runas_gr);
- if (user_group_list != NULL)
- grlist_delref(user_group_list);
+ sudo_pw_delref(sudo_user.pw);
+ sudo_user.pw = NULL;
+ sudo_pw_delref(runas_pw);
+ runas_pw = NULL;
+ if (runas_gr != NULL) {
+ 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;
}
/*
* The init_session function is called before executing the command
* and before uid/gid changes occur.
+ * Returns 1 on success, 0 on failure and -1 on error.
*/
static int
sudoers_policy_init_session(struct passwd *pwd, char **user_env[])
if (sigsetjmp(error_jmp, 1)) {
/* called via error(), errorx() or log_fatal() */
- return -1;
+ debug_return_bool(-1);
}
debug_return_bool(sudo_auth_begin_session(pwd, user_env));
/* Find command in path */
cmnd_status = set_cmnd();
- if (cmnd_status == -1) {
- rval = -1;
- goto done;
- }
#ifdef HAVE_SETLOCALE
if (!setlocale(LC_ALL, def_sudoers_locale)) {
validated = nss->lookup(nss, validated, pwflag);
if (ISSET(validated, VALIDATE_OK)) {
- /* Handle "= auth" in netsvc.conf */
+ /* Handle [SUCCESS=return] */
if (nss->ret_if_found)
break;
} else {
pw = sudo_getpwnam(def_timestampowner);
if (pw != NULL) {
timestamp_uid = pw->pw_uid;
- pw_delref(pw);
+ sudo_pw_delref(pw);
} else {
log_error(0, _("timestamp owner (%s): No such user"),
def_timestampowner);
/* Require a password if sudoers says so. */
rval = check_user(validated, sudo_mode);
- if (rval != true)
+ if (rval != true) {
+ if (!ISSET(validated, VALIDATE_OK))
+ log_denial(validated, false);
goto done;
+ }
/* 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 */
if ((pw = sudo_getpwnam(prev_user)) != NULL) {
if (sudo_user.pw != NULL)
- pw_delref(sudo_user.pw);
+ sudo_pw_delref(sudo_user.pw);
sudo_user.pw = pw;
}
}
/* If the user was not allowed to run the command we are done. */
if (!ISSET(validated, VALIDATE_OK)) {
- if (ISSET(validated, FLAG_NO_USER | FLAG_NO_HOST)) {
- 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"));
- }
+ log_failure(validated, cmnd_status);
goto bad;
}
gid_t egid;
size_t glsize;
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. */
glsize = sizeof("runas_groups=") - 1 +
(unsigned int)runas_pw->pw_gid;
len = snprintf(cp, glsize - (cp - gid_list), "%u", egid);
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;
for (i = 0; i < grlist->ngids; i++) {
if (grlist->gids[i] != egid) {
len = snprintf(cp, glsize - (cp - gid_list), ",%u",
(unsigned int) grlist->gids[i]);
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;
}
}
command_info[info_len++] = gid_list;
- grlist_delref(grlist);
+ sudo_grlist_delref(grlist);
}
if (def_closefrom >= 0)
easprintf(&command_info[info_len++], "closefrom=%d", def_closefrom);
if (user_type != NULL)
command_info[info_len++] = fmt_string("selinux_type", user_type);
#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. */
audit_success(NewArgv);
}
rval = sudoers_policy_main(argc, argv, I_LISTPW, NULL, NULL, NULL, NULL);
if (list_user) {
- pw_delref(list_pw);
+ sudo_pw_delref(list_pw);
list_pw = NULL;
}
* Get group list.
*/
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. */
sudo_defs_table[I_RUNAS_DEFAULT].callback = cb_runas_default;
for (to = user_args, av = NewArgv + 1; *av; av++) {
n = strlcpy(to, *av, 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++ = ' ';
}
}
#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.
+ * Use AI_FQDN if available since "canonical" is not always the same as fqdn.
*/
void
set_fqdn(void)
zero_bytes(&hint, sizeof(hint));
hint.ai_family = PF_UNSPEC;
- hint.ai_flags = AI_CANONNAME;
+ hint.ai_flags = AI_FQDN;
if (getaddrinfo(user_host, NULL, &hint, &res0) != 0) {
log_error(MSG_ONLY, _("unable to resolve host %s"), user_host);
} else {
efree(user_host);
user_host = estrdup(res0->ai_canonname);
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_decl(set_runaspw, SUDO_DEBUG_PLUGIN)
if (runas_pw != NULL)
- pw_delref(runas_pw);
+ sudo_pw_delref(runas_pw);
if (*user == '#') {
if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL)
runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0);
debug_decl(set_runasgr, SUDO_DEBUG_PLUGIN)
if (runas_gr != NULL)
- gr_delref(runas_gr);
+ sudo_gr_delref(runas_gr);
if (*group == '#') {
if ((runas_gr = sudo_getgrgid(atoi(group + 1))) == NULL)
runas_gr = sudo_fakegrnam(group);
}
if (MATCHES(*cur, "runas_user=")) {
runas_user = *cur + sizeof("runas_user=") - 1;
+ sudo_user.flags |= RUNAS_USER_SPECIFIED;
continue;
}
if (MATCHES(*cur, "runas_group=")) {
runas_group = *cur + sizeof("runas_group=") - 1;
+ sudo_user.flags |= RUNAS_GROUP_SPECIFIED;
continue;
}
if (MATCHES(*cur, "prompt=")) {
def_use_loginclass = true;
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
if (MATCHES(*cur, "selinux_role=")) {
user_role = *cur + sizeof("selinux_role=") - 1;
sudo_user.cols = atoi(*cur + sizeof("cols=") - 1);
continue;
}
+ if (MATCHES(*cur, "sid=")) {
+ sudo_user.sid = atoi(*cur + sizeof("sid=") - 1);
+ continue;
+ }
}
if (user_cwd == NULL)
user_cwd = "unknown";
break;
cp++; /* skip over comma */
}
- set_group_list(user_name, gids, ngids);
- efree(gids);
+ user_gids = gids;
+ user_ngids = ngids;
}
/* Setup debugging if indicated. */
register_hook(&hook);
}
-struct policy_plugin sudoers_policy = {
+__dso_public struct policy_plugin sudoers_policy = {
SUDO_POLICY_PLUGIN,
SUDO_API_VERSION,
sudoers_policy_open,