From 67cb641c126769af98289539ff3425dfbf5e12e2 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Mon, 20 Jun 2016 23:20:59 +0200 Subject: [PATCH] audiod: Move UID check from audiod_command.c to audiod.c. check_perms() is the only reason for the gengetopt config pointer being public and for passing the whitelist pointer to handle_connect() in audiod_command.c. The code get less convoluted by moving the permission check to audiod.c where both the conf pointer and the uid_whitelist are defined. This introduces the new public function uid_is_whitelisted() in audiod.c which replaces check_perms(). This allows to * pass only the UID to the check function, * drop the whitelist pointer argument from handle_connect(), * make the conf pointer in audiod.c static. The patch also reorders the function declarations in audiod.h a bit to separate the functions defined in audiod.c from those defined in audiod_command.c. --- audiod.c | 27 +++++++++++++++++++++++++-- audiod.h | 14 ++++++++------ audiod_command.c | 21 ++++----------------- 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/audiod.c b/audiod.c index 2f9d5da3..75073ec2 100644 --- a/audiod.c +++ b/audiod.c @@ -164,7 +164,7 @@ int audiod_status = AUDIOD_ON; * the gengetopt args_info struct that holds information on all command line * arguments */ -struct audiod_args_info conf; +static struct audiod_args_info conf; static char *socket_name; static struct audio_format_info afi[NUM_AUDIO_FORMATS]; @@ -1123,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, uid_whitelist); + ret = handle_connect(ct->fd[i], &s->rfds); if (ret < 0) { PARA_ERROR_LOG("%s\n", para_strerror(-ret)); if (ret == -E_AUDIOD_TERM) { @@ -1448,6 +1448,29 @@ __noreturn static void print_help_and_die(void) exit(0); } +/** + * Lookup the given UID in the whitelist. + * + * The whitelist is the array of arguments to the --user-allow opion. If the + * option was not given, the array is empty, in which case the check succeeds. + * + * \param uid User ID to look up. + * + * \return True if --user-allow was not given, or if uid matches an element of + * the whitelist. + */ +bool uid_is_whitelisted(uid_t uid) +{ + int i; + + if (!conf.user_allow_given) + return true; + for (i = 0; i < conf.user_allow_given; i++) + if (uid == uid_whitelist[i]) + return true; + return false; +} + /** * the main function of para_audiod * diff --git a/audiod.h b/audiod.h index b9cfb25e..7073c6dd 100644 --- a/audiod.h +++ b/audiod.h @@ -22,15 +22,17 @@ extern const char *audio_formats[]; */ enum audiod_status_info {AUDIOD_OFF, AUDIOD_ON, AUDIOD_STANDBY}; -extern struct audiod_args_info conf; extern int audiod_status; -int handle_connect(int accept_fd, fd_set *rfds, uid_t *uid_whitelist); -void audiod_status_dump(bool force); +/* defined in audiod.c */ +struct btr_node *audiod_get_btr_root(void); __malloc char *audiod_get_decoder_flags(void); +void clear_and_dump_items(void); char *get_time_string(void); -struct btr_node *audiod_get_btr_root(void); +bool uid_is_whitelisted(uid_t uid); -void stat_client_write_item(int item_num); -void clear_and_dump_items(void); +/* defined in audiod_command.c */ +void audiod_status_dump(bool force); void close_stat_clients(void); +int handle_connect(int accept_fd, fd_set *rfds); +void stat_client_write_item(int item_num); diff --git a/audiod_command.c b/audiod_command.c index 278e6ef6..3a390275 100644 --- a/audiod_command.c +++ b/audiod_command.c @@ -404,24 +404,11 @@ static int com_version(int fd, int argc, char **argv) return ret < 0? ret : 0; } -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 == whitelist[i]) - return 1; - return -E_UCRED_PERM; -} - /** * Handle arriving connections on the local socket. * * \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, @@ -434,7 +421,7 @@ static int check_perms(uid_t uid, uid_t *whitelist) * * \sa para_accept(), recv_cred_buffer() * */ -int handle_connect(int accept_fd, fd_set *rfds, uid_t *uid_whitelist) +int handle_connect(int accept_fd, fd_set *rfds) { int i, argc, ret, clifd; char buf[MAXLINE], **argv = NULL; @@ -448,9 +435,9 @@ int handle_connect(int accept_fd, fd_set *rfds, uid_t *uid_whitelist) if (ret < 0) goto out; uid = ret; - PARA_INFO_LOG("connection from user %i, buf: %s\n", ret, buf); - ret = check_perms(uid, uid_whitelist); - if (ret < 0) + PARA_INFO_LOG("connection from UID %d, buf: %s\n", ret, buf); + ret = -E_UCRED_PERM; + if (!uid_is_whitelisted(uid)) goto out; ret = create_argv(buf, "\n", &argv); if (ret <= 0) -- 2.39.2