diff options
author | 2010-04-22 17:43:30 +0000 | |
---|---|---|
committer | 2010-04-22 17:43:30 +0000 | |
commit | fba31cc54eb4e261e02815be4bf3312ad1f34efd (patch) | |
tree | 058dec436f6de587be3d8199ca3020658bf0601c | |
parent | tweak previous; ok nicm (diff) | |
download | wireguard-openbsd-fba31cc54eb4e261e02815be4bf3312ad1f34efd.tar.xz wireguard-openbsd-fba31cc54eb4e261e02815be4bf3312ad1f34efd.zip |
Allow multiple users to share the same aucat server. If aucat is
run by root, it binds a shared address to the socket, cranks the
process priority and drops privileges. sio_open(3) will try to
connect to the private socket first (if any), then to the shared
socket. Only one user may have connections to aucat at a given
time.
based on discussions with henning, pyr and others
ok jacek, deraadt
-rw-r--r-- | etc/ftpusers | 3 | ||||
-rw-r--r-- | etc/group | 1 | ||||
-rw-r--r-- | etc/mail/aliases | 3 | ||||
-rw-r--r-- | etc/master.passwd | 1 | ||||
-rw-r--r-- | lib/libsndio/aucat.c | 13 | ||||
-rw-r--r-- | lib/libsndio/mio_thru.c | 15 | ||||
-rw-r--r-- | usr.bin/aucat/aucat.1 | 14 | ||||
-rw-r--r-- | usr.bin/aucat/aucat.c | 55 | ||||
-rw-r--r-- | usr.bin/aucat/midicat.1 | 14 | ||||
-rw-r--r-- | usr.bin/aucat/sock.c | 39 |
10 files changed, 139 insertions, 19 deletions
diff --git a/etc/ftpusers b/etc/ftpusers index d728a74a3bb..e781a680227 100644 --- a/etc/ftpusers +++ b/etc/ftpusers @@ -1,4 +1,4 @@ -# $OpenBSD: ftpusers,v 1.40 2010/02/22 15:16:45 claudio Exp $ +# $OpenBSD: ftpusers,v 1.41 2010/04/22 17:43:30 ratchov Exp $ # # list of users disallowed any ftp access. # read by ftpd(8). @@ -50,3 +50,4 @@ _smtpd _rwalld _nsd _ldpd +_sndio diff --git a/etc/group b/etc/group index caede7b7e00..369dfa23771 100644 --- a/etc/group +++ b/etc/group @@ -63,6 +63,7 @@ _smtpd:*:95: _rwalld:*:96: _nsd:*:97: _ldpd:*:98: +_sndio:*:99: dialer:*:117: nogroup:*:32766: nobody:*:32767: diff --git a/etc/mail/aliases b/etc/mail/aliases index f580b501822..ee17f276607 100644 --- a/etc/mail/aliases +++ b/etc/mail/aliases @@ -1,5 +1,5 @@ # -# $OpenBSD: aliases,v 1.32 2010/02/22 15:16:45 claudio Exp $ +# $OpenBSD: aliases,v 1.33 2010/04/22 17:43:30 ratchov Exp $ # # Aliases in this file will NOT be expanded in the header from # Mail, but WILL be visible over networks or from /usr/libexec/mail.local. @@ -50,6 +50,7 @@ _rtadvd: /dev/null _rusersd: /dev/null _rwalld: /dev/null _smtpd: /dev/null +_sndio: /dev/null _snmpd: /dev/null _spamd: /dev/null _syslogd: /dev/null diff --git a/etc/master.passwd b/etc/master.passwd index 15e3f393ccf..9140e01e32d 100644 --- a/etc/master.passwd +++ b/etc/master.passwd @@ -45,4 +45,5 @@ _smtpd:*:95:95::0:0:SMTP Daemon:/var/empty:/sbin/nologin _rwalld:*:96:96::0:0:rpc.rwalld:/var/empty:/sbin/nologin _nsd:*:97:97::0:0:NSD Daemon:/var/empty:/sbin/nologin _ldpd:*:98:98::0:0:LDP Daemon:/var/empty:/sbin/nologin +_sndio:*:99:99::0:0:sndio privsep:/var/empty:/sbin/nologin nobody:*:32767:32767::0:0:Unprivileged user for NFS:/nonexistent:/sbin/nologin diff --git a/lib/libsndio/aucat.c b/lib/libsndio/aucat.c index 65cef3bb5d7..f79f235d532 100644 --- a/lib/libsndio/aucat.c +++ b/lib/libsndio/aucat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aucat.c,v 1.35 2010/04/06 20:07:01 ratchov Exp $ */ +/* $OpenBSD: aucat.c,v 1.36 2010/04/22 17:43:30 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -225,7 +225,16 @@ sio_open_aucat(const char *str, unsigned mode, int nbio) if (errno == EINTR) continue; DPERROR("sio_open_aucat: connect"); - goto bad_connect; + /* try shared server */ + snprintf(ca.sun_path, sizeof(ca.sun_path), + "/tmp/aucat/softaudio%s", unit); + while (connect(s, (struct sockaddr *)&ca, len) < 0) { + if (errno == EINTR) + continue; + DPERROR("sio_open_aucat: connect"); + goto bad_connect; + } + break; } if (fcntl(s, F_SETFD, FD_CLOEXEC) < 0) { DPERROR("FD_CLOEXEC"); diff --git a/lib/libsndio/mio_thru.c b/lib/libsndio/mio_thru.c index eb5dd81bdcc..1413f9ee5c2 100644 --- a/lib/libsndio/mio_thru.c +++ b/lib/libsndio/mio_thru.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mio_thru.c,v 1.6 2009/10/22 22:26:49 ratchov Exp $ */ +/* $OpenBSD: mio_thru.c,v 1.7 2010/04/22 17:43:30 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -82,8 +82,17 @@ thru_open(const char *str, char *sock, unsigned mode, int nbio) if (errno == EINTR) continue; DPERROR("thru_open: connect"); - goto bad_connect; - } + /* try shared server */ + snprintf(ca.sun_path, sizeof(ca.sun_path), + "/tmp/aucat/%s%s", sock, str); + while (connect(s, (struct sockaddr *)&ca, len) < 0) { + if (errno == EINTR) + continue; + DPERROR("thru_open: connect"); + goto bad_connect; + } + break; + } if (fcntl(s, F_SETFD, FD_CLOEXEC) < 0) { DPERROR("FD_CLOEXEC"); goto bad_connect; diff --git a/usr.bin/aucat/aucat.1 b/usr.bin/aucat/aucat.1 index 8fe76090f04..dfb35e0467e 100644 --- a/usr.bin/aucat/aucat.1 +++ b/usr.bin/aucat/aucat.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: aucat.1,v 1.68 2010/04/21 06:13:07 ratchov Exp $ +.\" $OpenBSD: aucat.1,v 1.69 2010/04/22 17:43:30 ratchov Exp $ .\" .\" Copyright (c) 2006 Alexandre Ratchov <alex@caoua.org> .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: April 21 2010 $ +.Dd $Mdocdate: April 22 2010 $ .Dt AUCAT 1 .Os .Sh NAME @@ -387,6 +387,16 @@ can be used in server mode to overcome hardware limitations and allow applications to run on fixed sample rate devices or on devices supporting only unusual encodings. +.Pp +The +.Nm +audio server may be started by the super-user, +in which case any user will be able to connect to it. +For privacy reasons, only one user may have connections to it +at a given time. +.Pp +Alternatively, each user may run his instance +of the server. It is generally not desirable to have multiple instances of .Nm diff --git a/usr.bin/aucat/aucat.c b/usr.bin/aucat/aucat.c index d713057cad6..89504bf5601 100644 --- a/usr.bin/aucat/aucat.c +++ b/usr.bin/aucat/aucat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aucat.c,v 1.85 2010/04/21 06:15:02 ratchov Exp $ */ +/* $OpenBSD: aucat.c,v 1.86 2010/04/22 17:43:30 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -18,11 +18,13 @@ #include <sys/queue.h> #include <sys/stat.h> #include <sys/types.h> +#include <sys/resource.h> #include <err.h> #include <errno.h> #include <fcntl.h> #include <limits.h> +#include <pwd.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> @@ -43,6 +45,16 @@ #include "dbg.h" #endif +/* + * unprivileged user name + */ +#define SNDIO_USER "_sndio" + +/* + * priority when run as root + */ +#define SNDIO_PRIO (-20) + #define PROG_AUCAT "aucat" #define PROG_MIDICAT "midicat" @@ -303,20 +315,47 @@ getbasepath(char *base, size_t size) { uid_t uid; struct stat sb; + mode_t mask; uid = geteuid(); - snprintf(base, PATH_MAX, "/tmp/aucat-%u", uid); - if (mkdir(base, 0700) < 0) { + if (uid == 0) { + mask = 022; + snprintf(base, PATH_MAX, "/tmp/aucat"); + } else { + mask = 077; + snprintf(base, PATH_MAX, "/tmp/aucat-%u", uid); + } + if (mkdir(base, 0777 & ~mask) < 0) { if (errno != EEXIST) err(1, "mkdir(\"%s\")", base); } if (stat(base, &sb) < 0) err(1, "stat(\"%s\")", base); - if (sb.st_uid != uid || (sb.st_mode & 077) != 0) + if (sb.st_uid != uid || (sb.st_mode & mask) != 0) errx(1, "%s has wrong permissions", base); } void +privdrop(void) +{ + struct passwd *pw; + struct stat sb; + + if ((pw = getpwnam(SNDIO_USER)) == NULL) + err(1, "getpwnam"); + if (stat(pw->pw_dir, &sb) < 0) + err(1, "stat(\"%s\")", pw->pw_dir); + if (sb.st_uid != 0 || (sb.st_mode & 022) != 0) + errx(1, "%s has wrong permissions", pw->pw_dir); + if (setpriority(PRIO_PROCESS, 0, SNDIO_PRIO) < 0) + err(1, "setpriority"); + if (setgroups(1, &pw->pw_gid) || + setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || + setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) + err(1, "cannot drop privileges"); +} + +void stopall(char *base) { struct file *f; @@ -647,6 +686,8 @@ aucat_main(int argc, char **argv) snprintf(path, sizeof(path), "%s/%s%u", base, DEFAULT_SOFTAUDIO, unit); listen_new(&listen_ops, path); + if (geteuid() == 0) + privdrop(); if (!d_flag && daemon(0, 0) < 0) err(1, "daemon"); } @@ -705,7 +746,7 @@ aucat_main(int argc, char **argv) dev_done(); filelist_done(); if (l_flag) { - if (rmdir(base) < 0 && errno != ENOTEMPTY) + if (rmdir(base) < 0 && errno != ENOTEMPTY && errno != EPERM) warn("rmdir(\"%s\")", base); } unsetsig(); @@ -817,6 +858,8 @@ midicat_main(int argc, char **argv) snprintf(path, sizeof(path), "%s/%s%u", base, DEFAULT_MIDITHRU, unit); listen_new(&listen_ops, path); + if (geteuid() == 0) + privdrop(); if (!d_flag && daemon(0, 0) < 0) err(1, "daemon"); } @@ -873,7 +916,7 @@ midicat_main(int argc, char **argv) dev_done(); filelist_done(); if (l_flag) { - if (rmdir(base) < 0 && errno != ENOTEMPTY) + if (rmdir(base) < 0 && errno != ENOTEMPTY && errno != EPERM) warn("rmdir(\"%s\")", base); } unsetsig(); diff --git a/usr.bin/aucat/midicat.1 b/usr.bin/aucat/midicat.1 index 6baec0a512c..0d760141c98 100644 --- a/usr.bin/aucat/midicat.1 +++ b/usr.bin/aucat/midicat.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: midicat.1,v 1.9 2010/04/06 20:07:01 ratchov Exp $ +.\" $OpenBSD: midicat.1,v 1.10 2010/04/22 17:43:30 ratchov Exp $ .\" .\" Copyright (c) 2006 Alexandre Ratchov <alex@caoua.org> .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: April 6 2010 $ +.Dd $Mdocdate: April 22 2010 $ .Dt MIDICAT 1 .Os .Sh NAME @@ -101,6 +101,16 @@ This feature is provided to allow multiple applications acting as sources to keep their connection open while idling; it does not replace a fully featured MIDI merger. .Pp +A +.Nm +process may be started by the super-user, +in which case any user will be able to connect to it. +For privacy reasons, only one user may have connections to +it at a given time. +.Pp +Alternatively, each user may start its own +.Nm +process. It is generally not desirable to have multiple instances of .Nm running in server mode, so it is good practice to start it thus: diff --git a/usr.bin/aucat/sock.c b/usr.bin/aucat/sock.c index da0fff1be1c..18f2f8f366f 100644 --- a/usr.bin/aucat/sock.c +++ b/usr.bin/aucat/sock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sock.c,v 1.43 2010/04/21 06:13:07 ratchov Exp $ */ +/* $OpenBSD: sock.c,v 1.44 2010/04/22 17:43:30 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -15,6 +15,9 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <sys/types.h> +#include <sys/socket.h> +#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -35,11 +38,12 @@ int sock_read(struct sock *); int sock_write(struct sock *); int sock_execmsg(struct sock *); void sock_reset(struct sock *); +void sock_close(struct file *); struct fileops sock_ops = { "sock", sizeof(struct sock), - pipe_close, + sock_close, pipe_read, pipe_write, NULL, /* start */ @@ -83,6 +87,16 @@ struct ctl_ops ctl_sockops = { sock_locreq }; +unsigned sock_sesrefs = 0; /* connections to the session */ +uid_t sock_sesuid; /* owner of the session */ + +void +sock_close(struct file *f) +{ + sock_sesrefs--; + pipe_close(f); +} + void rsock_done(struct aproc *p) { @@ -296,6 +310,27 @@ sock_new(struct fileops *ops, int fd) { struct aproc *rproc, *wproc; struct sock *f; + uid_t uid, gid; + + /* + * ensure that all connections belong to the same user, + * for privacy reasons. + * + * XXX: is there a portable way of doing this ? + */ + if (getpeereid(fd, &uid, &gid) < 0) { + close(fd); + return NULL; + } + if (sock_sesrefs == 0) { + /* start a new session */ + sock_sesuid = uid; + } else if (uid != sock_sesuid) { + /* session owned by another user, drop connection */ + close(fd); + return NULL; + } + sock_sesrefs++; f = (struct sock *)pipe_new(ops, fd, "sock"); if (f == NULL) |