From a382492204ad3588c0c837e120e5bc31578df72a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 19 Jul 2006 21:48:35 +0000 Subject: * add new function pa_check_in_group() * abstract credential APis a little bit by introducing HAVE_CREDS and a structure pa_creds * rework credential authentication * fix module-volume-restore and friends for usage in system-wide instance * remove loopback= argument from moulde-*-protocol-tcp since it is a superset of listen= and usually a bad idea anyway since the user shouldn't load the TCP module at all if he doesn't want remote access * rename a few variables in the jack modules to make sure they don't conflict with symbols defined in the system headers * add server address for system-wide daemons to the default server list for the the client libs * update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1109 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon-conf.c | 4 +-- src/daemon/main.c | 3 +- src/modules/module-jack-sink.c | 6 ++-- src/modules/module-jack-source.c | 6 ++-- src/modules/module-match.c | 2 +- src/modules/module-protocol-stub.c | 19 +++--------- src/modules/module-tunnel.c | 2 +- src/modules/module-volume-restore.c | 2 +- src/pulse/client-conf.c | 2 +- src/pulse/context.c | 22 ++++++++----- src/pulsecore/core-util.c | 61 ++++++++++++++++++++++++++----------- src/pulsecore/core-util.h | 1 + src/pulsecore/creds.h | 44 ++++++++++++++++++++++++++ src/pulsecore/iochannel.c | 44 +++++++++----------------- src/pulsecore/iochannel.h | 9 +++--- src/pulsecore/pdispatch.c | 6 ++-- src/pulsecore/pdispatch.h | 9 +++--- src/pulsecore/protocol-native.c | 55 ++++++++++++++++++++++----------- src/pulsecore/pstream-util.c | 2 +- src/pulsecore/pstream-util.h | 5 ++- src/pulsecore/pstream.c | 27 ++++++++-------- src/pulsecore/pstream.h | 8 ++--- src/pulsecore/socket-server.c | 9 +++++- 23 files changed, 216 insertions(+), 132 deletions(-) create mode 100644 src/pulsecore/creds.h (limited to 'src') diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index a5a62567..2577578c 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -46,9 +46,9 @@ #endif #define DEFAULT_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "default.pa" -#define DEFAULT_SCRIPT_FILE_USER ".pulse" PATH_SEP "default.pa" +#define DEFAULT_SCRIPT_FILE_USER PATH_SEP "default.pa" #define DEFAULT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf" -#define DEFAULT_CONFIG_FILE_USER ".pulse" PATH_SEP "daemon.conf" +#define DEFAULT_CONFIG_FILE_USER PATH_SEP "daemon.conf" #define ENV_SCRIPT_FILE "PULSE_SCRIPT" #define ENV_CONFIG_FILE "PULSE_CONFIG" diff --git a/src/daemon/main.c b/src/daemon/main.c index 4961f0ca..0449cb94 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -229,6 +229,7 @@ static int change_user(void) { /* Relevant for pa_runtime_path() */ set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH); + set_env("PULSE_CONFIG_PATH", PA_SYSTEM_RUNTIME_PATH); pa_log_info(__FILE__": Successfully dropped root privileges."); @@ -245,8 +246,6 @@ static int create_runtime_dir(void) { return -1; } - /* Relevant for pa_runtime_path() later on */ - set_env("PULSE_RUNTIME_PATH", fn); return 0; } diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index d761c1f7..c645caa9 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -242,7 +242,7 @@ int pa__init(pa_core *c, pa_module*m) { jack_status_t status; const char *server_name, *client_name; uint32_t channels = 0; - int connect = 1; + int do_connect = 1; unsigned i; const char **ports = NULL, **p; @@ -256,7 +256,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - if (pa_modargs_get_value_boolean(ma, "connect", &connect) < 0) { + if (pa_modargs_get_value_boolean(ma, "connect", &do_connect) < 0) { pa_log(__FILE__": failed to parse connect= argument."); goto fail; } @@ -339,7 +339,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - if (connect) { + if (do_connect) { for (i = 0, p = ports; i < ss.channels; i++, p++) { if (!*p) { diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 649a8f98..2a492929 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -240,7 +240,7 @@ int pa__init(pa_core *c, pa_module*m) { jack_status_t status; const char *server_name, *client_name; uint32_t channels = 0; - int connect = 1; + int do_connect = 1; unsigned i; const char **ports = NULL, **p; @@ -254,7 +254,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - if (pa_modargs_get_value_boolean(ma, "connect", &connect) < 0) { + if (pa_modargs_get_value_boolean(ma, "connect", &do_connect) < 0) { pa_log(__FILE__": failed to parse connect= argument."); goto fail; } @@ -337,7 +337,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - if (connect) { + if (do_connect) { for (i = 0, p = ports; i < ss.channels; i++, p++) { if (!*p) { diff --git a/src/modules/module-match.c b/src/modules/module-match.c index cd58a838..ab94b02d 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -53,7 +53,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define WHITESPACE "\n\r \t" #define DEFAULT_MATCH_TABLE_FILE PA_DEFAULT_CONFIG_DIR"/match.table" -#define DEFAULT_MATCH_TABLE_FILE_USER ".pulse/match.table" +#define DEFAULT_MATCH_TABLE_FILE_USER "match.table" static const char* const valid_modargs[] = { "table", diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index fa21b737..ecbc5676 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -52,10 +52,11 @@ #include #include #include +#include #ifdef USE_TCP_SOCKETS #define SOCKET_DESCRIPTION "(TCP sockets)" -#define SOCKET_USAGE "port= loopback= listen=
" +#define SOCKET_USAGE "port= listen=
" #else #define SOCKET_DESCRIPTION "(UNIX sockets)" #define SOCKET_USAGE "socket=" @@ -127,9 +128,9 @@ #include "module-native-protocol-unix-symdef.h" #endif - #if defined(SCM_CREDENTIALS) && !defined(USE_TCP_SOCKETS) - #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group", - #define AUTH_USAGE "auth-group=" + #if defined(HAVE_CREDS) && !defined(USE_TCP_SOCKETS) + #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group", "auth-group-enable=" + #define AUTH_USAGE "auth-group= auth-group-enable= " #else #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON #define AUTH_USAGE @@ -171,7 +172,6 @@ static const char* const valid_modargs[] = { MODULE_ARGUMENTS #if defined(USE_TCP_SOCKETS) "port", - "loopback", "listen", #else "socket", @@ -197,7 +197,6 @@ int pa__init(pa_core *c, pa_module*m) { #if defined(USE_TCP_SOCKETS) pa_socket_server *s_ipv4 = NULL, *s_ipv6 = NULL; - int loopback = 1; uint32_t port = IPV4_PORT; const char *listen_on; #else @@ -216,11 +215,6 @@ int pa__init(pa_core *c, pa_module*m) { u = pa_xnew0(struct userdata, 1); #if defined(USE_TCP_SOCKETS) - if (pa_modargs_get_value_boolean(ma, "loopback", &loopback) < 0) { - pa_log(__FILE__": loopback= expects a boolean argument."); - goto fail; - } - if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) { pa_log(__FILE__": port= expects a numerical argument between 1 and 65535."); goto fail; @@ -231,9 +225,6 @@ int pa__init(pa_core *c, pa_module*m) { if (listen_on) { s_ipv6 = pa_socket_server_new_ipv6_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE); s_ipv4 = pa_socket_server_new_ipv4_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE); - } else if (loopback) { - s_ipv6 = pa_socket_server_new_ipv6_loopback(c->mainloop, port, TCPWRAP_SERVICE); - s_ipv4 = pa_socket_server_new_ipv4_loopback(c->mainloop, port, TCPWRAP_SERVICE); } else { s_ipv6 = pa_socket_server_new_ipv6_any(c->mainloop, port, TCPWRAP_SERVICE); s_ipv4 = pa_socket_server_new_ipv4_any(c->mainloop, port, TCPWRAP_SERVICE); diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index c018c520..2fb34d12 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -611,7 +611,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { } -static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) { struct userdata *u = userdata; assert(p && packet && u); diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 2f45082b..d0956509 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -53,7 +53,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define WHITESPACE "\n\r \t" -#define DEFAULT_VOLUME_TABLE_FILE ".pulse/volume.table" +#define DEFAULT_VOLUME_TABLE_FILE "volume.table" static const char* const valid_modargs[] = { "table", diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index 28b4f2d1..21917597 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -46,7 +46,7 @@ #endif #define DEFAULT_CLIENT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "client.conf" -#define DEFAULT_CLIENT_CONFIG_FILE_USER ".pulse" PATH_SEP "client.conf" +#define DEFAULT_CLIENT_CONFIG_FILE_USER "client.conf" #define ENV_CLIENT_CONFIG_FILE "PULSE_CLIENTCONFIG" #define ENV_DEFAULT_SINK "PULSE_SINK" diff --git a/src/pulse/context.c b/src/pulse/context.c index f6452d4e..0150204c 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -62,6 +62,7 @@ #include #include #include +#include #include "internal.h" @@ -272,7 +273,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED); } -static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) { pa_context *c = userdata; assert(p); @@ -423,15 +424,17 @@ static void setup_context(pa_context *c, pa_iochannel *io) { pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION); pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie)); -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS { - struct ucred ucred; + pa_creds ucred; + gid_t g; - ucred.pid = getpid(); ucred.uid = getuid(); + ucred.gid = getgid(); - if ((ucred.gid = pa_get_gid_of_group(c->conf->access_group)) == (gid_t) -1) - ucred.gid = getgid(); + if ((g = pa_get_gid_of_group(c->conf->access_group)) != (gid_t) -1) + if (pa_check_in_group(g) > 0) + ucred.gid = g; pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred); } @@ -690,7 +693,12 @@ int pa_context_connect( } c->server_list = pa_strlist_prepend(c->server_list, "tcp6:localhost"); - c->server_list = pa_strlist_prepend(c->server_list, "localhost"); + c->server_list = pa_strlist_prepend(c->server_list, "tcp4:localhost"); + + /* The system wide instance */ + c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH "/" PA_NATIVE_DEFAULT_UNIX_SOCKET); + + /* The per-user instance */ c->server_list = pa_strlist_prepend(c->server_list, pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET, ufn, sizeof(ufn))); /* Wrap the connection attempts in a single transaction for sane autospawn locking */ diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 6375e5ef..0e6501b8 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -741,6 +741,20 @@ finish: return ret; } +int pa_check_in_group(gid_t g) { + gid_t gids[NGROUPS_MAX]; + int r; + + if ((r = getgroups(NGROUPS_MAX, gids)) < 0) + return -1; + + for (; r > 0; r--) + if (gids[r-1] == g) + return 1; + + return 0; +} + #else /* HAVE_GRP_H */ int pa_own_uid_in_group(const char *name, gid_t *gid) { @@ -752,6 +766,14 @@ int pa_uid_in_group(uid_t uid, const char *name) { return -1; } +gid_t pa_get_gid_of_group(const char *name) { + return (gid_t) -1; +} + +int pa_check_in_group(gid_t g) { + return -1; +} + #endif /* Lock or unlock a file entirely. @@ -909,28 +931,33 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env return fopen(fn, mode); } - if (local && pa_get_home_dir(h, sizeof(h))) { - FILE *f; - char *lfn; - - fn = lfn = pa_sprintf_malloc("%s/%s", h, local); + if (local) { + const char *e; + char *lfn = NULL; + if ((e = getenv("PULSE_CONFIG_PATH"))) + fn = lfn = pa_sprintf_malloc("%s/%s", e, local); + else if (pa_get_home_dir(h, sizeof(h))) + fn = lfn = pa_sprintf_malloc("%s/.pulse/%s", h, local); + + if (lfn) { + FILE *f; + #ifdef OS_IS_WIN32 - if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) - return NULL; - fn = buf; + if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) + return NULL; + fn = buf; #endif - - f = fopen(fn, mode); - - if (f || errno != ENOENT) { - if (result) - *result = pa_xstrdup(fn); + + if ((f = fopen(fn, mode)) || errno != ENOENT) { + if (result) + *result = pa_xstrdup(fn); + pa_xfree(lfn); + return f; + } + pa_xfree(lfn); - return f; } - - pa_xfree(lfn); } if (!global) { diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index db764de1..ba325968 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -67,6 +67,7 @@ const char *pa_strsignal(int sig); int pa_own_uid_in_group(const char *name, gid_t *gid); int pa_uid_in_group(uid_t uid, const char *name); gid_t pa_get_gid_of_group(const char *name); +int pa_check_in_group(gid_t g); int pa_lock_fd(int fd, int b); diff --git a/src/pulsecore/creds.h b/src/pulsecore/creds.h new file mode 100644 index 00000000..a95f4480 --- /dev/null +++ b/src/pulsecore/creds.h @@ -0,0 +1,44 @@ +#ifndef foocredshfoo +#define foocredshfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include +#include + +typedef struct pa_creds pa_creds; + +#if defined(SCM_CREDENTIALS) + +#define HAVE_CREDS 1 + +struct pa_creds { + gid_t gid; + uid_t uid; +}; + +#else +#undef HAVE_CREDS +#endif + +#endif diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c index 852e960e..b50293bf 100644 --- a/src/pulsecore/iochannel.c +++ b/src/pulsecore/iochannel.c @@ -231,7 +231,7 @@ ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) { return r; } -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS int pa_iochannel_creds_supported(pa_iochannel *io) { struct sockaddr_un sa; @@ -263,7 +263,7 @@ int pa_iochannel_creds_enable(pa_iochannel *io) { return 0; } -ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const struct ucred *ucred) { +ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const pa_creds *ucred) { ssize_t r; struct msghdr mh; struct iovec iov; @@ -288,10 +288,11 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l u = (struct ucred*) CMSG_DATA(cmsg); - if (ucred) - *u = *ucred; - else { - u->pid = getpid(); + u->pid = getpid(); + if (ucred) { + u->uid = ucred->uid; + u->gid = ucred->gid; + } else { u->uid = getuid(); u->gid = getgid(); } @@ -313,7 +314,7 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l return r; } -ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struct ucred *ucred, int *creds_valid) { +ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_creds *creds, int *creds_valid) { ssize_t r; struct msghdr mh; struct iovec iov; @@ -323,7 +324,7 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struc assert(data); assert(l); assert(io->ifd >= 0); - assert(ucred); + assert(creds); assert(creds_valid); memset(&iov, 0, sizeof(iov)); @@ -349,8 +350,12 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struc for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) { + struct ucred u; assert(cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))); - memcpy(ucred, CMSG_DATA(cmsg), sizeof(struct ucred)); + memcpy(&u, CMSG_DATA(cmsg), sizeof(struct ucred)); + + creds->gid = u.gid; + creds->uid = u.uid; *creds_valid = 1; break; } @@ -362,27 +367,8 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struc return r; } -#else /* SCM_CREDENTIALS */ - -int pa_iochannel_creds_supported(pa_iochannel *io) { - return 0; -} - -int pa_iochannel_creds_enable(pa_iochannel *io) { - return -1; -} - -ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l) { - pa_log_error("pa_iochannel_write_with_creds() not supported."); - return -1; -} - -ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struct ucred *ucred, int *creds_valid) { - pa_log_error("pa_iochannel_read_with_creds() not supported."); - return -1; -} -#endif /* SCM_CREDENTIALS */ +#endif /* HAVE_CREDS */ void pa_iochannel_set_callback(pa_iochannel*io, pa_iochannel_cb_t _callback, void *userdata) { assert(io); diff --git a/src/pulsecore/iochannel.h b/src/pulsecore/iochannel.h index 3b5cba1c..1f9ab0d4 100644 --- a/src/pulsecore/iochannel.h +++ b/src/pulsecore/iochannel.h @@ -25,6 +25,7 @@ #include #include +#include /* A wrapper around UNIX file descriptors for attaching them to the a main event loop. Everytime new data may be read or be written to @@ -49,13 +50,13 @@ void pa_iochannel_free(pa_iochannel*io); ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l); ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l); +#ifdef HAVE_CREDS int pa_iochannel_creds_supported(pa_iochannel *io); int pa_iochannel_creds_enable(pa_iochannel *io); -struct ucred; - -ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const struct ucred *ucred); -ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struct ucred *ucred, int *creds_valid); +ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const pa_creds *ucred); +ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_creds *ucred, int *creds_valid); +#endif int pa_iochannel_is_readable(pa_iochannel*io); int pa_iochannel_is_writable(pa_iochannel*io); diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c index 9bc20da4..db54b2a3 100644 --- a/src/pulsecore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -112,7 +112,7 @@ struct pa_pdispatch { PA_LLIST_HEAD(struct reply_info, replies); pa_pdispatch_drain_callback drain_callback; void *drain_userdata; - const void *creds; + const pa_creds *creds; }; static void reply_info_free(struct reply_info *r) { @@ -180,7 +180,7 @@ static void run_action(pa_pdispatch *pd, struct reply_info *r, uint32_t command, pa_pdispatch_unref(pd); } -int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const struct ucred *creds, void *userdata) { +int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds, void *userdata) { uint32_t tag, command; pa_tagstruct *ts = NULL; int ret = -1; @@ -310,7 +310,7 @@ pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd) { return pd; } -const struct ucred * pa_pdispatch_creds(pa_pdispatch *pd) { +const pa_creds * pa_pdispatch_creds(pa_pdispatch *pd) { assert(pd); assert(pd->ref >= 1); diff --git a/src/pulsecore/pdispatch.h b/src/pulsecore/pdispatch.h index 18073502..479eb6b4 100644 --- a/src/pulsecore/pdispatch.h +++ b/src/pulsecore/pdispatch.h @@ -23,12 +23,13 @@ ***/ #include + #include #include + #include #include - -struct ucred; +#include typedef struct pa_pdispatch pa_pdispatch; @@ -39,7 +40,7 @@ pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, const pa_pdispatch_cb_t*table void pa_pdispatch_unref(pa_pdispatch *pd); pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd); -int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, const struct ucred*creds, void *userdata); +int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, const pa_creds *creds, void *userdata); void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_cb_t callback, void *userdata, pa_free_cb_t free_cb); @@ -50,6 +51,6 @@ void pa_pdispatch_set_drain_callback(pa_pdispatch *pd, pa_pdispatch_drain_callba /* Remove all reply slots with the give userdata parameter */ void pa_pdispatch_unregister_reply(pa_pdispatch *pd, void *userdata); -const struct ucred * pa_pdispatch_creds(pa_pdispatch *pd); +const pa_creds * pa_pdispatch_creds(pa_pdispatch *pd); #endif diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 14f880d7..2775d774 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -55,6 +55,8 @@ #include #include #include +#include +#include #include "protocol-native.h" @@ -134,7 +136,7 @@ struct pa_protocol_native { pa_idxset *connections; uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; int auth_cookie_in_property; -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS char *auth_group; #endif }; @@ -910,25 +912,32 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t if (!c->authorized) { int success = 0; -#ifdef SCM_CREDENTIALS - const struct ucred *ucred = pa_pdispatch_creds(pd); +#ifdef HAVE_CREDS + const pa_creds *creds; - if (ucred) { - if (ucred->uid == getuid()) + if ((creds = pa_pdispatch_creds(pd))) { + if (creds->uid == getuid()) success = 1; else if (c->protocol->auth_group) { int r; - - if ((r = pa_uid_in_group(ucred->uid, c->protocol->auth_group)) < 0) - pa_log_warn(__FILE__": failed to check group membership."); - else if (r > 0) + gid_t gid; + + if ((gid = pa_get_gid_of_group(c->protocol->auth_group)) == (gid_t) -1) + pa_log_warn(__FILE__": failed to get GID of group '%s'", c->protocol->auth_group); + else if (gid == creds->gid) success = 1; + + if (!success) { + if ((r = pa_uid_in_group(creds->uid, c->protocol->auth_group)) < 0) + pa_log_warn(__FILE__": failed to check group membership."); + else if (r > 0) + success = 1; + } } - pa_log_info(__FILE__": Got credentials: pid=%lu uid=%lu gid=%lu auth=%i", - (unsigned long) ucred->pid, - (unsigned long) ucred->uid, - (unsigned long) ucred->gid, + pa_log_info(__FILE__": Got credentials: uid=%lu gid=%lu success=%i", + (unsigned long) creds->uid, + (unsigned long) creds->gid, success); } #endif @@ -2100,7 +2109,7 @@ static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC /*** pstream callbacks ***/ -static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) { struct connection *c = userdata; assert(p && packet && packet->data && c); @@ -2272,7 +2281,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo pa_idxset_put(p->connections, c, NULL); -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS if (pa_iochannel_creds_supported(io)) pa_iochannel_creds_enable(io); @@ -2323,8 +2332,18 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo p->public = public; p->server = NULL; -#ifdef SCM_CREDENTIALS - p->auth_group = pa_xstrdup(pa_modargs_get_value(ma, "auth-group", NULL)); +#ifdef HAVE_CREDS + { + int a = 1; + if (pa_modargs_get_value_boolean(ma, "auth-group-enabled", &a) < 0) { + pa_log(__FILE__": auth-group-enabled= expects a boolean argument."); + return NULL; + } + p->auth_group = a ? pa_xstrdup(pa_modargs_get_value(ma, "auth-group", c->is_system_instance ? PA_ACCESS_GROUP : NULL)) : NULL; + + if (p->auth_group) + pa_log_info(__FILE__": Allowing access to group '%s'.", p->auth_group); + } #endif if (load_key(p, pa_modargs_get_value(ma, "cookie", NULL)) < 0) { @@ -2386,7 +2405,7 @@ void pa_protocol_native_free(pa_protocol_native *p) { if (p->auth_cookie_in_property) pa_authkey_prop_unref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME); -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS pa_xfree(p->auth_group); #endif pa_xfree(p); diff --git a/src/pulsecore/pstream-util.c b/src/pulsecore/pstream-util.c index 09d6f2fa..d7c1b31b 100644 --- a/src/pulsecore/pstream-util.c +++ b/src/pulsecore/pstream-util.c @@ -29,7 +29,7 @@ #include "pstream-util.h" -void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const struct ucred *creds) { +void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const pa_creds *creds) { size_t length; uint8_t *data; pa_packet *packet; diff --git a/src/pulsecore/pstream-util.h b/src/pulsecore/pstream-util.h index c60000a8..f384d889 100644 --- a/src/pulsecore/pstream-util.h +++ b/src/pulsecore/pstream-util.h @@ -25,11 +25,10 @@ #include #include #include - -struct ucred; +#include /* The tagstruct is freed!*/ -void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const struct ucred *creds); +void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const pa_creds *creds); #define pa_pstream_send_tagstruct(p, t) pa_pstream_send_tagstruct_with_creds((p), (t), 0) diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index 7ef49305..de5fa43e 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "pstream.h" @@ -69,9 +70,9 @@ struct item_info { /* packet info */ pa_packet *packet; -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS int with_creds; - struct ucred creds; + pa_creds creds; #endif }; @@ -114,8 +115,8 @@ struct pa_pstream { pa_memblock_stat *memblock_stat; -#ifdef SCM_CREDENTIALS - struct ucred read_creds, write_creds; +#ifdef HAVE_CREDS + pa_creds read_creds, write_creds; int read_creds_valid, send_creds_now; #endif }; @@ -216,7 +217,7 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_sta pa_iochannel_socket_set_rcvbuf(io, 1024*8); pa_iochannel_socket_set_sndbuf(io, 1024*8); -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS p->send_creds_now = 0; p->read_creds_valid = 0; #endif @@ -258,7 +259,7 @@ static void pstream_free(pa_pstream *p) { pa_xfree(p); } -void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const struct ucred *creds) { +void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *creds) { struct item_info *i; assert(p && packet && p->ref >= 1); @@ -270,7 +271,7 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const struct ucred i = pa_xnew(struct item_info, 1); i->type = PA_PSTREAM_ITEM_PACKET; i->packet = pa_packet_ref(packet); -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS if ((i->with_creds = !!creds)) i->creds = *creds; #endif @@ -294,7 +295,7 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa i->channel = channel; i->offset = offset; i->seek_mode = seek_mode; -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS i->with_creds = 0; #endif @@ -334,7 +335,7 @@ static void prepare_next_write_item(pa_pstream *p) { p->write.descriptor[PA_PSTREAM_DESCRIPTOR_SEEK] = htonl(p->write.current->seek_mode); } -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS if ((p->send_creds_now = p->write.current->with_creds)) p->write_creds = p->write.current->creds; @@ -364,7 +365,7 @@ static int do_write(pa_pstream *p) { l = ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE); } -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS if (p->send_creds_now) { if ((r = pa_iochannel_write_with_creds(p->io, d, l, &p->write_creds)) < 0) @@ -406,7 +407,7 @@ static int do_read(pa_pstream *p) { l = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE); } -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS { int b = 0; @@ -495,7 +496,7 @@ static int do_read(pa_pstream *p) { assert(p->read.packet); if (p->recieve_packet_callback) -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS p->recieve_packet_callback(p, p->read.packet, p->read_creds_valid ? &p->read_creds : NULL, p->recieve_packet_callback_userdata); #else p->recieve_packet_callback(p, p->read.packet, NULL, p->recieve_packet_callback_userdata); @@ -506,7 +507,7 @@ static int do_read(pa_pstream *p) { } p->read.index = 0; -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS p->read_creds_valid = 0; #endif } diff --git a/src/pulsecore/pstream.h b/src/pulsecore/pstream.h index 39cb7591..789e40bc 100644 --- a/src/pulsecore/pstream.h +++ b/src/pulsecore/pstream.h @@ -26,16 +26,16 @@ #include #include + #include #include #include #include - -struct ucred; +#include typedef struct pa_pstream pa_pstream; -typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata); +typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata); typedef void (*pa_pstream_memblock_cb_t)(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata); typedef void (*pa_pstream_notify_cb_t)(pa_pstream *p, void *userdata); @@ -43,7 +43,7 @@ pa_pstream* pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_sta void pa_pstream_unref(pa_pstream*p); pa_pstream* pa_pstream_ref(pa_pstream*p); -void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const struct ucred *creds); +void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *creds); void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk); void pa_pstream_set_recieve_packet_callback(pa_pstream *p, pa_pstream_packet_cb_t cb, void *userdata); diff --git a/src/pulsecore/socket-server.c b/src/pulsecore/socket-server.c index 77ea13e7..25483592 100644 --- a/src/pulsecore/socket-server.c +++ b/src/pulsecore/socket-server.c @@ -30,6 +30,7 @@ #include #include #include +#include #ifdef HAVE_SYS_SOCKET_H #include @@ -185,12 +186,18 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file sa.sun_path[sizeof(sa.sun_path) - 1] = 0; pa_socket_low_delay(fd); - + if (bind(fd, (struct sockaddr*) &sa, SUN_LEN(&sa)) < 0) { pa_log(__FILE__": bind(): %s", pa_cstrerror(errno)); goto fail; } + /* Allow access from all clients. Sockets like this one should + * always be put inside a directory with proper access rights, + * because not all OS check the access rights on the socket + * inodes. */ + chmod(filename, 0777); + if (listen(fd, 5) < 0) { pa_log(__FILE__": listen(): %s", pa_cstrerror(errno)); goto fail; -- cgit