mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
* add new --system command line parameter to the daemon for running PulseAudio as system-wide instance
* 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
This commit is contained in:
parent
9db70682d6
commit
9c87a65ce9
28 changed files with 403 additions and 135 deletions
|
|
@ -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
|
||||
|
|
|
|||
55
configure.ac
55
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}
|
||||
"
|
||||
|
|
|
|||
|
|
@ -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")'
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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[] = {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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") :
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue