From: Klemens Nanni Date: Sat, 27 Jan 2024 04:36:29 +0000 (+0100) Subject: Hoist PTP socket handling, drop privileges on OpenBSD X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4586bb084a98e3b9f18d101fb91c72112a527323;p=thirdparty%2Fnqptp.git Hoist PTP socket handling, drop privileges on OpenBSD bind(2)ing ports below 1024 is the only privileged operation NQPTP does. Move its code up in main() before shared memory handling such that root privileges can be dropped immediately after it; no currently supported system does that, thus this should be a NOOP. Do so on OpenBSD where shm_open(3) does not allow access to shared memory objects by multiple UIDs, i.e. to communicate, shairport-sync and NQPTP must create them and run as the very same user. OpenBSD's official audio/shairport-sync user provides an rc.d(8) daemon script that runs as `_shairport` user. --- diff --git a/Makefile.am b/Makefile.am index ff86fea..5f12222 100644 --- a/Makefile.am +++ b/Makefile.am @@ -39,3 +39,8 @@ if INSTALL_FREEBSD_STARTUP chmod 555 /usr/local/etc/rc.d/nqptp endif endif + +if BUILD_FOR_OPENBSD +# NQPTP starts as root on OpenBSD to access ports 319 and 320 +# and drops privileges to the user shairport is running as. +endif diff --git a/nqptp-utilities.c b/nqptp-utilities.c index cfbd1ee..18e5a9c 100644 --- a/nqptp-utilities.c +++ b/nqptp-utilities.c @@ -106,7 +106,7 @@ void open_sockets_at_port(const char *node, uint16_t port, freeaddrinfo(info); if (sockets_opened == 0) { if (errno == EACCES) { - die("nqptp does not have permission to access port %u. It must (a) [Linux only] have been given CAP_NET_BIND_SERVICE capabilities using e.g. setcap or systemd's AmbientCapabilities, or (b) run as root.", port); + die("nqptp does not have permission to access port %u. It must (a) [Linux only] have been given CAP_NET_BIND_SERVICE capabilities using e.g. setcap or systemd's AmbientCapabilities, or (b) start as root.", port); } else { die("nqptp is unable to listen on port %u. The error is: %d, \"%s\".", port, errno, strerror(errno)); } diff --git a/nqptp.c b/nqptp.c index 6af9495..88cf939 100644 --- a/nqptp.c +++ b/nqptp.c @@ -53,6 +53,12 @@ #include #endif +#ifdef CONFIG_FOR_OPENBSD +#include +#include +#include +#endif + #ifndef FIELD_SIZEOF #define FIELD_SIZEOF(t, f) (sizeof(((t *)0)->f)) #endif @@ -177,6 +183,10 @@ int main(int argc, char **argv) { sockets_open_stuff.sockets_open = 0; + // open PTP sockets + open_sockets_at_port(NULL, 319, &sockets_open_stuff); + open_sockets_at_port(NULL, 320, &sockets_open_stuff); + epoll_fd = -1; // control-c (SIGINT) cleanly @@ -191,6 +201,22 @@ int main(int argc, char **argv) { act2.sa_handler = termHandler; sigaction(SIGTERM, &act2, NULL); +#ifdef CONFIG_FOR_OPENBSD + // shm_open(3) prohibits sharing between different UIDs, so nqptp must run as + // the same user shairport-sync does. + struct passwd *pw; + const char *shairport_user = "_shairport"; + pw = getpwnam(shairport_user); + if (pw == NULL) { + die("unknown user %s", shairport_user); + } + if (setgroups(1, &pw->pw_gid) == -1 || + setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1 || + setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) { + die("cannot drop privileges to %s", shairport_user); + } +#endif + // open the SMI shm_fd = -1; @@ -233,10 +259,7 @@ int main(int argc, char **argv) { char buf[BUFLEN]; - // open sockets 319 and 320 - - open_sockets_at_port(NULL, 319, &sockets_open_stuff); - open_sockets_at_port(NULL, 320, &sockets_open_stuff); + // open control socket open_sockets_at_port("localhost", NQPTP_CONTROL_PORT, &sockets_open_stuff); // this for messages from the client