From ea28c5586af179bdc968a420a3d5e7ba42d00029 Mon Sep 17 00:00:00 2001
From: Wim Taymans <wtaymans@redhat.com>
Date: Fri, 15 Jul 2016 12:34:31 +0200
Subject: [PATCH 04/18] creds: add pid to pa_creds and use store it in
pa_client
Add the pid to the credentials ancillary data and store it in the
pa_client object when valid.
Add a new hook to be notified when a pa_client it authenticated
---
src/modules/module-tunnel.c | 1 +
src/pulse/context.c | 1 +
src/pulsecore/client.h | 4 ++++
src/pulsecore/core.h | 1 +
src/pulsecore/creds.h | 1 +
src/pulsecore/iochannel.c | 4 +++-
src/pulsecore/protocol-native.c | 25 +++++++++++++++----------
7 files changed, 26 insertions(+), 11 deletions(-)
diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index e08816b..d7114ee 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -1857,6 +1857,7 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata
ucred.uid = getuid();
ucred.gid = getgid();
+ ucred.pid = getpid();
pa_pstream_send_tagstruct_with_creds(u->pstream, t, &ucred);
}
diff --git a/src/pulse/context.c b/src/pulse/context.c
index c39cbe7..445973e 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -642,6 +642,7 @@ static void setup_context(pa_context *c, pa_iochannel *io) {
ucred.uid = getuid();
ucred.gid = getgid();
+ ucred.pid = getpid();
pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred);
}
diff --git a/src/pulsecore/client.h b/src/pulsecore/client.h
index eb8173d..e34fb1e 100644
--- a/src/pulsecore/client.h
+++ b/src/pulsecore/client.h
@@ -26,6 +26,7 @@
#include <pulse/proplist.h>
#include <pulsecore/core.h>
#include <pulsecore/module.h>
+#include <pulsecore/creds.h>
/* Every connection to the server should have a pa_client
* attached. That way the user may generate a listing of all connected
@@ -39,6 +40,9 @@ struct pa_client {
pa_module *module;
char *driver;
+ pa_creds creds;
+ bool creds_valid;
+
pa_idxset *sink_inputs;
pa_idxset *source_outputs;
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index 802111b..8418289 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -114,6 +114,7 @@ typedef enum pa_core_hook {
PA_CORE_HOOK_SOURCE_OUTPUT_SEND_EVENT,
PA_CORE_HOOK_CLIENT_NEW,
PA_CORE_HOOK_CLIENT_PUT,
+ PA_CORE_HOOK_CLIENT_AUTH,
PA_CORE_HOOK_CLIENT_UNLINK,
PA_CORE_HOOK_CLIENT_PROPLIST_CHANGED,
PA_CORE_HOOK_CLIENT_SEND_EVENT,
diff --git a/src/pulsecore/creds.h b/src/pulsecore/creds.h
index 9fdbb4f..f489b0d 100644
--- a/src/pulsecore/creds.h
+++ b/src/pulsecore/creds.h
@@ -41,6 +41,7 @@ typedef struct pa_cmsg_ancil_data pa_cmsg_ancil_data;
struct pa_creds {
gid_t gid;
uid_t uid;
+ uid_t pid;
};
/* Struct for handling ancillary data, i e, extra data that can be sent together with a message
diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c
index 8ace297..32fe0f2 100644
--- a/src/pulsecore/iochannel.c
+++ b/src/pulsecore/iochannel.c
@@ -323,13 +323,14 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l
u = (struct ucred*) CMSG_DATA(&cmsg.hdr);
- u->pid = getpid();
if (ucred) {
u->uid = ucred->uid;
u->gid = ucred->gid;
+ u->pid = ucred->pid;
} else {
u->uid = getuid();
u->gid = getgid();
+ u->pid = getpid();
}
pa_zero(mh);
@@ -439,6 +440,7 @@ ssize_t pa_iochannel_read_with_ancil_data(pa_iochannel*io, void*data, size_t l,
ancil_data->creds.gid = u.gid;
ancil_data->creds.uid = u.uid;
+ ancil_data->creds.pid = u.pid;
ancil_data->creds_valid = true;
}
else if (cmh->cmsg_type == SCM_RIGHTS) {
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 13f4f62..8f07b2d 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -2541,6 +2541,7 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
pa_tagstruct *reply;
pa_mem_type_t shm_type;
bool shm_on_remote = false, do_shm;
+ const pa_creds *creds = NULL;
pa_native_connection_assert_ref(c);
pa_assert(t);
@@ -2578,13 +2579,19 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
pa_proplist_setf(c->client->proplist, "native-protocol.version", "%u", c->version);
+#ifdef HAVE_CREDS
+ creds = pa_pdispatch_creds(pd);
+#endif
+
+ if (creds) {
+ c->client->creds = *creds;
+ c->client->creds_valid = true;
+ }
+
if (!c->authorized) {
bool success = false;
-#ifdef HAVE_CREDS
- const pa_creds *creds;
-
- if ((creds = pa_pdispatch_creds(pd))) {
+ if (creds) {
if (creds->uid == getuid())
success = true;
else if (c->options->auth_group) {
@@ -2609,7 +2616,6 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
(unsigned long) creds->gid,
(int) success);
}
-#endif
if (!success && c->options->auth_cookie) {
const uint8_t *ac;
@@ -2643,17 +2649,13 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
if (c->version < 10 || (c->version >= 13 && !shm_on_remote))
do_shm = false;
-#ifdef HAVE_CREDS
if (do_shm) {
/* Only enable SHM if both sides are owned by the same
* user. This is a security measure because otherwise data
* private to the user might leak. */
-
- const pa_creds *creds;
- if (!(creds = pa_pdispatch_creds(pd)) || getuid() != creds->uid)
+ if (!creds || getuid() != creds->uid)
do_shm = false;
}
-#endif
pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm));
pa_pstream_enable_shm(c->pstream, do_shm);
@@ -2691,6 +2693,7 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
ucred.uid = getuid();
ucred.gid = getgid();
+ ucred.pid = getpid();
pa_pstream_send_tagstruct_with_creds(c->pstream, reply, &ucred);
}
@@ -2711,6 +2714,8 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
}
setup_srbchannel(c, shm_type);
+
+ pa_hook_fire(&c->protocol->core->hooks[PA_CORE_HOOK_CLIENT_AUTH], c->client);
}
static void command_register_memfd_shmid(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
--
2.9.3