]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
Merge branch 'refs/heads/t/audiod_acl'
authorAndre Noll <maan@tuebingen.mpg.de>
Sun, 3 May 2015 09:51:22 +0000 (11:51 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Sun, 3 May 2015 09:54:22 +0000 (11:54 +0200)
Cooking for about one month.

* audiod: Allow to specify usernames in --user-allow.

NEWS
audiod.c
audiod.h
audiod_command.c
m4/gengetopt/audiod.m4

diff --git a/NEWS b/NEWS
index 2eaad812d3b617cd1fb048c129139e354a4d59e5..87f678f578b27d8d3708b38fb2a14e6af7f4bd42 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,8 @@ current master branch "magnetic momentum"
        - On Linux systems, local sockets are now created in the
          abstract name space by default. This allows to get rid of
          the socket specials in /var/paraslash.
+       - The --user-allow option of para_audiod now accepts also
+         usernames rather than only user IDs.
        - New autoconf macros to avoid duplication in configure.ac.
        - Status items (as shown by para_gui) are updated correctly
          when the meta information of the current audio changes.
@@ -14,6 +16,7 @@ current master branch "magnetic momentum"
          the background if no log file is given. Instead, all log
          messages go to /dev/null in this case.
 
+
 Download: ./releases/paraslash-git.tar.bz2 (tarball)
 
 ------------------------------------------
index 1f226265b0c9c79593f255bba4805cfdb8a53e9a..40443a612569988e00ade13c8f384a7090d133e3 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -14,6 +14,7 @@
 #include <sys/un.h>
 #include <netdb.h>
 #include <signal.h>
+#include <pwd.h>
 
 #include "para.h"
 #include "error.h"
@@ -172,6 +173,8 @@ static struct signal_task *signal_task;
 
 static struct status_task status_task_struct;
 
+static uid_t *uid_whitelist;
+
 /**
  * the task that calls the status command of para_server
  *
@@ -390,7 +393,7 @@ empty:
 
 static void parse_config_or_die(void)
 {
-       int ret;
+       int ret, i;
        char *config_file;
        struct audiod_cmdline_parser_params params = {
                .override = 0,
@@ -410,6 +413,7 @@ static void parse_config_or_die(void)
        ret = file_exists(config_file);
        if (conf.config_file_given && !ret) {
                PARA_EMERG_LOG("can not read config file %s\n", config_file);
+               free(config_file);
                goto err;
        }
        if (ret) {
@@ -417,9 +421,29 @@ static void parse_config_or_die(void)
                daemon_set_loglevel(conf.loglevel_arg);
        }
        free(config_file);
+       if (conf.user_allow_given > 0) {
+               uid_whitelist = para_malloc(conf.user_allow_given
+                       * sizeof(uid_t));
+               for (i = 0; i < conf.user_allow_given; i++) {
+                       int32_t val;
+                       struct passwd *pw;
+                       ret = para_atoi32(conf.user_allow_arg[i], &val);
+                       if (ret >= 0) {
+                               uid_whitelist[i] = val;
+                               continue;
+                       }
+                       errno = 0; /* see getpwnam(3) */
+                       pw = getpwnam(conf.user_allow_arg[i]);
+                       if (!pw) {
+                               PARA_EMERG_LOG("invalid username: %s\n",
+                                       conf.user_allow_arg[i]);
+                               goto err;
+                       }
+                       uid_whitelist[i] = pw->pw_uid;
+               }
+       }
        return;
 err:
-       free(config_file);
        exit(EXIT_FAILURE);
 }
 
@@ -1099,7 +1123,7 @@ static int command_post_select(struct sched *s, void *context)
        for (i = 0; i < 2; i++) {
                if (ct->fd[i] < 0)
                        continue;
-               ret = handle_connect(ct->fd[i], &s->rfds);
+               ret = handle_connect(ct->fd[i], &s->rfds, uid_whitelist);
                if (ret < 0) {
                        PARA_ERROR_LOG("%s\n", para_strerror(-ret));
                        if (ret == -E_AUDIOD_TERM) {
@@ -1226,6 +1250,7 @@ static void audiod_cleanup(void)
        close_unused_slots();
        audiod_cmdline_parser_free(&conf);
        close_stat_clients();
+       free(uid_whitelist);
 }
 
 /*
index 94288eec702dd016dbebcaa2f5bf68a882aab1e7..3b4b9bd0416720e5e7d9455df23221cb049a2fc8 100644 (file)
--- a/audiod.h
+++ b/audiod.h
@@ -40,7 +40,7 @@ __malloc char *audiod_get_decoder_flags(void);
 extern struct audiod_args_info conf;
 extern int audiod_status;
 
-int handle_connect(int accept_fd, fd_set *rfds);
+int handle_connect(int accept_fd, fd_set *rfds, uid_t *uid_whitelist);
 void audiod_status_dump(bool force);
 char *get_time_string(void);
 struct btr_node *audiod_get_btr_root(void);
index b847e5aa264fa4ccb9e8c9aafcfcb61713ae2131..98dba3b32dfcaee1a7532d8e3021947102d98f89 100644 (file)
@@ -396,14 +396,14 @@ static int com_version(int fd, int argc, char **argv)
        return ret;
 }
 
-static int check_perms(uid_t uid)
+static int check_perms(uid_t uid, uid_t *whitelist)
 {
        int i;
 
        if (!conf.user_allow_given)
                return 1;
        for (i = 0; i < conf.user_allow_given; i++)
-               if (uid == conf.user_allow_arg[i])
+               if (uid == whitelist[i])
                        return 1;
        return -E_UCRED_PERM;
 }
@@ -413,6 +413,7 @@ static int check_perms(uid_t uid)
  *
  * \param accept_fd The fd to accept connections on.
  * \param rfds If \a accept_fd is not set in \a rfds, do nothing.
+ * \param uid_whitelist Array of UIDs which are allowed to connect.
  *
  * This is called in each iteration of the select loop. If there is an incoming
  * connection on \a accept_fd, this function reads the command sent by the peer,
@@ -425,7 +426,7 @@ static int check_perms(uid_t uid)
  *
  * \sa para_accept(), recv_cred_buffer()
  * */
-int handle_connect(int accept_fd, fd_set *rfds)
+int handle_connect(int accept_fd, fd_set *rfds, uid_t *uid_whitelist)
 {
        int i, argc, ret, clifd;
        char buf[MAXLINE], **argv = NULL;
@@ -440,7 +441,7 @@ int handle_connect(int accept_fd, fd_set *rfds)
                goto out;
        uid = ret;
        PARA_INFO_LOG("connection from user %i, buf: %s\n",  ret, buf);
-       ret = check_perms(uid);
+       ret = check_perms(uid, uid_whitelist);
        if (ret < 0)
                goto out;
        ret = create_argv(buf, "\n", &argv);
index 2e6f936f3a94d058ee35d24afd59ca9966f958cf..732f80873cdf39529e61f158a4d6cc40c2ae0735 100644 (file)
@@ -82,20 +82,21 @@ details="
 
 option "user-allow" -
 #~~~~~~~~~~~~~~~~~~~~
-"allow this uid"
-int typestr="uid"
-default="-1"
+"allow this user to connect to audiod"
+string typestr = "username"
 optional
 multiple
-details="
-       Allow the user identified by \"uid\" to connect to para_audiod.
-       May be specified multiple times. If not specified at all,
-       all users are allowed to connect.
-
-       This feature requires unix socket credentials and is currently
-       only supported on Linux systems. On other operating systems,
-       the option is silently ignored and all local users are allowed
-       to connect to para_audiod.
+details = "
+       Allow the user identified by username (either a string or
+       a UID) to connect to para_audiod. This option may be given
+       multiple times. If not specified at all, all users are allowed
+       to connect.
+
+       This feature is based on the ability to send unix
+       credentials through local sockets using ancillary data
+       (SCM_CREDENTIALS). Currently it only works on Linux. On
+       other operating systems the option is silently ignored and
+       all local users are allowed to connect.
 "
 
 option "clock-diff-count" -