version 1.1, 2012/02/21 16:23:02
|
version 1.1.1.3, 2012/10/09 09:29:52
|
Line 70
|
Line 70
|
# ifndef LOGIN_DEFROOTCLASS |
# ifndef LOGIN_DEFROOTCLASS |
# define LOGIN_DEFROOTCLASS "daemon" |
# define LOGIN_DEFROOTCLASS "daemon" |
# endif |
# endif |
|
# ifndef LOGIN_SETENV |
|
# define LOGIN_SETENV 0 |
|
# endif |
#endif |
#endif |
#ifdef HAVE_SELINUX |
#ifdef HAVE_SELINUX |
# include <selinux/selinux.h> |
# include <selinux/selinux.h> |
#endif |
#endif |
#include <ctype.h> |
#include <ctype.h> |
#include <setjmp.h> |
#include <setjmp.h> |
|
#ifndef HAVE_GETADDRINFO |
|
# include "compat/getaddrinfo.h" |
|
#endif |
|
|
#include "sudoers.h" |
#include "sudoers.h" |
#include "interfaces.h" |
#include "interfaces.h" |
#include "sudoers_version.h" |
#include "sudoers_version.h" |
#include "auth/sudo_auth.h" |
#include "auth/sudo_auth.h" |
|
#include "secure_path.h" |
|
|
/* |
/* |
* Prototypes |
* Prototypes |
Line 92 static void set_runaspw(const char *);
|
Line 99 static void set_runaspw(const char *);
|
static void set_runasgr(const char *); |
static void set_runasgr(const char *); |
static int cb_runas_default(const char *); |
static int cb_runas_default(const char *); |
static int sudoers_policy_version(int verbose); |
static int sudoers_policy_version(int verbose); |
static int deserialize_info(char * const settings[], char * const user_info[]); | static int deserialize_info(char * const args[], char * const settings[], |
| char * const user_info[]); |
static char *find_editor(int nfiles, char **files, char ***argv_out); |
static char *find_editor(int nfiles, char **files, char ***argv_out); |
static void create_admin_success_flag(void); |
static void create_admin_success_flag(void); |
|
|
/* |
/* |
* Globals |
* Globals |
*/ |
*/ |
const char *sudoers_file = _PATH_SUDOERS; |
|
mode_t sudoers_mode = SUDOERS_MODE; |
|
uid_t sudoers_uid = SUDOERS_UID; |
|
gid_t sudoers_gid = SUDOERS_GID; |
|
struct sudo_user sudo_user; |
struct sudo_user sudo_user; |
struct passwd *list_pw; |
struct passwd *list_pw; |
struct interface *interfaces; |
struct interface *interfaces; |
int long_list; |
int long_list; |
int debug_level; |
|
uid_t timestamp_uid; |
uid_t timestamp_uid; |
extern int errorlineno; |
extern int errorlineno; |
extern int parse_error; | extern bool parse_error; |
extern char *errorfile; |
extern char *errorfile; |
#ifdef HAVE_LOGIN_CAP_H |
|
login_cap_t *lc; |
|
#endif /* HAVE_LOGIN_CAP_H */ |
|
#ifdef HAVE_BSD_AUTH_H |
#ifdef HAVE_BSD_AUTH_H |
char *login_style; |
char *login_style; |
#endif /* HAVE_BSD_AUTH_H */ |
#endif /* HAVE_BSD_AUTH_H */ |
Line 122 sudo_conv_t sudo_conv;
|
Line 122 sudo_conv_t sudo_conv;
|
sudo_printf_t sudo_printf; |
sudo_printf_t sudo_printf; |
int sudo_mode; |
int sudo_mode; |
|
|
|
static int sudo_version; |
static char *prev_user; |
static char *prev_user; |
static char *runas_user; |
static char *runas_user; |
static char *runas_group; |
static char *runas_group; |
Line 133 static sigaction_t saved_sa_int, saved_sa_quit, saved_
|
Line 134 static sigaction_t saved_sa_int, saved_sa_quit, saved_
|
int NewArgc; |
int NewArgc; |
char **NewArgv; |
char **NewArgv; |
|
|
/* plugin_error.c */ | /* Declared here instead of plugin_error.c for static sudo builds. */ |
extern sigjmp_buf error_jmp; | sigjmp_buf error_jmp; |
|
|
static int |
static int |
sudoers_policy_open(unsigned int version, sudo_conv_t conversation, |
sudoers_policy_open(unsigned int version, sudo_conv_t conversation, |
sudo_printf_t plugin_printf, char * const settings[], |
sudo_printf_t plugin_printf, char * const settings[], |
char * const user_info[], char * const envp[]) | char * const user_info[], char * const envp[], char * const args[]) |
{ |
{ |
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) |
|
|
|
sudo_version = version; |
if (!sudo_conv) |
if (!sudo_conv) |
sudo_conv = conversation; |
sudo_conv = conversation; |
if (!sudo_printf) |
if (!sudo_printf) |
sudo_printf = plugin_printf; |
sudo_printf = plugin_printf; |
|
|
|
/* Plugin args are only specified for API version 1.2 and higher. */ |
|
if (sudo_version < SUDO_API_MKVERSION(1, 2)) |
|
args = NULL; |
|
|
if (sigsetjmp(error_jmp, 1)) { |
if (sigsetjmp(error_jmp, 1)) { |
/* called via error(), errorx() or log_error() */ | /* called via error(), errorx() or log_fatal() */ |
rewind_perms(); |
rewind_perms(); |
return -1; | debug_return_bool(-1); |
} |
} |
|
|
bindtextdomain("sudoers", LOCALEDIR); |
bindtextdomain("sudoers", LOCALEDIR); |
Line 181 sudoers_policy_open(unsigned int version, sudo_conv_t
|
Line 189 sudoers_policy_open(unsigned int version, sudo_conv_t
|
/* Setup defaults data structures. */ |
/* Setup defaults data structures. */ |
init_defaults(); |
init_defaults(); |
|
|
/* Parse settings and user_info */ | /* Parse args, settings and user_info */ |
sudo_mode = deserialize_info(settings, user_info); | sudo_mode = deserialize_info(args, settings, user_info); |
|
|
init_vars(envp); /* XXX - move this later? */ |
init_vars(envp); /* XXX - move this later? */ |
|
|
Line 194 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|NO_EXIT, _("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")); |
return -1; | debug_return_bool(-1); |
} |
} |
|
|
/* XXX - collect post-sudoers parse settings into a function */ |
/* XXX - collect post-sudoers parse settings into a function */ |
Line 212 sudoers_policy_open(unsigned int version, sudo_conv_t
|
Line 223 sudoers_policy_open(unsigned int version, sudo_conv_t
|
* Initialize external group plugin, if any. |
* Initialize external group plugin, if any. |
*/ |
*/ |
if (def_group_plugin) { |
if (def_group_plugin) { |
if (group_plugin_load(def_group_plugin) != TRUE) | if (group_plugin_load(def_group_plugin) != true) |
def_group_plugin = NULL; |
def_group_plugin = NULL; |
} |
} |
|
|
Line 229 sudoers_policy_open(unsigned int version, sudo_conv_t
|
Line 240 sudoers_policy_open(unsigned int version, sudo_conv_t
|
set_runaspw(runas_user ? runas_user : def_runas_default); |
set_runaspw(runas_user ? runas_user : def_runas_default); |
|
|
if (!update_defaults(SETDEF_RUNAS)) |
if (!update_defaults(SETDEF_RUNAS)) |
log_error(NO_STDERR|NO_EXIT, _("problem with defaults entries")); | log_error(NO_STDERR, _("problem with defaults entries")); |
|
|
if (def_fqdn) |
if (def_fqdn) |
set_fqdn(); /* deferred until after sudoers is parsed */ |
set_fqdn(); /* deferred until after sudoers is parsed */ |
|
|
/* Set login class if applicable. */ |
/* Set login class if applicable. */ |
set_loginclass(sudo_user.pw); | set_loginclass(runas_pw ? runas_pw : sudo_user.pw); |
|
|
restore_perms(); |
restore_perms(); |
|
|
return TRUE; | debug_return_bool(true); |
} |
} |
|
|
static void |
static void |
sudoers_policy_close(int exit_status, int error_code) |
sudoers_policy_close(int exit_status, int error_code) |
{ |
{ |
|
debug_decl(sudoers_policy_close, SUDO_DEBUG_PLUGIN) |
|
|
if (sigsetjmp(error_jmp, 1)) { |
if (sigsetjmp(error_jmp, 1)) { |
/* called via error(), errorx() or log_error() */ | /* called via error(), errorx() or log_fatal() */ |
return; | debug_return; |
} |
} |
|
|
/* We do not currently log the exit status. */ |
/* We do not currently log the exit status. */ |
Line 259 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; |
} |
} |
|
|
/* |
/* |
* 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) | sudoers_policy_init_session(struct passwd *pwd, char **user_env[]) |
{ |
{ |
|
debug_decl(sudoers_policy_init, SUDO_DEBUG_PLUGIN) |
|
|
|
/* user_env is only specified for API version 1.2 and higher. */ |
|
if (sudo_version < SUDO_API_MKVERSION(1, 2)) |
|
user_env = NULL; |
|
|
if (sigsetjmp(error_jmp, 1)) { |
if (sigsetjmp(error_jmp, 1)) { |
/* called via error(), errorx() or log_error() */ | /* called via error(), errorx() or log_fatal() */ |
return -1; | debug_return_bool(-1); |
} |
} |
|
|
return sudo_auth_begin_session(pwd); | debug_return_bool(sudo_auth_begin_session(pwd, user_env)); |
} |
} |
|
|
static int |
static int |
Line 291 sudoers_policy_main(int argc, char * const argv[], int
|
Line 321 sudoers_policy_main(int argc, char * const argv[], int
|
struct sudo_nss *nss; |
struct sudo_nss *nss; |
int cmnd_status = -1, validated; |
int cmnd_status = -1, validated; |
volatile int info_len = 0; |
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)) { |
if (sigsetjmp(error_jmp, 1)) { |
/* error recovery via error(), errorx() or log_error() */ | /* error recovery via error(), errorx() or log_fatal() */ |
rval = -1; |
rval = -1; |
goto done; |
goto done; |
} |
} |
Line 335 sudoers_policy_main(int argc, char * const argv[], int
|
Line 366 sudoers_policy_main(int argc, char * const argv[], int
|
NewArgv = emalloc2(NewArgc + 2, sizeof(char *)); |
NewArgv = emalloc2(NewArgc + 2, sizeof(char *)); |
memcpy(++NewArgv, argv, argc * sizeof(char *)); |
memcpy(++NewArgv, argv, argc * sizeof(char *)); |
NewArgv[NewArgc] = NULL; |
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); |
NewArgv[0] = estrdup(runas_pw->pw_shell); |
} |
} |
|
|
/* If given the -P option, set the "preserve_groups" flag. */ |
/* If given the -P option, set the "preserve_groups" flag. */ |
if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS)) |
if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS)) |
def_preserve_groups = TRUE; | def_preserve_groups = true; |
|
|
/* 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 366 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 397 sudoers_policy_main(int argc, char * const argv[], int
|
Line 424 sudoers_policy_main(int argc, char * const argv[], int
|
pw = sudo_getpwuid(atoi(def_timestampowner + 1)); |
pw = sudo_getpwuid(atoi(def_timestampowner + 1)); |
else |
else |
pw = sudo_getpwnam(def_timestampowner); |
pw = sudo_getpwnam(def_timestampowner); |
if (!pw) | if (pw != NULL) { |
| timestamp_uid = pw->pw_uid; |
| sudo_pw_delref(pw); |
| } else { |
log_error(0, _("timestamp owner (%s): No such user"), |
log_error(0, _("timestamp owner (%s): No such user"), |
def_timestampowner); |
def_timestampowner); |
timestamp_uid = pw->pw_uid; | timestamp_uid = ROOT_UID; |
pw_delref(pw); | } |
} |
} |
|
|
/* If no command line args and "shell_noargs" is not set, error out. */ |
/* If no command line args and "shell_noargs" is not set, error out. */ |
Line 427 sudoers_policy_main(int argc, char * const argv[], int
|
Line 457 sudoers_policy_main(int argc, char * const argv[], int
|
*/ |
*/ |
if (ISSET(sudo_mode, MODE_EDIT) || |
if (ISSET(sudo_mode, MODE_EDIT) || |
(ISSET(sudo_mode, MODE_PRESERVE_ENV) && def_setenv)) |
(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. */ |
/* Build a new environment that avoids any nasty bits. */ |
rebuild_env(); |
rebuild_env(); |
|
|
/* 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 445 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 453 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 582 sudoers_policy_main(int argc, char * const argv[], int
|
Line 592 sudoers_policy_main(int argc, char * const argv[], int
|
NewArgv[1] = "--login"; |
NewArgv[1] = "--login"; |
} |
} |
|
|
#if defined(__linux__) || defined(_AIX) | #if defined(_AIX) || (defined(__linux__) && !defined(HAVE_PAM)) |
/* Insert system-wide environment variables. */ |
/* Insert system-wide environment variables. */ |
read_env_file(_PATH_ENVIRONMENT, TRUE); | read_env_file(_PATH_ENVIRONMENT, true); |
#endif |
#endif |
|
#ifdef HAVE_LOGIN_CAP_H |
|
/* Set environment based on login class. */ |
|
if (login_class) { |
|
login_cap_t *lc = login_getclass(login_class); |
|
if (lc != NULL) { |
|
setusercontext(lc, runas_pw, runas_pw->pw_uid, LOGIN_SETPATH|LOGIN_SETENV); |
|
login_close(lc); |
|
} |
|
} |
|
#endif /* HAVE_LOGIN_CAP_H */ |
} |
} |
|
|
/* Insert system-wide environment variables. */ |
/* Insert system-wide environment variables. */ |
if (def_env_file) |
if (def_env_file) |
read_env_file(def_env_file, FALSE); | read_env_file(def_env_file, false); |
|
|
/* Insert user-specified environment variables. */ |
/* Insert user-specified environment variables. */ |
insert_env_vars(sudo_user.env_vars); |
insert_env_vars(sudo_user.env_vars); |
Line 630 sudoers_policy_main(int argc, char * const argv[], int
|
Line 650 sudoers_policy_main(int argc, char * const argv[], int
|
command_info[info_len++] = "preserve_groups=true"; |
command_info[info_len++] = "preserve_groups=true"; |
} else { |
} else { |
int i, len; |
int i, len; |
|
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); |
|
|
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); |
gid_list = emalloc(glsize); |
memcpy(gid_list, "runas_groups=", sizeof("runas_groups=") - 1); |
memcpy(gid_list, "runas_groups=", sizeof("runas_groups=") - 1); |
cp = gid_list + 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, %s overflow"), "runas_groups"); |
|
cp += len; |
for (i = 0; i < grlist->ngids; i++) { |
for (i = 0; i < grlist->ngids; i++) { |
/* XXX - check rval */ | if (grlist->gids[i] != egid) { |
len = snprintf(cp, glsize - (cp - gid_list), "%s%u", | len = snprintf(cp, glsize - (cp - gid_list), ",%u", |
i ? "," : "", (unsigned int) grlist->gids[i]); | (unsigned int) grlist->gids[i]); |
cp += len; | if (len < 0 || len >= glsize - (cp - gid_list)) |
| errorx(1, _("internal error, %s overflow"), "runas_groups"); |
| 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); |
if (def_noexec) |
if (def_noexec) |
command_info[info_len++] = estrdup("noexec=true"); |
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) |
if (def_set_utmp) |
command_info[info_len++] = estrdup("set_utmp=true"); |
command_info[info_len++] = estrdup("set_utmp=true"); |
if (def_use_pty) |
if (def_use_pty) |
Line 660 sudoers_policy_main(int argc, char * const argv[], int
|
Line 692 sudoers_policy_main(int argc, char * const argv[], int
|
if (def_utmp_runas) |
if (def_utmp_runas) |
command_info[info_len++] = fmt_string("utmp_user", runas_pw->pw_name); |
command_info[info_len++] = fmt_string("utmp_user", runas_pw->pw_name); |
#ifdef HAVE_LOGIN_CAP_H |
#ifdef HAVE_LOGIN_CAP_H |
if (lc != NULL) | if (def_use_loginclass) |
command_info[info_len++] = fmt_string("login_class", lc->lc_class); | command_info[info_len++] = fmt_string("login_class", login_class); |
#endif /* HAVE_LOGIN_CAP_H */ |
#endif /* HAVE_LOGIN_CAP_H */ |
#ifdef HAVE_SELINUX |
#ifdef HAVE_SELINUX |
if (user_role != NULL) |
if (user_role != NULL) |
Line 669 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 676 sudoers_policy_main(int argc, char * const argv[], int
|
Line 714 sudoers_policy_main(int argc, char * const argv[], int
|
*command_infop = command_info; |
*command_infop = command_info; |
|
|
*argv_out = edit_argv ? edit_argv : NewArgv; |
*argv_out = edit_argv ? edit_argv : NewArgv; |
*user_env_out = env_get(); /* our private copy */ |
|
|
|
|
/* Get private version of the environment and zero out stashed copy. */ |
|
*user_env_out = env_get(); |
|
env_init(NULL); |
|
|
goto done; |
goto done; |
|
|
bad: |
bad: |
rval = FALSE; | rval = false; |
|
|
done: |
done: |
rewind_perms(); |
rewind_perms(); |
Line 690 done:
|
Line 731 done:
|
sudo_endpwent(); |
sudo_endpwent(); |
sudo_endgrent(); |
sudo_endgrent(); |
|
|
return rval; | debug_return_bool(rval); |
} |
} |
|
|
static int |
static int |
sudoers_policy_check(int argc, char * const argv[], char *env_add[], |
sudoers_policy_check(int argc, char * const argv[], char *env_add[], |
char **command_infop[], char **argv_out[], char **user_env_out[]) |
char **command_infop[], char **argv_out[], char **user_env_out[]) |
{ |
{ |
|
debug_decl(sudoers_policy_check, SUDO_DEBUG_PLUGIN) |
|
|
if (!ISSET(sudo_mode, MODE_EDIT)) |
if (!ISSET(sudo_mode, MODE_EDIT)) |
SET(sudo_mode, MODE_RUN); |
SET(sudo_mode, MODE_RUN); |
|
|
return sudoers_policy_main(argc, argv, 0, env_add, command_infop, | debug_return_bool(sudoers_policy_main(argc, argv, 0, env_add, command_infop, |
argv_out, user_env_out); | argv_out, user_env_out)); |
} |
} |
|
|
static int |
static int |
sudoers_policy_validate(void) |
sudoers_policy_validate(void) |
{ |
{ |
|
debug_decl(sudoers_policy_validate, SUDO_DEBUG_PLUGIN) |
|
|
user_cmnd = "validate"; |
user_cmnd = "validate"; |
SET(sudo_mode, MODE_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 |
static void |
sudoers_policy_invalidate(int remove) |
sudoers_policy_invalidate(int remove) |
{ |
{ |
|
debug_decl(sudoers_policy_invalidate, SUDO_DEBUG_PLUGIN) |
|
|
user_cmnd = "kill"; |
user_cmnd = "kill"; |
if (sigsetjmp(error_jmp, 1) == 0) { |
if (sigsetjmp(error_jmp, 1) == 0) { |
remove_timestamp(remove); |
remove_timestamp(remove); |
plugin_cleanup(0); |
plugin_cleanup(0); |
} |
} |
|
|
|
debug_return; |
} |
} |
|
|
static int |
static int |
Line 728 sudoers_policy_list(int argc, char * const argv[], int
|
Line 777 sudoers_policy_list(int argc, char * const argv[], int
|
const char *list_user) |
const char *list_user) |
{ |
{ |
int rval; |
int rval; |
|
debug_decl(sudoers_policy_list, SUDO_DEBUG_PLUGIN) |
|
|
user_cmnd = "list"; |
user_cmnd = "list"; |
if (argc) |
if (argc) |
Line 740 sudoers_policy_list(int argc, char * const argv[], int
|
Line 790 sudoers_policy_list(int argc, char * const argv[], int
|
list_pw = sudo_getpwnam(list_user); |
list_pw = sudo_getpwnam(list_user); |
if (list_pw == NULL) { |
if (list_pw == NULL) { |
warningx(_("unknown user: %s"), list_user); |
warningx(_("unknown user: %s"), list_user); |
return -1; | debug_return_bool(-1); |
} |
} |
} |
} |
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; |
} |
} |
|
|
return rval; | debug_return_bool(rval); |
} |
} |
|
|
/* |
/* |
Line 760 static void
|
Line 810 static void
|
init_vars(char * const envp[]) |
init_vars(char * const envp[]) |
{ |
{ |
char * const * ep; |
char * const * ep; |
|
debug_decl(init_vars, SUDO_DEBUG_PLUGIN) |
|
|
#ifdef HAVE_TZSET |
#ifdef HAVE_TZSET |
(void) tzset(); /* set the timezone if applicable */ |
(void) tzset(); /* set the timezone if applicable */ |
Line 799 init_vars(char * const envp[])
|
Line 850 init_vars(char * const envp[])
|
if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) |
if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) |
errorx(1, _("unknown uid: %u"), (unsigned int) user_uid); |
errorx(1, _("unknown uid: %u"), (unsigned int) user_uid); |
|
|
/* Need to make a fake struct passwd for the call to log_error(). */ | /* Need to make a fake struct passwd for the call to log_fatal(). */ |
sudo_user.pw = sudo_fakepwnamid(user_name, user_uid, user_gid); |
sudo_user.pw = sudo_fakepwnamid(user_name, user_uid, user_gid); |
log_error(0, _("unknown uid: %u"), (unsigned int) user_uid); | log_fatal(0, _("unknown uid: %u"), (unsigned int) user_uid); |
/* NOTREACHED */ |
/* NOTREACHED */ |
} |
} |
|
|
Line 809 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; |
|
|
/* It is now safe to use log_error() and set_perms() */ | /* It is now safe to use log_fatal() and set_perms() */ |
| debug_return; |
} |
} |
|
|
/* |
/* |
Line 826 set_cmnd(void)
|
Line 878 set_cmnd(void)
|
{ |
{ |
int rval; |
int rval; |
char *path = user_path; |
char *path = user_path; |
|
debug_decl(set_cmnd, SUDO_DEBUG_PLUGIN) |
|
|
/* Resolve the path and return. */ |
/* Resolve the path and return. */ |
rval = FOUND; |
rval = FOUND; |
user_stat = emalloc(sizeof(struct stat)); | user_stat = ecalloc(1, sizeof(struct stat)); |
|
|
/* Default value for cmnd, overridden below. */ |
/* Default value for cmnd, overridden below. */ |
if (user_cmnd == NULL) |
if (user_cmnd == NULL) |
Line 880 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 897 set_cmnd(void)
|
Line 950 set_cmnd(void)
|
user_base = user_cmnd; |
user_base = user_cmnd; |
|
|
if (!update_defaults(SETDEF_CMND)) |
if (!update_defaults(SETDEF_CMND)) |
log_error(NO_STDERR|NO_EXIT, _("problem with defaults entries")); | log_error(NO_STDERR, _("problem with defaults entries")); |
|
|
return rval; | debug_return_int(rval); |
} |
} |
|
|
/* |
/* |
Line 907 set_cmnd(void)
|
Line 960 set_cmnd(void)
|
* Returns a handle to the sudoers file or NULL on error. |
* Returns a handle to the sudoers file or NULL on error. |
*/ |
*/ |
FILE * |
FILE * |
open_sudoers(const char *sudoers, int doedit, int *keepopen) | open_sudoers(const char *sudoers, bool doedit, bool *keepopen) |
{ |
{ |
struct stat statbuf; | struct stat sb; |
FILE *fp = NULL; |
FILE *fp = NULL; |
int rootstat; | debug_decl(open_sudoers, SUDO_DEBUG_PLUGIN) |
|
|
/* | set_perms(PERM_SUDOERS); |
* Fix the mode and group on sudoers file from old default. | |
* Only works if file system is readable/writable by root. | |
*/ | |
if ((rootstat = stat_sudoers(sudoers, &statbuf)) == 0 && | |
sudoers_uid == statbuf.st_uid && sudoers_mode != 0400 && | |
(statbuf.st_mode & 0007777) == 0400) { | |
|
|
if (chmod(sudoers, sudoers_mode) == 0) { | switch (sudo_secure_file(sudoers, sudoers_uid, sudoers_gid, &sb)) { |
warningx(_("fixed mode on %s"), sudoers); | case SUDO_PATH_SECURE: |
SET(statbuf.st_mode, sudoers_mode); | /* |
if (statbuf.st_gid != sudoers_gid) { | * If we are expecting sudoers to be group readable but |
if (chown(sudoers, (uid_t) -1, sudoers_gid) == 0) { | * it is not, we must open the file as root, not uid 1. |
warningx(_("set group on %s"), sudoers); | */ |
statbuf.st_gid = sudoers_gid; | if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP)) { |
} else | if ((sb.st_mode & S_IRGRP) == 0) { |
warning(_("unable to set group on %s"), sudoers); | restore_perms(); |
| set_perms(PERM_ROOT); |
| } |
} |
} |
} else | /* |
warning(_("unable to fix mode on %s"), sudoers); | * 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) { |
| log_error(USE_ERRNO, _("unable to open %s"), sudoers); |
| } else { |
| if (sb.st_size != 0 && fgetc(fp) == EOF) { |
| log_error(USE_ERRNO, _("unable to read %s"), |
| sudoers); |
| fclose(fp); |
| fp = NULL; |
| } else { |
| /* Rewind fp and set close on exec flag. */ |
| rewind(fp); |
| (void) fcntl(fileno(fp), F_SETFD, 1); |
| } |
| } |
| break; |
| case SUDO_PATH_MISSING: |
| log_error(USE_ERRNO, _("unable to stat %s"), sudoers); |
| break; |
| case SUDO_PATH_BAD_TYPE: |
| log_error(0, _("%s is not a regular file"), sudoers); |
| break; |
| case SUDO_PATH_WRONG_OWNER: |
| log_error(0, _("%s is owned by uid %u, should be %u"), |
| sudoers, (unsigned int) sb.st_uid, (unsigned int) sudoers_uid); |
| break; |
| case SUDO_PATH_WORLD_WRITABLE: |
| log_error(0, _("%s is world writable"), sudoers); |
| break; |
| case SUDO_PATH_GROUP_WRITABLE: |
| log_error(0, _("%s is owned by gid %u, should be %u"), |
| sudoers, (unsigned int) sb.st_gid, (unsigned int) sudoers_gid); |
| break; |
| default: |
| /* NOTREACHED */ |
| break; |
} |
} |
|
|
/* |
|
* Sanity checks on sudoers file. Must be done as sudoers |
|
* file owner. We already did a stat as root, so use that |
|
* data if we can't stat as sudoers file owner. |
|
*/ |
|
set_perms(PERM_SUDOERS); |
|
|
|
if (rootstat != 0 && stat_sudoers(sudoers, &statbuf) != 0) |
|
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) |
|
log_error(NO_EXIT, _("%s is mode 0%o, should be 0%o"), sudoers, |
|
(unsigned int) (statbuf.st_mode & 07777), |
|
(unsigned int) sudoers_mode); |
|
else if (statbuf.st_uid != sudoers_uid) |
|
log_error(NO_EXIT, _("%s is owned by uid %u, should be %u"), sudoers, |
|
(unsigned int) statbuf.st_uid, (unsigned int) sudoers_uid); |
|
else if (statbuf.st_gid != sudoers_gid && ISSET(statbuf.st_mode, S_IRGRP|S_IWGRP)) |
|
log_error(NO_EXIT, _("%s is owned by gid %u, should be %u"), sudoers, |
|
(unsigned int) statbuf.st_gid, (unsigned int) sudoers_gid); |
|
else if ((fp = fopen(sudoers, "r")) == NULL) |
|
log_error(USE_ERRNO|NO_EXIT, _("unable to open %s"), sudoers); |
|
else { |
|
/* |
|
* Make sure we can actually read sudoers so we can present the |
|
* user with a reasonable error message (unlike the lexer). |
|
*/ |
|
if (statbuf.st_size != 0 && fgetc(fp) == EOF) { |
|
log_error(USE_ERRNO|NO_EXIT, _("unable to read %s"), sudoers); |
|
fclose(fp); |
|
fp = NULL; |
|
} |
|
} |
|
|
|
if (fp != NULL) { |
|
rewind(fp); |
|
(void) fcntl(fileno(fp), F_SETFD, 1); |
|
} |
|
|
|
restore_perms(); /* change back to root */ |
restore_perms(); /* change back to root */ |
return fp; | |
| debug_return_ptr(fp); |
} |
} |
|
|
#ifdef HAVE_LOGIN_CAP_H |
#ifdef HAVE_LOGIN_CAP_H |
static void |
static void |
set_loginclass(struct passwd *pw) |
set_loginclass(struct passwd *pw) |
{ |
{ |
int errflags; | const int errflags = NO_MAIL|MSG_ONLY; |
| login_cap_t *lc; |
| debug_decl(set_loginclass, SUDO_DEBUG_PLUGIN) |
|
|
/* | if (!def_use_loginclass) |
* Don't make it a fatal error if the user didn't specify the login | debug_return; |
* class themselves. We do this because if login.conf gets | |
* corrupted we want the admin to be able to use sudo to fix it. | |
*/ | |
if (login_class) | |
errflags = NO_MAIL|MSG_ONLY; | |
else | |
errflags = NO_MAIL|MSG_ONLY|NO_EXIT; | |
|
|
if (login_class && strcmp(login_class, "-") != 0) { |
if (login_class && strcmp(login_class, "-") != 0) { |
if (user_uid != 0 && |
if (user_uid != 0 && |
Line 1006 set_loginclass(struct passwd *pw)
|
Line 1048 set_loginclass(struct passwd *pw)
|
(pw->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS; |
(pw->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS; |
} |
} |
|
|
|
/* Make sure specified login class is valid. */ |
lc = login_getclass(login_class); |
lc = login_getclass(login_class); |
if (!lc || !lc->lc_class || strcmp(lc->lc_class, login_class) != 0) { |
if (!lc || !lc->lc_class || strcmp(lc->lc_class, login_class) != 0) { |
log_error(errflags, _("unknown login class: %s"), login_class); | /* |
if (!lc) | * Don't make it a fatal error if the user didn't specify the login |
lc = login_getclass(NULL); /* needed for login_getstyle() later */ | * class themselves. We do this because if login.conf gets |
| * corrupted we want the admin to be able to use sudo to fix it. |
| */ |
| if (login_class) |
| log_fatal(errflags, _("unknown login class: %s"), login_class); |
| else |
| log_error(errflags, _("unknown login class: %s"), login_class); |
| def_use_loginclass = false; |
} |
} |
|
login_close(lc); |
|
debug_return; |
} |
} |
#else |
#else |
static void |
static void |
Line 1020 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) |
{ |
{ |
#ifdef HAVE_GETADDRINFO |
|
struct addrinfo *res0, hint; |
struct addrinfo *res0, hint; |
#else |
|
struct hostent *hp; |
|
#endif |
|
char *p; |
char *p; |
|
debug_decl(set_fqdn, SUDO_DEBUG_PLUGIN) |
|
|
#ifdef HAVE_GETADDRINFO |
|
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) { |
#else | log_error(MSG_ONLY, _("unable to resolve host %s"), user_host); |
if (!(hp = gethostbyname(user_host))) { | |
#endif | |
log_error(MSG_ONLY|NO_EXIT, | |
_("unable to resolve host %s"), user_host); | |
} else { |
} else { |
if (user_shost != user_host) |
if (user_shost != user_host) |
efree(user_shost); |
efree(user_shost); |
efree(user_host); |
efree(user_host); |
#ifdef HAVE_GETADDRINFO |
|
user_host = estrdup(res0->ai_canonname); |
user_host = estrdup(res0->ai_canonname); |
freeaddrinfo(res0); |
freeaddrinfo(res0); |
#else | if ((p = strchr(user_host, '.')) != NULL) |
user_host = estrdup(hp->h_name); | user_shost = estrndup(user_host, (size_t)(p - user_host)); |
#endif | else |
| user_shost = user_host; |
} |
} |
if ((p = strchr(user_host, '.')) != NULL) | debug_return; |
user_shost = estrndup(user_host, (size_t)(p - user_host)); | |
else | |
user_shost = user_host; | |
} |
} |
|
|
/* |
/* |
* Get passwd entry for the user we are going to run commands as |
* 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". |
* and store it in runas_pw. By default, commands run as "root". |
*/ |
*/ |
void | static void |
set_runaspw(const char *user) |
set_runaspw(const char *user) |
{ |
{ |
|
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); |
} else { |
} else { |
if ((runas_pw = sudo_getpwnam(user)) == NULL) |
if ((runas_pw = sudo_getpwnam(user)) == NULL) |
log_error(NO_MAIL|MSG_ONLY, _("unknown user: %s"), user); | log_fatal(NO_MAIL|MSG_ONLY, _("unknown user: %s"), user); |
} |
} |
|
debug_return; |
} |
} |
|
|
/* |
/* |
Line 1085 set_runaspw(const char *user)
|
Line 1134 set_runaspw(const char *user)
|
static void |
static void |
set_runasgr(const char *group) |
set_runasgr(const char *group) |
{ |
{ |
|
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); |
} else { |
} else { |
if ((runas_gr = sudo_getgrnam(group)) == NULL) |
if ((runas_gr = sudo_getgrnam(group)) == NULL) |
log_error(NO_MAIL|MSG_ONLY, _("unknown group: %s"), group); | log_fatal(NO_MAIL|MSG_ONLY, _("unknown group: %s"), group); |
} |
} |
|
debug_return; |
} |
} |
|
|
/* |
/* |
Line 1105 cb_runas_default(const char *user)
|
Line 1157 cb_runas_default(const char *user)
|
/* Only reset runaspw if user didn't specify one. */ |
/* Only reset runaspw if user didn't specify one. */ |
if (!runas_user && !runas_group) |
if (!runas_user && !runas_group) |
set_runaspw(user); |
set_runaspw(user); |
return TRUE; | return true; |
} |
} |
|
|
/* |
/* |
Line 1117 plugin_cleanup(int gotsignal)
|
Line 1169 plugin_cleanup(int gotsignal)
|
struct sudo_nss *nss; |
struct sudo_nss *nss; |
|
|
if (!gotsignal) { |
if (!gotsignal) { |
|
debug_decl(plugin_cleanup, SUDO_DEBUG_PLUGIN) |
if (snl != NULL) { |
if (snl != NULL) { |
tq_foreach_fwd(snl, nss) |
tq_foreach_fwd(snl, nss) |
nss->close(nss); |
nss->close(nss); |
Line 1125 plugin_cleanup(int gotsignal)
|
Line 1178 plugin_cleanup(int gotsignal)
|
group_plugin_unload(); |
group_plugin_unload(); |
sudo_endpwent(); |
sudo_endpwent(); |
sudo_endgrent(); |
sudo_endgrent(); |
|
debug_return; |
} |
} |
} |
} |
|
|
static int |
static int |
sudoers_policy_version(int verbose) |
sudoers_policy_version(int verbose) |
{ |
{ |
|
debug_decl(sudoers_policy_version, SUDO_DEBUG_PLUGIN) |
|
|
if (sigsetjmp(error_jmp, 1)) { |
if (sigsetjmp(error_jmp, 1)) { |
/* error recovery via error(), errorx() or log_error() */ | /* error recovery via error(), errorx() or log_fatal() */ |
return -1; | debug_return_bool(-1); |
} |
} |
|
|
sudo_printf(SUDO_CONV_INFO_MSG, _("Sudoers policy plugin version %s\n"), |
sudo_printf(SUDO_CONV_INFO_MSG, _("Sudoers policy plugin version %s\n"), |
Line 1153 sudoers_policy_version(int verbose)
|
Line 1209 sudoers_policy_version(int verbose)
|
dump_auth_methods(); |
dump_auth_methods(); |
dump_defaults(); |
dump_defaults(); |
sudo_printf(SUDO_CONV_INFO_MSG, "\n"); |
sudo_printf(SUDO_CONV_INFO_MSG, "\n"); |
dump_interfaces(interfaces_string); | if (interfaces_string != NULL) { |
sudo_printf(SUDO_CONV_INFO_MSG, "\n"); | dump_interfaces(interfaces_string); |
| sudo_printf(SUDO_CONV_INFO_MSG, "\n"); |
| } |
} |
} |
return TRUE; | debug_return_bool(true); |
} |
} |
|
|
static int |
static int |
deserialize_info(char * const settings[], char * const user_info[]) | deserialize_info(char * const args[], char * const settings[], char * const user_info[]) |
{ |
{ |
char * const *cur; |
char * const *cur; |
const char *p, *groups = NULL; |
const char *p, *groups = NULL; |
|
const char *debug_flags = NULL; |
int flags = 0; |
int flags = 0; |
|
debug_decl(deserialize_info, SUDO_DEBUG_PLUGIN) |
|
|
#define MATCHES(s, v) (strncmp(s, v, sizeof(v) - 1) == 0) |
#define MATCHES(s, v) (strncmp(s, v, sizeof(v) - 1) == 0) |
|
|
|
/* Parse sudo.conf plugin args. */ |
|
if (args != NULL) { |
|
for (cur = args; *cur != NULL; cur++) { |
|
if (MATCHES(*cur, "sudoers_file=")) { |
|
sudoers_file = *cur + sizeof("sudoers_file=") - 1; |
|
continue; |
|
} |
|
if (MATCHES(*cur, "sudoers_uid=")) { |
|
sudoers_uid = (uid_t) atoi(*cur + sizeof("sudoers_uid=") - 1); |
|
continue; |
|
} |
|
if (MATCHES(*cur, "sudoers_gid=")) { |
|
sudoers_gid = (gid_t) atoi(*cur + sizeof("sudoers_gid=") - 1); |
|
continue; |
|
} |
|
if (MATCHES(*cur, "sudoers_mode=")) { |
|
sudoers_mode = (mode_t) strtol(*cur + sizeof("sudoers_mode=") - 1, |
|
NULL, 8); |
|
continue; |
|
} |
|
} |
|
} |
|
|
/* Parse command line settings. */ |
/* Parse command line settings. */ |
user_closefrom = -1; |
user_closefrom = -1; |
for (cur = settings; *cur != NULL; cur++) { |
for (cur = settings; *cur != NULL; cur++) { |
Line 1175 deserialize_info(char * const settings[], char * const
|
Line 1258 deserialize_info(char * const settings[], char * const
|
user_closefrom = atoi(*cur + sizeof("closefrom=") - 1); |
user_closefrom = atoi(*cur + sizeof("closefrom=") - 1); |
continue; |
continue; |
} |
} |
if (MATCHES(*cur, "debug_level=")) { | if (MATCHES(*cur, "debug_flags=")) { |
debug_level = atoi(*cur + sizeof("debug_level=") - 1); | debug_flags = *cur + sizeof("debug_flags=") - 1; |
continue; |
continue; |
} |
} |
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=")) { |
user_prompt = *cur + sizeof("prompt=") - 1; |
user_prompt = *cur + sizeof("prompt=") - 1; |
def_passprompt_override = TRUE; | def_passprompt_override = true; |
continue; |
continue; |
} |
} |
if (MATCHES(*cur, "set_home=")) { |
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); |
SET(flags, MODE_RESET_HOME); |
continue; |
continue; |
} |
} |
if (MATCHES(*cur, "preserve_environment=")) { |
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); |
SET(flags, MODE_PRESERVE_ENV); |
continue; |
continue; |
} |
} |
if (MATCHES(*cur, "run_shell=")) { |
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); |
SET(flags, MODE_SHELL); |
continue; |
continue; |
} |
} |
if (MATCHES(*cur, "login_shell=")) { |
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); |
SET(flags, MODE_LOGIN_SHELL); |
def_env_reset = TRUE; | def_env_reset = true; |
} |
} |
continue; |
continue; |
} |
} |
if (MATCHES(*cur, "implied_shell=")) { |
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); |
SET(flags, MODE_IMPLIED_SHELL); |
continue; |
continue; |
} |
} |
if (MATCHES(*cur, "preserve_groups=")) { |
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); |
SET(flags, MODE_PRESERVE_GROUPS); |
continue; |
continue; |
} |
} |
if (MATCHES(*cur, "ignore_ticket=")) { |
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); |
SET(flags, MODE_IGNORE_TICKET); |
continue; |
continue; |
} |
} |
if (MATCHES(*cur, "noninteractive=")) { |
if (MATCHES(*cur, "noninteractive=")) { |
if (atobool(*cur + sizeof("noninteractive=") - 1) == TRUE) | if (atobool(*cur + sizeof("noninteractive=") - 1) == true) |
SET(flags, MODE_NONINTERACTIVE); |
SET(flags, MODE_NONINTERACTIVE); |
continue; |
continue; |
} |
} |
if (MATCHES(*cur, "sudoedit=")) { |
if (MATCHES(*cur, "sudoedit=")) { |
if (atobool(*cur + sizeof("sudoedit=") - 1) == TRUE) | if (atobool(*cur + sizeof("sudoedit=") - 1) == true) |
SET(flags, MODE_EDIT); |
SET(flags, MODE_EDIT); |
continue; |
continue; |
} |
} |
if (MATCHES(*cur, "login_class=")) { |
if (MATCHES(*cur, "login_class=")) { |
login_class = *cur + sizeof("login_class=") - 1; |
login_class = *cur + sizeof("login_class=") - 1; |
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 1271 deserialize_info(char * const settings[], char * const
|
Line 1366 deserialize_info(char * const settings[], char * const
|
set_interfaces(interfaces_string); |
set_interfaces(interfaces_string); |
continue; |
continue; |
} |
} |
if (MATCHES(*cur, "sudoers_file=")) { |
|
sudoers_file = *cur + sizeof("sudoers_file=") - 1; |
|
continue; |
|
} |
|
if (MATCHES(*cur, "sudoers_uid=")) { |
|
sudoers_uid = (uid_t) atoi(*cur + sizeof("sudoers_uid=") - 1); |
|
continue; |
|
} |
|
if (MATCHES(*cur, "sudoers_gid=")) { |
|
sudoers_gid = (gid_t) atoi(*cur + sizeof("sudoers_gid=") - 1); |
|
continue; |
|
} |
|
if (MATCHES(*cur, "sudoers_mode=")) { |
|
sudoers_mode = (mode_t) strtol(*cur + sizeof("sudoers_mode=") - 1, |
|
NULL, 8); |
|
continue; |
|
} |
|
} |
} |
|
|
for (cur = user_info; *cur != NULL; cur++) { |
for (cur = user_info; *cur != NULL; cur++) { |
Line 1364 deserialize_info(char * const settings[], char * const
|
Line 1442 deserialize_info(char * const settings[], char * const
|
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. */ |
|
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 |
#undef MATCHES |
return flags; | debug_return_int(flags); |
} |
} |
|
|
static char * |
static char * |
resolve_editor(char *editor, int nfiles, char **files, char ***argv_out) |
resolve_editor(char *editor, int nfiles, char **files, char ***argv_out) |
{ |
{ |
char *cp, **nargv, *editor_path = NULL; |
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 */ |
editor = estrdup(editor); /* becomes part of argv_out */ |
|
|
Line 1386 resolve_editor(char *editor, int nfiles, char **files,
|
Line 1475 resolve_editor(char *editor, int nfiles, char **files,
|
* line args so look for those and alloc space for them too. |
* line args so look for those and alloc space for them too. |
*/ |
*/ |
nargc = 1; |
nargc = 1; |
for (wasblank = FALSE, cp = editor; *cp != '\0'; cp++) { | for (wasblank = false, cp = editor; *cp != '\0'; cp++) { |
if (isblank((unsigned char) *cp)) |
if (isblank((unsigned char) *cp)) |
wasblank = TRUE; | wasblank = true; |
else if (wasblank) { |
else if (wasblank) { |
wasblank = FALSE; | wasblank = false; |
nargc++; |
nargc++; |
} |
} |
} |
} |
Line 1399 resolve_editor(char *editor, int nfiles, char **files,
|
Line 1488 resolve_editor(char *editor, int nfiles, char **files,
|
if (cp == NULL || |
if (cp == NULL || |
find_path(cp, &editor_path, NULL, getenv("PATH"), 0) != FOUND) { |
find_path(cp, &editor_path, NULL, getenv("PATH"), 0) != FOUND) { |
efree(editor); |
efree(editor); |
return NULL; | debug_return_str(NULL); |
} |
} |
nargv = (char **) emalloc2(nargc + 1 + nfiles + 1, sizeof(char *)); |
nargv = (char **) emalloc2(nargc + 1 + nfiles + 1, sizeof(char *)); |
for (ac = 0; cp != NULL && ac < nargc; ac++) { |
for (ac = 0; cp != NULL && ac < nargc; ac++) { |
Line 1412 resolve_editor(char *editor, int nfiles, char **files,
|
Line 1501 resolve_editor(char *editor, int nfiles, char **files,
|
nargv[ac] = NULL; |
nargv[ac] = NULL; |
|
|
*argv_out = nargv; |
*argv_out = nargv; |
return editor_path; | debug_return_str(editor_path); |
} |
} |
|
|
/* |
/* |
Line 1424 static char *
|
Line 1513 static char *
|
find_editor(int nfiles, char **files, char ***argv_out) |
find_editor(int nfiles, char **files, char ***argv_out) |
{ |
{ |
char *cp, *editor, *editor_path = NULL, **ev, *ev0[4]; |
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. |
* If any of SUDO_EDITOR, VISUAL or EDITOR are set, choose the first one. |
Line 1454 find_editor(int nfiles, char **files, char ***argv_out
|
Line 1544 find_editor(int nfiles, char **files, char ***argv_out
|
audit_failure(NewArgv, _("%s: command not found"), editor); |
audit_failure(NewArgv, _("%s: command not found"), editor); |
warningx(_("%s: command not found"), editor); |
warningx(_("%s: command not found"), editor); |
} |
} |
return editor_path; | debug_return_str(editor_path); |
} |
} |
|
|
#ifdef USE_ADMIN_FLAG |
#ifdef USE_ADMIN_FLAG |
Line 1464 create_admin_success_flag(void)
|
Line 1554 create_admin_success_flag(void)
|
struct stat statbuf; |
struct stat statbuf; |
char flagfile[PATH_MAX]; |
char flagfile[PATH_MAX]; |
int fd, n; |
int fd, n; |
|
debug_decl(create_admin_success_flag, SUDO_DEBUG_PLUGIN) |
|
|
/* Check whether the user is in the admin group. */ |
/* Check whether the user is in the admin group. */ |
if (!user_in_group(sudo_user.pw, "admin")) |
if (!user_in_group(sudo_user.pw, "admin")) |
return; | debug_return; |
|
|
/* Build path to flag file. */ |
/* Build path to flag file. */ |
n = snprintf(flagfile, sizeof(flagfile), "%s/.sudo_as_admin_successful", |
n = snprintf(flagfile, sizeof(flagfile), "%s/.sudo_as_admin_successful", |
user_dir); |
user_dir); |
if (n <= 0 || n >= sizeof(flagfile)) |
if (n <= 0 || n >= sizeof(flagfile)) |
return; | debug_return; |
|
|
/* Create admin flag file if it doesn't already exist. */ |
/* Create admin flag file if it doesn't already exist. */ |
set_perms(PERM_USER); |
set_perms(PERM_USER); |
Line 1482 create_admin_success_flag(void)
|
Line 1573 create_admin_success_flag(void)
|
close(fd); |
close(fd); |
} |
} |
restore_perms(); |
restore_perms(); |
|
debug_return; |
} |
} |
#else /* !USE_ADMIN_FLAG */ |
#else /* !USE_ADMIN_FLAG */ |
static void |
static void |
Line 1491 create_admin_success_flag(void)
|
Line 1583 create_admin_success_flag(void)
|
} |
} |
#endif /* USE_ADMIN_FLAG */ |
#endif /* USE_ADMIN_FLAG */ |
|
|
struct policy_plugin sudoers_policy = { | static void |
| sudoers_policy_register_hooks(int version, int (*register_hook)(struct sudo_hook *hook)) |
| { |
| struct sudo_hook hook; |
| |
| memset(&hook, 0, sizeof(hook)); |
| hook.hook_version = SUDO_HOOK_VERSION; |
| |
| hook.hook_type = SUDO_HOOK_SETENV; |
| hook.hook_fn = sudoers_hook_setenv; |
| register_hook(&hook); |
| |
| hook.hook_type = SUDO_HOOK_UNSETENV; |
| hook.hook_fn = sudoers_hook_unsetenv; |
| register_hook(&hook); |
| |
| hook.hook_type = SUDO_HOOK_GETENV; |
| hook.hook_fn = sudoers_hook_getenv; |
| register_hook(&hook); |
| |
| hook.hook_type = SUDO_HOOK_PUTENV; |
| hook.hook_fn = sudoers_hook_putenv; |
| register_hook(&hook); |
| } |
| |
| __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, |
Line 1501 struct policy_plugin sudoers_policy = {
|
Line 1618 struct policy_plugin sudoers_policy = {
|
sudoers_policy_list, |
sudoers_policy_list, |
sudoers_policy_validate, |
sudoers_policy_validate, |
sudoers_policy_invalidate, |
sudoers_policy_invalidate, |
sudoers_policy_init_session | sudoers_policy_init_session, |
| sudoers_policy_register_hooks |
}; |
}; |