/*
- * Copyright (c) 1999-2005, 2007-2016 Todd C. Miller <Todd.Miller@sudo.ws>
+ * Copyright (c) 1999-2005, 2007-2018 Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
debug_decl(sudo_aix_verify, SUDOERS_DEBUG_AUTH)
do {
- pass = auth_getpass(prompt, def_passwd_timeout * 60,
- SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ pass = auth_getpass(prompt, SUDO_CONV_PROMPT_ECHO_OFF, callback);
if (pass == NULL)
break;
free(message);
* S/Key.
*/
if ((s = auth_challenge(as)) == NULL) {
- pass = auth_getpass(prompt, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ pass = auth_getpass(prompt, SUDO_CONV_PROMPT_ECHO_OFF, callback);
} else {
- pass = auth_getpass(s, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ pass = auth_getpass(s, SUDO_CONV_PROMPT_ECHO_OFF, callback);
if (pass && *pass == '\0') {
if ((prompt = strrchr(s, '\n')))
prompt++;
debug_return_int(AUTH_FATAL);
}
free(pass);
- pass = auth_getpass(s, def_passwd_timeout * 60,
- SUDO_CONV_PROMPT_ECHO_ON, callback);
+ pass = auth_getpass(s, SUDO_CONV_PROMPT_ECHO_ON, callback);
free(s);
}
}
/* Get the password/response from the user. */
if (strncmp(resp, "challenge ", 10) == 0) {
(void) snprintf(buf, sizeof(buf), "%s\nResponse: ", &resp[10]);
- pass = auth_getpass(buf, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ pass = auth_getpass(buf, SUDO_CONV_PROMPT_ECHO_OFF, callback);
if (pass && *pass == '\0') {
free(pass);
pass = auth_getpass("Response [echo on]: ",
- def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_ON, callback);
+ SUDO_CONV_PROMPT_ECHO_ON, callback);
}
} else if (strncmp(resp, "chalnecho ", 10) == 0) {
- pass = auth_getpass(&resp[10], def_passwd_timeout * 60,
- SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ pass = auth_getpass(&resp[10], SUDO_CONV_PROMPT_ECHO_OFF, callback);
} else if (strncmp(resp, "password", 8) == 0) {
- pass = auth_getpass(prompt, def_passwd_timeout * 60,
- SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ pass = auth_getpass(prompt, SUDO_CONV_PROMPT_ECHO_OFF, callback);
} else if (strncmp(resp, "display ", 8) == 0) {
sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", &resp[8]);
strlcpy(buf, "response dummy", sizeof(buf));
prompt = use_pam_prompt(pm->msg) ? pm->msg : def_prompt;
/* Read the password unless interrupted. */
- pass = auth_getpass(prompt, def_passwd_timeout * 60, type, callback);
+ pass = auth_getpass(prompt, type, callback);
if (pass == NULL) {
/* Error (or ^C) reading password, don't try again. */
getpass_error = true;
int ret;
debug_decl(sudo_securid_verify, SUDOERS_DEBUG_AUTH)
- pass = auth_getpass("Enter your PASSCODE: ",
- def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ pass = auth_getpass("Enter your PASSCODE: ", SUDO_CONV_PROMPT_ECHO_OFF,
+ callback);
/* Have ACE verify password */
switch (SD_Check(*sd, pass, pw->pw_name)) {
!!! ATTENTION !!!\n\
Wait for the token code to change, \n\
then enter the new token code.\n", \
- def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ SUDO_CONV_PROMPT_ECHO_OFF, callback);
if (SD_Next(*sd, pass) == ACM_OK) {
ret = AUTH_SUCCESS;
debug_decl(sudo_sia_verify, SUDOERS_DEBUG_AUTH)
/* Get password, return AUTH_INTR if we got ^C */
- pass = auth_getpass(prompt, def_passwd_timeout * 60,
- SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ pass = auth_getpass(prompt, SUDO_CONV_PROMPT_ECHO_OFF, callback);
if (pass == NULL)
debug_return_int(AUTH_INTR);
/* Get the password unless the auth function will do it for us */
if (!standalone) {
- pass = auth_getpass(prompt, def_passwd_timeout * 60,
- SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ pass = auth_getpass(prompt, SUDO_CONV_PROMPT_ECHO_OFF, callback);
if (pass == NULL)
break;
}
* The user is responsible for freeing the returned value.
*/
char *
-auth_getpass(const char *prompt, int timeout, int type,
- struct sudo_conv_callback *callback)
+auth_getpass(const char *prompt, int type, struct sudo_conv_callback *callback)
{
struct sudo_conv_message msg;
struct sudo_conv_reply repl;
/* Call conversation function. */
memset(&msg, 0, sizeof(msg));
msg.msg_type = type;
- msg.timeout = def_passwd_timeout * 60;
+ msg.timeout = def_passwd_timeout.tv_sec;
msg.msg = prompt;
memset(&repl, 0, sizeof(repl));
sudo_conv(1, &msg, &repl, callback);
#define IS_ONEANDONLY(x) ((x)->flags & FLAG_ONEANDONLY)
/* Like tgetpass() but uses conversation function */
-char *auth_getpass(const char *prompt, int timeout, int type,
- struct sudo_conv_callback *callback);
+char *auth_getpass(const char *prompt, int type, struct sudo_conv_callback *callback);
/* Pointer to conversation function to use with auth_getpass(). */
extern sudo_conv_t sudo_conv;
N_("Length at which to wrap log file lines (0 for no wrap): %u"),
NULL,
}, {
- "timestamp_timeout", T_FLOAT|T_BOOL,
+ "timestamp_timeout", T_TIMESPEC|T_BOOL,
N_("Authentication timestamp timeout: %.1f minutes"),
NULL,
}, {
- "passwd_timeout", T_FLOAT|T_BOOL,
+ "passwd_timeout", T_TIMESPEC|T_BOOL,
N_("Password prompt timeout: %.1f minutes"),
NULL,
}, {
#define I_LOGLINELEN 33
#define def_loglinelen (sudo_defs_table[I_LOGLINELEN].sd_un.uival)
#define I_TIMESTAMP_TIMEOUT 34
-#define def_timestamp_timeout (sudo_defs_table[I_TIMESTAMP_TIMEOUT].sd_un.fval)
+#define def_timestamp_timeout (sudo_defs_table[I_TIMESTAMP_TIMEOUT].sd_un.tspec)
#define I_PASSWD_TIMEOUT 35
-#define def_passwd_timeout (sudo_defs_table[I_PASSWD_TIMEOUT].sd_un.fval)
+#define def_passwd_timeout (sudo_defs_table[I_PASSWD_TIMEOUT].sd_un.tspec)
#define I_PASSWD_TRIES 36
#define def_passwd_tries (sudo_defs_table[I_PASSWD_TRIES].sd_un.uival)
#define I_UMASK 37
T_UINT|T_BOOL
"Length at which to wrap log file lines (0 for no wrap): %u"
timestamp_timeout
- T_FLOAT|T_BOOL
+ T_TIMESPEC|T_BOOL
"Authentication timestamp timeout: %.1f minutes"
passwd_timeout
- T_FLOAT|T_BOOL
+ T_TIMESPEC|T_BOOL
"Password prompt timeout: %.1f minutes"
passwd_tries
T_UINT
static bool store_timeout(const char *str, union sudo_defs_val *sd_un);
static bool store_tuple(const char *str, union sudo_defs_val *sd_un, struct def_values *tuple_vals);
static bool store_uint(const char *str, union sudo_defs_val *sd_un);
-static bool store_float(const char *str, union sudo_defs_val *sd_un);
+static bool store_timespec(const char *str, union sudo_defs_val *sd_un);
static bool list_op(const char *str, size_t, union sudo_defs_val *sd_un, enum list_ops op);
static const char *logfac2str(int);
static const char *logpri2str(int);
sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.uival);
sudo_printf(SUDO_CONV_INFO_MSG, "\n");
break;
- case T_FLOAT:
- sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.fval);
+ case T_TIMESPEC: {
+ /* display time spec in minutes as a double */
+ double d = cur->sd_un.tspec.tv_sec / 60.0;
+ d += cur->sd_un.tspec.tv_nsec / 1000000000.0;
+ sudo_printf(SUDO_CONV_INFO_MSG, desc, d);
sudo_printf(SUDO_CONV_INFO_MSG, "\n");
break;
+ }
case T_MODE:
sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.mode);
sudo_printf(SUDO_CONV_INFO_MSG, "\n");
case T_UINT:
rc = store_uint(val, sd_un);
break;
- case T_FLOAT:
- rc = store_float(val, sd_un);
- break;
case T_MODE:
rc = store_mode(val, sd_un);
break;
case T_TUPLE:
rc = store_tuple(val, sd_un, def->values);
break;
+ case T_TIMESPEC:
+ rc = store_timespec(val, sd_un);
+ break;
default:
if (!quiet) {
if (lineno > 0) {
def_umask = ACCESSPERMS;
#endif
def_loglinelen = MAXLOGFILELEN;
- def_timestamp_timeout = TIMEOUT;
- def_passwd_timeout = PASSWORD_TIMEOUT;
+ def_timestamp_timeout.tv_sec = TIMEOUT * 60;
+ def_passwd_timeout.tv_sec = PASSWORD_TIMEOUT * 60;
def_passwd_tries = TRIES_FOR_PASSWORD;
#ifdef HAVE_ZLIB_H
def_compress_io = true;
}
static bool
-store_float(const char *str, union sudo_defs_val *sd_un)
+store_timespec(const char *str, union sudo_defs_val *sd_un)
{
char *endp;
double d;
- debug_decl(store_float, SUDOERS_DEBUG_DEFAULTS)
+ debug_decl(store_timespec, SUDOERS_DEBUG_DEFAULTS)
if (str == NULL) {
- sd_un->fval = 0.0;
+ sd_un->tspec.tv_sec = 0;
+ sd_un->tspec.tv_nsec = 0;
} else {
d = strtod(str, &endp);
if (*endp != '\0')
debug_return_bool(false);
/* XXX - should check against HUGE_VAL */
- sd_un->fval = d;
+
+ /* Convert from minutes to seconds and nanoseconds. */
+ d *= 60.0;
+ sd_un->tspec.tv_sec = (time_t)d;
+ sd_un->tspec.tv_nsec = (long)(d - sd_un->tspec.tv_sec) * 1000000000L;
}
debug_return_bool(true);
}
#ifndef SUDOERS_DEFAULTS_H
#define SUDOERS_DEFAULTS_H
+#include <time.h>
#include <def_data.h>
struct list_member {
int flag;
int ival;
unsigned int uival;
- double fval;
enum def_tuple tuple;
char *str;
mode_t mode;
+ struct timespec tspec;
struct list_members list;
};
/*
* Four types of defaults: strings, integers, and flags.
- * Also, T_INT, T_FLOAT or T_STR may be ANDed with T_BOOL to indicate that
+ * Also, T_INT, T_TIMESPEC or T_STR may be ANDed with T_BOOL to indicate that
* a value is not required. Flags are boolean by nature...
*/
#undef T_INT
#define T_LOGPRI 0x008
#undef T_TUPLE
#define T_TUPLE 0x009
-#undef T_FLOAT
-#define T_FLOAT 0x010
+#undef T_TIMESPEC
+#define T_TIMESPEC 0x010
#undef T_TIMEOUT
#define T_TIMEOUT 0x020
#undef T_MASK
$defname = "I_" . uc($rec->[0]);
printf HEADER "#define %-23s %d\n", $defname, $recnum;
for ($rec->[1]) {
- if (/^T_INT/) { $v = "ival"; }
- elsif (/^T_UINT/) { $v = "uival"; }
- elsif (/^T_STR/) { $v = "str"; }
- elsif (/^T_FLAG/) { $v = "flag"; }
- elsif (/^T_MODE/) { $v = "mode"; }
- elsif (/^T_LIST/) { $v = "list"; }
- elsif (/^T_LOGFAC/) { $v = "ival"; }
- elsif (/^T_LOGPRI/) { $v = "ival"; }
- elsif (/^T_TUPLE/) { $v = "tuple"; }
- elsif (/^T_FLOAT/) { $v = "fval"; }
+ if (/^T_INT/) { $v = "ival"; }
+ elsif (/^T_UINT/) { $v = "uival"; }
+ elsif (/^T_STR/) { $v = "str"; }
+ elsif (/^T_FLAG/) { $v = "flag"; }
+ elsif (/^T_MODE/) { $v = "mode"; }
+ elsif (/^T_LIST/) { $v = "list"; }
+ elsif (/^T_LOGFAC/) { $v = "ival"; }
+ elsif (/^T_LOGPRI/) { $v = "ival"; }
+ elsif (/^T_TUPLE/) { $v = "tuple"; }
+ elsif (/^T_TIMESPEC/) { $v = "tspec"; }
elsif (/^T_TIMEOUT/) { $v = "ival"; }
else { die "$0: unknown defaults type: $_\n"; }
}
debug_decl(timestamp_open, SUDOERS_DEBUG_AUTH)
/* Zero timeout means don't use the time stamp file. */
- if (def_timestamp_timeout == 0.0) {
+ if (!sudo_timespecisset(&def_timestamp_timeout)) {
errno = ENOENT;
goto bad;
}
{
struct ts_cookie *cookie = vcookie;
struct timestamp_entry entry;
- struct timespec diff, now, timeout;
+ struct timespec diff, now;
int status = TS_ERROR; /* assume the worst */
ssize_t nread;
debug_decl(timestamp_status, SUDOERS_DEBUG_AUTH)
/* Zero timeout means don't use time stamp files. */
- if (def_timestamp_timeout == 0.0) {
+ if (!sudo_timespecisset(&def_timestamp_timeout)) {
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"timestamps disabled");
status = TS_OLD;
}
/* Negative timeouts only expire manually (sudo -k). */
- if (def_timestamp_timeout < 0) {
+ sudo_timespecclear(&diff);
+ if (sudo_timespeccmp(&def_timestamp_timeout, &diff, <)) {
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"time stamp record does not expire");
status = TS_CURRENT;
goto done;
}
sudo_timespecsub(&now, &entry.ts, &diff);
- timeout.tv_sec = 60 * def_timestamp_timeout;
- timeout.tv_nsec = ((60.0 * def_timestamp_timeout) - (double)timeout.tv_sec)
- * 1000000000.0;
- if (sudo_timespeccmp(&diff, &timeout, <)) {
+ if (sudo_timespeccmp(&diff, &def_timestamp_timeout, <)) {
status = TS_CURRENT;
-#ifdef CLOCK_MONOTONIC
+#if defined(CLOCK_MONOTONIC) || defined(__MACH__)
/* A monotonic clock should never run backwards. */
if (diff.tv_sec < 0) {
log_warningx(SLOG_SEND_MAIL,
(void)ts_write(cookie->fd, cookie->fname, &entry, cookie->pos);
}
#else
- /* Check for bogus (future) time in the stampfile. */
+ /*
+ * Check for bogus (future) time in the stampfile.
+ * If diff / 2 > timeout, someone has been fooling with the clock.
+ */
sudo_timespecsub(&entry.ts, &now, &diff);
- timeout.tv_sec *= 2;
- if (sudo_timespeccmp(&diff, &timeout, >)) {
+ diff.tv_nsec /= 2;
+ if (diff.tv_sec & 1)
+ diff.tv_nsec += 500000000;
+ diff.tv_sec /= 2;
+ while (diff.tv_nsec >= 1000000000) {
+ diff.tv_sec++;
+ diff.tv_nsec -= 1000000000;
+ }
+
+ if (sudo_timespeccmp(&diff, &def_timestamp_timeout, >)) {
time_t tv_sec = (time_t)entry.ts.tv_sec;
log_warningx(SLOG_SEND_MAIL,
N_("time stamp too far in the future: %20.20s"),
debug_decl(timestamp_update, SUDOERS_DEBUG_AUTH)
/* Zero timeout means don't use time stamp files. */
- if (def_timestamp_timeout == 0.0) {
+ if (!sudo_timespecisset(&def_timestamp_timeout)) {
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"timestamps disabled");
goto done;
#ifdef TIOCSETVERAUTH
int fd = open(_PATH_TTY, O_RDWR);
if (fd != -1) {
- int secs = 60 * def_timestamp_timeout;
+ int secs = def_timestamp_timeout.tv_sec;
ioctl(fd, TIOCSETVERAUTH, &secs);
close(fd);
}