diff options
| author | Roy Marples <roy@marples.name> | 2020-06-02 17:48:34 +0100 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2020-06-02 17:48:34 +0100 |
| commit | b8ed6cdf7919b1fc406634ccd043b1a995c89921 (patch) | |
| tree | 2c6e067fa0bb59e1fb9f439c1ef2cdcb5a0ec699 | |
| parent | d3de73d80c7f307bab0278162ff81c3731ac2ce7 (diff) | |
| download | dhcpcd-b8ed6cdf7919b1fc406634ccd043b1a995c89921.tar.xz | |
privsep: Access the RDM monotic file via IPC
As we can't get at it in the chroot.
While here, harden the file.
| -rw-r--r-- | src/auth.c | 71 | ||||
| -rw-r--r-- | src/auth.h | 6 | ||||
| -rw-r--r-- | src/dhcp.c | 4 | ||||
| -rw-r--r-- | src/dhcp6.c | 8 | ||||
| -rw-r--r-- | src/privsep-root.c | 35 | ||||
| -rw-r--r-- | src/privsep-root.h | 1 | ||||
| -rw-r--r-- | src/privsep.h | 1 |
7 files changed, 94 insertions, 32 deletions
@@ -27,6 +27,8 @@ */ #include <sys/file.h> +#include <sys/stat.h> + #include <errno.h> #include <fcntl.h> #include <inttypes.h> @@ -42,6 +44,7 @@ #include "dhcp.h" #include "dhcp6.h" #include "dhcpcd.h" +#include "privsep-root.h" #ifdef HAVE_HMAC_H #include <hmac.h> @@ -408,11 +411,11 @@ finish: return t; } -static uint64_t -get_next_rdm_monotonic_counter(struct auth *auth) +int +auth_get_rdm_monotonic(uint64_t *rdm) { FILE *fp; - uint64_t rdm; + int err; #ifdef LOCK_EX int flocked; #endif @@ -420,41 +423,43 @@ get_next_rdm_monotonic_counter(struct auth *auth) fp = fopen(RDM_MONOFILE, "r+"); if (fp == NULL) { if (errno != ENOENT) - return ++auth->last_replay; /* report error? */ + return -1; fp = fopen(RDM_MONOFILE, "w"); if (fp == NULL) - return ++auth->last_replay; /* report error? */ + return -1; + if (chmod(RDM_MONOFILE, 0400) == -1) { + fclose(fp); + unlink(RDM_MONOFILE); + return -1; + } #ifdef LOCK_EX flocked = flock(fileno(fp), LOCK_EX); #endif - rdm = 0; + *rdm = 0; } else { #ifdef LOCK_EX flocked = flock(fileno(fp), LOCK_EX); #endif - if (fscanf(fp, "0x%016" PRIu64, &rdm) != 1) - rdm = 0; /* truncated? report error? */ + if (fscanf(fp, "0x%016" PRIu64, rdm) != 1) { + fclose(fp); + return -1; + } } - rdm++; + (*rdm)++; if (fseek(fp, 0, SEEK_SET) == -1 || ftruncate(fileno(fp), 0) == -1 || - fprintf(fp, "0x%016" PRIu64 "\n", rdm) != 19 || + fprintf(fp, "0x%016" PRIu64 "\n", *rdm) != 19 || fflush(fp) == EOF) - { - if (!auth->last_replay_set) { - auth->last_replay = rdm; - auth->last_replay_set = 1; - } else - rdm = ++auth->last_replay; - /* report error? */ - } + err = -1; + else + err = 0; #ifdef LOCK_EX if (flocked == 0) flock(fileno(fp), LOCK_UN); #endif fclose(fp); - return rdm; + return err; } #define NTP_EPOCH 2208988800U /* 1970 - 1900 in seconds */ @@ -476,11 +481,26 @@ get_next_rdm_monotonic_clock(struct auth *auth) } static uint64_t -get_next_rdm_monotonic(struct auth *auth) +get_next_rdm_monotonic(struct dhcpcd_ctx *ctx, struct auth *auth) { - if (auth->options & DHCPCD_AUTH_RDM_COUNTER) - return get_next_rdm_monotonic_counter(auth); + if (auth->options & DHCPCD_AUTH_RDM_COUNTER) { + uint64_t rdm; + int err; + +#ifdef PRIVSEP + if (IN_PRIVSEP(ctx)) { + + err = ps_root_getauthrdm(ctx, &rdm); + } else +#endif + err = auth_get_rdm_monotonic(&rdm); + if (err == -1) + return ++auth->last_replay; + + auth->last_replay = rdm; + return rdm; + } return get_next_rdm_monotonic_clock(auth); } @@ -495,7 +515,8 @@ get_next_rdm_monotonic(struct auth *auth) * data and dlen refer to the authentication option within the message. */ ssize_t -dhcp_auth_encode(struct auth *auth, const struct token *t, +dhcp_auth_encode(struct dhcpcd_ctx *ctx, struct auth *auth, + const struct token *t, void *vm, size_t mlen, int mp, int mt, void *vdata, size_t dlen) { @@ -611,11 +632,11 @@ dhcp_auth_encode(struct auth *auth, const struct token *t, *data++ = auth->rdm; switch (auth->rdm) { case AUTH_RDM_MONOTONIC: - rdm = get_next_rdm_monotonic(auth); + rdm = get_next_rdm_monotonic(ctx, auth); break; default: /* This block appeases gcc, clang doesn't need it */ - rdm = get_next_rdm_monotonic(auth); + rdm = get_next_rdm_monotonic(ctx, auth); break; } rdm = htonll(rdm); @@ -90,7 +90,11 @@ const struct token * dhcp_auth_validate(struct authstate *, const void *, size_t, int, int, const void *, size_t); -ssize_t dhcp_auth_encode(struct auth *, const struct token *, +struct dhcpcd_ctx; +ssize_t dhcp_auth_encode(struct dhcpcd_ctx *, struct auth *, + const struct token *, void *, size_t, int, int, void *, size_t); + +int auth_get_rdm_monotonic(uint64_t *rdm); #endif @@ -1034,7 +1034,7 @@ make_message(struct bootp **bootpm, const struct interface *ifp, uint8_t type) auth = NULL; /* appease GCC */ auth_len = 0; if (ifo->auth.options & DHCPCD_AUTH_SEND) { - ssize_t alen = dhcp_auth_encode(&ifo->auth, + ssize_t alen = dhcp_auth_encode(ifp->ctx, &ifo->auth, state->auth.token, NULL, 0, 4, type, NULL, 0); if (alen != -1 && alen > UINT8_MAX) { @@ -1129,7 +1129,7 @@ make_message(struct bootp **bootpm, const struct interface *ifp, uint8_t type) #ifdef AUTH if (ifo->auth.options & DHCPCD_AUTH_SEND && auth_len != 0) - dhcp_auth_encode(&ifo->auth, state->auth.token, + dhcp_auth_encode(ifp->ctx, &ifo->auth, state->auth.token, (uint8_t *)bootp, len, 4, type, auth, auth_len); #endif diff --git a/src/dhcp6.c b/src/dhcp6.c index 1c65ed0c..0e7743e3 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -881,7 +881,7 @@ dhcp6_makemessage(struct interface *ifp) #ifdef AUTH auth_len = 0; if (ifo->auth.options & DHCPCD_AUTH_SEND) { - ssize_t alen = dhcp_auth_encode(&ifo->auth, + ssize_t alen = dhcp_auth_encode(ifp->ctx, &ifo->auth, state->auth.token, NULL, 0, 6, type, NULL, 0); if (alen != -1 && alen > UINT16_MAX) { errno = ERANGE; @@ -1196,9 +1196,9 @@ dhcp6_update_auth(struct interface *ifp, struct dhcp6_message *m, size_t len) return -1; state = D6_STATE(ifp); - return dhcp_auth_encode(&ifp->options->auth, state->auth.token, - (uint8_t *)state->send, state->send_len, - 6, state->send->type, opt, opt_len); + return dhcp_auth_encode(ifp->ctx, &ifp->options->auth, + state->auth.token, (uint8_t *)state->send, state->send_len, 6, + state->send->type, opt, opt_len); } #endif diff --git a/src/privsep-root.c b/src/privsep-root.c index 4f963d31..ae52c6ed 100644 --- a/src/privsep-root.c +++ b/src/privsep-root.c @@ -43,6 +43,7 @@ #include <string.h> #include <unistd.h> +#include "auth.h" #include "common.h" #include "dev.h" #include "dhcpcd.h" @@ -333,6 +334,19 @@ ps_root_dowritefile(const struct dhcpcd_ctx *ctx, return writefile(file, mode, nc, len - (size_t)(nc - file)); } +#ifdef AUTH +static ssize_t +ps_root_monordm(uint64_t *rdm, size_t len) +{ + + if (len != sizeof(*rdm)) { + errno = EINVAL; + return -1; + } + return auth_get_rdm_monotonic(rdm); +} +#endif + #ifdef HAVE_CAPSICUM #define IFA_NADDRS 3 static ssize_t @@ -537,6 +551,15 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg) rlen = sizeof(mtime); } break; +#ifdef AUTH + case PS_AUTH_MONORDM: + err = ps_root_monordm(data, len); + if (err != -1) { + rdata = data; + rlen = len; + } + break; +#endif #ifdef HAVE_CAPSICUM case PS_GETIFADDRS: err = ps_root_dogetifaddrs(&rdata, &rlen); @@ -937,6 +960,18 @@ ps_root_ip6forwarding(struct dhcpcd_ctx *ctx, const char *ifname) } #endif +#ifdef AUTH +int +ps_root_getauthrdm(struct dhcpcd_ctx *ctx, uint64_t *rdm) +{ + + if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_AUTH_MONORDM, 0, + rdm, sizeof(rdm))== -1) + return -1; + return (int)ps_root_readerror(ctx, rdm, sizeof(*rdm)); +} +#endif + #ifdef PLUGIN_DEV int ps_root_dev_initialized(struct dhcpcd_ctx *ctx, const char *ifname) diff --git a/src/privsep-root.h b/src/privsep-root.h index a56e30af..683e5654 100644 --- a/src/privsep-root.h +++ b/src/privsep-root.h @@ -44,6 +44,7 @@ ssize_t ps_root_readfile(struct dhcpcd_ctx *, const char *, void *, size_t); ssize_t ps_root_writefile(struct dhcpcd_ctx *, const char *, mode_t, const void *, size_t); ssize_t ps_root_script(struct dhcpcd_ctx *, const void *, size_t); +int ps_root_getauthrdm(struct dhcpcd_ctx *, uint64_t *); int ps_root_getifaddrs(struct dhcpcd_ctx *, struct ifaddrs **); ssize_t ps_root_os(struct ps_msghdr *, struct msghdr *); diff --git a/src/privsep.h b/src/privsep.h index 93058225..f1fee41e 100644 --- a/src/privsep.h +++ b/src/privsep.h @@ -49,6 +49,7 @@ #define PS_READFILE 0x0014 #define PS_WRITEFILE 0x0015 #define PS_FILEMTIME 0x0016 +#define PS_AUTH_MONORDM 0x0017 /* BSD Commands */ #define PS_IOCTLLINK 0x0101 |
