From 0f6df2322c12b1cc20dea08bb6c397465d4f5b46 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sun, 13 Jan 2008 16:41:36 +0100 Subject: [PATCH] Move acl functions to separate file acl.c. --- acl.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++ acl.h | 8 +++ configure.ac | 4 +- error.h | 1 + http_send.c | 119 +-------------------------------------------- 5 files changed, 146 insertions(+), 120 deletions(-) create mode 100644 acl.c create mode 100644 acl.h diff --git a/acl.c b/acl.c new file mode 100644 index 00000000..3a30bd45 --- /dev/null +++ b/acl.c @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2005-2008 Andre Noll + * + * Licensed under the GPL v2. For licencing details see COPYING. + */ + +/** \file acl.c Access control lists for paraslash senders. */ + +#include "para.h" +#include "error.h" +#include "string.h" +#include "list.h" +#include "net.h" + +/** + * Describes one entry in the blacklist/whitelist of a paraslash sender. + */ +struct access_info { + /** The address to be black/whitelisted. */ + struct in_addr addr; + /** The netmask for this entry. */ + unsigned netmask; + /** The position of this entry in the acl. */ + struct list_head node; +}; + + +/** + * Return true if addr_1 matches addr_2 in the first `netmask' bits. + */ +static int v4_addr_match(uint32_t addr_1, uint32_t addr_2, uint8_t netmask) +{ + uint32_t mask = ~0U; + + if (netmask < 32) + mask <<= (32 - netmask); + return (htonl(addr_1) & mask) == (htonl(addr_2) & mask); +} + +int host_in_acl(int fd, struct list_head *acl) +{ + struct access_info *ai, *tmp; + struct sockaddr_storage ss; + socklen_t sslen = sizeof(ss); + struct in_addr v4_addr; + + if (getpeername(fd, (struct sockaddr *)&ss, &sslen) < 0) { + PARA_ERROR_LOG("Can not determine peer address: %s\n", strerror(errno)); + goto no_match; + } + v4_addr = extract_v4_addr(&ss); + if (!v4_addr.s_addr) + goto no_match; + + list_for_each_entry_safe(ai, tmp, acl, node) + if (v4_addr_match(v4_addr.s_addr, ai->addr.s_addr, ai->netmask)) + return 1; +no_match: + return 0; +} + +void add_acl_entry(struct list_head *acl, struct in_addr addr, + int netmask) +{ + struct access_info *ai = para_malloc(sizeof(struct access_info)); + ai->addr = addr; + ai->netmask = netmask; + PARA_INFO_LOG("adding %s/%i to access list\n", inet_ntoa(ai->addr), + ai->netmask); + para_list_add(&ai->node, acl); +} + + +void del_acl_entry(struct list_head *acl, struct in_addr addr, + int netmask) +{ + struct access_info *ai, *tmp; + + list_for_each_entry_safe(ai, tmp, acl, node) { + char *nad = para_strdup(inet_ntoa(ai->addr)); + if (!strcmp(nad, inet_ntoa(addr)) && + ai->netmask == netmask) { + PARA_NOTICE_LOG("removing %s/%i from access list\n", + nad, ai->netmask); + list_del(&ai->node); + free(ai); + } + free(nad); + } +} + +char *get_acl_contents(struct list_head *acl) +{ + struct access_info *ai, *tmp_ai; + char *ret = NULL; + + list_for_each_entry_safe(ai, tmp_ai, acl, node) { + char *tmp = make_message("%s%s/%d ", ret? ret : "", + inet_ntoa(ai->addr), ai->netmask); + free(ret); + ret = tmp; + } + return ret; +} + +void init_acl(struct list_head *acl, char * const *acl_info, int num) +{ + int i; + + INIT_LIST_HEAD(acl); + for (i = 0; i < num; i++) { + char *arg = para_strdup(acl_info[i]); + char *p = strchr(arg, '/'); + struct in_addr addr; + int netmask; + + if (!p) + goto err; + *p = '\0'; + if (!inet_pton(AF_INET, arg, &addr)) + goto err; + netmask = atoi(++p); + if (netmask < 0 || netmask > 32) + goto err; + add_acl_entry(acl, addr, netmask); + goto success; +err: + PARA_CRIT_LOG("syntax error: %s\n", acl_info[i]); +success: + free(arg); + continue; + } +} + diff --git a/acl.h b/acl.h new file mode 100644 index 00000000..994fd6fe --- /dev/null +++ b/acl.h @@ -0,0 +1,8 @@ + +void init_acl(struct list_head *acl, char * const *acl_info, int num); +int host_in_acl(int fd, struct list_head *acl); +void add_acl_entry(struct list_head *acl, struct in_addr addr, + int netmask); +void del_acl_entry(struct list_head *acl, struct in_addr addr, + int netmask); +char *get_acl_contents(struct list_head *acl); diff --git a/configure.ac b/configure.ac index 6c555538..a8efcc15 100644 --- a/configure.ac +++ b/configure.ac @@ -79,7 +79,7 @@ AC_CHECK_FUNCS([atexit dup2 memchr memmove memset \ [AC_MSG_ERROR([function not found, cannot live without it])]) all_errlist_objs="server mp3_afh afh_common vss command net string signal time -daemon stat crypt http_send close_on_fork ipc +daemon stat crypt http_send close_on_fork ipc acl dccp_send fd user_list chunk_queue afs osl aft mood score attribute blob ringbuffer playlist sha1 rbtree sched audiod grab_client filter_chain wav compress http_recv dccp_recv recv_common write_common file_write audiod_command @@ -117,7 +117,7 @@ server_cmdline_objs="server.cmdline server_command_list afs_command_list" server_errlist_objs="server afh_common mp3_afh vss command net string signal time daemon stat crypt http_send close_on_fork ipc dccp_send fd user_list chunk_queue afs osl aft mood score attribute - blob playlist sha1 rbtree sched" + blob playlist sha1 rbtree sched acl" server_ldflags="" server_audio_formats=" mp3" diff --git a/error.h b/error.h index ce9ab528..dd5cc579 100644 --- a/error.h +++ b/error.h @@ -27,6 +27,7 @@ DEFINE_ERRLIST_OBJECT_ENUM; #define AFH_COMMON_ERRORS #define RBTREE_ERRORS #define RECV_ERRORS +#define ACL_ERRORS extern const char **para_errlist[]; diff --git a/http_send.c b/http_send.c index 037d4f24..d2bd3531 100644 --- a/http_send.c +++ b/http_send.c @@ -24,6 +24,7 @@ #include "net.h" #include "fd.h" #include "chunk_queue.h" +#include "acl.h" /** Message sent to clients that do not send a valid get request. */ #define HTTP_ERR_MSG "HTTP/1.0 400 Bad Request\n" @@ -70,18 +71,6 @@ struct http_client { struct chunk_queue *cq; }; -/** - * Describes one entry in the blacklist/whitelist of the http sender. - */ -struct access_info { - /** The address to be black/whitelisted. */ - struct in_addr addr; - /** The netmask for this entry. */ - unsigned netmask; - /** The position of this entry in the acl. */ - struct list_head node; -}; - static int server_fd = -1, numclients; static struct sender *self; @@ -202,40 +191,6 @@ static void http_send( long unsigned current_chunk, } } -/** - * Return true if addr_1 matches addr_2 in the first `netmask' bits. - */ -static int v4_addr_match(uint32_t addr_1, uint32_t addr_2, uint8_t netmask) -{ - uint32_t mask = ~0U; - - if (netmask < 32) - mask <<= (32 - netmask); - return (htonl(addr_1) & mask) == (htonl(addr_2) & mask); -} - -static int host_in_acl(int fd, struct list_head *acl) -{ - struct access_info *ai, *tmp; - struct sockaddr_storage ss; - socklen_t sslen = sizeof(ss); - struct in_addr v4_addr; - - if (getpeername(fd, (struct sockaddr *)&ss, &sslen) < 0) { - PARA_ERROR_LOG("Can not determine peer address: %s\n", strerror(errno)); - goto no_match; - } - v4_addr = extract_v4_addr(&ss); - if (!v4_addr.s_addr) - goto no_match; - - list_for_each_entry_safe(ai, tmp, acl, node) - if (v4_addr_match(v4_addr.s_addr, ai->addr.s_addr, ai->netmask)) - return 1; -no_match: - return 0; -} - static void http_post_select(fd_set *rfds, fd_set *wfds) { int i = -1, match; @@ -391,35 +346,6 @@ static int http_com_off(__a_unused struct sender_command_data *scd) return 1; } -static void del_acl_entry(struct list_head *acl, struct in_addr addr, - int netmask) -{ - struct access_info *ai, *tmp; - - list_for_each_entry_safe(ai, tmp, acl, node) { - char *nad = para_strdup(inet_ntoa(ai->addr)); - if (!strcmp(nad, inet_ntoa(addr)) && - ai->netmask == netmask) { - PARA_NOTICE_LOG("removing %s/%i from access list\n", - nad, ai->netmask); - list_del(&ai->node); - free(ai); - } - free(nad); - } -} - -static void add_acl_entry(struct list_head *acl, struct in_addr addr, - int netmask) -{ - struct access_info *ai = para_malloc(sizeof(struct access_info)); - ai->addr = addr; - ai->netmask = netmask; - PARA_INFO_LOG("adding %s/%i to access list\n", inet_ntoa(ai->addr), - ai->netmask); - para_list_add(&ai->node, acl); -} - static int http_com_deny(struct sender_command_data *scd) { if (conf.http_default_deny_given) @@ -438,20 +364,6 @@ static int http_com_allow(struct sender_command_data *scd) return 1; } -static char *get_acl_contents(struct list_head *acl) -{ - struct access_info *ai, *tmp_ai; - char *ret = NULL; - - list_for_each_entry_safe(ai, tmp_ai, acl, node) { - char *tmp = make_message("%s%s/%d ", ret? ret : "", - inet_ntoa(ai->addr), ai->netmask); - free(ret); - ret = tmp; - } - return ret; -} - static char *http_info(void) { char *clnts = NULL, *ret; @@ -484,35 +396,6 @@ static char *http_info(void) return ret; } -static void init_acl(struct list_head *acl, char * const *acl_info, int num) -{ - int i; - - INIT_LIST_HEAD(acl); - for (i = 0; i < num; i++) { - char *arg = para_strdup(acl_info[i]); - char *p = strchr(arg, '/'); - struct in_addr addr; - int netmask; - - if (!p) - goto err; - *p = '\0'; - if (!inet_pton(AF_INET, arg, &addr)) - goto err; - netmask = atoi(++p); - if (netmask < 0 || netmask > 32) - goto err; - add_acl_entry(acl, addr, netmask); - goto success; -err: - PARA_CRIT_LOG("syntax error: %s\n", acl_info[i]); -success: - free(arg); - continue; - } -} - static char *http_help(void) { return make_message( -- 2.30.2