/*
- * Copyright (c) 1993-1996,1998-2005, 2007-2010
+ * Copyright (c) 1993-1996,1998-2005, 2007-2011
* Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
static void lecture __P((int));
static void update_timestamp __P((char *, char *));
static int tty_is_devpts __P((const char *));
+static struct passwd *get_authpw __P((void));
/*
* This function only returns if the user can successfully
if (ISSET(mode, MODE_INVALIDATE)) {
SET(validated, FLAG_CHECK_USER);
} else {
- if (user_uid == 0 || user_uid == runas_pw->pw_uid || user_is_exempt())
+ /*
+ * Don't prompt for the root passwd or if the user is exempt.
+ * If the user is not changing uid/gid, no need for a password.
+ */
+ if (user_uid == 0 || (user_uid == runas_pw->pw_uid &&
+ (!runas_gr || user_in_group(sudo_user.pw, runas_gr->gr_name))) ||
+ user_is_exempt())
return;
}
TS_MAKE_DIRS);
if (status != TS_CURRENT || ISSET(validated, FLAG_CHECK_USER)) {
+ struct passwd *auth_pw;
+
/* Bail out if we are non-interactive and a password is required */
if (ISSET(mode, MODE_NONINTERACTIVE))
errorx(1, "sorry, a password is required to run %s", getprogname());
prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt,
user_name, user_shost);
+ auth_pw = get_authpw();
verify_user(auth_pw, prompt);
+ pw_delref(auth_pw);
}
/* Only update timestamp if user was validated. */
if (ISSET(validated, VALIDATE_OK) && !ISSET(mode, MODE_INVALIDATE) && status != TS_ERROR)
char *timestampfile;
{
/* If using tty timestamps but we have no tty there is nothing to do. */
- if (timestampfile && !user_ttypath)
+ if (def_tty_tickets && !user_ttypath)
return;
if (timestamp_uid != 0)
log_error(NO_EXIT|USE_ERRNO, "Can't open %s", timestampfile);
else {
lock_file(fd, SUDO_LOCK);
- write(fd, &tty_info, sizeof(tty_info));
+ if (write(fd, &tty_info, sizeof(tty_info)) != sizeof(tty_info))
+ log_error(NO_EXIT|USE_ERRNO, "Can't write %s", timestampfile);
close(fd);
}
} else {
}
if (subst) {
- new_prompt = (char *) emalloc(++len);
+ new_prompt = emalloc(++len);
endp = new_prompt + len;
for (p = old_prompt, np = new_prompt; *p; p++) {
if (p[0] =='%') {
} else
new_prompt = old_prompt;
- return(new_prompt);
+ return new_prompt;
oflow:
/* We pre-allocate enough space, so this should never happen. */
user_is_exempt()
{
if (!def_exempt_group)
- return(FALSE);
- return(user_in_group(sudo_user.pw, def_exempt_group));
+ return FALSE;
+ return user_in_group(sudo_user.pw, def_exempt_group);
}
/*
log_error(NO_EXIT, "%s exists but is not a directory (0%o)",
dirparent, (unsigned int) sb.st_mode);
else if (sb.st_uid != timestamp_uid)
- log_error(NO_EXIT, "%s owned by uid %lu, should be uid %lu",
- dirparent, (unsigned long) sb.st_uid,
- (unsigned long) timestamp_uid);
+ log_error(NO_EXIT, "%s owned by uid %u, should be uid %u",
+ dirparent, (unsigned int) sb.st_uid,
+ (unsigned int) timestamp_uid);
else if ((sb.st_mode & 0000022))
log_error(NO_EXIT,
"%s writable by non-owner (0%o), should be mode 0700",
if (status == TS_ERROR) {
if (timestamp_uid != 0)
set_perms(PERM_ROOT);
- return(status);
+ return status;
}
/*
log_error(NO_EXIT, "%s exists but is not a directory (0%o)",
timestampdir, (unsigned int) sb.st_mode);
} else if (sb.st_uid != timestamp_uid)
- log_error(NO_EXIT, "%s owned by uid %lu, should be uid %lu",
- timestampdir, (unsigned long) sb.st_uid,
- (unsigned long) timestamp_uid);
+ log_error(NO_EXIT, "%s owned by uid %u, should be uid %u",
+ timestampdir, (unsigned int) sb.st_uid,
+ (unsigned int) timestamp_uid);
else if ((sb.st_mode & 0000022))
log_error(NO_EXIT,
"%s writable by non-owner (0%o), should be mode 0700",
if (timestampfile && status != TS_ERROR) {
if (status != TS_MISSING)
status = TS_NOFILE; /* dir there, file missing */
- if (!user_ttypath)
+ if (def_tty_tickets && !user_ttypath)
goto done; /* no tty, always prompt */
if (lstat(timestampfile, &sb) == 0) {
if (!S_ISREG(sb.st_mode)) {
/* If bad uid or file mode, complain and kill the bogus file. */
if (sb.st_uid != timestamp_uid) {
log_error(NO_EXIT,
- "%s owned by uid %lu, should be uid %lu",
- timestampfile, (unsigned long) sb.st_uid,
- (unsigned long) timestamp_uid);
+ "%s owned by uid %u, should be uid %u",
+ timestampfile, (unsigned int) sb.st_uid,
+ (unsigned int) timestamp_uid);
(void) unlink(timestampfile);
} else if ((sb.st_mode & 0000022)) {
log_error(NO_EXIT,
/*
* Check for stored tty info. If the file is zero-sized
* it is an old-style timestamp with no tty info in it.
+ * If removing, we don't care about the contents.
* The actual mtime check is done later.
*/
- if (sb.st_size != 0) {
+ if (ISSET(flags, TS_REMOVE)) {
+ status = TS_OLD;
+ } else if (sb.st_size != 0) {
struct tty_info info;
int fd = open(timestampfile, O_RDONLY, 0644);
if (fd != -1) {
done:
if (timestamp_uid != 0)
set_perms(PERM_ROOT);
- return(status);
+ return status;
}
/*
}
} else {
timevalclear(&tv);
- if (touch(-1, path, &tv) == -1)
+ if (touch(-1, path, &tv) == -1 && errno != ENOENT)
error(1, "can't reset %s to Epoch", path);
}
}
#endif /* __linux__ */
return retval;
}
+
+/*
+ * Get passwd entry for the user we are going to authenticate as.
+ * By default, this is the user invoking sudo. In the most common
+ * case, this matches sudo_user.pw or runas_pw.
+ */
+static struct passwd *
+get_authpw()
+{
+ struct passwd *pw;
+
+ if (def_rootpw) {
+ if ((pw = sudo_getpwuid(0)) == NULL)
+ log_error(0, "unknown uid: 0");
+ } else if (def_runaspw) {
+ if ((pw = sudo_getpwnam(def_runas_default)) == NULL)
+ log_error(0, "unknown user: %s", def_runas_default);
+ } else if (def_targetpw) {
+ if (runas_pw->pw_name == NULL)
+ log_error(NO_MAIL|MSG_ONLY, "unknown uid: %u",
+ (unsigned int) runas_pw->pw_uid);
+ pw_addref(runas_pw);
+ pw = runas_pw;
+ } else {
+ pw_addref(sudo_user.pw);
+ pw = sudo_user.pw;
+ }
+
+ return pw;
+}