diff options
-rw-r--r-- | src/daemon/main.c | 2 | ||||
-rw-r--r-- | src/modules/module-protocol-stub.c | 17 | ||||
-rw-r--r-- | src/polypcore/protocol-esound.c | 4 | ||||
-rw-r--r-- | src/polypcore/protocol-native.c | 25 | ||||
-rw-r--r-- | src/polypcore/util.c | 52 | ||||
-rw-r--r-- | src/polypcore/util.h | 5 |
6 files changed, 86 insertions, 19 deletions
diff --git a/src/daemon/main.c b/src/daemon/main.c index 4b972fe2..8457916a 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -160,7 +160,7 @@ int main(int argc, char *argv[]) { #ifdef HAVE_GETUID suid_root = getuid() != 0 && geteuid() == 0; - if (suid_root && (pa_uid_in_group("realtime", &gid) <= 0 || gid >= 1000)) { + 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'."); pa_drop_root(); } diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 749a7ace..b02b9688 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -110,14 +110,23 @@ #define TCPWRAP_SERVICE "polypaudio-native" #define IPV4_PORT PA_NATIVE_DEFAULT_PORT #define UNIX_SOCKET PA_NATIVE_DEFAULT_UNIX_SOCKET - #define MODULE_ARGUMENTS "public", "cookie", + #define MODULE_ARGUMENTS_COMMON "cookie", "auth-anonymous", #ifdef USE_TCP_SOCKETS #include "module-native-protocol-tcp-symdef.h" #else #include "module-native-protocol-unix-symdef.h" #endif + + #if defined(SCM_CREDENTIALS) && !defined(USE_TCP_SOCKETS) + #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group", + #define AUTH_USAGE "auth-group=<local group to allow access>" + #else + #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON + #define AUTH_USAGE + #endif + PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION) - PA_MODULE_USAGE("public=<don't check for cookies?> cookie=<path to cookie file> "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 <polypcore/protocol-esound.h> #include <polypcore/esound.h> @@ -126,14 +135,14 @@ #define TCPWRAP_SERVICE "esound" #define IPV4_PORT ESD_DEFAULT_PORT #define UNIX_SOCKET ESD_UNIX_SOCKET_NAME - #define MODULE_ARGUMENTS "sink", "source", "public", "cookie", + #define MODULE_ARGUMENTS "sink", "source", "auth-anonymous", "cookie", #ifdef USE_TCP_SOCKETS #include "module-esound-protocol-tcp-symdef.h" #else #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> public=<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 check for cookies?> cookie=<path to cookie file> "SOCKET_USAGE) #else #error "Broken build system" #endif diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 3ef1cd04..e30ff067 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -1139,8 +1139,8 @@ pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *serve p = pa_xnew(pa_protocol_esound, 1); - if (pa_modargs_get_value_boolean(ma, "public", &public) < 0) { - pa_log(__FILE__": public= expects a boolean argument."); + if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &public) < 0) { + pa_log(__FILE__": auth-anonymous= expects a boolean argument."); return NULL; } diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 0fb9339b..81d91f0c 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -129,6 +129,9 @@ struct pa_protocol_native { pa_idxset *connections; uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; int auth_cookie_in_property; +#ifdef SCM_CREDENTIALS + char *auth_group; +#endif }; static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk); @@ -878,15 +881,22 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t const struct ucred *ucred = pa_pdispatch_creds(pd); if (ucred) { - if (ucred->uid == getuid()) + if (ucred->uid == getuid()) success = 1; + else if (c->protocol->auth_group) { + int r; + + if ((r = pa_uid_in_group(ucred->uid, c->protocol->auth_group)) < 0) + pa_log_warn(__FILE__": failed to check group membership."); + else if (r > 0) + success = 1; + } pa_log_info(__FILE__": Got credentials: pid=%lu uid=%lu gid=%lu auth=%i", (unsigned long) ucred->pid, (unsigned long) ucred->uid, (unsigned long) ucred->gid, success); - } #endif @@ -2247,8 +2257,8 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo int public = 0; assert(c && ma); - if (pa_modargs_get_value_boolean(ma, "public", &public) < 0) { - pa_log(__FILE__": public= expects a boolean argument."); + if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &public) < 0) { + pa_log(__FILE__": auth-anonymous= expects a boolean argument."); return NULL; } @@ -2258,6 +2268,10 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo p->public = public; p->server = NULL; +#ifdef SCM_CREDENTIALS + p->auth_group = pa_xstrdup(pa_modargs_get_value(ma, "auth-group", NULL)); +#endif + if (load_key(p, pa_modargs_get_value(ma, "cookie", NULL)) < 0) { pa_xfree(p); return NULL; @@ -2317,6 +2331,9 @@ void pa_protocol_native_free(pa_protocol_native *p) { if (p->auth_cookie_in_property) pa_authkey_prop_unref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME); +#ifdef SCM_CREDENTIALS + pa_xfree(p->auth_group); +#endif pa_xfree(p); } diff --git a/src/polypcore/util.c b/src/polypcore/util.c index f53eef34..f810b3bf 100644 --- a/src/polypcore/util.c +++ b/src/polypcore/util.c @@ -166,7 +166,7 @@ int pa_make_secure_parent_dir(const char *fn) { int ret = -1; char *slash, *dir = pa_xstrdup(fn); - slash = pa_path_get_filename(dir); + slash = (char*) pa_path_get_filename(dir); if (slash == fn) goto finish; *(slash-1) = 0; @@ -636,13 +636,13 @@ char *pa_get_binary_name(char *s, size_t l) { /* Return a pointer to the filename inside a path (which is the last * component). */ -char *pa_path_get_filename(const char *p) { +const char *pa_path_get_filename(const char *p) { char *fn; if ((fn = strrchr(p, PATH_SEP))) return fn+1; - return (char*) p; + return (const char*) p; } /* Try to parse a boolean string value.*/ @@ -745,7 +745,6 @@ static int is_group(gid_t gid, const char *name) { goto finish; } - r = strcmp(name, result->gr_name) == 0; finish: @@ -767,7 +766,7 @@ finish: } /* Check the current user is member of the specified group */ -int pa_uid_in_group(const char *name, gid_t *gid) { +int pa_own_uid_in_group(const char *name, gid_t *gid) { GETGROUPS_T *gids, tgid; int n = sysconf(_SC_NGROUPS_MAX); int r = -1, i; @@ -803,9 +802,50 @@ finish: return r; } +int pa_uid_in_group(uid_t uid, const char *name) { + char *g_buf, *p_buf; + long g_n, p_n; + struct group grbuf, *gr; + char **i; + int r = -1; + + g_n = sysconf(_SC_GETGR_R_SIZE_MAX); + g_buf = pa_xmalloc(g_n); + + p_n = sysconf(_SC_GETPW_R_SIZE_MAX); + p_buf = pa_xmalloc(p_n); + + if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr) + goto finish; + + r = 0; + for (i = gr->gr_mem; *i; i++) { + struct passwd pwbuf, *pw; + + if (getpwnam_r(*i, &pwbuf, p_buf, (size_t) p_n, &pw) != 0 || !pw) + continue; + + if (pw->pw_uid == uid) { + r = 1; + break; + } + } + +finish: + pa_xfree(g_buf); + pa_xfree(p_buf); + + return r; +} + #else /* HAVE_GRP_H */ -int pa_uid_in_group(const char *name, gid_t *gid) { +int pa_own_uid_in_group(const char *name, gid_t *gid) { + return -1; + +} + +int pa_uid_in_group(uid_t uid, const char *name) { return -1; } diff --git a/src/polypcore/util.h b/src/polypcore/util.h index af4e14c8..424283e7 100644 --- a/src/polypcore/util.h +++ b/src/polypcore/util.h @@ -53,7 +53,7 @@ char *pa_get_fqdn(char *s, size_t l); char *pa_get_binary_name(char *s, size_t l); char *pa_get_home_dir(char *s, size_t l); -char *pa_path_get_filename(const char *p); +const char *pa_path_get_filename(const char *p); int pa_gettimeofday(struct timeval *tv); pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b); @@ -75,7 +75,8 @@ char *pa_strip_nl(char *s); const char *pa_strsignal(int sig); -int pa_uid_in_group(const char *name, gid_t *gid); +int pa_own_uid_in_group(const char *name, gid_t *gid); +int pa_uid_in_group(uid_t uid, const char *name); int pa_lock_fd(int fd, int b); |