]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
privsep: Access the RDM monotic file via IPC
authorRoy Marples <roy@marples.name>
Tue, 2 Jun 2020 16:48:34 +0000 (17:48 +0100)
committerRoy Marples <roy@marples.name>
Tue, 2 Jun 2020 16:48:34 +0000 (17:48 +0100)
As we can't get at it in the chroot.
While here, harden the file.

src/auth.c
src/auth.h
src/dhcp.c
src/dhcp6.c
src/privsep-root.c
src/privsep-root.h
src/privsep.h

index 29c00a9c479b3ca42d31e495c3ed011a005808aa..38b43116176a04ace1d8cf94bf553b598c55a020 100644 (file)
@@ -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);
index aa668c26289aee41165ec750512a19e3e55fcb31..30cc38b33a62ba569b524d32a4ec5f228e3c0979 100644 (file)
@@ -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
index d38677410d49c2660579beba40c229ff9ba1ed7c..b309b01c4ce9c124891fbca3ba983434493093fa 100644 (file)
@@ -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
 
index 1c65ed0cb4b144e5269d9f0162d6cf5f61f0bfb3..0e7743e366b55b97d3cabf5b5e3c4bb47381784c 100644 (file)
@@ -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
 
index 4f963d3170830c9b6d3897205a03c3f053597db3..ae52c6ede43fcc5c05ce5af63e218781b4647ce0 100644 (file)
@@ -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)
index a56e30af0348090a6a146f35d8987334ea52f154..683e56543736c5b934c7e19bede70feabbf473fd 100644 (file)
@@ -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 *);
index 930582257591f3427aa59c91e78a796485e77fc4..f1fee41e9eddc7638fe5a205a4ebb86363e42469 100644 (file)
@@ -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