aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuncaen <mail@duncano.de>2019-01-30 22:31:47 +0100
committerDuncaen <mail@duncano.de>2019-01-30 23:19:17 +0100
commit331dda05d1d06fcb12763be9c34c82b5e280b3bc (patch)
treee329d61f2c23c3696145491e75408b9d24e58c76
parentbf8b7becf2167e13a5b43d8f61b7e16913de2ead (diff)
downloadopendoas-331dda05d1d06fcb12763be9c34c82b5e280b3bc.tar.gz
timestamp: rename and simplify
-rwxr-xr-xconfigure4
-rw-r--r--doas.c8
-rw-r--r--includes.h8
-rw-r--r--timestamp.c (renamed from persist_timestamp.c)199
4 files changed, 129 insertions, 90 deletions
diff --git a/configure b/configure
index 1266444..1f3e2cb 100755
--- a/configure
+++ b/configure
@@ -185,8 +185,8 @@ int main(void) {
persistmethod() {
[ -z "$WITHOUT_TIMESTAMP" ] && {
- printf 'CFLAGS += -DPERSIST_TIMESTAMP\n' >>$CONFIG_MK
- printf 'SRCS += persist_timestamp.c\n' >>$CONFIG_MK
+ printf 'CPPFLAGS += -DUSE_TIMESTAMP\n' >>$CONFIG_MK
+ printf 'SRCS += timestamp.c\n' >>$CONFIG_MK
printf 'timestamp\n'
return 0
}
diff --git a/doas.c b/doas.c
index 2bdaac2..0782f87 100644
--- a/doas.c
+++ b/doas.c
@@ -298,13 +298,15 @@ main(int argc, char **argv)
confpath = optarg;
break;
case 'L':
-#ifdef TIOCCLRVERAUTH
+#if defined(USE_BSD_AUTH)
i = open("/dev/tty", O_RDWR);
if (i != -1)
ioctl(i, TIOCCLRVERAUTH);
exit(i == -1);
-#elif PERSIST_TIMESTAMP
- exit(persist_clear() != 0);
+#elif defined(USE_TIMESTAMP)
+ exit(timestamp_clear() == -1);
+#else
+ exit(0);
#endif
case 'u':
if (parseuid(optarg, &target) != 0)
diff --git a/includes.h b/includes.h
index 7083674..d3d4e39 100644
--- a/includes.h
+++ b/includes.h
@@ -24,10 +24,10 @@ int pamauth(const char *, const char *, int, int);
void shadowauth(const char *, int);
#endif
-#ifdef PERSIST_TIMESTAMP
-int persist_open(int *, int);
-int persist_set(int, int);
-int persist_clear();
+#ifdef USE_TIMESTAMP
+int timestamp_open(int *, int);
+int timestamp_set(int, int);
+int timestamp_clear(void);
#endif
#endif /* INCLUDES_H */
diff --git a/persist_timestamp.c b/timestamp.c
index 99b5378..0d8f9c3 100644
--- a/persist_timestamp.c
+++ b/timestamp.c
@@ -53,6 +53,7 @@
#endif
#include <ctype.h>
+#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
@@ -66,7 +67,7 @@
#include "includes.h"
#ifndef TIMESTAMP_DIR
-# define TIMESTAMP_DIR "/tmp/doas"
+# define TIMESTAMP_DIR "/run/doas"
#endif
#if defined(TIMESTAMP_TMPFS) && defined(__linux__)
@@ -103,7 +104,8 @@ proc_info(pid_t pid, int *ttynr, unsigned long long *starttime)
if (n == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
- break;
+ close(fd);
+ return -1;
}
p += n;
if (p >= buf + sizeof buf)
@@ -150,108 +152,107 @@ proc_info(pid_t pid, int *ttynr, unsigned long long *starttime)
#error "proc_info not implemented"
#endif
+/* The session prefix is the tty number, the pid
+ * of the session leader and the start time of the
+ * session leader.
+ */
static const char *
-tsname()
+session_prefix()
{
- static char buf[128];
+ static char prefix[128];
int tty, fd;
unsigned long long starttime;
- pid_t ppid, sid, leader;
+ pid_t leader;
+
if ((fd = open("/dev/tty", O_RDONLY)) == -1)
err(1, "open: /dev/tty");
if (ioctl(fd, TIOCGSID, &leader) == -1)
err(1, "ioctl: failed to get session leader");
close(fd);
+
if (proc_info(leader, &tty, &starttime) == -1)
errx(1, "failed to get tty number");
- ppid = getppid();
- if ((sid = getsid(0)) == -1)
- err(1, "getsid");
- if (snprintf(buf, sizeof buf, ".%d_%d_%llu_%d_%d",
- tty, leader, starttime, ppid, sid) == -1)
+ if (snprintf(prefix, sizeof prefix, ".%d_%d_%llu_",
+ tty, leader, starttime) == -1)
return NULL;
- return buf;
+ return prefix;
}
-static int
-checktsdir(int fd)
+static const char *
+timestamp_name()
{
- struct stat st;
-
- if (fstat(fd, &st) == -1)
- err(1, "fstatat");
-
- if ((st.st_mode & S_IFMT) != S_IFDIR)
- errx(0, "timestamp directory is not a directory");
- if ((st.st_mode & (S_IWGRP|S_IRGRP|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH)) != 0)
- errx(1, "timestamp directory permissions wrong");
- if (st.st_uid != 0 || st.st_gid != 0)
- errx(1, "timestamp directory is not owned by root");
-
-#if defined(TIMESTAMP_TMPFS) && defined(__linux__)
- struct statfs sf;
- if (fstatfs(fd, &sf) == -1)
- err(1, "statfs");
-
- if (sf.f_type != TMPFS_MAGIC)
- errx(1, "timestamp directory not on tmpfs");
-#endif
+ static char name[128];
+ pid_t ppid, sid;
+ const char *prefix;
- return 0;
+ ppid = getppid();
+ if ((sid = getsid(0)) == -1)
+ err(1, "getsid");
+ if ((prefix = session_prefix()) == NULL)
+ return NULL;
+ if (snprintf(name, sizeof name, "%s_%d_%d", prefix, ppid, sid) == -1)
+ return NULL;
+ return name;
}
static int
opentsdir()
{
- gid_t gid;
+ struct stat st;
int fd;
+ int isnew;
+
+ fd = -1;
+ isnew = 0;
reopen:
if ((fd = open(TIMESTAMP_DIR, O_RDONLY | O_DIRECTORY)) == -1) {
- if (errno == ENOENT) {
- gid = getegid();
- if (setegid(0) != 0)
- err(1, "setegid");
+ if (errno == ENOENT && isnew == 0) {
if (mkdir(TIMESTAMP_DIR, (S_IRUSR|S_IWUSR|S_IXUSR)) != 0)
err(1, "mkdir");
- if (setegid(gid) != 0)
- err(1, "setegid");
+ isnew = 1;
goto reopen;
} else {
err(1, "failed to open timestamp directory: %s", TIMESTAMP_DIR);
}
}
- if (checktsdir(fd) != 0)
- return -1;
-
- return fd;
-}
-
-static int
-checktsfile(int fd, size_t *tssize)
-{
- struct stat st;
- gid_t gid;
-
+recheck:
if (fstat(fd, &st) == -1)
- err(1, "stat");
- if ((st.st_mode & S_IFMT) != S_IFREG)
- errx(1, "timestamp is not a regular file");
+ err(1, "fstatat");
+
+ if ((st.st_mode & S_IFMT) != S_IFDIR)
+ errx(1, "timestamp directory is not a directory");
if ((st.st_mode & (S_IWGRP|S_IRGRP|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH)) != 0)
- errx(1, "timestamp has wrong permissions");
+ errx(1, "timestamp directory has wrong permissions");
+
+ if (isnew == 1) {
+ if (fchown(fd, 0, 0) == -1)
+ err(1, "fchown");
+ isnew = 0;
+ goto recheck;
+ } else {
+ if (st.st_uid != 0 || st.st_gid != 0)
+ errx(1, "timestamp directory has wrong owner or group");
+ }
- gid = getegid();
- if (st.st_uid != 0 || st.st_gid != gid)
- errx(1, "timestamp has wrong owner");
+#if defined(TIMESTAMP_TMPFS) && defined(__linux__)
+ struct statfs sf;
+ if (fstatfs(fd, &sf) == -1)
+ err(1, "statfs");
- *tssize = st.st_size;
+ if (sf.f_type != TMPFS_MAGIC)
+ errx(1, "timestamp directory not on tmpfs");
+#endif
- return 0;
+ return fd;
}
+/*
+ * Returns 1 if the timestamp is valid, 0 if its invalid
+ */
static int
-validts(int fd, int secs)
+timestamp_valid(int fd, int secs)
{
struct timespec mono, real, ts_mono, ts_real, timeout;
@@ -267,7 +268,7 @@ validts(int fd, int secs)
if (timespeccmp(&mono, &ts_mono, >) ||
timespeccmp(&real, &ts_real, >))
- return -1;
+ return 0;
memset(&timeout, 0, sizeof timeout);
timeout.tv_sec = secs;
@@ -278,11 +279,11 @@ validts(int fd, int secs)
timespeccmp(&real, &ts_real, <))
errx(1, "timestamp is too far in the future");
- return 0;
+ return 1;
}
int
-persist_set(int fd, int secs)
+timestamp_set(int fd, int secs)
{
struct timespec mono, real, ts_mono, ts_real, timeout;
@@ -297,6 +298,8 @@ persist_set(int fd, int secs)
if (lseek(fd, 0, SEEK_SET) == -1)
err(1, "lseek");
+ if (ftruncate(fd, 0) == -1)
+ err(1, "ftruncate");
if (write(fd, (void *)&ts_mono, sizeof ts_mono) != sizeof ts_mono ||
write(fd, (void *)&ts_real, sizeof ts_real) != sizeof ts_real)
err(1, "write");
@@ -305,14 +308,16 @@ persist_set(int fd, int secs)
}
int
-persist_open(int *valid, int secs)
+timestamp_open(int *valid, int secs)
{
+ struct stat st;
int dirfd, fd;
+ gid_t gid;
const char *name;
*valid = 0;
- if ((name = tsname()) == NULL)
+ if ((name = timestamp_name()) == NULL)
errx(1, "failed to get timestamp name");
if ((dirfd = opentsdir()) == -1)
errx(1, "opentsdir");
@@ -327,9 +332,16 @@ persist_open(int *valid, int secs)
err(1, "open timestamp file");
}
- size_t tssize;
- if (checktsfile(fd, &tssize) == -1)
- err(1, "checktsfile");
+ if (fstat(fd, &st) == -1)
+ err(1, "stat");
+ if ((st.st_mode & S_IFMT) != S_IFREG)
+ errx(1, "timestamp is not a regular file");
+ if ((st.st_mode & (S_IWGRP|S_IRGRP|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH)) != 0)
+ errx(1, "timestamp file has wrong permissions");
+
+ gid = getegid();
+ if (st.st_uid != 0 || st.st_gid != gid)
+ errx(1, "timestamp file has wrong owner or group");
/* The timestamp size is 0 if its a new file or a
* timestamp that was never set, its not valid but
@@ -337,26 +349,51 @@ persist_open(int *valid, int secs)
* If the size does not match the expected size it
* is incomplete and should never be used
*/
- if (tssize == sizeof(struct timespec) * 2)
- *valid = validts(fd, secs) == 0;
- else if (tssize != 0)
+ if (st.st_size == sizeof (struct timespec) * 2) {
+ *valid = timestamp_valid(fd, secs);
+ } else if (st.st_size == 0) {
+ *valid = 0;
+ } else {
errx(1, "corrupt timestamp file");
+ }
close(dirfd);
return fd;
}
int
-persist_clear()
+timestamp_clear()
{
- const char *name;
+ struct dirent *ent;
+ DIR *dp;
+ const char *prefix;
int dirfd;
- if ((name = tsname()) == NULL)
- errx(1, "failed to get timestamp name");
+ int ret = 0;
+ size_t plen;
+
+ if ((prefix = session_prefix()) == NULL)
+ errx(1, "failed to get timestamp session prefix");
+ plen = strlen(prefix);
+
if ((dirfd = opentsdir()) == -1)
errx(1, "opentsdir");
- if (unlinkat(dirfd, name, 0) == -1 && errno != ENOENT)
- return -1;
+ if ((dp = fdopendir(dirfd)) == NULL)
+ err(1, "fopendir");
+
+ /*
+ * Delete all files in the timestamp directory
+ * with the same session prefix.
+ */
+ while ((ent = readdir(dp)) != NULL) {
+ if (ent->d_type != DT_REG)
+ continue;
+ if (strncmp(prefix, ent->d_name, plen) != 0)
+ continue;
+ if (unlinkat(dirfd, ent->d_name, 0) == -1)
+ ret = -1;
+ }
+ closedir(dp);
close(dirfd);
- return 0;
+
+ return ret;
}