Skip to content

Commit

Permalink
Hoist PTP socket handling, drop privileges on OpenBSD
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
klemensn committed Jan 27, 2024
1 parent 3487ba6 commit 4586bb0
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 5 deletions.
5 changes: 5 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion nqptp-utilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down
31 changes: 27 additions & 4 deletions nqptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@
#include <sys/socket.h>
#endif

#ifdef CONFIG_FOR_OPENBSD
#include <sys/types.h>
#include <unistd.h>
#include <pwd.h>
#endif

#ifndef FIELD_SIZEOF
#define FIELD_SIZEOF(t, f) (sizeof(((t *)0)->f))
#endif
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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

Expand Down

0 comments on commit 4586bb0

Please sign in to comment.