As we can't get at it in the chroot.
While here, harden the file.
*/
#include <sys/file.h>
+#include <sys/stat.h>
+
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include "dhcp.h"
#include "dhcp6.h"
#include "dhcpcd.h"
+#include "privsep-root.h"
#ifdef HAVE_HMAC_H
#include <hmac.h>
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
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 */
}
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);
}
* 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)
{
*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);
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
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) {
#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
#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;
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
#include <string.h>
#include <unistd.h>
+#include "auth.h"
#include "common.h"
#include "dev.h"
#include "dhcpcd.h"
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
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);
}
#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)
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 *);
#define PS_READFILE 0x0014
#define PS_WRITEFILE 0x0015
#define PS_FILEMTIME 0x0016
+#define PS_AUTH_MONORDM 0x0017
/* BSD Commands */
#define PS_IOCTLLINK 0x0101