diff --git a/plugins/sudoers/policy.c b/plugins/sudoers/policy.c index d822f1371..65f904ba2 100644 --- a/plugins/sudoers/policy.c +++ b/plugins/sudoers/policy.c @@ -410,6 +410,7 @@ sudoers_policy_deserialize_info(struct sudoers_context *ctx, void *v, ctx->user.gid = (gid_t)-1; ctx->user.uid = (gid_t)-1; ctx->user.umask = (mode_t)-1; + ctx->user.ttydev = (dev_t)-1; for (cur = info->user_info; *cur != NULL; cur++) { if (MATCHES(*cur, "user=")) { CHECK(*cur, "user="); @@ -476,6 +477,21 @@ sudoers_policy_deserialize_info(struct sudoers_context *ctx, void *v, ctx->user.tty += sizeof(_PATH_DEV) - 1; continue; } + if (MATCHES(*cur, "ttydev=")) { + unsigned long long ullval; + char *ep; + + p = *cur + sizeof("ttydev=") - 1; + errno = 0; + ullval = strtoull(p, &ep, 10); + if ((*p == '\0' || *ep != '\0') || + (errno == ERANGE && ullval == ULLONG_MAX)) { + INVALID("ttydev="); + goto bad; + } + ctx->user.ttydev = (dev_t)ullval; + continue; + } if (MATCHES(*cur, "host=")) { CHECK(*cur, "host="); host = *cur + sizeof("host=") - 1; @@ -589,6 +605,15 @@ sudoers_policy_deserialize_info(struct sudoers_context *ctx, void *v, } } + /* ttydev is only set in user_info[] for API 1.22 and above. */ + if (ctx->user.ttydev == (dev_t)-1 && ctx->user.ttypath != NULL) { + struct stat sb; + if (stat(ctx->user.ttypath, &sb) == 0) + ctx->user.ttydev = sb.st_rdev; + else + sudo_warn("%s", ctx->user.ttypath); + } + /* umask is only set in user_info[] for API 1.10 and above. */ if (ctx->user.umask == (mode_t)-1) { ctx->user.umask = umask(0); diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h index 60e4af997..132bd7c62 100644 --- a/plugins/sudoers/sudoers.h +++ b/plugins/sudoers/sudoers.h @@ -24,7 +24,7 @@ #ifndef SUDOERS_SUDOERS_H #define SUDOERS_SUDOERS_H -#include /* for gid_t, mode_t, pid_t, size_t, uid_t */ +#include /* dev_t, gid_t, mode_t, pid_t, size_t, uid_t */ #include #ifdef HAVE_STDBOOL_H # include @@ -142,6 +142,7 @@ struct sudoers_user_context { int lines; int cols; int timeout; + dev_t ttydev; mode_t umask; uid_t euid; uid_t uid; diff --git a/plugins/sudoers/timestamp.c b/plugins/sudoers/timestamp.c index d9eb447e0..feb8f8918 100644 --- a/plugins/sudoers/timestamp.c +++ b/plugins/sudoers/timestamp.c @@ -379,7 +379,6 @@ ts_init_key(const struct sudoers_context *ctx, struct timestamp_entry *entry, struct passwd *pw, unsigned short flags, enum def_tuple ticket_type) { - struct stat sb; debug_decl(ts_init_key, SUDOERS_DEBUG_AUTH); memset(entry, 0, sizeof(*entry)); @@ -398,10 +397,10 @@ ts_init_key(const struct sudoers_context *ctx, sudo_warnx("unknown time stamp ticket type %d", ticket_type); FALLTHROUGH; case tty: - if (ctx->user.ttypath != NULL && stat(ctx->user.ttypath, &sb) == 0) { + if (ctx->user.ttydev != (dev_t)-1) { /* tty-based time stamp */ entry->type = TS_TTY; - entry->u.ttydev = sb.st_rdev; + entry->u.ttydev = ctx->user.ttydev; if (entry->sid != -1) get_starttime(entry->sid, &entry->start_time); break;