version 1.1.1.1, 2012/02/21 16:23:02
|
version 1.1.1.4, 2013/07/22 10:46:12
|
Line 1
|
Line 1
|
/* |
/* |
* Copyright (c) 1993-1996, 1998-2011 Todd C. Miller <Todd.Miller@courtesan.com> | * Copyright (c) 1993-1996, 1998-2013 Todd C. Miller <Todd.Miller@courtesan.com> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the above |
* purpose with or without fee is hereby granted, provided that the above |
Line 16
|
Line 16
|
* Sponsored in part by the Defense Advanced Research Projects |
* Sponsored in part by the Defense Advanced Research Projects |
* Agency (DARPA) and Air Force Research Laboratory, Air Force |
* Agency (DARPA) and Air Force Research Laboratory, Air Force |
* Materiel Command, USAF, under agreement number F39502-99-1-0512. |
* Materiel Command, USAF, under agreement number F39502-99-1-0512. |
* |
|
* For a brief history of sudo, please see the HISTORY file included |
|
* with this distribution. |
|
*/ |
*/ |
|
|
#define _SUDO_MAIN |
#define _SUDO_MAIN |
Line 31
|
Line 28
|
|
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include <sys/stat.h> |
#include <sys/param.h> |
|
#include <sys/socket.h> |
#include <sys/socket.h> |
#include <stdio.h> |
#include <stdio.h> |
#ifdef STDC_HEADERS |
#ifdef STDC_HEADERS |
Line 60
|
Line 56
|
#include <signal.h> |
#include <signal.h> |
#include <grp.h> |
#include <grp.h> |
#include <time.h> |
#include <time.h> |
#ifdef HAVE_SETLOCALE |
|
# include <locale.h> |
|
#endif |
|
#include <netinet/in.h> |
|
#include <netdb.h> |
#include <netdb.h> |
#ifdef HAVE_LOGIN_CAP_H |
#ifdef HAVE_LOGIN_CAP_H |
# include <login_cap.h> |
# include <login_cap.h> |
# 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> | #ifndef HAVE_GETADDRINFO |
| # include "compat/getaddrinfo.h" |
| #endif |
|
|
#include "sudoers.h" |
#include "sudoers.h" |
#include "interfaces.h" |
|
#include "sudoers_version.h" |
|
#include "auth/sudo_auth.h" |
#include "auth/sudo_auth.h" |
|
#include "secure_path.h" |
|
|
/* |
/* |
* Prototypes |
* Prototypes |
*/ |
*/ |
static void init_vars(char * const *); | static char *find_editor(int nfiles, char **files, char ***argv_out); |
| static int cb_runas_default(const char *); |
| static int cb_sudoers_locale(const char *); |
static int set_cmnd(void); |
static int set_cmnd(void); |
|
static void create_admin_success_flag(void); |
|
static void init_vars(char * const *); |
|
static void set_fqdn(void); |
static void set_loginclass(struct passwd *); |
static void set_loginclass(struct passwd *); |
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 void set_runaspw(const char *); |
static int sudoers_policy_version(int verbose); | static bool tty_present(void); |
static int deserialize_info(char * const settings[], char * const user_info[]); | |
static char *find_editor(int nfiles, char **files, char ***argv_out); | |
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; |
|
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 */ |
sudo_conv_t sudo_conv; |
|
sudo_printf_t sudo_printf; |
|
int sudo_mode; |
int sudo_mode; |
|
|
static char *prev_user; |
static char *prev_user; |
static char *runas_user; |
static char *runas_user; |
static char *runas_group; |
static char *runas_group; |
static struct sudo_nss_list *snl; |
static struct sudo_nss_list *snl; |
static const char *interfaces_string; |
|
static sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp; |
|
|
|
/* XXX - must be extern for audit bits of sudo_auth.c */ |
/* XXX - must be extern for audit bits of sudo_auth.c */ |
int NewArgc; |
int NewArgc; |
char **NewArgv; |
char **NewArgv; |
|
|
/* plugin_error.c */ | int |
extern sigjmp_buf error_jmp; | sudoers_policy_init(void *info, char * const envp[]) |
| |
static int | |
sudoers_policy_open(unsigned int version, sudo_conv_t conversation, | |
sudo_printf_t plugin_printf, char * const settings[], | |
char * const user_info[], char * const envp[]) | |
{ |
{ |
volatile int sources = 0; |
volatile int sources = 0; |
sigaction_t sa; | struct sudo_nss *nss, *nss_next; |
struct sudo_nss *nss; | debug_decl(sudoers_policy_init, SUDO_DEBUG_PLUGIN) |
|
|
if (!sudo_conv) |
|
sudo_conv = conversation; |
|
if (!sudo_printf) |
|
sudo_printf = plugin_printf; |
|
|
|
if (sigsetjmp(error_jmp, 1)) { |
|
/* called via error(), errorx() or log_error() */ |
|
rewind_perms(); |
|
return -1; |
|
} |
|
|
|
bindtextdomain("sudoers", LOCALEDIR); |
bindtextdomain("sudoers", LOCALEDIR); |
|
|
/* |
|
* Signal setup: |
|
* Ignore keyboard-generated signals so the user cannot interrupt |
|
* us at some point and avoid the logging. |
|
* Install handler to wait for children when they exit. |
|
*/ |
|
zero_bytes(&sa, sizeof(sa)); |
|
sigemptyset(&sa.sa_mask); |
|
sa.sa_flags = SA_RESTART; |
|
sa.sa_handler = SIG_IGN; |
|
(void) sigaction(SIGINT, &sa, &saved_sa_int); |
|
(void) sigaction(SIGQUIT, &sa, &saved_sa_quit); |
|
(void) sigaction(SIGTSTP, &sa, &saved_sa_tstp); |
|
|
|
sudo_setpwent(); |
sudo_setpwent(); |
sudo_setgrent(); |
sudo_setgrent(); |
|
|
|
/* Register fatal/fatalx callback. */ |
|
fatal_callback_register(sudoers_cleanup); |
|
|
/* Initialize environment functions (including replacements). */ |
/* Initialize environment functions (including replacements). */ |
env_init(envp); |
env_init(envp); |
|
|
/* Setup defaults data structures. */ |
/* Setup defaults data structures. */ |
init_defaults(); |
init_defaults(); |
|
|
/* Parse settings and user_info */ | /* Parse info from front-end. */ |
sudo_mode = deserialize_info(settings, user_info); | sudo_mode = sudoers_policy_deserialize_info(info, &runas_user, &runas_group); |
|
|
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 151 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_warning(NO_STDERR, N_("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 172 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 221 sudoers_policy_open(unsigned int version, sudo_conv_t
|
Line 181 sudoers_policy_open(unsigned int version, sudo_conv_t
|
* Note that if runas_group was specified without runas_user we |
* Note that if runas_group was specified without runas_user we |
* defer setting runas_pw so the match routines know to ignore it. |
* defer setting runas_pw so the match routines know to ignore it. |
*/ |
*/ |
|
/* XXX - qpm4u does more here as it may have already set runas_pw */ |
if (runas_group != NULL) { |
if (runas_group != NULL) { |
set_runasgr(runas_group); |
set_runasgr(runas_group); |
if (runas_user != NULL) |
if (runas_user != NULL) |
Line 229 sudoers_policy_open(unsigned int version, sudo_conv_t
|
Line 190 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_warning(NO_STDERR, N_("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 | int |
sudoers_policy_close(int exit_status, int error_code) | |
{ | |
if (sigsetjmp(error_jmp, 1)) { | |
/* called via error(), errorx() or log_error() */ | |
return; | |
} | |
| |
/* We do not currently log the exit status. */ | |
if (error_code) | |
warningx(_("unable to execute %s: %s"), safe_cmnd, strerror(error_code)); | |
| |
/* Close the session we opened in sudoers_policy_init_session(). */ | |
if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT)) | |
(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); | |
} | |
| |
/* | |
* The init_session function is called before executing the command | |
* and before uid/gid changes occur. | |
*/ | |
static int | |
sudoers_policy_init_session(struct passwd *pwd) | |
{ | |
if (sigsetjmp(error_jmp, 1)) { | |
/* called via error(), errorx() or log_error() */ | |
return -1; | |
} | |
| |
return sudo_auth_begin_session(pwd); | |
} | |
| |
static int | |
sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], |
sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], |
char **command_infop[], char **argv_out[], char **user_env_out[]) | void *closure) |
{ |
{ |
static char *command_info[32]; /* XXX */ |
|
char **edit_argv = NULL; |
char **edit_argv = NULL; |
|
char *iolog_path = NULL; |
|
mode_t cmnd_umask = 0777; |
struct sudo_nss *nss; |
struct sudo_nss *nss; |
int cmnd_status = -1, validated; | int cmnd_status = -1, oldlocale, 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)) { | /* XXX - would like to move this to policy.c but need the cleanup. */ |
/* error recovery via error(), errorx() or log_error() */ | if (fatal_setjmp() != 0) { |
| /* error recovery via fatal(), fatalx() or log_fatal() */ |
rval = -1; |
rval = -1; |
goto done; |
goto done; |
} |
} |
Line 335 sudoers_policy_main(int argc, char * const argv[], int
|
Line 258 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 |
|
if (!setlocale(LC_ALL, def_sudoers_locale)) { |
|
warningx(_("unable to set locale to \"%s\", using \"C\""), |
|
def_sudoers_locale); |
|
setlocale(LC_ALL, "C"); |
|
} |
|
#endif |
|
|
|
/* |
/* |
* Check sudoers sources. | * Check sudoers sources, using the locale specified in sudoers. |
*/ |
*/ |
|
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale); |
validated = FLAG_NO_USER | FLAG_NO_HOST; |
validated = FLAG_NO_USER | FLAG_NO_HOST; |
tq_foreach_fwd(snl, nss) { |
tq_foreach_fwd(snl, nss) { |
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 376 sudoers_policy_main(int argc, char * const argv[], int
|
Line 288 sudoers_policy_main(int argc, char * const argv[], int
|
} |
} |
} |
} |
|
|
|
/* Restore user's locale. */ |
|
sudoers_setlocale(oldlocale, NULL); |
|
|
if (safe_cmnd == NULL) |
if (safe_cmnd == NULL) |
safe_cmnd = estrdup(user_cmnd); |
safe_cmnd = estrdup(user_cmnd); |
|
|
#ifdef HAVE_SETLOCALE |
|
setlocale(LC_ALL, ""); |
|
#endif |
|
|
|
/* If only a group was specified, set runas_pw based on invoking user. */ |
/* If only a group was specified, set runas_pw based on invoking user. */ |
if (runas_pw == NULL) |
if (runas_pw == NULL) |
set_runaspw(user_name); |
set_runaspw(user_name); |
Line 397 sudoers_policy_main(int argc, char * const argv[], int
|
Line 308 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) { |
log_error(0, _("timestamp owner (%s): No such user"), | timestamp_uid = pw->pw_uid; |
| sudo_pw_delref(pw); |
| } else { |
| log_warning(0, N_("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 411 sudoers_policy_main(int argc, char * const argv[], int
|
Line 325 sudoers_policy_main(int argc, char * const argv[], int
|
} |
} |
|
|
/* Bail if a tty is required and we don't have one. */ |
/* Bail if a tty is required and we don't have one. */ |
if (def_requiretty) { | if (def_requiretty && !tty_present()) { |
int fd = open(_PATH_TTY, O_RDWR|O_NOCTTY); | audit_failure(NewArgv, N_("no tty")); |
if (fd == -1) { | warningx(_("sorry, you must have a tty to run sudo")); |
audit_failure(NewArgv, _("no tty")); | goto bad; |
warningx(_("sorry, you must have a tty to run sudo")); | |
goto bad; | |
} else | |
(void) close(fd); | |
} |
} |
|
|
/* |
/* |
Line 427 sudoers_policy_main(int argc, char * const argv[], int
|
Line 337 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_denial(validated, false); |
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 358 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 366 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 485 sudoers_policy_main(int argc, char * const argv[], int
|
Line 375 sudoers_policy_main(int argc, char * const argv[], int
|
|
|
/* Finally tell the user if the command did not exist. */ |
/* Finally tell the user if the command did not exist. */ |
if (cmnd_status == NOT_FOUND_DOT) { |
if (cmnd_status == NOT_FOUND_DOT) { |
audit_failure(NewArgv, _("command in current directory")); | audit_failure(NewArgv, N_("command in current directory")); |
warningx(_("ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run."), user_cmnd, user_cmnd, user_cmnd); |
warningx(_("ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run."), user_cmnd, user_cmnd, user_cmnd); |
goto bad; |
goto bad; |
} else if (cmnd_status == NOT_FOUND) { |
} else if (cmnd_status == NOT_FOUND) { |
audit_failure(NewArgv, _("%s: command not found"), user_cmnd); | if (ISSET(sudo_mode, MODE_CHECK)) { |
warningx(_("%s: command not found"), user_cmnd); | audit_failure(NewArgv, N_("%s: command not found"), NewArgv[0]); |
| warningx(_("%s: command not found"), NewArgv[0]); |
| } else { |
| audit_failure(NewArgv, N_("%s: command not found"), user_cmnd); |
| warningx(_("%s: command not found"), user_cmnd); |
| } |
goto bad; |
goto bad; |
} |
} |
|
|
Line 503 sudoers_policy_main(int argc, char * const argv[], int
|
Line 398 sudoers_policy_main(int argc, char * const argv[], int
|
validate_env_vars(sudo_user.env_vars); |
validate_env_vars(sudo_user.env_vars); |
} |
} |
|
|
if (ISSET(sudo_mode, (MODE_RUN | MODE_EDIT)) && (def_log_input || def_log_output)) { | if (ISSET(sudo_mode, (MODE_RUN | MODE_EDIT))) { |
if (def_iolog_file && def_iolog_dir) { | if ((def_log_input || def_log_output) && def_iolog_file && def_iolog_dir) { |
command_info[info_len++] = expand_iolog_path("iolog_path=", | const char prefix[] = "iolog_path="; |
def_iolog_dir, def_iolog_file, &sudo_user.iolog_file); | iolog_path = expand_iolog_path(prefix, def_iolog_dir, |
| def_iolog_file, &sudo_user.iolog_file); |
sudo_user.iolog_file++; |
sudo_user.iolog_file++; |
} |
} |
if (def_log_input) { |
|
command_info[info_len++] = estrdup("iolog_stdin=true"); |
|
command_info[info_len++] = estrdup("iolog_ttyin=true"); |
|
} |
|
if (def_log_output) { |
|
command_info[info_len++] = estrdup("iolog_stdout=true"); |
|
command_info[info_len++] = estrdup("iolog_stderr=true"); |
|
command_info[info_len++] = estrdup("iolog_ttyout=true"); |
|
} |
|
if (def_compress_io) |
|
command_info[info_len++] = estrdup("iolog_compress=true"); |
|
} |
} |
|
|
log_allowed(validated); |
log_allowed(validated); |
Line 546 sudoers_policy_main(int argc, char * const argv[], int
|
Line 431 sudoers_policy_main(int argc, char * const argv[], int
|
* unless umask_override is set. |
* unless umask_override is set. |
*/ |
*/ |
if (def_umask != 0777) { |
if (def_umask != 0777) { |
mode_t mask = def_umask; | cmnd_umask = def_umask; |
if (!def_umask_override) { | if (!def_umask_override) |
mode_t omask = umask(mask); | cmnd_umask |= user_umask; |
mask |= omask; | |
umask(omask); | |
} | |
easprintf(&command_info[info_len++], "umask=0%o", (unsigned int)mask); | |
} |
} |
|
|
if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) { |
if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) { |
Line 564 sudoers_policy_main(int argc, char * const argv[], int
|
Line 445 sudoers_policy_main(int argc, char * const argv[], int
|
*p = '-'; |
*p = '-'; |
NewArgv[0] = p; |
NewArgv[0] = p; |
|
|
/* Set cwd to run user's homedir. */ |
|
command_info[info_len++] = fmt_string("cwd", runas_pw->pw_dir); |
|
|
|
/* |
/* |
* Newer versions of bash require the --login option to be used |
* Newer versions of bash require the --login option to be used |
* in conjunction with the -c option even if the shell name starts |
* in conjunction with the -c option even if the shell name starts |
Line 582 sudoers_policy_main(int argc, char * const argv[], int
|
Line 460 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); |
|
|
/* Restore signal handlers before we exec. */ |
|
(void) sigaction(SIGINT, &saved_sa_int, NULL); |
|
(void) sigaction(SIGQUIT, &saved_sa_quit, NULL); |
|
(void) sigaction(SIGTSTP, &saved_sa_tstp, NULL); |
|
|
|
if (ISSET(sudo_mode, MODE_EDIT)) { |
if (ISSET(sudo_mode, MODE_EDIT)) { |
char *editor = find_editor(NewArgc - 1, NewArgv + 1, &edit_argv); | efree(safe_cmnd); |
if (editor == NULL) | safe_cmnd = find_editor(NewArgc - 1, NewArgv + 1, &edit_argv); |
| if (safe_cmnd == NULL) |
goto bad; |
goto bad; |
command_info[info_len++] = fmt_string("command", editor); |
|
command_info[info_len++] = estrdup("sudoedit=true"); |
|
} else { |
|
command_info[info_len++] = fmt_string("command", safe_cmnd); |
|
} |
} |
if (def_stay_setuid) { |
|
easprintf(&command_info[info_len++], "runas_uid=%u", |
|
(unsigned int)user_uid); |
|
easprintf(&command_info[info_len++], "runas_gid=%u", |
|
(unsigned int)user_gid); |
|
easprintf(&command_info[info_len++], "runas_euid=%u", |
|
(unsigned int)runas_pw->pw_uid); |
|
easprintf(&command_info[info_len++], "runas_egid=%u", |
|
runas_gr ? (unsigned int)runas_gr->gr_gid : |
|
(unsigned int)runas_pw->pw_gid); |
|
} else { |
|
easprintf(&command_info[info_len++], "runas_uid=%u", |
|
(unsigned int)runas_pw->pw_uid); |
|
easprintf(&command_info[info_len++], "runas_gid=%u", |
|
runas_gr ? (unsigned int)runas_gr->gr_gid : |
|
(unsigned int)runas_pw->pw_gid); |
|
} |
|
if (def_preserve_groups) { |
|
command_info[info_len++] = "preserve_groups=true"; |
|
} else { |
|
int i, len; |
|
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)); |
|
gid_list = emalloc(glsize); |
|
memcpy(gid_list, "runas_groups=", sizeof("runas_groups=") - 1); |
|
cp = gid_list + sizeof("runas_groups=") - 1; |
|
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; |
|
} |
|
command_info[info_len++] = gid_list; |
|
grlist_delref(grlist); |
|
} |
|
if (def_closefrom >= 0) |
|
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) |
|
command_info[info_len++] = estrdup("use_pty=true"); |
|
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); |
|
#endif /* HAVE_LOGIN_CAP_H */ |
|
#ifdef HAVE_SELINUX |
|
if (user_role != NULL) |
|
command_info[info_len++] = fmt_string("selinux_role", user_role); |
|
if (user_type != NULL) |
|
command_info[info_len++] = fmt_string("selinux_type", user_type); |
|
#endif /* HAVE_SELINUX */ |
|
|
|
/* Must audit before uid change. */ |
/* Must audit before uid change. */ |
audit_success(NewArgv); |
audit_success(NewArgv); |
|
|
*command_infop = command_info; | /* Setup execution environment to pass back to front-end. */ |
| rval = sudoers_policy_exec_setup(edit_argv ? edit_argv : NewArgv, |
| env_get(), cmnd_umask, iolog_path, closure); |
|
|
*argv_out = edit_argv ? edit_argv : NewArgv; | /* Zero out stashed copy of environment, it is owned by the front-end. */ |
*user_env_out = env_get(); /* our private copy */ | env_init(NULL); |
|
|
goto done; |
goto done; |
|
|
bad: |
bad: |
rval = FALSE; | rval = false; |
|
|
done: |
done: |
|
fatal_disable_setjmp(); |
rewind_perms(); |
rewind_perms(); |
|
|
/* Close the password and group files and free up memory. */ |
/* Close the password and group files and free up memory. */ |
sudo_endpwent(); |
sudo_endpwent(); |
sudo_endgrent(); |
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[]) |
|
{ |
|
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); |
|
} |
|
|
|
static int |
|
sudoers_policy_validate(void) |
|
{ |
|
user_cmnd = "validate"; |
|
SET(sudo_mode, MODE_VALIDATE); |
|
|
|
return sudoers_policy_main(0, NULL, I_VERIFYPW, NULL, NULL, NULL, NULL); |
|
} |
|
|
|
static void |
|
sudoers_policy_invalidate(int remove) |
|
{ |
|
user_cmnd = "kill"; |
|
if (sigsetjmp(error_jmp, 1) == 0) { |
|
remove_timestamp(remove); |
|
plugin_cleanup(0); |
|
} |
|
} |
|
|
|
static int |
|
sudoers_policy_list(int argc, char * const argv[], int verbose, |
|
const char *list_user) |
|
{ |
|
int rval; |
|
|
|
user_cmnd = "list"; |
|
if (argc) |
|
SET(sudo_mode, MODE_CHECK); |
|
else |
|
SET(sudo_mode, MODE_LIST); |
|
if (verbose) |
|
long_list = 1; |
|
if (list_user) { |
|
list_pw = sudo_getpwnam(list_user); |
|
if (list_pw == NULL) { |
|
warningx(_("unknown user: %s"), list_user); |
|
return -1; |
|
} |
|
} |
|
rval = sudoers_policy_main(argc, argv, I_LISTPW, NULL, NULL, NULL, NULL); |
|
if (list_user) { |
|
pw_delref(list_pw); |
|
list_pw = NULL; |
|
} |
|
|
|
return rval; |
|
} |
|
|
|
/* |
/* |
* Initialize timezone, set umask, fill in ``sudo_user'' struct and | * Initialize timezone and fill in ``sudo_user'' struct. |
* load the ``interfaces'' array. | |
*/ |
*/ |
static void |
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 | sudoers_initlocale(setlocale(LC_ALL, NULL), def_sudoers_locale); |
(void) tzset(); /* set the timezone if applicable */ | |
#endif /* HAVE_TZSET */ | |
|
|
for (ep = envp; *ep; ep++) { |
for (ep = envp; *ep; ep++) { |
/* XXX - don't fill in if empty string */ |
/* XXX - don't fill in if empty string */ |
Line 786 init_vars(char * const envp[])
|
Line 548 init_vars(char * const envp[])
|
} |
} |
|
|
/* |
/* |
* Get a local copy of the user's struct passwd with the shadow password | * Get a local copy of the user's struct passwd if we don't already |
* if necessary. It is assumed that euid is 0 at this point so we | * have one. |
* can read the shadow passwd file if necessary. | |
*/ |
*/ |
if ((sudo_user.pw = sudo_getpwuid(user_uid)) == NULL) { | if (sudo_user.pw == NULL) { |
/* | if ((sudo_user.pw = sudo_getpwnam(user_name)) == NULL) { |
* It is not unusual for users to place "sudo -k" in a .logout | /* |
* file which can cause sudo to be run during reboot after the | * It is not unusual for users to place "sudo -k" in a .logout |
* YP/NIS/NIS+/LDAP/etc daemon has died. | * file which can cause sudo to be run during reboot after the |
*/ | * YP/NIS/NIS+/LDAP/etc daemon has died. |
if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) | */ |
errorx(1, _("unknown uid: %u"), (unsigned int) user_uid); | if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) |
| fatalx(_("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_mkpwent(user_name, user_uid, user_gid, NULL, NULL); |
log_error(0, _("unknown uid: %u"), (unsigned int) user_uid); | log_fatal(0, N_("unknown uid: %u"), (unsigned int) user_uid); |
/* NOTREACHED */ | /* NOTREACHED */ |
| } |
} |
} |
|
|
/* |
/* |
* 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() */ | /* Set locale callback. */ |
| sudo_defs_table[I_SUDOERS_LOCALE].callback = cb_sudoers_locale; |
| |
| /* Set maxseq callback. */ |
| sudo_defs_table[I_MAXSEQ].callback = io_set_max_sessid; |
| |
| /* It is now safe to use log_fatal() and set_perms() */ |
| debug_return; |
} |
} |
|
|
/* |
/* |
Line 826 set_cmnd(void)
|
Line 596 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 651 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")); | fatalx(_("internal error, %s overflow"), "set_cmnd()"); |
to += n; |
to += n; |
*to++ = ' '; |
*to++ = ' '; |
} |
} |
Line 888 set_cmnd(void)
|
Line 659 set_cmnd(void)
|
} |
} |
} |
} |
} |
} |
if (strlen(user_cmnd) >= PATH_MAX) | if (strlen(user_cmnd) >= PATH_MAX) { |
errorx(1, _("%s: %s"), user_cmnd, strerror(ENAMETOOLONG)); | errno = ENAMETOOLONG; |
| fatal("%s", user_cmnd); |
| } |
|
|
if ((user_base = strrchr(user_cmnd, '/')) != NULL) |
if ((user_base = strrchr(user_cmnd, '/')) != NULL) |
user_base++; |
user_base++; |
Line 897 set_cmnd(void)
|
Line 670 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_warning(NO_STDERR, N_("problem with defaults entries")); |
|
|
return rval; | debug_return_int(rval); |
} |
} |
|
|
/* |
/* |
Line 907 set_cmnd(void)
|
Line 680 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_warning(USE_ERRNO, N_("unable to open %s"), sudoers); |
| } else { |
| if (sb.st_size != 0 && fgetc(fp) == EOF) { |
| log_warning(USE_ERRNO, N_("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_warning(USE_ERRNO, N_("unable to stat %s"), sudoers); |
| break; |
| case SUDO_PATH_BAD_TYPE: |
| log_warning(0, N_("%s is not a regular file"), sudoers); |
| break; |
| case SUDO_PATH_WRONG_OWNER: |
| log_warning(0, N_("%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_warning(0, N_("%s is world writable"), sudoers); |
| break; |
| case SUDO_PATH_GROUP_WRITABLE: |
| log_warning(0, N_("%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 && |
strcmp(runas_user ? runas_user : def_runas_default, "root") != 0) |
strcmp(runas_user ? runas_user : def_runas_default, "root") != 0) |
errorx(1, _("only root can use `-c %s'"), login_class); | fatalx(_("only root can use `-c %s'"), login_class); |
} else { |
} else { |
login_class = pw->pw_class; |
login_class = pw->pw_class; |
if (!login_class || !*login_class) |
if (!login_class || !*login_class) |
Line 1006 set_loginclass(struct passwd *pw)
|
Line 768 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, N_("unknown login class: %s"), login_class); |
| else |
| log_warning(errflags, N_("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 792 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 | static 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_warning(MSG_ONLY, N_("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, N_("unknown user: %s"), user); |
} |
} |
|
debug_return; |
} |
} |
|
|
/* |
/* |
Line 1085 set_runaspw(const char *user)
|
Line 854 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, N_("unknown group: %s"), group); |
} |
} |
|
debug_return; |
} |
} |
|
|
/* |
/* |
Line 1105 cb_runas_default(const char *user)
|
Line 877 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; |
} |
} |
|
|
/* |
/* |
* Cleanup hook for error()/errorx() | * Callback for sudoers_locale sudoers setting. |
*/ |
*/ |
void |
|
plugin_cleanup(int gotsignal) |
|
{ |
|
struct sudo_nss *nss; |
|
|
|
if (!gotsignal) { |
|
if (snl != NULL) { |
|
tq_foreach_fwd(snl, nss) |
|
nss->close(nss); |
|
} |
|
if (def_group_plugin) |
|
group_plugin_unload(); |
|
sudo_endpwent(); |
|
sudo_endgrent(); |
|
} |
|
} |
|
|
|
static int |
static int |
sudoers_policy_version(int verbose) | cb_sudoers_locale(const char *locale) |
{ |
{ |
if (sigsetjmp(error_jmp, 1)) { | sudoers_initlocale(NULL, locale); |
/* error recovery via error(), errorx() or log_error() */ | return true; |
return -1; | |
} | |
| |
sudo_printf(SUDO_CONV_INFO_MSG, _("Sudoers policy plugin version %s\n"), | |
PACKAGE_VERSION); | |
sudo_printf(SUDO_CONV_INFO_MSG, _("Sudoers file grammar version %d\n"), | |
SUDOERS_GRAMMAR_VERSION); | |
| |
if (verbose) { | |
sudo_printf(SUDO_CONV_INFO_MSG, _("\nSudoers path: %s\n"), sudoers_file); | |
#ifdef HAVE_LDAP | |
# ifdef _PATH_NSSWITCH_CONF | |
sudo_printf(SUDO_CONV_INFO_MSG, _("nsswitch path: %s\n"), _PATH_NSSWITCH_CONF); | |
# endif | |
sudo_printf(SUDO_CONV_INFO_MSG, _("ldap.conf path: %s\n"), _PATH_LDAP_CONF); | |
sudo_printf(SUDO_CONV_INFO_MSG, _("ldap.secret path: %s\n"), _PATH_LDAP_SECRET); | |
#endif | |
dump_auth_methods(); | |
dump_defaults(); | |
sudo_printf(SUDO_CONV_INFO_MSG, "\n"); | |
dump_interfaces(interfaces_string); | |
sudo_printf(SUDO_CONV_INFO_MSG, "\n"); | |
} | |
return TRUE; | |
} |
} |
|
|
static int | /* |
deserialize_info(char * const settings[], char * const user_info[]) | * Cleanup hook for fatal()/fatalx() |
| */ |
| void |
| sudoers_cleanup(void) |
{ |
{ |
char * const *cur; | struct sudo_nss *nss; |
const char *p, *groups = NULL; | debug_decl(sudoers_cleanup, SUDO_DEBUG_PLUGIN) |
int flags = 0; | |
|
|
#define MATCHES(s, v) (strncmp(s, v, sizeof(v) - 1) == 0) | if (snl != NULL) { |
| tq_foreach_fwd(snl, nss) |
/* Parse command line settings. */ | nss->close(nss); |
user_closefrom = -1; | |
for (cur = settings; *cur != NULL; cur++) { | |
if (MATCHES(*cur, "closefrom=")) { | |
user_closefrom = atoi(*cur + sizeof("closefrom=") - 1); | |
continue; | |
} | |
if (MATCHES(*cur, "debug_level=")) { | |
debug_level = atoi(*cur + sizeof("debug_level=") - 1); | |
continue; | |
} | |
if (MATCHES(*cur, "runas_user=")) { | |
runas_user = *cur + sizeof("runas_user=") - 1; | |
continue; | |
} | |
if (MATCHES(*cur, "runas_group=")) { | |
runas_group = *cur + sizeof("runas_group=") - 1; | |
continue; | |
} | |
if (MATCHES(*cur, "prompt=")) { | |
user_prompt = *cur + sizeof("prompt=") - 1; | |
def_passprompt_override = TRUE; | |
continue; | |
} | |
if (MATCHES(*cur, "set_home=")) { | |
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) | |
SET(flags, MODE_PRESERVE_ENV); | |
continue; | |
} | |
if (MATCHES(*cur, "run_shell=")) { | |
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) { | |
SET(flags, MODE_LOGIN_SHELL); | |
def_env_reset = TRUE; | |
} | |
continue; | |
} | |
if (MATCHES(*cur, "implied_shell=")) { | |
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) | |
SET(flags, MODE_PRESERVE_GROUPS); | |
continue; | |
} | |
if (MATCHES(*cur, "ignore_ticket=")) { | |
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) | |
SET(flags, MODE_NONINTERACTIVE); | |
continue; | |
} | |
if (MATCHES(*cur, "sudoedit=")) { | |
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; | |
continue; | |
} | |
#ifdef HAVE_SELINUX | |
if (MATCHES(*cur, "selinux_role=")) { | |
user_role = *cur + sizeof("selinux_role=") - 1; | |
continue; | |
} | |
if (MATCHES(*cur, "selinux_type=")) { | |
user_type = *cur + sizeof("selinux_type=") - 1; | |
continue; | |
} | |
#endif /* HAVE_SELINUX */ | |
#ifdef HAVE_BSD_AUTH_H | |
if (MATCHES(*cur, "bsdauth_type=")) { | |
login_style = *cur + sizeof("bsdauth_type=") - 1; | |
continue; | |
} | |
#endif /* HAVE_BSD_AUTH_H */ | |
#if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME) | |
if (MATCHES(*cur, "progname=")) { | |
setprogname(*cur + sizeof("progname=") - 1); | |
continue; | |
} | |
#endif | |
if (MATCHES(*cur, "network_addrs=")) { | |
interfaces_string = *cur + sizeof("network_addrs=") - 1; | |
set_interfaces(interfaces_string); | |
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; | |
} | |
} |
} |
|
if (def_group_plugin) |
|
group_plugin_unload(); |
|
sudo_endpwent(); |
|
sudo_endgrent(); |
|
|
for (cur = user_info; *cur != NULL; cur++) { | debug_return; |
if (MATCHES(*cur, "user=")) { | |
user_name = estrdup(*cur + sizeof("user=") - 1); | |
continue; | |
} | |
if (MATCHES(*cur, "uid=")) { | |
user_uid = (uid_t) atoi(*cur + sizeof("uid=") - 1); | |
continue; | |
} | |
if (MATCHES(*cur, "gid=")) { | |
p = *cur + sizeof("gid=") - 1; | |
user_gid = (gid_t) atoi(p); | |
continue; | |
} | |
if (MATCHES(*cur, "groups=")) { | |
groups = *cur + sizeof("groups=") - 1; | |
continue; | |
} | |
if (MATCHES(*cur, "cwd=")) { | |
user_cwd = estrdup(*cur + sizeof("cwd=") - 1); | |
continue; | |
} | |
if (MATCHES(*cur, "tty=")) { | |
user_tty = user_ttypath = estrdup(*cur + sizeof("tty=") - 1); | |
if (strncmp(user_tty, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) | |
user_tty += sizeof(_PATH_DEV) - 1; | |
continue; | |
} | |
if (MATCHES(*cur, "host=")) { | |
user_host = user_shost = estrdup(*cur + sizeof("host=") - 1); | |
if ((p = strchr(user_host, '.'))) | |
user_shost = estrndup(user_host, (size_t)(p - user_host)); | |
continue; | |
} | |
if (MATCHES(*cur, "lines=")) { | |
sudo_user.lines = atoi(*cur + sizeof("lines=") - 1); | |
continue; | |
} | |
if (MATCHES(*cur, "cols=")) { | |
sudo_user.cols = atoi(*cur + sizeof("cols=") - 1); | |
continue; | |
} | |
} | |
if (user_cwd == NULL) | |
user_cwd = "unknown"; | |
if (user_tty == NULL) | |
user_tty = "unknown"; /* user_ttypath remains NULL */ | |
| |
if (groups != NULL && groups[0] != '\0') { | |
const char *cp; | |
GETGROUPS_T *gids; | |
int ngids; | |
| |
/* Count number of groups, including passwd gid. */ | |
ngids = 2; | |
for (cp = groups; *cp != '\0'; cp++) { | |
if (*cp == ',') | |
ngids++; | |
} | |
| |
/* The first gid in the list is the passwd group gid. */ | |
gids = emalloc2(ngids, sizeof(GETGROUPS_T)); | |
gids[0] = user_gid; | |
ngids = 1; | |
cp = groups; | |
for (;;) { | |
gids[ngids] = atoi(cp); | |
if (gids[0] != gids[ngids]) | |
ngids++; | |
cp = strchr(cp, ','); | |
if (cp == NULL) | |
break; | |
cp++; /* skip over comma */ | |
} | |
set_group_list(user_name, gids, ngids); | |
efree(gids); | |
} | |
| |
#undef MATCHES | |
return flags; | |
} |
} |
|
|
static char * |
static char * |
resolve_editor(char *editor, int nfiles, char **files, char ***argv_out) | resolve_editor(const char *ed, size_t edlen, int nfiles, char **files, char ***argv_out) |
{ |
{ |
char *cp, **nargv, *editor_path = NULL; | char *cp, **nargv, *editor, *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 */ | /* Note: editor becomes part of argv_out and is not freed. */ |
| editor = emalloc(edlen + 1); |
| memcpy(editor, ed, edlen); |
| editor[edlen] = '\0'; |
|
|
/* |
/* |
* Split editor into an argument vector; editor is reused (do not free). |
* Split editor into an argument vector; editor is reused (do not free). |
Line 1386 resolve_editor(char *editor, int nfiles, char **files,
|
Line 930 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 943 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 956 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 1423 resolve_editor(char *editor, int nfiles, char **files,
|
Line 967 resolve_editor(char *editor, int nfiles, char **files,
|
static char * |
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]; | const char *cp, *ep, *editor; |
| char *editor_path = NULL, **ev, *ev0[4]; |
| size_t len; |
| 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 1432 find_editor(int nfiles, char **files, char ***argv_out
|
Line 979 find_editor(int nfiles, char **files, char ***argv_out
|
ev0[1] = "VISUAL"; |
ev0[1] = "VISUAL"; |
ev0[2] = "EDITOR"; |
ev0[2] = "EDITOR"; |
ev0[3] = NULL; |
ev0[3] = NULL; |
for (ev = ev0; *ev != NULL; ev++) { | for (ev = ev0; editor_path == NULL && *ev != NULL; ev++) { |
if ((editor = getenv(*ev)) != NULL && *editor != '\0') { |
if ((editor = getenv(*ev)) != NULL && *editor != '\0') { |
editor_path = resolve_editor(editor, nfiles, files, argv_out); | editor_path = resolve_editor(editor, strlen(editor), nfiles, |
if (editor_path != NULL) | files, argv_out); |
break; | |
} |
} |
} |
} |
if (editor_path == NULL) { |
if (editor_path == NULL) { |
/* def_editor could be a path, split it up */ | /* def_editor could be a path, split it up, avoiding strtok() */ |
editor = estrdup(def_editor); | cp = editor = def_editor; |
cp = strtok(editor, ":"); | do { |
while (cp != NULL && editor_path == NULL) { | if ((ep = strchr(cp, ':')) != NULL) |
editor_path = resolve_editor(cp, nfiles, files, argv_out); | len = ep - cp; |
cp = strtok(NULL, ":"); | else |
} | len = strlen(cp); |
if (editor_path) | editor_path = resolve_editor(cp, len, nfiles, files, argv_out); |
efree(editor); | cp = ep + 1; |
| } while (ep != NULL && editor_path == NULL); |
} |
} |
if (!editor_path) { |
if (!editor_path) { |
audit_failure(NewArgv, _("%s: command not found"), editor); | audit_failure(NewArgv, N_("%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 1011 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 1030 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 1040 create_admin_success_flag(void)
|
} |
} |
#endif /* USE_ADMIN_FLAG */ |
#endif /* USE_ADMIN_FLAG */ |
|
|
struct policy_plugin sudoers_policy = { | static bool |
SUDO_POLICY_PLUGIN, | tty_present(void) |
SUDO_API_VERSION, | { |
sudoers_policy_open, | #if defined(HAVE_STRUCT_KINFO_PROC2_P_TDEV) || defined(HAVE_STRUCT_KINFO_PROC_P_TDEV) || defined(HAVE_STRUCT_KINFO_PROC_KI_TDEV) || defined(HAVE_STRUCT_KINFO_PROC_KP_EPROC_E_TDEV) || defined(HAVE_STRUCT_PSINFO_PR_TTYDEV) || defined(HAVE_PSTAT_GETPROC) || defined(__linux__) |
sudoers_policy_close, | return user_ttypath != NULL; |
sudoers_policy_version, | #else |
sudoers_policy_check, | int fd = open(_PATH_TTY, O_RDWR|O_NOCTTY); |
sudoers_policy_list, | if (fd != -1) |
sudoers_policy_validate, | close(fd); |
sudoers_policy_invalidate, | return fd != -1; |
sudoers_policy_init_session | #endif |
}; | } |