static int
check_user_interactive(int validated, int mode, struct passwd *auth_pw)
{
- int status, rval = true;
+ int status, rval = -1;
+ char *prompt;
+ bool lectured;
debug_decl(check_user_interactive, SUDOERS_DEBUG_AUTH)
/* Always need a password when -k was specified with the command. */
if (ISSET(mode, MODE_IGNORE_TICKET))
SET(validated, FLAG_CHECK_USER);
- if (build_timestamp(auth_pw) == -1) {
- rval = -1;
+ if (build_timestamp(auth_pw) == -1)
goto done;
- }
status = timestamp_status(auth_pw);
+ switch (status) {
+ case TS_FATAL:
+ /* Fatal error (usually setuid failure), unsafe to proceed. */
+ goto done;
- if (status != TS_CURRENT || ISSET(validated, FLAG_CHECK_USER)) {
- char *prompt;
- bool lectured;
+ case TS_CURRENT:
+ /* Time stamp file is valid and current. */
+ if (!ISSET(validated, FLAG_CHECK_USER)) {
+ rval = true;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
/* Bail out if we are non-interactive and a password is required */
if (ISSET(mode, MODE_NONINTERACTIVE)) {
validated |= FLAG_NON_INTERACTIVE;
log_auth_failure(validated, 0);
- rval = -1;
goto done;
}
/* Expand any escapes in the prompt. */
prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt,
auth_pw->pw_name);
- if (prompt == NULL) {
- rval = -1;
+ if (prompt == NULL)
goto done;
- }
rval = verify_user(auth_pw, prompt, validated);
- if (rval == true && lectured)
- set_lectured();
+ if (rval == true && lectured) {
+ if (set_lectured() == -1)
+ rval = -1;
+ }
free(prompt);
+ break;
}
+
/* Only update timestamp if user was validated. */
if (rval == true && ISSET(validated, VALIDATE_SUCCESS) &&
- !ISSET(mode, MODE_IGNORE_TICKET) && status != TS_ERROR)
- update_timestamp(auth_pw);
+ !ISSET(mode, MODE_IGNORE_TICKET) && status != TS_ERROR) {
+ if (update_timestamp(auth_pw) == -1)
+ rval = -1;
+ }
done:
debug_return_int(rval);
}
static bool cb_runas_default(const char *);
static bool cb_sudoers_locale(const char *);
static int set_cmnd(void);
-static void create_admin_success_flag(void);
+static int create_admin_success_flag(void);
static bool init_vars(char * const *);
static bool set_fqdn(void);
static bool set_loginclass(struct passwd *);
}
/* Create Ubuntu-style dot file to indicate sudo was successful. */
- create_admin_success_flag();
+ if (create_admin_success_flag() == -1)
+ goto bad;
/* Finally tell the user if the command did not exist. */
if (cmnd_status == NOT_FOUND_DOT) {
}
#ifdef USE_ADMIN_FLAG
-static void
+static int
create_admin_success_flag(void)
{
struct stat statbuf;
char flagfile[PATH_MAX];
- int fd, n;
+ int len, fd = -1;
debug_decl(create_admin_success_flag, SUDOERS_DEBUG_PLUGIN)
/* Check whether the user is in the admin group. */
if (!user_in_group(sudo_user.pw, "admin"))
- debug_return;
+ debug_return_int(true);
/* Build path to flag file. */
- n = snprintf(flagfile, sizeof(flagfile), "%s/.sudo_as_admin_successful",
+ len = snprintf(flagfile, sizeof(flagfile), "%s/.sudo_as_admin_successful",
user_dir);
- if (n <= 0 || (size_t)n >= sizeof(flagfile))
- debug_return;
+ if (len <= 0 || (size_t)len >= sizeof(flagfile))
+ debug_return_int(false);
/* Create admin flag file if it doesn't already exist. */
if (set_perms(PERM_USER)) {
if (stat(flagfile, &statbuf) != 0) {
fd = open(flagfile, O_CREAT|O_WRONLY|O_EXCL, 0644);
- close(fd);
+ if (fd != -1)
+ close(fd);
}
- (void) restore_perms();
+ if (!restore_perms())
+ debug_return_int(-1);
}
- debug_return;
+ debug_return_int(fd != -1);
}
#else /* !USE_ADMIN_FLAG */
-static void
+static int
create_admin_success_flag(void)
{
/* STUB */
+ return true;
}
#endif /* USE_ADMIN_FLAG */
#include "sudoers.h"
#include "check.h"
+#define TIMESTAMP_OPEN_ERROR -1
+#define TIMESTAMP_PERM_ERROR -2
+
static char timestamp_file[PATH_MAX];
static off_t timestamp_hint = (off_t)-1;
static struct timestamp_entry timestamp_key;
debug_return_int(len);
}
+/*
+ * Open and lock the specified timestamp file.
+ * Returns 0 on success or -1 on failure.
+ */
+static int
+open_timestamp(const char *path, int flags)
+{
+ bool uid_changed = false;
+ int fd;
+ debug_decl(open_timestamp, SUDOERS_DEBUG_AUTH)
+
+ if (timestamp_uid != 0)
+ uid_changed = set_perms(PERM_TIMESTAMP);
+ fd = open(timestamp_file, flags, 0600);
+ if (uid_changed && !restore_perms()) {
+ /* Unable to restore permissions, should not happen. */
+ if (fd != -1) {
+ int serrno = errno;
+ close(fd);
+ errno = serrno;
+ fd = TIMESTAMP_PERM_ERROR;
+ }
+ }
+ if (fd >= 0)
+ sudo_lock_file(fd, SUDO_LOCK);
+
+ debug_return_int(fd);
+}
+
/*
* Update the time on the timestamp file/dir or create it if necessary.
- * Returns true on success or false on failure.
+ * Returns true on success, false on failure or -1 on setuid failure.
*/
-bool
+int
update_timestamp(struct passwd *pw)
{
struct timestamp_entry entry;
- bool uid_changed = false;
- bool rval = false;
- int fd;
+ int rval = false;
+ int fd = -1;
debug_decl(update_timestamp, SUDOERS_DEBUG_AUTH)
/* Zero timeout means don't update the time stamp file. */
}
/* Open time stamp file and lock it for exclusive access. */
- if (timestamp_uid != 0)
- uid_changed = set_perms(PERM_TIMESTAMP);
- fd = open(timestamp_file, O_RDWR|O_CREAT, 0600);
- if (uid_changed)
- (void) restore_perms();
- if (fd == -1) {
+ fd = open_timestamp(timestamp_file, O_RDWR|O_CREAT);
+ switch (fd) {
+ case TIMESTAMP_OPEN_ERROR:
log_warning(SLOG_SEND_MAIL, N_("unable to open %s"), timestamp_file);
goto done;
+ case TIMESTAMP_PERM_ERROR:
+ /* Already logged set_perms/restore_perms error. */
+ rval = -1;
+ goto done;
}
/* Update record or append a new one. */
- sudo_lock_file(fd, SUDO_LOCK);
ts_update_record(fd, &entry, timestamp_hint);
close(fd);
rval = true;
done:
- debug_return_bool(rval);
+ debug_return_int(rval);
}
/*
{
struct timestamp_entry entry;
struct timespec diff, timeout;
- bool uid_changed = false;
int status = TS_ERROR; /* assume the worst */
struct stat sb;
int fd = -1;
goto done;
/* Open time stamp file and lock it for exclusive access. */
- if (timestamp_uid != 0)
- uid_changed = set_perms(PERM_TIMESTAMP);
- fd = open(timestamp_file, O_RDWR);
- if (uid_changed)
- (void) restore_perms();
- if (fd == -1) {
+ fd = open_timestamp(timestamp_file, O_RDWR);
+ switch (fd) {
+ case TIMESTAMP_OPEN_ERROR:
status = TS_MISSING;
goto done;
+ case TIMESTAMP_PERM_ERROR:
+ /* Already logged set_perms/restore_perms error. */
+ status = TS_FATAL;
+ goto done;
}
- sudo_lock_file(fd, SUDO_LOCK);
/* Ignore and clear time stamp file if mtime predates boot time. */
if (fstat(fd, &sb) == 0) {
/*
* Remove the timestamp entry or file if unlink_it is set.
+ * Returns true on success, false on failure or -1 on setuid failure.
+ * A missing timestamp entry is not considered an error.
*/
-void
+int
remove_timestamp(bool unlink_it)
{
struct timestamp_entry entry;
- bool uid_changed = false;
- int fd = -1;
+ int fd, rval = true;
debug_decl(remove_timestamp, SUDOERS_DEBUG_AUTH)
- if (build_timestamp(NULL) == -1)
- debug_return;
+ if (build_timestamp(NULL) == -1) {
+ rval = -1;
+ goto done;
+ }
/* For "sudo -K" simply unlink the time stamp file. */
if (unlink_it) {
- (void) unlink(timestamp_file);
- debug_return;
+ rval = unlink(timestamp_file) ? -1 : true;
+ goto done;
}
/*
}
/* Open time stamp file and lock it for exclusive access. */
- if (timestamp_uid != 0)
- uid_changed = set_perms(PERM_TIMESTAMP);
- fd = open(timestamp_file, O_RDWR);
- if (uid_changed)
- (void) restore_perms();
- if (fd == -1)
+ fd = open_timestamp(timestamp_file, O_RDWR);
+ switch (fd) {
+ case TIMESTAMP_OPEN_ERROR:
+ if (errno != ENOENT)
+ rval = false;
+ goto done;
+ case TIMESTAMP_PERM_ERROR:
+ /* Already logged set_perms/restore_perms error. */
+ rval = -1;
goto done;
- sudo_lock_file(fd, SUDO_LOCK);
+ }
/*
* Find matching entries and invalidate them.
timestamp_hint -= (off_t)entry.size;
/* Disable the entry. */
SET(entry.flags, TS_DISABLED);
- ts_update_record(fd, &entry, timestamp_hint);
+ if (!ts_update_record(fd, &entry, timestamp_hint))
+ rval = false;
}
close(fd);
done:
- debug_return;
+ debug_return_int(rval);
}
/*
/*
* Create the lecture status file.
- * Returns true on success or false on failure.
+ * Returns true on success, false on failure or -1 on setuid failure.
*/
-bool
+int
set_lectured(void)
{
char lecture_status[PATH_MAX];
- bool uid_changed = false;
- int len, fd = -1;
+ int len, fd, rval = false;
debug_decl(set_lectured, SUDOERS_DEBUG_AUTH)
len = snprintf(lecture_status, sizeof(lecture_status), "%s/%s",
goto done;
/* Create lecture file. */
- if (timestamp_uid != 0)
- uid_changed = set_perms(PERM_TIMESTAMP);
- fd = open(lecture_status, O_WRONLY|O_CREAT|O_TRUNC, 0600);
- if (uid_changed)
- (void) restore_perms();
- if (fd != -1)
+ fd = open_timestamp(lecture_status, O_RDWR|O_CREAT|O_TRUNC);
+ switch (fd) {
+ case TIMESTAMP_OPEN_ERROR:
+ /* Failed to open, not a fatal error. */
+ break;
+ case TIMESTAMP_PERM_ERROR:
+ /* Already logged set_perms/restore_perms error. */
+ rval = -1;
+ break;
+ default:
+ /* Success. */
close(fd);
+ rval = true;
+ break;
+ }
done:
- debug_return_bool(fd != -1 ? true : false);
+ debug_return_int(rval);
}