diff options
| -rwxr-xr-x | bootstrap.sh | 2 | ||||
| -rw-r--r-- | configure.ac | 55 | ||||
| -rw-r--r-- | src/Makefile.am | 14 | ||||
| -rw-r--r-- | src/daemon/cmdline.c | 12 | ||||
| -rw-r--r-- | src/daemon/daemon-conf.c | 22 | ||||
| -rw-r--r-- | src/daemon/daemon-conf.h | 3 | ||||
| -rw-r--r-- | src/daemon/daemon.conf.in | 6 | ||||
| -rw-r--r-- | src/daemon/main.c | 129 | ||||
| -rw-r--r-- | src/modules/module-match.c | 6 | ||||
| -rw-r--r-- | src/modules/module-protocol-stub.c | 55 | ||||
| -rw-r--r-- | src/modules/module-tunnel.c | 2 | ||||
| -rw-r--r-- | src/pulse/client-conf.c | 19 | ||||
| -rw-r--r-- | src/pulse/client-conf.h | 2 | ||||
| -rw-r--r-- | src/pulse/context.c | 24 | ||||
| -rw-r--r-- | src/pulsecore/core-util.c | 86 | ||||
| -rw-r--r-- | src/pulsecore/core-util.h | 5 | ||||
| -rw-r--r-- | src/pulsecore/core.c | 5 | ||||
| -rw-r--r-- | src/pulsecore/core.h | 2 | ||||
| -rw-r--r-- | src/pulsecore/iochannel.c | 17 | ||||
| -rw-r--r-- | src/pulsecore/iochannel.h | 2 | ||||
| -rw-r--r-- | src/pulsecore/pdispatch.c | 4 | ||||
| -rw-r--r-- | src/pulsecore/pdispatch.h | 6 | ||||
| -rw-r--r-- | src/pulsecore/pid.c | 15 | ||||
| -rw-r--r-- | src/pulsecore/protocol-native.c | 2 | ||||
| -rw-r--r-- | src/pulsecore/pstream-util.c | 2 | ||||
| -rw-r--r-- | src/pulsecore/pstream-util.h | 4 | ||||
| -rw-r--r-- | src/pulsecore/pstream.c | 31 | ||||
| -rw-r--r-- | src/pulsecore/pstream.h | 6 | 
28 files changed, 403 insertions, 135 deletions
| diff --git a/bootstrap.sh b/bootstrap.sh index 1f8b29d0..b85f025e 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -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 diff --git a/configure.ac b/configure.ac index cf7b5534..a7f85ea0 100644 --- a/configure.ac +++ b/configure.ac @@ -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}  " diff --git a/src/Makefile.am b/src/Makefile.am index 0235741b..1a4bcb04 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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")' diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index a106dc09..ab876edf 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -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; diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index d1afed7b..a5a62567 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -39,23 +39,15 @@  #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);  } diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index c325495c..bfea7358 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -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; diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index 30bf3ca1..6e55c0ee 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -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 diff --git a/src/daemon/main.c b/src/daemon/main.c index c41c69df..4961f0ca 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -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); diff --git a/src/modules/module-match.c b/src/modules/module-match.c index 28d6a08b..cd58a838 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -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[] = { diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 20728766..fa21b737 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -75,7 +75,14 @@      #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 @@ -129,7 +136,10 @@    #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> @@ -145,7 +155,11 @@      #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);  } diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index bf2627a7..c018c520 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 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); diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index 5cebcf46..28b4f2d1 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -39,21 +39,13 @@  #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") : diff --git a/src/pulse/client-conf.h b/src/pulse/client-conf.h index a532f0df..dfb1148d 100644 --- a/src/pulse/client-conf.h +++ b/src/pulse/client-conf.h @@ -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 */ diff --git a/src/pulse/context.c b/src/pulse/context.c index 228053bc..a25e2f78 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -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); diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 7cb85209..6375e5ef 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -84,10 +84,10 @@  #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      { diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index 864a96ec..db764de1 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -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); diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 7c780ea8..d6af3ca9 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -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)); diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index 261c5f75..61f17432 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -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); diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c index 15aa8e35..852e960e 100644 --- a/src/pulsecore/iochannel.c +++ b/src/pulsecore/iochannel.c @@ -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; diff --git a/src/pulsecore/iochannel.h b/src/pulsecore/iochannel.h index 64cf331e..3b5cba1c 100644 --- a/src/pulsecore/iochannel.h +++ b/src/pulsecore/iochannel.h @@ -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); diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c index 5b76b432..9bc20da4 100644 --- a/src/pulsecore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -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); diff --git a/src/pulsecore/pdispatch.h b/src/pulsecore/pdispatch.h index 07620e5a..18073502 100644 --- a/src/pulsecore/pdispatch.h +++ b/src/pulsecore/pdispatch.h @@ -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 diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c index 0ad76a6e..044d223d 100644 --- a/src/pulsecore/pid.c +++ b/src/pulsecore/pid.c @@ -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: diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 784610bd..14f880d7 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -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); diff --git a/src/pulsecore/pstream-util.c b/src/pulsecore/pstream-util.c index 3a995324..09d6f2fa 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, 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; diff --git a/src/pulsecore/pstream-util.h b/src/pulsecore/pstream-util.h index fc6d18c0..c60000a8 100644 --- a/src/pulsecore/pstream-util.h +++ b/src/pulsecore/pstream-util.h @@ -26,8 +26,10 @@  #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) diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index 7992ccb6..7ef49305 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -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          }      } diff --git a/src/pulsecore/pstream.h b/src/pulsecore/pstream.h index 1a2932d4..39cb7591 100644 --- a/src/pulsecore/pstream.h +++ b/src/pulsecore/pstream.h @@ -31,9 +31,11 @@  #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); | 
