Mercurial > hg > dhcpcd
changeset 5299:b7e676ac73c1 draft
privsep: Access the RDM monotic file via IPC
As we can't get at it in the chroot.
While here, harden the file.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Tue, 02 Jun 2020 17:48:34 +0100 |
| parents | 95d69db26ac5 |
| children | d6366bcea63f |
| files | src/auth.c src/auth.h src/dhcp.c src/dhcp6.c src/privsep-root.c src/privsep-root.h src/privsep.h |
| diffstat | 7 files changed, 94 insertions(+), 32 deletions(-) [+] |
line wrap: on
line diff
--- a/src/auth.c Tue Jun 02 17:07:12 2020 +0100 +++ b/src/auth.c Tue Jun 02 17:48:34 2020 +0100 @@ -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 @@ 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 @@ 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 @@ } 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 @@ * 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 @@ *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);
--- a/src/auth.h Tue Jun 02 17:07:12 2020 +0100 +++ b/src/auth.h Tue Jun 02 17:48:34 2020 +0100 @@ -90,7 +90,11 @@ 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
--- a/src/dhcp.c Tue Jun 02 17:07:12 2020 +0100 +++ b/src/dhcp.c Tue Jun 02 17:48:34 2020 +0100 @@ -1034,7 +1034,7 @@ 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 @@ #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
--- a/src/dhcp6.c Tue Jun 02 17:07:12 2020 +0100 +++ b/src/dhcp6.c Tue Jun 02 17:48:34 2020 +0100 @@ -881,7 +881,7 @@ #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 @@ 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
--- a/src/privsep-root.c Tue Jun 02 17:07:12 2020 +0100 +++ b/src/privsep-root.c Tue Jun 02 17:48:34 2020 +0100 @@ -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 @@ 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 @@ 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 @@ } #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)
--- a/src/privsep-root.h Tue Jun 02 17:07:12 2020 +0100 +++ b/src/privsep-root.h Tue Jun 02 17:48:34 2020 +0100 @@ -44,6 +44,7 @@ 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 *);
