#endif
#include <ctype.h>
#include <setjmp.h>
+#ifndef HAVE_GETADDRINFO
+# include "compat/getaddrinfo.h"
+#endif
#include "sudoers.h"
#include "interfaces.h"
struct passwd *list_pw;
struct interface *interfaces;
int long_list;
-int debug_level;
uid_t timestamp_uid;
extern int errorlineno;
-extern int parse_error;
+extern bool parse_error;
extern char *errorfile;
-#ifdef HAVE_LOGIN_CAP_H
-login_cap_t *lc;
-#endif /* HAVE_LOGIN_CAP_H */
#ifdef HAVE_BSD_AUTH_H
char *login_style;
#endif /* HAVE_BSD_AUTH_H */
int NewArgc;
char **NewArgv;
-/* plugin_error.c */
-extern sigjmp_buf error_jmp;
+/* Declared here instead of plugin_error.c for static sudo builds. */
+sigjmp_buf error_jmp;
static int
sudoers_policy_open(unsigned int version, sudo_conv_t conversation,
volatile int sources = 0;
sigaction_t sa;
struct sudo_nss *nss;
+ debug_decl(sudoers_policy_open, SUDO_DEBUG_PLUGIN)
if (!sudo_conv)
sudo_conv = conversation;
if (sigsetjmp(error_jmp, 1)) {
/* called via error(), errorx() or log_error() */
rewind_perms();
- return -1;
+ debug_return_bool(-1);
}
bindtextdomain("sudoers", LOCALEDIR);
}
if (sources == 0) {
warningx(_("no valid sudoers sources found, quitting"));
- return -1;
+ debug_return_bool(-1);
}
/* XXX - collect post-sudoers parse settings into a function */
* Initialize external group plugin, if any.
*/
if (def_group_plugin) {
- if (group_plugin_load(def_group_plugin) != TRUE)
+ if (group_plugin_load(def_group_plugin) != true)
def_group_plugin = NULL;
}
set_fqdn(); /* deferred until after sudoers is parsed */
/* Set login class if applicable. */
- set_loginclass(sudo_user.pw);
+ set_loginclass(runas_pw ? runas_pw : sudo_user.pw);
restore_perms();
- return TRUE;
+ debug_return_bool(true);
}
static void
sudoers_policy_close(int exit_status, int error_code)
{
+ debug_decl(sudoers_policy_close, SUDO_DEBUG_PLUGIN)
+
if (sigsetjmp(error_jmp, 1)) {
/* called via error(), errorx() or log_error() */
- return;
+ debug_return;
}
/* We do not currently log the exit status. */
gr_delref(runas_gr);
if (user_group_list != NULL)
grlist_delref(user_group_list);
+
+ debug_return;
}
/*
static int
sudoers_policy_init_session(struct passwd *pwd)
{
+ debug_decl(sudoers_policy_init, SUDO_DEBUG_PLUGIN)
+
if (sigsetjmp(error_jmp, 1)) {
/* called via error(), errorx() or log_error() */
return -1;
}
- return sudo_auth_begin_session(pwd);
+ debug_return_bool(sudo_auth_begin_session(pwd));
}
static int
struct sudo_nss *nss;
int cmnd_status = -1, validated;
volatile int info_len = 0;
- volatile int rval = TRUE;
+ volatile int rval = true;
+ debug_decl(sudoers_policy_main, SUDO_DEBUG_PLUGIN)
if (sigsetjmp(error_jmp, 1)) {
/* error recovery via error(), errorx() or log_error() */
NewArgv = emalloc2(NewArgc + 2, sizeof(char *));
memcpy(++NewArgv, argv, argc * sizeof(char *));
NewArgv[NewArgc] = NULL;
- if (ISSET(sudo_mode, MODE_LOGIN_SHELL))
+ if (ISSET(sudo_mode, MODE_LOGIN_SHELL) && runas_pw != NULL)
NewArgv[0] = estrdup(runas_pw->pw_shell);
}
/* If given the -P option, set the "preserve_groups" flag. */
if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS))
- def_preserve_groups = TRUE;
+ def_preserve_groups = true;
/* Find command in path */
cmnd_status = set_cmnd();
*/
if (ISSET(sudo_mode, MODE_EDIT) ||
(ISSET(sudo_mode, MODE_PRESERVE_ENV) && def_setenv))
- def_env_reset = FALSE;
+ def_env_reset = false;
/* Build a new environment that avoids any nasty bits. */
rebuild_env();
/* Require a password if sudoers says so. */
rval = check_user(validated, sudo_mode);
- if (rval != TRUE)
+ if (rval != true)
goto done;
/* If run as root with SUDO_USER set, set sudo_user.pw to that user. */
#if defined(__linux__) || defined(_AIX)
/* Insert system-wide environment variables. */
- read_env_file(_PATH_ENVIRONMENT, TRUE);
+ read_env_file(_PATH_ENVIRONMENT, true);
#endif
}
/* Insert system-wide environment variables. */
if (def_env_file)
- read_env_file(def_env_file, FALSE);
+ read_env_file(def_env_file, false);
/* Insert user-specified environment variables. */
insert_env_vars(sudo_user.env_vars);
command_info[info_len++] = "preserve_groups=true";
} else {
int i, len;
+ gid_t egid;
size_t glsize;
char *cp, *gid_list;
struct group_list *grlist = get_group_list(runas_pw);
- glsize = sizeof("runas_groups=") - 1 + (grlist->ngids * (MAX_UID_T_LEN + 1));
+ /* We reserve an extra spot in the list for the effective gid. */
+ glsize = sizeof("runas_groups=") - 1 +
+ ((grlist->ngids + 1) * (MAX_UID_T_LEN + 1));
gid_list = emalloc(glsize);
memcpy(gid_list, "runas_groups=", sizeof("runas_groups=") - 1);
cp = gid_list + sizeof("runas_groups=") - 1;
+
+ /* On BSD systems the effective gid is the first group in the list. */
+ egid = runas_gr ? (unsigned int)runas_gr->gr_gid :
+ (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"));
+ cp += len;
for (i = 0; i < grlist->ngids; i++) {
- /* XXX - check rval */
- len = snprintf(cp, glsize - (cp - gid_list), "%s%u",
- i ? "," : "", (unsigned int) grlist->gids[i]);
- cp += len;
+ 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"));
+ cp += len;
+ }
}
command_info[info_len++] = gid_list;
grlist_delref(grlist);
easprintf(&command_info[info_len++], "closefrom=%d", def_closefrom);
if (def_noexec)
command_info[info_len++] = estrdup("noexec=true");
- if (def_noexec_file)
- command_info[info_len++] = fmt_string("noexec_file", def_noexec_file);
if (def_set_utmp)
command_info[info_len++] = estrdup("set_utmp=true");
if (def_use_pty)
if (def_utmp_runas)
command_info[info_len++] = fmt_string("utmp_user", runas_pw->pw_name);
#ifdef HAVE_LOGIN_CAP_H
- if (lc != NULL)
- command_info[info_len++] = fmt_string("login_class", lc->lc_class);
+ if (def_use_loginclass)
+ command_info[info_len++] = fmt_string("login_class", login_class);
#endif /* HAVE_LOGIN_CAP_H */
#ifdef HAVE_SELINUX
if (user_role != NULL)
goto done;
bad:
- rval = FALSE;
+ rval = false;
done:
rewind_perms();
sudo_endpwent();
sudo_endgrent();
- return rval;
+ debug_return_bool(rval);
}
static int
sudoers_policy_check(int argc, char * const argv[], char *env_add[],
char **command_infop[], char **argv_out[], char **user_env_out[])
{
+ debug_decl(sudoers_policy_check, SUDO_DEBUG_PLUGIN)
+
if (!ISSET(sudo_mode, MODE_EDIT))
SET(sudo_mode, MODE_RUN);
- return sudoers_policy_main(argc, argv, 0, env_add, command_infop,
- argv_out, user_env_out);
+ debug_return_bool(sudoers_policy_main(argc, argv, 0, env_add, command_infop,
+ argv_out, user_env_out));
}
static int
sudoers_policy_validate(void)
{
+ debug_decl(sudoers_policy_validate, SUDO_DEBUG_PLUGIN)
+
user_cmnd = "validate";
SET(sudo_mode, MODE_VALIDATE);
- return sudoers_policy_main(0, NULL, I_VERIFYPW, NULL, NULL, NULL, NULL);
+ debug_return_bool(sudoers_policy_main(0, NULL, I_VERIFYPW, NULL, NULL, NULL, NULL));
}
static void
sudoers_policy_invalidate(int remove)
{
+ debug_decl(sudoers_policy_invalidate, SUDO_DEBUG_PLUGIN)
+
user_cmnd = "kill";
if (sigsetjmp(error_jmp, 1) == 0) {
remove_timestamp(remove);
plugin_cleanup(0);
}
+
+ debug_return;
}
static int
const char *list_user)
{
int rval;
+ debug_decl(sudoers_policy_list, SUDO_DEBUG_PLUGIN)
user_cmnd = "list";
if (argc)
list_pw = sudo_getpwnam(list_user);
if (list_pw == NULL) {
warningx(_("unknown user: %s"), list_user);
- return -1;
+ debug_return_bool(-1);
}
}
rval = sudoers_policy_main(argc, argv, I_LISTPW, NULL, NULL, NULL, NULL);
list_pw = NULL;
}
- return rval;
+ debug_return_bool(rval);
}
/*
init_vars(char * const envp[])
{
char * const * ep;
+ debug_decl(init_vars, SUDO_DEBUG_PLUGIN)
#ifdef HAVE_TZSET
(void) tzset(); /* set the timezone if applicable */
sudo_defs_table[I_RUNAS_DEFAULT].callback = cb_runas_default;
/* It is now safe to use log_error() and set_perms() */
+ debug_return;
}
/*
{
int rval;
char *path = user_path;
+ debug_decl(set_cmnd, SUDO_DEBUG_PLUGIN)
/* Resolve the path and return. */
rval = FOUND;
if (!update_defaults(SETDEF_CMND))
log_error(NO_STDERR|NO_EXIT, _("problem with defaults entries"));
- return rval;
+ debug_return_int(rval);
}
/*
* Returns a handle to the sudoers file or NULL on error.
*/
FILE *
-open_sudoers(const char *sudoers, int doedit, int *keepopen)
+open_sudoers(const char *sudoers, bool doedit, bool *keepopen)
{
struct stat statbuf;
FILE *fp = NULL;
int rootstat;
+ debug_decl(open_sudoers, SUDO_DEBUG_PLUGIN)
/*
* Fix the mode and group on sudoers file from old default.
log_error(USE_ERRNO|NO_EXIT, _("unable to stat %s"), sudoers);
else if (!S_ISREG(statbuf.st_mode))
log_error(NO_EXIT, _("%s is not a regular file"), sudoers);
- else if ((statbuf.st_mode & 07577) != sudoers_mode)
+ else if ((statbuf.st_mode & 07577) != (sudoers_mode & 07577))
log_error(NO_EXIT, _("%s is mode 0%o, should be 0%o"), sudoers,
(unsigned int) (statbuf.st_mode & 07777),
(unsigned int) sudoers_mode);
}
restore_perms(); /* change back to root */
- return fp;
+ debug_return_ptr(fp);
}
#ifdef HAVE_LOGIN_CAP_H
set_loginclass(struct passwd *pw)
{
int errflags;
+ login_cap_t *lc;
+ debug_decl(set_loginclass, SUDO_DEBUG_PLUGIN)
+
+ if (!def_use_loginclass)
+ debug_return;
/*
* Don't make it a fatal error if the user didn't specify the login
(pw->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS;
}
+ /* Make sure specified login class is valid. */
lc = login_getclass(login_class);
if (!lc || !lc->lc_class || strcmp(lc->lc_class, login_class) != 0) {
log_error(errflags, _("unknown login class: %s"), login_class);
- if (!lc)
- lc = login_getclass(NULL); /* needed for login_getstyle() later */
+ def_use_loginclass = false;
}
+ login_close(lc);
+ debug_return;
}
#else
static void
void
set_fqdn(void)
{
-#ifdef HAVE_GETADDRINFO
struct addrinfo *res0, hint;
-#else
- struct hostent *hp;
-#endif
char *p;
+ debug_decl(set_fqdn, SUDO_DEBUG_PLUGIN)
-#ifdef HAVE_GETADDRINFO
zero_bytes(&hint, sizeof(hint));
hint.ai_family = PF_UNSPEC;
hint.ai_flags = AI_CANONNAME;
if (getaddrinfo(user_host, NULL, &hint, &res0) != 0) {
-#else
- if (!(hp = gethostbyname(user_host))) {
-#endif
log_error(MSG_ONLY|NO_EXIT,
_("unable to resolve host %s"), user_host);
} else {
if (user_shost != user_host)
efree(user_shost);
efree(user_host);
-#ifdef HAVE_GETADDRINFO
user_host = estrdup(res0->ai_canonname);
freeaddrinfo(res0);
-#else
- user_host = estrdup(hp->h_name);
-#endif
}
if ((p = strchr(user_host, '.')) != NULL)
user_shost = estrndup(user_host, (size_t)(p - user_host));
else
user_shost = user_host;
+ debug_return;
}
/*
* Get passwd entry for the user we are going to run commands as
* and store it in runas_pw. By default, commands run as "root".
*/
-void
+static void
set_runaspw(const char *user)
{
+ debug_decl(set_runaspw, SUDO_DEBUG_PLUGIN)
+
if (runas_pw != NULL)
pw_delref(runas_pw);
if (*user == '#') {
if ((runas_pw = sudo_getpwnam(user)) == NULL)
log_error(NO_MAIL|MSG_ONLY, _("unknown user: %s"), user);
}
+ debug_return;
}
/*
static void
set_runasgr(const char *group)
{
+ debug_decl(set_runasgr, SUDO_DEBUG_PLUGIN)
+
if (runas_gr != NULL)
gr_delref(runas_gr);
if (*group == '#') {
if ((runas_gr = sudo_getgrnam(group)) == NULL)
log_error(NO_MAIL|MSG_ONLY, _("unknown group: %s"), group);
}
+ debug_return;
}
/*
/* Only reset runaspw if user didn't specify one. */
if (!runas_user && !runas_group)
set_runaspw(user);
- return TRUE;
+ return true;
}
/*
struct sudo_nss *nss;
if (!gotsignal) {
+ debug_decl(plugin_cleanup, SUDO_DEBUG_PLUGIN)
if (snl != NULL) {
tq_foreach_fwd(snl, nss)
nss->close(nss);
group_plugin_unload();
sudo_endpwent();
sudo_endgrent();
+ debug_return;
}
}
static int
sudoers_policy_version(int verbose)
{
+ debug_decl(sudoers_policy_version, SUDO_DEBUG_PLUGIN)
+
if (sigsetjmp(error_jmp, 1)) {
/* error recovery via error(), errorx() or log_error() */
- return -1;
+ debug_return_bool(-1);
}
sudo_printf(SUDO_CONV_INFO_MSG, _("Sudoers policy plugin version %s\n"),
dump_auth_methods();
dump_defaults();
sudo_printf(SUDO_CONV_INFO_MSG, "\n");
- dump_interfaces(interfaces_string);
- sudo_printf(SUDO_CONV_INFO_MSG, "\n");
+ if (interfaces_string != NULL) {
+ dump_interfaces(interfaces_string);
+ sudo_printf(SUDO_CONV_INFO_MSG, "\n");
+ }
}
- return TRUE;
+ debug_return_bool(true);
}
static int
{
char * const *cur;
const char *p, *groups = NULL;
+ const char *debug_flags = NULL;
int flags = 0;
+ debug_decl(deserialize_info, SUDO_DEBUG_PLUGIN)
#define MATCHES(s, v) (strncmp(s, v, sizeof(v) - 1) == 0)
user_closefrom = atoi(*cur + sizeof("closefrom=") - 1);
continue;
}
- if (MATCHES(*cur, "debug_level=")) {
- debug_level = atoi(*cur + sizeof("debug_level=") - 1);
+ if (MATCHES(*cur, "debug_flags=")) {
+ debug_flags = *cur + sizeof("debug_flags=") - 1;
continue;
}
if (MATCHES(*cur, "runas_user=")) {
}
if (MATCHES(*cur, "prompt=")) {
user_prompt = *cur + sizeof("prompt=") - 1;
- def_passprompt_override = TRUE;
+ def_passprompt_override = true;
continue;
}
if (MATCHES(*cur, "set_home=")) {
- if (atobool(*cur + sizeof("set_home=") - 1) == TRUE)
+ if (atobool(*cur + sizeof("set_home=") - 1) == true)
SET(flags, MODE_RESET_HOME);
continue;
}
if (MATCHES(*cur, "preserve_environment=")) {
- if (atobool(*cur + sizeof("preserve_environment=") - 1) == TRUE)
+ if (atobool(*cur + sizeof("preserve_environment=") - 1) == true)
SET(flags, MODE_PRESERVE_ENV);
continue;
}
if (MATCHES(*cur, "run_shell=")) {
- if (atobool(*cur + sizeof("run_shell=") - 1) == TRUE)
+ if (atobool(*cur + sizeof("run_shell=") - 1) == true)
SET(flags, MODE_SHELL);
continue;
}
if (MATCHES(*cur, "login_shell=")) {
- if (atobool(*cur + sizeof("login_shell=") - 1) == TRUE) {
+ if (atobool(*cur + sizeof("login_shell=") - 1) == true) {
SET(flags, MODE_LOGIN_SHELL);
- def_env_reset = TRUE;
+ def_env_reset = true;
}
continue;
}
if (MATCHES(*cur, "implied_shell=")) {
- if (atobool(*cur + sizeof("implied_shell=") - 1) == TRUE)
+ if (atobool(*cur + sizeof("implied_shell=") - 1) == true)
SET(flags, MODE_IMPLIED_SHELL);
continue;
}
if (MATCHES(*cur, "preserve_groups=")) {
- if (atobool(*cur + sizeof("preserve_groups=") - 1) == TRUE)
+ if (atobool(*cur + sizeof("preserve_groups=") - 1) == true)
SET(flags, MODE_PRESERVE_GROUPS);
continue;
}
if (MATCHES(*cur, "ignore_ticket=")) {
- if (atobool(*cur + sizeof("ignore_ticket=") - 1) == TRUE)
+ if (atobool(*cur + sizeof("ignore_ticket=") - 1) == true)
SET(flags, MODE_IGNORE_TICKET);
continue;
}
if (MATCHES(*cur, "noninteractive=")) {
- if (atobool(*cur + sizeof("noninteractive=") - 1) == TRUE)
+ if (atobool(*cur + sizeof("noninteractive=") - 1) == true)
SET(flags, MODE_NONINTERACTIVE);
continue;
}
if (MATCHES(*cur, "sudoedit=")) {
- if (atobool(*cur + sizeof("sudoedit=") - 1) == TRUE)
+ if (atobool(*cur + sizeof("sudoedit=") - 1) == true)
SET(flags, MODE_EDIT);
continue;
}
if (MATCHES(*cur, "login_class=")) {
login_class = *cur + sizeof("login_class=") - 1;
- def_use_loginclass = TRUE;
+ def_use_loginclass = true;
continue;
}
#ifdef HAVE_SELINUX
efree(gids);
}
+ /* Setup debugging if indicated. */
+ if (debug_flags != NULL) {
+ sudo_debug_init(NULL, debug_flags);
+ for (cur = settings; *cur != NULL; cur++)
+ sudo_debug_printf(SUDO_DEBUG_INFO, "settings: %s", *cur);
+ for (cur = user_info; *cur != NULL; cur++)
+ sudo_debug_printf(SUDO_DEBUG_INFO, "user_info: %s", *cur);
+ }
+
#undef MATCHES
- return flags;
+ debug_return_int(flags);
}
static char *
resolve_editor(char *editor, int nfiles, char **files, char ***argv_out)
{
char *cp, **nargv, *editor_path = NULL;
- int ac, i, nargc, wasblank;
+ int ac, i, nargc;
+ bool wasblank;
+ debug_decl(resolve_editor, SUDO_DEBUG_PLUGIN)
editor = estrdup(editor); /* becomes part of argv_out */
* line args so look for those and alloc space for them too.
*/
nargc = 1;
- for (wasblank = FALSE, cp = editor; *cp != '\0'; cp++) {
+ for (wasblank = false, cp = editor; *cp != '\0'; cp++) {
if (isblank((unsigned char) *cp))
- wasblank = TRUE;
+ wasblank = true;
else if (wasblank) {
- wasblank = FALSE;
+ wasblank = false;
nargc++;
}
}
if (cp == NULL ||
find_path(cp, &editor_path, NULL, getenv("PATH"), 0) != FOUND) {
efree(editor);
- return NULL;
+ debug_return_str(NULL);
}
nargv = (char **) emalloc2(nargc + 1 + nfiles + 1, sizeof(char *));
for (ac = 0; cp != NULL && ac < nargc; ac++) {
nargv[ac] = NULL;
*argv_out = nargv;
- return editor_path;
+ debug_return_str(editor_path);
}
/*
find_editor(int nfiles, char **files, char ***argv_out)
{
char *cp, *editor, *editor_path = NULL, **ev, *ev0[4];
+ debug_decl(find_editor, SUDO_DEBUG_PLUGIN)
/*
* If any of SUDO_EDITOR, VISUAL or EDITOR are set, choose the first one.
audit_failure(NewArgv, _("%s: command not found"), editor);
warningx(_("%s: command not found"), editor);
}
- return editor_path;
+ debug_return_str(editor_path);
}
#ifdef USE_ADMIN_FLAG
struct stat statbuf;
char flagfile[PATH_MAX];
int fd, n;
+ debug_decl(create_admin_success_flag, SUDO_DEBUG_PLUGIN)
/* Check whether the user is in the admin group. */
if (!user_in_group(sudo_user.pw, "admin"))
- return;
+ debug_return;
/* Build path to flag file. */
n = snprintf(flagfile, sizeof(flagfile), "%s/.sudo_as_admin_successful",
user_dir);
if (n <= 0 || n >= sizeof(flagfile))
- return;
+ debug_return;
/* Create admin flag file if it doesn't already exist. */
set_perms(PERM_USER);
close(fd);
}
restore_perms();
+ debug_return;
}
#else /* !USE_ADMIN_FLAG */
static void