]> code.delx.au - pulseaudio/commitdiff
* add new --system command line parameter to the daemon for running PulseAudio as...
authorLennart Poettering <lennart@poettering.net>
Wed, 19 Jul 2006 17:44:19 +0000 (17:44 +0000)
committerLennart Poettering <lennart@poettering.net>
Wed, 19 Jul 2006 17:44:19 +0000 (17:44 +0000)
* add PA_ prefixes to all global #defines
* modify auth-by-creds: define a new group "pulse-access" which is used for authentication
* add proper privilige dropping when running in --system mode
* create runtime directory once on startup and not by each module seperately

git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1105 fefdeb5f-60dc-0310-8127-8f9354f1896f

28 files changed:
bootstrap.sh
configure.ac
src/Makefile.am
src/daemon/cmdline.c
src/daemon/daemon-conf.c
src/daemon/daemon-conf.h
src/daemon/daemon.conf.in
src/daemon/main.c
src/modules/module-match.c
src/modules/module-protocol-stub.c
src/modules/module-tunnel.c
src/pulse/client-conf.c
src/pulse/client-conf.h
src/pulse/context.c
src/pulsecore/core-util.c
src/pulsecore/core-util.h
src/pulsecore/core.c
src/pulsecore/core.h
src/pulsecore/iochannel.c
src/pulsecore/iochannel.h
src/pulsecore/pdispatch.c
src/pulsecore/pdispatch.h
src/pulsecore/pid.c
src/pulsecore/protocol-native.c
src/pulsecore/pstream-util.c
src/pulsecore/pstream-util.h
src/pulsecore/pstream.c
src/pulsecore/pstream.h

index 1f8b29d0b724e8a06b153ed7e9b623183ddb4f67..b85f025eb39d6c5fc51364efc9233dae2362b38e 100755 (executable)
@@ -57,7 +57,7 @@ else
     run_versioned automake "$VERSION" -a -c --foreign
 
     if test "x$NOCONFIGURE" = "x"; then
-        CFLAGS="-g -O0" ./configure --sysconfdir=/etc --enable-force-preopen "$@" 
+        CFLAGS="-g -O0" ./configure --sysconfdir=/etc --localstatedir=/var --enable-force-preopen "$@" 
         make clean
     fi
 fi
index cf7b5534c62147e66cc86b72bec8f2ca151ba3f2..a7f85ea0e663db2ce43fd53a19169bb28b32d501 100644 (file)
@@ -239,7 +239,11 @@ AC_CHECK_FUNCS([lstat])
 # Non-standard
 
 AC_CHECK_FUNCS(setresuid)
+AC_CHECK_FUNCS(setresgid)
 AC_CHECK_FUNCS(setreuid)
+AC_CHECK_FUNCS(setregid)
+AC_CHECK_FUNCS(seteuid)
+AC_CHECK_FUNCS(setegid)
 
 #### POSIX threads ####
 
@@ -602,6 +606,48 @@ AC_SUBST(LIRC_CFLAGS)
 AC_SUBST(LIRC_LIBS)
 AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1])
 
+#### PulseAudio system group & user  #####
+
+AC_ARG_WITH(system_user, AS_HELP_STRING([--with-system-user=<user>],[User for running the PulseAudio daemon as a system-wide instance (pulse)]))
+if test -z "$with_system_user" ; then
+    PA_SYSTEM_USER=pulse
+else
+    PA_SYSTEM_USER=$with_system_user
+fi
+AC_SUBST(PA_SYSTEM_USER)
+AC_DEFINE_UNQUOTED(PA_SYSTEM_USER,"$PA_SYSTEM_USER", [User for running the PulseAudio system daemon])
+
+AC_ARG_WITH(system_group,AS_HELP_STRING([--with-system-group=<group>],[Group for running the PulseAudio daemon as a system-wide instance (pulse)]))
+if test -z "$with_system_group" ; then
+    PA_SYSTEM_GROUP=pulse
+else
+    PA_SYSTEM_GROUP=$with_system_group
+fi
+AC_SUBST(PA_SYSTEM_GROUP)
+AC_DEFINE_UNQUOTED(PA_SYSTEM_GROUP,"$PA_SYSTEM_GROUP", [Group for the PulseAudio system daemon])
+
+AC_ARG_WITH(realtime_group,AS_HELP_STRING([--with-realtime-group=<group>],[Group for users that are allowed to start the PulseAudio daemon with realtime scheduling (realtime)]))
+if test -z "$with_realtime_group" ; then
+    PA_REALTIME_GROUP=realtime
+else
+    PA_REALTIME_GROUP=$with_realtime_group
+fi
+AC_SUBST(PA_REALTIME_GROUP)
+AC_DEFINE_UNQUOTED(PA_REALTIME_GROUP,"$PA_REALTIME_GROUP", [Realtime group])
+
+AC_ARG_WITH(access_group,AS_HELP_STRING([--with-access-group=<group>],[Group which is allowed access to a system-wide PulseAudio daemon (pulse-access)]))
+if test -z "$with_access_group" ; then
+    PA_ACCESS_GROUP=pulse-access
+else
+    PA_ACCESS_GROUP=$with_access_group
+fi
+AC_SUBST(PA_ACCESS_GROUP)
+AC_DEFINE_UNQUOTED(PA_ACCESS_GROUP,"$PA_ACCESS_GROUP", [Access group])
+
+#### PulseAudio system runtime dir ####
+PA_SYSTEM_RUNTIME_PATH="${localstatedir}/run/pulse"
+AC_SUBST(PA_SYSTEM_RUNTIME_PATH)
+
 ###################################
 #            Output               #
 ###################################
@@ -709,8 +755,9 @@ echo "
     prefix:                 ${prefix}
     sysconfdir:             ${sysconfdir}
     localstatedir:          ${localstatedir}
-    compiler:               ${CC}
-    cflags:                 ${CFLAGS}
+    System Runtime Path:    ${PA_SYSTEM_RUNTIME_PATH}
+    Compiler:               ${CC}
+    CFLAGS:                 ${CFLAGS}
     Have X11:               ${ENABLE_X11}
     Enable OSS:             ${ENABLE_OSS}
     Enable Alsa:            ${ENABLE_ALSA}
@@ -721,4 +768,8 @@ echo "
     Enable Async DNS:       ${ENABLE_LIBASYNCNS}
     Enable LIRC:            ${ENABLE_LIRC}
     Enable TCP Wrappers:    ${ENABLE_TCPWRAP}
+    System User:            ${PA_SYSTEM_USER}
+    System Group:           ${PA_SYSTEM_GROUP}
+    Realtime Group:         ${PA_REALTIME_GROUP}
+    Access Group:           ${PA_ACCESS_GROUP}
 "
index 0235741bb55b21c47f953a410010d9f91f228e37..1a4bcb04dbbe1d85b634c6bd649298f4e19d3cc2 100644 (file)
@@ -30,11 +30,11 @@ pulseconfdir=$(sysconfdir)/pulse
 #            Defines              #
 ###################################
 
-PULSEAUDIO_BINARY=$(bindir)/pulseaudio$(EXEEXT)
+PA_BINARY=$(bindir)/pulseaudio$(EXEEXT)
 if OS_IS_WIN32
-DEFAULT_CONFIG_DIR=%PULSE_ROOT%
+PA_DEFAULT_CONFIG_DIR=%PULSE_ROOT%
 else
-DEFAULT_CONFIG_DIR=$(pulseconfdir)
+PA_DEFAULT_CONFIG_DIR=$(pulseconfdir)
 endif
 
 ###################################
@@ -45,10 +45,10 @@ AM_CFLAGS = -I$(top_srcdir)/src
 AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS
 AM_CFLAGS += $(LTDLINCL)
 AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS)
-AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibexecdir)\"
-#AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\"
-AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\"
-AM_CFLAGS += -DPULSEAUDIO_BINARY=\"$(PULSEAUDIO_BINARY)\"
+AM_CFLAGS += -DPA_DLSEARCHPATH=\"$(modlibexecdir)\"
+AM_CFLAGS += -DPA_DEFAULT_CONFIG_DIR=\"$(PA_DEFAULT_CONFIG_DIR)\"
+AM_CFLAGS += -DPA_BINARY=\"$(PA_BINARY)\"
+AM_CFLAGS += -DPA_SYSTEM_RUNTIME_PATH=\"$(PA_SYSTEM_RUNTIME_PATH)\"
 
 # This cool debug trap works on i386/gcc only
 AM_CFLAGS += '-DDEBUG_TRAP=__asm__("int $$3")'
index a106dc0901217b3b8bfdb9103b2f4c5dbf88b909..ab876edf2aea44c8a6e2ac1c103ffd823b7d6e2b 100644 (file)
@@ -58,7 +58,8 @@ enum {
     ARG_RESAMPLE_METHOD,
     ARG_KILL,
     ARG_USE_PID_FILE,
-    ARG_CHECK
+    ARG_CHECK,
+    ARG_SYSTEM
 };
 
 /* Tabel for getopt_long() */
@@ -84,6 +85,7 @@ static struct option long_options[] = {
     {"kill",                        0, 0, ARG_KILL},
     {"use-pid-file",                2, 0, ARG_USE_PID_FILE},
     {"check",                       0, 0, ARG_CHECK},
+    {"system",                      2, 0, ARG_SYSTEM},
     {NULL, 0, 0, 0}
 };
 
@@ -105,6 +107,7 @@ void pa_cmdline_help(const char *argv0) {
            "      --check                           Check for a running daemon\n\n"
 
            "OPTIONS:\n"
+           "      --system[=BOOL]                   Run as system-wide instance\n"
            "  -D, --daemonize[=BOOL]                Daemonize after startup\n"
            "      --fail[=BOOL]                     Quit when startup fails\n"
            "      --high-priority[=BOOL]            Try to set high process priority\n"
@@ -276,6 +279,13 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
                     goto fail;
                 }
                 break;
+
+            case ARG_SYSTEM:
+                if ((conf->system_instance = optarg ? pa_parse_boolean(optarg) : 1) < 0) {
+                    pa_log(__FILE__": --system expects boolean argument");
+                    goto fail;
+                }
+                break;
                 
             default:
                 goto fail;
index d1afed7b1ad5bb7f043cc4e9dc08ee4a4eddb7c4..a5a62567af83873de965130fae826a7e3969ff55 100644 (file)
 
 #include "daemon-conf.h"
 
-#ifndef DEFAULT_CONFIG_DIR
-# ifndef OS_IS_WIN32
-#  define DEFAULT_CONFIG_DIR "/etc/pulse"
-# else
-#  define DEFAULT_CONFIG_DIR "%PULSE_ROOT%"
-# endif
-#endif
-
 #ifndef OS_IS_WIN32
 # define PATH_SEP "/"
 #else
 # define PATH_SEP "\\"
 #endif
 
-#define DEFAULT_SCRIPT_FILE DEFAULT_CONFIG_DIR PATH_SEP "default.pa"
+#define DEFAULT_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "default.pa"
 #define DEFAULT_SCRIPT_FILE_USER ".pulse" PATH_SEP "default.pa"
-#define DEFAULT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf"
+#define DEFAULT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf"
 #define DEFAULT_CONFIG_FILE_USER ".pulse" PATH_SEP "daemon.conf"
 
 #define ENV_SCRIPT_FILE "PULSE_SCRIPT"
@@ -79,7 +71,8 @@ static const pa_daemon_conf default_conf = {
     .log_level = PA_LOG_NOTICE,
     .resample_method = PA_RESAMPLER_SRC_SINC_FASTEST,
     .config_file = NULL,
-    .use_pid_file = 1
+    .use_pid_file = 1,
+    .system_instance = 0
 };
 
 pa_daemon_conf* pa_daemon_conf_new(void) {
@@ -89,9 +82,7 @@ pa_daemon_conf* pa_daemon_conf_new(void) {
     if ((f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file, "r")))
         fclose(f);
 
-#ifdef DLSEARCHPATH
-    c->dl_search_path = pa_xstrdup(DLSEARCHPATH);
-#endif
+    c->dl_search_path = pa_xstrdup(PA_DLSEARCHPATH);
     return c;
 }
 
@@ -212,6 +203,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
         { "verbose",                 parse_log_level,         NULL },
         { "resample-method",         parse_resample_method,   NULL },
         { "use-pid-file",            pa_config_parse_bool,    NULL },
+        { "system-instance",         pa_config_parse_bool,    NULL },
         { NULL,                      NULL,                    NULL },
     };
     
@@ -229,6 +221,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
     table[11].data = c;
     table[12].data = c;
     table[13].data = &c->use_pid_file;
+    table[14].data = &c->system_instance;
     
     pa_xfree(c->config_file);
     c->config_file = NULL;
@@ -295,6 +288,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
     pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]);
     pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method));
     pa_strbuf_printf(s, "use-pid-file = %i\n", c->use_pid_file);
+    pa_strbuf_printf(s, "system-instance = %i\n", !!c->system_instance);
     
     return pa_strbuf_tostring_free(s);
 }
index c325495c2982739996677daf67bfffd58f6ca0bf..bfea735833bcc1f473eca5d55d0add56515b315f 100644 (file)
@@ -46,7 +46,8 @@ typedef struct pa_daemon_conf {
         module_idle_time,
         scache_idle_time,
         auto_log_target,
-        use_pid_file;
+        use_pid_file,
+        system_instance;
     char *script_commands, *dl_search_path, *default_script_file;
     pa_log_target_t log_target;
     pa_log_level_t log_level;
index 30bf3ca16afdc9f7e5b4c6beb160196e3d45a001..6e55c0ee68616e0e3c12900b2565ea856862f9fa 100644 (file)
@@ -46,6 +46,9 @@
 ## Unload autoloaded modules after being idle for this time 
 ; module-idle-time = 20
 
+## Unload autoloaded sample cache entries after being idle for this time 
+; scache-idle-time = 20
+
 ## The path were to look for dynamic shared objects (DSOs aka
 ## plugins).  You may specify more than one path seperated by
 ## colons. 
@@ -75,3 +78,6 @@
 ## process per user, you better disable this option since it
 ## effectively disables multiple instances.
 ; use-pid-file = 1
+
+## Run the daemon as system-wide instance, requires root priviliges
+; system-instance = 0
index c41c69df627a56671b6623434e3a57ef98daa634..4961f0ca3e5fe8f53c82ef2502f2bda168baaa96 100644 (file)
@@ -37,6 +37,9 @@
 #include <unistd.h>
 #include <locale.h>
 #include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+
 #include <liboil/liboil.h>
 
 #ifdef HAVE_SYS_IOCTL_H
@@ -149,6 +152,104 @@ static void close_pipe(int p[2]) {
     p[0] = p[1] = -1;
 }
 
+#define set_env(key, value) putenv(pa_sprintf_malloc("%s=%s", (key), (value)))
+
+static int change_user(void) {
+    struct passwd *pw;
+    struct group * gr;
+    int r;
+    
+    if (!(pw = getpwnam(PA_SYSTEM_USER))) {
+        pa_log(__FILE__": Failed to find user '%s'.", PA_SYSTEM_USER);
+        return -1;
+    }
+
+    if (!(gr = getgrnam(PA_SYSTEM_GROUP))) {
+        pa_log(__FILE__": Failed to find group '%s'.", PA_SYSTEM_GROUP);
+        return -1;
+    }
+
+    pa_log_info(__FILE__": Found user '%s' (UID %lu) and group '%s' (GID %lu).",
+                PA_SYSTEM_USER, (unsigned long) pw->pw_uid,
+                PA_SYSTEM_GROUP, (unsigned long) gr->gr_gid);
+
+    if (pw->pw_gid != gr->gr_gid) {
+        pa_log(__FILE__": GID of user '%s' and of group '%s' don't match.", PA_SYSTEM_USER, PA_SYSTEM_GROUP);
+        return -1;
+    }
+
+    if (strcmp(pw->pw_dir, PA_SYSTEM_RUNTIME_PATH) != 0)
+        pa_log_warn(__FILE__": Warning: home directory of user '%s' is not '%s', ignoring.", PA_SYSTEM_USER, PA_SYSTEM_RUNTIME_PATH);
+
+    if (pa_make_secure_dir(PA_SYSTEM_RUNTIME_PATH, 0755, pw->pw_uid, gr->gr_gid) < 0) {
+        pa_log(__FILE__": Failed to create '%s': %s", PA_SYSTEM_RUNTIME_PATH, pa_cstrerror(errno));
+        return -1;
+    }
+    
+    if (initgroups(PA_SYSTEM_USER, gr->gr_gid) != 0) {
+        pa_log(__FILE__": Failed to change group list: %s", pa_cstrerror(errno));
+        return -1;
+    }
+
+#if defined(HAVE_SETRESGID)
+    r = setresgid(gr->gr_gid, gr->gr_gid, gr->gr_gid);
+#elif defined(HAVE_SETEGID)
+    if ((r = setgid(gr->gr_gid)) >= 0)
+        r = setegid(gr->gr_gid);
+#elif defined(HAVE_SETREGID)
+    r = setregid(gr->gr_gid, gr->gr_gid);
+#else
+#error "No API to drop priviliges"
+#endif
+
+    if (r < 0) {
+        pa_log(__FILE__": Failed to change GID: %s", pa_cstrerror(errno));
+        return -1;
+    }
+
+#if defined(HAVE_SETRESUID)
+    r = setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid);
+#elif defined(HAVE_SETEUID)
+    if ((r = setuid(pw->pw_uid)) >= 0)
+        r = seteuid(pw->pw_uid);
+#elif defined(HAVE_SETREUID)
+    r = setreuid(pw->pw_uid, pw->pw_uid);
+#else
+#error "No API to drop priviliges"
+#endif
+
+    if (r < 0) {
+        pa_log(__FILE__": Failed to change UID: %s", pa_cstrerror(errno));
+        return -1;
+    }
+
+    set_env("USER", PA_SYSTEM_USER);
+    set_env("LOGNAME", PA_SYSTEM_GROUP);
+    set_env("HOME", PA_SYSTEM_RUNTIME_PATH);
+
+    /* Relevant for pa_runtime_path() */
+    set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH);
+
+    pa_log_info(__FILE__": Successfully dropped root privileges.");
+
+    return 0;
+}
+
+static int create_runtime_dir(void) {
+    char fn[PATH_MAX];
+    
+    pa_runtime_path(NULL, fn, sizeof(fn));
+    
+    if (pa_make_secure_dir(fn, 0700, getuid(), getgid()) < 0) {
+        pa_log(__FILE__": Failed to create '%s': %s", fn, pa_cstrerror(errno));
+        return -1;
+    }
+
+    /* Relevant for pa_runtime_path() later on */
+    set_env("PULSE_RUNTIME_PATH", fn);
+    return 0;
+}
+
 int main(int argc, char *argv[]) {
     pa_core *c;
     pa_strbuf *buf = NULL;
@@ -172,13 +273,14 @@ int main(int argc, char *argv[]) {
 
     setlocale(LC_ALL, "");
 
-    pa_limit_caps();
+    if (getuid() != 0)
+        pa_limit_caps();
 
 #ifdef HAVE_GETUID
     suid_root = getuid() != 0 && geteuid() == 0;
     
-    if (suid_root && (pa_own_uid_in_group("realtime", &gid) <= 0 || gid >= 1000)) {
-        pa_log_warn(__FILE__": WARNING: called SUID root, but not in group 'realtime'.");
+    if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0 || gid >= 1000)) {
+        pa_log_warn(__FILE__": WARNING: called SUID root, but not in group '"PA_REALTIME_GROUP"'.");
         pa_drop_root();
     }
 #else
@@ -220,7 +322,8 @@ int main(int argc, char *argv[]) {
     if (conf->high_priority && conf->cmd == PA_CMD_DAEMON)
         pa_raise_priority();
 
-    pa_drop_caps();
+    if (getuid() != 0)
+        pa_drop_caps();
 
     if (suid_root)
         pa_drop_root();
@@ -278,6 +381,14 @@ int main(int argc, char *argv[]) {
             assert(conf->cmd == PA_CMD_DAEMON);
     }
 
+    if (getuid() == 0 && !conf->system_instance) {
+        pa_log(__FILE__": This program is not intended to be run as root (unless --system is specified).");
+        goto finish;
+    } else if (getuid() != 0 && conf->system_instance) {
+        pa_log(__FILE__": Root priviliges required.");
+        goto finish;
+    }
+
     if (conf->daemonize) {
         pid_t child;
         int tty_fd;
@@ -362,6 +473,13 @@ int main(int argc, char *argv[]) {
     }
 
     chdir("/");
+    umask(0022);
+    
+    if (conf->system_instance) {
+        if (change_user() < 0)
+            goto finish;
+    } else if (create_runtime_dir() < 0)
+        goto finish;
     
     if (conf->use_pid_file) {
         if (pa_pid_file_create() < 0) {
@@ -379,12 +497,13 @@ int main(int argc, char *argv[]) {
 #ifdef SIGPIPE
     signal(SIGPIPE, SIG_IGN);
 #endif
-    
+
     mainloop = pa_mainloop_new();
     assert(mainloop);
 
     c = pa_core_new(pa_mainloop_get_api(mainloop));
     assert(c);
+    c->is_system_instance = !!conf->system_instance;
 
     r = pa_signal_init(pa_mainloop_get_api(mainloop));
     assert(r == 0);
index 28d6a08be78b769c8d9c72d3727b754cbcb86f01..cd58a8388ff714a6d82373742a6d1e7a9143e0e7 100644 (file)
@@ -52,11 +52,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION)
 
 #define WHITESPACE "\n\r \t"
 
-#ifndef DEFAULT_CONFIG_DIR
-#define DEFAULT_CONFIG_DIR "/etc/pulse"
-#endif
-
-#define DEFAULT_MATCH_TABLE_FILE DEFAULT_CONFIG_DIR"/match.table"
+#define DEFAULT_MATCH_TABLE_FILE PA_DEFAULT_CONFIG_DIR"/match.table"
 #define DEFAULT_MATCH_TABLE_FILE_USER ".pulse/match.table"
 
 static const char* const valid_modargs[] = {
index 2072876618782ebdd669de4f942bbae853414032..fa21b737e33490e61ee56c518a355e6d32b55ef2 100644 (file)
     #include "module-simple-protocol-unix-symdef.h"
   #endif
   PA_MODULE_DESCRIPTION("Simple protocol "SOCKET_DESCRIPTION)
-  PA_MODULE_USAGE("rate=<sample rate> format=<sample format> channels=<number of channels> sink=<sink to connect to> source=<source to connect to> playback=<enable playback?> record=<enable record?> "SOCKET_USAGE)
+  PA_MODULE_USAGE("rate=<sample rate> "
+                  "format=<sample format> "
+                  "channels=<number of channels> "
+                  "sink=<sink to connect to> "
+                  "source=<source to connect to> "
+                  "playback=<enable playback?> "
+                  "record=<enable record?> "
+                  SOCKET_USAGE)
 #elif defined(USE_PROTOCOL_CLI)
   #include <pulsecore/protocol-cli.h> 
   #define protocol_new pa_protocol_cli_new
   #endif
   
   PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION)
-  PA_MODULE_USAGE("auth-anonymous=<don't check for cookies?> cookie=<path to cookie file> "AUTH_USAGE SOCKET_USAGE)
+  PA_MODULE_USAGE("auth-anonymous=<don't check for cookies?> "
+                  "cookie=<path to cookie file> "
+                  AUTH_USAGE
+                  SOCKET_USAGE)
 #elif defined(USE_PROTOCOL_ESOUND)
   #include <pulsecore/protocol-esound.h>
   #include <pulsecore/esound.h>
     #include "module-esound-protocol-unix-symdef.h"
   #endif
   PA_MODULE_DESCRIPTION("ESOUND protocol "SOCKET_DESCRIPTION)
-  PA_MODULE_USAGE("sink=<sink to connect to> source=<source to connect to> auth-anonymous=<don't check for cookies?> cookie=<path to cookie file> "SOCKET_USAGE)
+  PA_MODULE_USAGE("sink=<sink to connect to> "
+                  "source=<source to connect to> "
+                  "auth-anonymous=<don't verify cookies?> "
+                  "cookie=<path to cookie file> "
+                  SOCKET_USAGE)
 #else
   #error "Broken build system" 
 #endif
@@ -189,7 +203,6 @@ int pa__init(pa_core *c, pa_module*m) {
 #else
     pa_socket_server *s;
     int r;
-    const char *v;
     char tmp[PATH_MAX];
 #endif
 
@@ -241,15 +254,21 @@ int pa__init(pa_core *c, pa_module*m) {
         goto fail;
 
 #else
-    v = pa_modargs_get_value(ma, "socket", UNIX_SOCKET);
-    pa_runtime_path(v, tmp, sizeof(tmp));
+
+    pa_runtime_path(pa_modargs_get_value(ma, "socket", UNIX_SOCKET), tmp, sizeof(tmp));
     u->socket_path = pa_xstrdup(tmp);
 
-    if (pa_make_secure_parent_dir(tmp) < 0) {
-        pa_log(__FILE__": Failed to create secure socket directory.");
+#if defined(USE_PROTOCOL_ESOUND)
+
+    /* This socket doesn't reside in our own runtime dir but in
+     * /tmp/.esd/, hence we have to create the dir first */
+    
+    if (pa_make_secure_parent_dir(u->socket_path, c->is_system_instance ? 0755 : 0700, getuid(), getgid()) < 0) {
+        pa_log(__FILE__": Failed to create socket directory: %s\n", pa_cstrerror(errno));
         goto fail;
     }
-
+#endif
+    
     if ((r = pa_unix_socket_remove_stale(tmp)) < 0) {
         pa_log(__FILE__": Failed to remove stale UNIX socket '%s': %s", tmp, pa_cstrerror(errno));
         goto fail;
@@ -324,19 +343,17 @@ void pa__done(pa_core *c, pa_module*m) {
     if (u->protocol_unix)
         protocol_free(u->protocol_unix);
 
+#if defined(USE_PROTOCOL_ESOUND)
     if (u->socket_path) {
-        char *p;
-        
-        if ((p = pa_parent_dir(u->socket_path))) {
-            if (rmdir(p) < 0 && errno != ENOENT && errno != ENOTEMPTY)
-                pa_log(__FILE__": Failed to remove %s: %s.", u->socket_path, pa_cstrerror(errno));
-
-            pa_xfree(p);
-        }
-
-        pa_xfree(u->socket_path);
+        char *p = pa_parent_dir(u->socket_path);
+        rmdir(p);
+        pa_xfree(p);
     }
 #endif
+    
+    
+    pa_xfree(u->socket_path);
+#endif
 
     pa_xfree(u);
 }
index bf2627a7ea6d04617368e6f2c6902b992f9fb520..c018c5205f34b2261ae86bbc79af2e0b30dd3325 100644 (file)
@@ -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 void*creds, void *userdata) {
+static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata) {
     struct userdata *u = userdata;
     assert(p && packet && u);
 
index 5cebcf460506651cb914f1dafbf111c59ea11132..28b4f2d19b306668692c29f2bd25b920f398eff6 100644 (file)
 
 #include "client-conf.h"
 
-#ifndef DEFAULT_CONFIG_DIR
-# ifndef OS_IS_WIN32
-#  define DEFAULT_CONFIG_DIR "/etc/pulse"
-# else
-#  define DEFAULT_CONFIG_DIR "%PULSE_ROOT%"
-# endif
-#endif
-
 #ifndef OS_IS_WIN32
 # define PATH_SEP "/"
 #else
 # define PATH_SEP "\\"
 #endif
 
-#define DEFAULT_CLIENT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "client.conf"
+#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 ENV_CLIENT_CONFIG_FILE "PULSE_CLIENTCONFIG"
@@ -71,15 +63,17 @@ static const pa_client_conf default_conf = {
     .default_server = NULL,
     .autospawn = 0,
     .cookie_file = NULL,
-    .cookie_valid = 0
+    .cookie_valid = 0,
+    .access_group = NULL
 };
 
 pa_client_conf *pa_client_conf_new(void) {
     pa_client_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf));
     
-    c->daemon_binary = pa_xstrdup(PULSEAUDIO_BINARY);
+    c->daemon_binary = pa_xstrdup(PA_BINARY);
     c->extra_arguments = pa_xstrdup("--log-target=syslog --exit-idle-time=5");
     c->cookie_file = pa_xstrdup(PA_NATIVE_COOKIE_FILE);
+    c->access_group = pa_xstrdup(PA_ACCESS_GROUP);
     
     return c;
 }
@@ -92,6 +86,7 @@ void pa_client_conf_free(pa_client_conf *c) {
     pa_xfree(c->default_source);
     pa_xfree(c->default_server);
     pa_xfree(c->cookie_file);
+    pa_xfree(c->access_group);
     pa_xfree(c);
 }
 int pa_client_conf_load(pa_client_conf *c, const char *filename) {
@@ -108,6 +103,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) {
         { "default-server",         pa_config_parse_string,  NULL },
         { "autospawn",              pa_config_parse_bool,    NULL },
         { "cookie-file",            pa_config_parse_string,  NULL },
+        { "access-group",           pa_config_parse_string,  NULL },
         { NULL,                     NULL,                    NULL },
     };
 
@@ -118,6 +114,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) {
     table[4].data = &c->default_server;
     table[5].data = &c->autospawn;
     table[6].data = &c->cookie_file;
+    table[7].data = &c->access_group;
 
     f = filename ?
         fopen((fn = pa_xstrdup(filename)), "r") :
index a532f0dfec5e1c98236999a43935d284f33a5ef9..dfb1148dc380ef417026168e17de990997dff5cc 100644 (file)
@@ -27,7 +27,7 @@
 /* A structure containing configuration data for PulseAudio clients. */
 
 typedef struct pa_client_conf {
-    char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *cookie_file;
+    char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *cookie_file, *access_group;
     int autospawn;
     uint8_t cookie[PA_NATIVE_COOKIE_LENGTH];
     int cookie_valid; /* non-zero, when cookie is valid */
index 228053bcfc8c9b0abf80d18c70ed89c22ce9914e..a25e2f78e123ab6528cccfe0d2542c2e10f8c15b 100644 (file)
@@ -33,6 +33,8 @@
 #include <errno.h>
 #include <signal.h>
 #include <limits.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 
 #ifdef HAVE_SYS_WAIT_H
 #include <sys/wait.h>
@@ -270,7 +272,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 void *creds, void *userdata) {
+static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata) {
     pa_context *c = userdata;
     
     assert(p);
@@ -420,7 +422,23 @@ static void setup_context(pa_context *c, pa_iochannel *io) {
     t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag);
     pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION);
     pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie));
-    pa_pstream_send_tagstruct_with_creds(c->pstream, t, 1);
+
+#ifdef SCM_CREDENTIALS
+{
+    struct ucred ucred;
+
+    ucred.pid = getpid();
+    ucred.uid = getuid();
+                   
+    if ((ucred.gid = pa_get_gid_of_group(PA_ACCESS_GROUP)) == (gid_t) -1)
+        ucred.gid = getgid();
+    
+    pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred);
+}
+#else
+    pa_pstream_send_tagstruct_with_creds(c->pstream, t, NULL);
+#endif
+    
     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL);
 
     pa_context_set_state(c, PA_CONTEXT_AUTHORIZING);
@@ -680,7 +698,7 @@ int pa_context_connect(
             char lf[PATH_MAX];
 
             pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf));
-            pa_make_secure_parent_dir(lf);
+            pa_make_secure_parent_dir(lf, 0700, getuid(), getgid());
             assert(c->autospawn_lock_fd <= 0);
             c->autospawn_lock_fd = pa_lock_lockfile(lf);
 
index 7cb85209cb2a9c0f525883a4d935996248911a62..6375e5ef53c4afed01702dccdcfbc560776e9691 100644 (file)
 #endif
 
 #ifndef OS_IS_WIN32
-#define PA_RUNTIME_PATH_PREFIX "/tmp/pulse-"
+#define PA_USER_RUNTIME_PATH_PREFIX "/tmp/pulse-"
 #define PATH_SEP '/'
 #else
-#define PA_RUNTIME_PATH_PREFIX "%TEMP%\\pulse-"
+#define PA_USER_RUNTIME_PATH_PREFIX "%TEMP%\\pulse-"
 #define PATH_SEP '\\'
 #endif
 
@@ -136,23 +136,32 @@ void pa_make_nonblock_fd(int fd) {
 }
 
 /** Creates a directory securely */
-int pa_make_secure_dir(const char* dir) {
+int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
     struct stat st;
+    int r;
+    
     assert(dir);
 
 #ifdef OS_IS_WIN32
-    if (mkdir(dir) < 0)
+    r = mkdir(dir);
 #else
-    if (mkdir(dir, 0700) < 0)
+    {
+    mode_t u;
+    u = umask(~m);
+    r = mkdir(dir, m);
+    umask(u);
+    }
 #endif
-        if (errno != EEXIST)
-            return -1;
+    
+    if (r < 0 && errno != EEXIST)
+        return -1;
 
 #ifdef HAVE_CHOWN
-    chown(dir, getuid(), getgid());
+    chown(dir, uid, gid);
 #endif
+    
 #ifdef HAVE_CHMOD
-    chmod(dir, 0700);
+    chmod(dir, m);
 #endif
     
 #ifdef HAVE_LSTAT
@@ -163,8 +172,13 @@ int pa_make_secure_dir(const char* dir) {
         goto fail;
     
 #ifndef OS_IS_WIN32
-    if (!S_ISDIR(st.st_mode) || (st.st_uid != getuid()) || ((st.st_mode & 0777) != 0700))
+    if (!S_ISDIR(st.st_mode) ||
+        (st.st_uid != uid) ||
+        (st.st_gid != gid) ||
+        ((st.st_mode & 0777) != m)) {
+        errno = EACCES;
         goto fail;
+    }
 #else
     fprintf(stderr, "FIXME: pa_make_secure_dir()\n");
 #endif
@@ -180,23 +194,24 @@ fail:
 char *pa_parent_dir(const char *fn) {
     char *slash, *dir = pa_xstrdup(fn);
 
-    slash = (char*) pa_path_get_filename(dir);
-    if (slash == fn)
+    if ((slash = (char*) pa_path_get_filename(dir)) == dir) {
+        pa_xfree(dir);
         return NULL;
+    }
 
     *(slash-1) = 0;
     return dir;
 }
 
 /* Creates a the parent directory of the specified path securely */
-int pa_make_secure_parent_dir(const char *fn) {
+int pa_make_secure_parent_dir(const char *fn, mode_t m, uid_t uid, gid_t gid) {
     int ret = -1;
     char *dir;
 
     if (!(dir = pa_parent_dir(fn)))
         goto finish;
     
-    if (pa_make_secure_dir(dir) < 0)
+    if (pa_make_secure_dir(dir, m, uid, gid) < 0)
         goto finish;
 
     ret = 0;
@@ -669,6 +684,7 @@ finish:
     return r;
 }
 
+/* Check whether the specifc user id is a member of the specified group */
 int pa_uid_in_group(uid_t uid, const char *name) {
     char *g_buf, *p_buf;
     long g_n, p_n;
@@ -705,6 +721,26 @@ finish:
     return r;
 }
 
+/* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
+gid_t pa_get_gid_of_group(const char *name) {
+    gid_t ret = (gid_t) -1;
+    char *g_buf;
+    long g_n;
+    struct group grbuf, *gr;
+
+    g_n = sysconf(_SC_GETGR_R_SIZE_MAX);
+    g_buf = pa_xmalloc(g_n);
+
+    if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr)
+        goto finish;
+
+    ret = gr->gr_gid;
+
+finish:
+    pa_xfree(g_buf);
+    return ret;
+}
+
 #else /* HAVE_GRP_H */
 
 int pa_own_uid_in_group(const char *name, gid_t *gid) {
@@ -1003,7 +1039,7 @@ int pa_endswith(const char *s, const char *sfx) {
  * if fn is non-null and starts with / return fn in s
  * otherwise append fn to the run time path and return it in s */
 char *pa_runtime_path(const char *fn, char *s, size_t l) {
-    char u[256];
+    const char *e;
 
 #ifndef OS_IS_WIN32
     if (fn && *fn == '/')
@@ -1012,10 +1048,22 @@ char *pa_runtime_path(const char *fn, char *s, size_t l) {
 #endif
         return pa_strlcpy(s, fn, l);
 
-    if (fn)    
-        snprintf(s, l, "%s%s%c%s", PA_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)), PATH_SEP, fn);
-    else
-        snprintf(s, l, "%s%s", PA_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)));
+    if ((e = getenv("PULSE_RUNTIME_PATH"))) {
+
+        if (fn)    
+            snprintf(s, l, "%s%c%s", e, PATH_SEP, fn);
+        else
+            snprintf(s, l, "%s", e);
+        
+    } else {
+        char u[256];
+        
+        if (fn)    
+            snprintf(s, l, "%s%s%c%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)), PATH_SEP, fn);
+        else
+            snprintf(s, l, "%s%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)));
+    }
+    
 
 #ifdef OS_IS_WIN32
     {
index 864a96ecc2f6455e75f833334bfaf205ef102468..db764de100549364e2068f58767c23eb53c763c9 100644 (file)
@@ -33,8 +33,8 @@ struct timeval;
 
 void pa_make_nonblock_fd(int fd);
 
-int pa_make_secure_dir(const char* dir);
-int pa_make_secure_parent_dir(const char *fn);
+int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid);
+int pa_make_secure_parent_dir(const char *fn, mode_t, uid_t uid, gid_t gid);
 
 ssize_t pa_read(int fd, void *buf, size_t count, int *type);
 ssize_t pa_write(int fd, const void *buf, size_t count, int *type);
@@ -66,6 +66,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_lock_fd(int fd, int b);
 
index 7c780ea8e7a82ea2618787f0c8a0ffa4acbed6ea..d6af3ca9135f654f266d2c94383379cb2713804e 100644 (file)
@@ -46,7 +46,8 @@
 
 pa_core* pa_core_new(pa_mainloop_api *m) {
     pa_core* c;
-    c = pa_xmalloc(sizeof(pa_core));
+    
+    c = pa_xnew(pa_core, 1);
 
     c->mainloop = m;
     c->clients = pa_idxset_new(NULL, NULL);
@@ -88,6 +89,8 @@ pa_core* pa_core_new(pa_mainloop_api *m) {
 
     c->resample_method = PA_RESAMPLER_SRC_SINC_FASTEST;
 
+    c->is_system_instance = 0;
+
     pa_property_init(c);
 
     pa_random(&c->cookie, sizeof(c->cookie));
index 261c5f7521940f286644e4d85a0be67d9b20c7a4..61f17432186120b5fb0cae87b782b962e875d0ca 100644 (file)
@@ -71,6 +71,8 @@ struct pa_core {
     pa_time_event *scache_auto_unload_event;
 
     pa_resample_method_t resample_method;
+
+    int is_system_instance;
 };
 
 pa_core* pa_core_new(pa_mainloop_api *m);
index 15aa8e35c79051374da3239e4ccc33a495ec2d4d..852e960ea7ecf152e39e73c8e477ac6eb493f45f 100644 (file)
@@ -263,12 +263,12 @@ 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) {
+ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const struct ucred *ucred) {
     ssize_t r;
     struct msghdr mh;
     struct iovec iov;
     uint8_t cmsg_data[CMSG_SPACE(sizeof(struct ucred))];
-    struct ucred *ucred;
+    struct ucred *u;
     struct cmsghdr *cmsg;
     
     assert(io);
@@ -286,10 +286,15 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l
     cmsg->cmsg_level = SOL_SOCKET;
     cmsg->cmsg_type = SCM_CREDENTIALS;
 
-    ucred = (struct ucred*) CMSG_DATA(cmsg);
-    ucred->pid = getpid();
-    ucred->uid = getuid();
-    ucred->gid = getgid();
+    u = (struct ucred*) CMSG_DATA(cmsg);
+
+    if (ucred)
+        *u = *ucred;
+    else {
+        u->pid = getpid();
+        u->uid = getuid();
+        u->gid = getgid();
+    }
     
     memset(&mh, 0, sizeof(mh));
     mh.msg_name = NULL;
index 64cf331ec266227d8b56c551c639c0d3019ba72c..3b5cba1c2ed6a9cc8aaca9fc32f647874b2000d9 100644 (file)
@@ -54,7 +54,7 @@ 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);
+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);
 
 int pa_iochannel_is_readable(pa_iochannel*io);
index 5b76b432cc46627cb75361688dd5007ecd9dbb70..9bc20da47461f121f573777f8cd8931329097b0d 100644 (file)
@@ -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 void *creds, void *userdata) {
+int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const struct ucred *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 void * pa_pdispatch_creds(pa_pdispatch *pd) {
+const struct ucred * pa_pdispatch_creds(pa_pdispatch *pd) {
     assert(pd);
     assert(pd->ref >= 1);
     
index 07620e5ae550cba7c903ac7dda760bca988d8e89..18073502f3f2428affa889127a072126d4b6afb8 100644 (file)
@@ -28,6 +28,8 @@
 #include <pulsecore/tagstruct.h>
 #include <pulsecore/packet.h>
 
+struct ucred;
+
 typedef struct pa_pdispatch pa_pdispatch;
 
 typedef void (*pa_pdispatch_cb_t)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
@@ -37,7 +39,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 void*creds, void *userdata);
+int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, const struct ucred*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);
 
@@ -48,6 +50,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 void * pa_pdispatch_creds(pa_pdispatch *pd);
+const struct ucred * pa_pdispatch_creds(pa_pdispatch *pd);
 
 #endif
index 0ad76a6e250fbe2834d8c4e1923448a92ca27cd2..044d223d2cff8d845f81dbb7c802c0dc836d1231 100644 (file)
@@ -79,13 +79,10 @@ static pid_t read_pid(const char *fn, int fd) {
 
 static int open_pid_file(const char *fn, int mode) {
     int fd = -1;
-    int lock = -1;
     
     for (;;) {
         struct stat st;
         
-        pa_make_secure_parent_dir(fn);
-        
         if ((fd = open(fn, mode, S_IRUSR|S_IWUSR)) < 0) {
             if (mode != O_RDONLY || errno != ENOENT)
                 pa_log_warn(__FILE__": WARNING: failed to open PID file '%s': %s",
@@ -123,10 +120,8 @@ static int open_pid_file(const char *fn, int mode) {
 
 fail:
 
-    if (fd < 0) {
-        if (lock >= 0)
-            pa_lock_fd(fd, 0);
-        
+    if (fd >= 0) {
+        pa_lock_fd(fd, 0);
         close(fd);
     }
 
@@ -199,7 +194,6 @@ int pa_pid_file_remove(void) {
     char fn[PATH_MAX];
     int ret = -1;
     pid_t pid;
-    char *p;
 
     pa_runtime_path("pid", fn, sizeof(fn));
 
@@ -235,11 +229,6 @@ int pa_pid_file_remove(void) {
         goto fail;
     }
 
-    if ((p = pa_parent_dir(fn))) {
-        rmdir(p);
-        pa_xfree(p);
-    }
-    
     ret = 0;
     
 fail:
index 784610bd8cb699b8e746b0bfe783533c4990b531..14f880d7f302d1999373d2eaf82b8132737e8cda 100644 (file)
@@ -2100,7 +2100,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 void *creds, void *userdata) {
+static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata) {
     struct connection *c = userdata;
     assert(p && packet && packet->data && c);
 
index 3a995324d035a01bfad3af7d69e4a5d486d6c4d5..09d6f2fa88a49531601dab1225aa406ae4e35ed4 100644 (file)
@@ -29,7 +29,7 @@
 
 #include "pstream-util.h"
 
-void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, int creds) {
+void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const struct ucred *creds) {
     size_t length;
     uint8_t *data;
     pa_packet *packet;
index fc6d18c052c0eeb951a1af71d2c219fbc7b9e33b..c60000a8bdd430741b7d7682811764c06c9bce74 100644 (file)
 #include <pulsecore/pstream.h>
 #include <pulsecore/tagstruct.h>
 
+struct ucred;
+
 /* The tagstruct is freed!*/
-void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, int creds);
+void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const struct ucred *creds);
 
 #define pa_pstream_send_tagstruct(p, t) pa_pstream_send_tagstruct_with_creds((p), (t), 0)
 
index 7992ccb660dcd9b6b0605dd352777e0a735e880e..7ef493051081333d871dde1d57ca44ef31b4922a 100644 (file)
@@ -27,6 +27,8 @@
 #include <stdlib.h>
 #include <assert.h>
 #include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
@@ -69,6 +71,7 @@ struct item_info {
     pa_packet *packet;
 #ifdef SCM_CREDENTIALS
     int with_creds;
+    struct ucred creds;
 #endif
 };
 
@@ -112,9 +115,8 @@ struct pa_pstream {
     pa_memblock_stat *memblock_stat;
 
 #ifdef SCM_CREDENTIALS
-    int send_creds_now;
-    struct ucred ucred;
-    int creds_valid;
+    struct ucred read_creds, write_creds;
+    int read_creds_valid, send_creds_now;
 #endif
 };
 
@@ -216,7 +218,7 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_sta
 
 #ifdef SCM_CREDENTIALS
     p->send_creds_now = 0;
-    p->creds_valid = 0;
+    p->read_creds_valid = 0;
 #endif
     return p;
 }
@@ -256,7 +258,7 @@ static void pstream_free(pa_pstream *p) {
     pa_xfree(p);
 }
 
-void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, int with_creds) {
+void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const struct ucred *creds) {
     struct item_info *i;
     assert(p && packet && p->ref >= 1);
 
@@ -269,7 +271,8 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, int with_creds) {
     i->type = PA_PSTREAM_ITEM_PACKET;
     i->packet = pa_packet_ref(packet);
 #ifdef SCM_CREDENTIALS
-    i->with_creds = with_creds;
+    if ((i->with_creds = !!creds))
+        i->creds = *creds;
 #endif
 
     pa_queue_push(p->send_queue, i);
@@ -332,7 +335,9 @@ static void prepare_next_write_item(pa_pstream *p) {
     }
 
 #ifdef SCM_CREDENTIALS
-    p->send_creds_now = p->write.current->with_creds;
+    if ((p->send_creds_now = p->write.current->with_creds))
+        p->write_creds = p->write.current->creds;
+    
 #endif
 
 }
@@ -362,7 +367,7 @@ static int do_write(pa_pstream *p) {
 #ifdef SCM_CREDENTIALS
     if (p->send_creds_now) {
 
-        if ((r = pa_iochannel_write_with_creds(p->io, d, l)) < 0)
+        if ((r = pa_iochannel_write_with_creds(p->io, d, l, &p->write_creds)) < 0)
             return -1;
 
         p->send_creds_now = 0;
@@ -403,12 +408,12 @@ static int do_read(pa_pstream *p) {
 
 #ifdef SCM_CREDENTIALS
     {
-        int b;
+        int b = 0;
         
-        if ((r = pa_iochannel_read_with_creds(p->io, d, l, &p->ucred, &b)) <= 0)
+        if ((r = pa_iochannel_read_with_creds(p->io, d, l, &p->read_creds, &b)) <= 0)
             return -1;
 
-        p->creds_valid = p->creds_valid || b;
+        p->read_creds_valid = p->read_creds_valid || b;
     }
 #else
     if ((r = pa_iochannel_read(p->io, d, l)) <= 0)
@@ -491,7 +496,7 @@ static int do_read(pa_pstream *p) {
                 
                 if (p->recieve_packet_callback)
 #ifdef SCM_CREDENTIALS                    
-                    p->recieve_packet_callback(p, p->read.packet, p->creds_valid ? &p->ucred : NULL, p->recieve_packet_callback_userdata);
+                    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);
 #endif
@@ -502,7 +507,7 @@ static int do_read(pa_pstream *p) {
 
             p->read.index = 0;
 #ifdef SCM_CREDENTIALS
-            p->creds_valid = 0;
+            p->read_creds_valid = 0;
 #endif
         }
     }
index 1a2932d4f2aeb000e0788eb66e7f820759d0bbf5..39cb75919d6579d95da78a32ba75128ae4c17c28 100644 (file)
 #include <pulsecore/iochannel.h>
 #include <pulsecore/memchunk.h>
 
+struct ucred;
+
 typedef struct pa_pstream pa_pstream;
 
-typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const void *creds, void *userdata);
+typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const struct ucred *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);
 
@@ -41,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, int with_creds);
+void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const struct ucred *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);