{
int len, rc;
enum priv_cmd cmd = PRIV_OPEN;
- must_write(&cmd, sizeof(enum priv_cmd));
+ must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
len = strlen(file);
- must_write(&len, sizeof(int));
- must_write(file, len + 1);
- must_read(&rc, sizeof(int));
+ must_write(PRIV_UNPRIVILEGED, &len, sizeof(int));
+ must_write(PRIV_UNPRIVILEGED, file, len + 1);
+ must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
if (rc == -1)
return rc;
- return receive_fd();
+ return receive_fd(PRIV_UNPRIVILEGED);
}
/* Proxy for ethtool ioctl */
{
int rc, len;
enum priv_cmd cmd = PRIV_ETHTOOL;
- must_write(&cmd, sizeof(enum priv_cmd));
+ must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
len = strlen(ifname);
- must_write(&len, sizeof(int));
- must_write(ifname, len + 1);
- must_read(&rc, sizeof(int));
+ must_write(PRIV_UNPRIVILEGED, &len, sizeof(int));
+ must_write(PRIV_UNPRIVILEGED, ifname, len + 1);
+ must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
if (rc != 0)
return rc;
- must_read(ethc, length);
+ must_read(PRIV_UNPRIVILEGED, ethc, length);
return rc;
}
int fd, len, rc;
regex_t preg;
- must_read(&len, sizeof(len));
+ must_read(PRIV_PRIVILEGED, &len, sizeof(len));
if ((file = (char *)malloc(len + 1)) == NULL)
fatal("privsep", NULL);
- must_read(file, len);
+ must_read(PRIV_PRIVILEGED, file, len);
file[len] = '\0';
for (f=authorized; *f != NULL; f++) {
if (*f == NULL) {
log_warnx("privsep", "not authorized to open %s", file);
rc = -1;
- must_write(&rc, sizeof(int));
+ must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
free(file);
return;
}
if ((fd = open(file, O_RDONLY)) == -1) {
rc = -1;
- must_write(&rc, sizeof(int));
+ must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
free(file);
return;
}
free(file);
- must_write(&fd, sizeof(int));
- send_fd(fd);
+ must_write(PRIV_PRIVILEGED, &fd, sizeof(int));
+ send_fd(PRIV_PRIVILEGED, fd);
close(fd);
}
int len, rc, sock = -1;
char *ifname;
- must_read(&len, sizeof(int));
+ must_read(PRIV_PRIVILEGED, &len, sizeof(int));
if ((ifname = (char*)malloc(len + 1)) == NULL)
fatal("privsep", NULL);
- must_read(ifname, len);
+ must_read(PRIV_PRIVILEGED, ifname, len);
ifname[len] = '\0';
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
free(ifname);
if (((rc = sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) ||
(rc = ioctl(sock, SIOCETHTOOL, &ifr)) != 0) {
if (sock != -1) close(sock);
- must_write(&rc, sizeof(int));
+ must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
return;
}
close(sock);
- must_write(&rc, sizeof(int));
- must_write(ðc, sizeof(struct ethtool_cmd));
+ must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
+ must_write(PRIV_PRIVILEGED, ðc, sizeof(struct ethtool_cmd));
}
int
if ((*fd = socket(PF_PACKET, SOCK_RAW,
htons(ETH_P_ALL))) < 0) {
rc = errno;
- must_write(&rc, sizeof(rc));
+ must_write(PRIV_PRIVILEGED, &rc, sizeof(rc));
return rc;
}
{
int rc;
enum priv_cmd cmd = PRIV_PING;
- must_write(&cmd, sizeof(enum priv_cmd));
- must_read(&rc, sizeof(int));
+ must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
+ must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
log_debug("privsep", "monitor ready");
}
{
int rc, len = strlen(ctlname);
enum priv_cmd cmd = PRIV_DELETE_CTL_SOCKET;
- must_write(&cmd, sizeof(enum priv_cmd));
- must_write(&len, sizeof(int));
- must_write(ctlname, len);
- must_read(&rc, sizeof(int));
+ must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
+ must_write(PRIV_UNPRIVILEGED, &len, sizeof(int));
+ must_write(PRIV_UNPRIVILEGED, ctlname, len);
+ must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
}
/* Proxy for gethostbyname */
static char *buf = NULL;
int rc;
enum priv_cmd cmd = PRIV_GET_HOSTNAME;
- must_write(&cmd, sizeof(enum priv_cmd));
- must_read(&rc, sizeof(int));
+ must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
+ must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
if ((buf = (char*)realloc(buf, rc+1)) == NULL)
fatal("privsep", NULL);
- must_read(buf, rc+1);
+ must_read(PRIV_UNPRIVILEGED, buf, rc+1);
return buf;
}
int rc;
char dev[IFNAMSIZ];
enum priv_cmd cmd = PRIV_IFACE_INIT;
- must_write(&cmd, sizeof(enum priv_cmd));
- must_write(&index, sizeof(int));
+ must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
+ must_write(PRIV_UNPRIVILEGED, &index, sizeof(int));
strlcpy(dev, iface, IFNAMSIZ);
- must_write(dev, IFNAMSIZ);
- must_read(&rc, sizeof(int));
+ must_write(PRIV_UNPRIVILEGED, dev, IFNAMSIZ);
+ must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
if (rc != 0) return -1;
- return receive_fd();
+ return receive_fd(PRIV_UNPRIVILEGED);
}
int
{
int rc;
enum priv_cmd cmd = PRIV_IFACE_MULTICAST;
- must_write(&cmd, sizeof(enum priv_cmd));
- must_write(name, IFNAMSIZ);
- must_write(mac, ETHER_ADDR_LEN);
- must_write(&add, sizeof(int));
- must_read(&rc, sizeof(int));
+ must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
+ must_write(PRIV_UNPRIVILEGED, name, IFNAMSIZ);
+ must_write(PRIV_UNPRIVILEGED, mac, ETHER_ADDR_LEN);
+ must_write(PRIV_UNPRIVILEGED, &add, sizeof(int));
+ must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
return rc;
}
{
int rc, len = strlen(description);
enum priv_cmd cmd = PRIV_IFACE_DESCRIPTION;
- must_write(&cmd, sizeof(enum priv_cmd));
- must_write(name, IFNAMSIZ);
- must_write(&len, sizeof(int));
- must_write(description, len);
- must_read(&rc, sizeof(int));
+ must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
+ must_write(PRIV_UNPRIVILEGED, name, IFNAMSIZ);
+ must_write(PRIV_UNPRIVILEGED, &len, sizeof(int));
+ must_write(PRIV_UNPRIVILEGED, description, len);
+ must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
return rc;
}
{
int rc;
enum priv_cmd cmd = PRIV_SNMP_SOCKET;
- must_write(&cmd, sizeof(enum priv_cmd));
- must_write(addr, sizeof(struct sockaddr_un));
- must_read(&rc, sizeof(int));
+ must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
+ must_write(PRIV_UNPRIVILEGED, addr, sizeof(struct sockaddr_un));
+ must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
if (rc < 0)
return rc;
- return receive_fd();
+ return receive_fd(PRIV_UNPRIVILEGED);
}
static void
asroot_ping()
{
int rc = 1;
- must_write(&rc, sizeof(int));
+ must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
}
static void
char *ctlname;
int rc = 0;
- must_read(&len, sizeof(int));
+ must_read(PRIV_PRIVILEGED, &len, sizeof(int));
if ((ctlname = (char*)malloc(len+1)) == NULL)
fatal("ctlname", NULL);
- must_read(ctlname, len);
+ must_read(PRIV_PRIVILEGED, ctlname, len);
ctlname[len] = 0;
ctl_cleanup(ctlname);
free(ctlname);
/* Ack */
- must_write(&rc, sizeof(int));
+ must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
}
static void
res_init();
#endif
len = strlen(un.nodename);
- must_write(&len, sizeof(int));
- must_write(un.nodename, len + 1);
+ must_write(PRIV_PRIVILEGED, &len, sizeof(int));
+ must_write(PRIV_PRIVILEGED, un.nodename, len + 1);
} else {
len = strlen(hp->h_name);
- must_write(&len, sizeof(int));
- must_write(hp->h_name, len + 1);
+ must_write(PRIV_PRIVILEGED, &len, sizeof(int));
+ must_write(PRIV_PRIVILEGED, hp->h_name, len + 1);
}
}
int rc = -1, fd = -1;
int ifindex;
char name[IFNAMSIZ];
- must_read(&ifindex, sizeof(ifindex));
- must_read(&name, sizeof(name));
+ must_read(PRIV_PRIVILEGED, &ifindex, sizeof(ifindex));
+ must_read(PRIV_PRIVILEGED, &name, sizeof(name));
name[sizeof(name) - 1] = '\0';
TRACE(LLDPD_PRIV_INTERFACE_INIT(name));
rc = asroot_iface_init_os(ifindex, name, &fd);
- must_write(&rc, sizeof(rc));
- if (rc == 0 && fd >=0) send_fd(fd);
+ must_write(PRIV_PRIVILEGED, &rc, sizeof(rc));
+ if (rc == 0 && fd >=0) send_fd(PRIV_PRIVILEGED, fd);
if (fd >= 0) close(fd);
}
{
int sock = -1, add, rc = 0;
struct ifreq ifr = { .ifr_name = {} };
- must_read(ifr.ifr_name, IFNAMSIZ);
+ must_read(PRIV_PRIVILEGED, ifr.ifr_name, IFNAMSIZ);
#if defined HOST_OS_LINUX
- must_read(ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
+ must_read(PRIV_PRIVILEGED, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
#elif defined HOST_OS_FREEBSD || defined HOST_OS_OSX || defined HOST_OS_DRAGONFLY
/* Black magic from mtest.c */
struct sockaddr_dl *dlp = (struct sockaddr_dl *)&ifr.ifr_addr;
dlp->sdl_nlen = 0;
dlp->sdl_alen = ETHER_ADDR_LEN;
dlp->sdl_slen = 0;
- must_read(LLADDR(dlp), ETHER_ADDR_LEN);
+ must_read(PRIV_PRIVILEGED, LLADDR(dlp), ETHER_ADDR_LEN);
#elif defined HOST_OS_OPENBSD || defined HOST_OS_NETBSD || defined HOST_OS_SOLARIS
struct sockaddr *sap = (struct sockaddr *)&ifr.ifr_addr;
#if ! defined HOST_OS_SOLARIS
sap->sa_len = sizeof(struct sockaddr);
#endif
sap->sa_family = AF_UNSPEC;
- must_read(sap->sa_data, ETHER_ADDR_LEN);
+ must_read(PRIV_PRIVILEGED, sap->sa_data, ETHER_ADDR_LEN);
#else
#error Unsupported OS
#endif
- must_read(&add, sizeof(int));
+ must_read(PRIV_PRIVILEGED, &add, sizeof(int));
if (((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) ||
((ioctl(sock, (add)?SIOCADDMULTI:SIOCDELMULTI,
&ifr) < 0) && (errno != EADDRINUSE)))
rc = errno;
if (sock != -1) close(sock);
- must_write(&rc, sizeof(rc));
+ must_write(PRIV_PRIVILEGED, &rc, sizeof(rc));
}
static void
char name[IFNAMSIZ];
char *description;
int len, rc;
- must_read(&name, sizeof(name));
+ must_read(PRIV_PRIVILEGED, &name, sizeof(name));
name[sizeof(name) - 1] = '\0';
- must_read(&len, sizeof(int));
+ must_read(PRIV_PRIVILEGED, &len, sizeof(int));
if ((description = (char*)malloc(len+1)) == NULL)
fatal("description", NULL);
- must_read(description, len);
+ must_read(PRIV_PRIVILEGED, description, len);
description[len] = 0;
TRACE(LLDPD_PRIV_INTERFACE_DESCRIPTION(name, description));
rc = asroot_iface_description_os(name, description);
- must_write(&rc, sizeof(rc));
+ must_write(PRIV_PRIVILEGED, &rc, sizeof(rc));
free(description);
}
if (!addr) {
addr = (struct sockaddr_un *)malloc(sizeof(struct sockaddr_un));
- must_read(addr, sizeof(struct sockaddr_un));
+ must_read(PRIV_PRIVILEGED, addr, sizeof(struct sockaddr_un));
} else
/* We have already been asked to connect to a socket. We will
* connect to the same socket. */
- must_read(&bogus, sizeof(struct sockaddr_un));
+ must_read(PRIV_PRIVILEGED, &bogus, sizeof(struct sockaddr_un));
if (addr->sun_family != AF_UNIX)
fatal("privsep", "someone is trying to trick me");
addr->sun_path[sizeof(addr->sun_path)-1] = '\0';
if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
log_warn("privsep", "cannot open socket");
- must_write(&sock, sizeof(int));
+ must_write(PRIV_PRIVILEGED, &sock, sizeof(int));
return;
}
if ((rc = connect(sock, (struct sockaddr *) addr,
addr->sun_path, strerror(errno));
close(sock);
rc = -1;
- must_write(&rc, sizeof(int));
+ must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
return;
}
- must_write(&rc, sizeof(int));
- send_fd(sock);
+ must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
+ send_fd(PRIV_PRIVILEGED, sock);
close(sock);
}
/* Main loop, run as root */
static void
-priv_loop(int remote)
+priv_loop(int privileged)
{
enum priv_cmd cmd;
struct dispatch_actions *a;
setproctitle("monitor");
#ifdef USE_SECCOMP
- if (priv_seccomp_init(remote, monitored) != 0)
+ if (priv_seccomp_init(privileged, monitored) != 0)
fatal("privsep", "cannot continue without seccomp setup");
#endif
- while (!may_read(&cmd, sizeof(enum priv_cmd))) {
+ while (!may_read(PRIV_PRIVILEGED, &cmd, sizeof(enum priv_cmd))) {
for (a = actions; a->function != NULL; a++) {
if (cmd == a->msg) {
a->function();
fatal("privsep", "setreuid() failed");
#endif
}
- priv_remote(pair[0]);
+ priv_unprivileged_fd(pair[0]);
close(pair[1]);
priv_ping();
break;
default:
/* We are in the monitor */
if (ctl != -1) close(ctl);
- priv_remote(pair[1]);
+ priv_privileged_fd(pair[1]);
close(pair[0]);
if (atexit(priv_exit) != 0)
fatal("privsep", "unable to set exit function");
/* -*- mode: c; c-file-style: "openbsd" -*- */
-static int remote;
+/* The following are needed by Solaris. The first to get CMSG_* and the second
+ * to keep net/if.h working */
+#define _XPG4_2
+#define __EXTENSIONS__
+#include "lldpd.h"
+
+#include <sys/param.h>
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int privileged, unprivileged;
+void
+priv_privileged_fd(int fd)
+{
+ privileged = fd;
+}
+void
+priv_unprivileged_fd(int fd)
+{
+ unprivileged = fd;
+}
+static int
+priv_fd(enum priv_context ctx)
+{
+ switch (ctx) {
+ case PRIV_PRIVILEGED: return privileged;
+ case PRIV_UNPRIVILEGED: return unprivileged;
+ }
+ return -1; /* Not possible */
+}
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
* POSSIBILITY OF SUCH DAMAGE.
*/
-/* The following are needed by Solaris. The first to get CMSG_* and the second
- * to keep net/if.h working */
-#define _XPG4_2
-#define __EXTENSIONS__
-#include "lldpd.h"
-
-#include <sys/param.h>
-#include <sys/uio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
void
-send_fd(int fd)
+send_fd(enum priv_context ctx, int fd)
{
struct msghdr msg;
union {
msg.msg_iov = &vec;
msg.msg_iovlen = 1;
- if ((n = sendmsg(remote, &msg, 0)) == -1)
- log_warn("privsep", "sendmsg(%d)", remote);
+ if ((n = sendmsg(priv_fd(ctx), &msg, 0)) == -1)
+ log_warn("privsep", "sendmsg(%d)", priv_fd(ctx));
if (n != sizeof(int))
log_warnx("privsep", "sendmsg: expected sent 1 got %ld",
(long)n);
}
int
-receive_fd()
+receive_fd(enum priv_context ctx)
{
struct msghdr msg;
union {
msg.msg_control = &cmsgbuf.buf;
msg.msg_controllen = sizeof(cmsgbuf.buf);
- if ((n = recvmsg(remote, &msg, 0)) == -1)
+ if ((n = recvmsg(priv_fd(ctx), &msg, 0)) == -1)
log_warn("privsep", "recvmsg");
if (n != sizeof(int))
log_warnx("privsep", "recvmsg: expected received 1 got %ld",
/* Read all data or return 1 for error. */
int
-may_read(void *buf, size_t n)
+may_read(enum priv_context ctx, void *buf, size_t n)
{
char *s = buf;
ssize_t res, pos = 0;
while (n > pos) {
- res = read(remote, s + pos, n - pos);
+ res = read(priv_fd(ctx), s + pos, n - pos);
switch (res) {
case -1:
if (errno == EINTR || errno == EAGAIN)
/* Read data with the assertion that it all must come through, or
* else abort the process. Based on atomicio() from openssh. */
void
-must_read(void *buf, size_t n)
+must_read(enum priv_context ctx, void *buf, size_t n)
{
char *s = buf;
ssize_t res, pos = 0;
while (n > pos) {
- res = read(remote, s + pos, n - pos);
+ res = read(priv_fd(ctx), s + pos, n - pos);
switch (res) {
case -1:
if (errno == EINTR || errno == EAGAIN)
/* Write data with the assertion that it all has to be written, or
* else abort the process. Based on atomicio() from openssh. */
void
-must_write(const void *buf, size_t n)
+must_write(enum priv_context ctx, const void *buf, size_t n)
{
const char *s = buf;
ssize_t res, pos = 0;
while (n > pos) {
- res = write(remote, s + pos, n - pos);
+ res = write(priv_fd(ctx), s + pos, n - pos);
switch (res) {
case -1:
if (errno == EINTR || errno == EAGAIN)
}
}
}
-
-void
-priv_remote(int fd)
-{
- remote = fd;
-}