summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorratchov <ratchov@openbsd.org>2010-04-22 17:43:30 +0000
committerratchov <ratchov@openbsd.org>2010-04-22 17:43:30 +0000
commitfba31cc54eb4e261e02815be4bf3312ad1f34efd (patch)
tree058dec436f6de587be3d8199ca3020658bf0601c
parenttweak previous; ok nicm (diff)
downloadwireguard-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/ftpusers3
-rw-r--r--etc/group1
-rw-r--r--etc/mail/aliases3
-rw-r--r--etc/master.passwd1
-rw-r--r--lib/libsndio/aucat.c13
-rw-r--r--lib/libsndio/mio_thru.c15
-rw-r--r--usr.bin/aucat/aucat.114
-rw-r--r--usr.bin/aucat/aucat.c55
-rw-r--r--usr.bin/aucat/midicat.114
-rw-r--r--usr.bin/aucat/sock.c39
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)