[xiph-commits] r14039 - icecast/trunk/icecast/src
karl at svn.xiph.org
karl at svn.xiph.org
Tue Oct 23 15:25:31 PDT 2007
Author: karl
Date: 2007-10-23 15:25:31 -0700 (Tue, 23 Oct 2007)
New Revision: 14039
Modified:
icecast/trunk/icecast/src/auth_htpasswd.c
icecast/trunk/icecast/src/cfgfile.c
icecast/trunk/icecast/src/cfgfile.h
icecast/trunk/icecast/src/connection.c
icecast/trunk/icecast/src/util.c
icecast/trunk/icecast/src/util.h
Log:
Allow for files to be specified that will contain IPs that can be used to
accept or deny client connections.
Modified: icecast/trunk/icecast/src/auth_htpasswd.c
===================================================================
--- icecast/trunk/icecast/src/auth_htpasswd.c 2007-10-23 21:07:21 UTC (rev 14038)
+++ icecast/trunk/icecast/src/auth_htpasswd.c 2007-10-23 22:25:31 UTC (rev 14039)
@@ -66,19 +66,6 @@
free(state);
}
-static int get_line(FILE *file, char *buf, int len)
-{
- if(fgets(buf, len, file)) {
- int len = strlen(buf);
- if(len > 0 && buf[len-1] == '\n') {
- buf[--len] = 0;
- if(len > 0 && buf[len-1] == '\r')
- buf[--len] = 0;
- }
- return 1;
- }
- return 0;
-}
/* md5 hash */
static char *get_hash(const char *data, int len)
@@ -95,9 +82,7 @@
return util_bin_to_hex(digest, 16);
}
-#define MAX_LINE_LEN 512
-
static int compare_users (void *arg, void *a, void *b)
{
htpasswd_user *user1 = (htpasswd_user *)a;
Modified: icecast/trunk/icecast/src/cfgfile.c
===================================================================
--- icecast/trunk/icecast/src/cfgfile.c 2007-10-23 21:07:21 UTC (rev 14038)
+++ icecast/trunk/icecast/src/cfgfile.c 2007-10-23 22:25:31 UTC (rev 14039)
@@ -192,6 +192,8 @@
if (c->cert_file) xmlFree(c->cert_file);
if (c->pidfile)
xmlFree(c->pidfile);
+ if (c->banfile) xmlFree(c->banfile);
+ if (c->allowfile) xmlFree(c->allowfile);
if (c->playlist_log) xmlFree(c->playlist_log);
if (c->access_log) xmlFree(c->access_log);
if (c->error_log) xmlFree(c->error_log);
@@ -906,6 +908,12 @@
} else if (xmlStrcmp (node->name, XMLSTR("pidfile")) == 0) {
if (configuration->pidfile) xmlFree(configuration->pidfile);
configuration->pidfile = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+ } else if (xmlStrcmp (node->name, XMLSTR("deny-ip")) == 0) {
+ if (configuration->banfile) xmlFree(configuration->banfile);
+ configuration->banfile = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+ } else if (xmlStrcmp (node->name, XMLSTR("allow-ip")) == 0) {
+ if (configuration->allowfile) xmlFree(configuration->allowfile);
+ configuration->allowfile = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (xmlStrcmp (node->name, XMLSTR("ssl-certificate")) == 0) {
if (configuration->cert_file) xmlFree(configuration->cert_file);
configuration->cert_file = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Modified: icecast/trunk/icecast/src/cfgfile.h
===================================================================
--- icecast/trunk/icecast/src/cfgfile.h 2007-10-23 21:07:21 UTC (rev 14038)
+++ icecast/trunk/icecast/src/cfgfile.h 2007-10-23 22:25:31 UTC (rev 14039)
@@ -156,6 +156,8 @@
char *base_dir;
char *log_dir;
char *pidfile;
+ char *banfile;
+ char *allowfile;
char *cert_file;
char *webroot_dir;
char *adminroot_dir;
Modified: icecast/trunk/icecast/src/connection.c
===================================================================
--- icecast/trunk/icecast/src/connection.c 2007-10-23 21:07:21 UTC (rev 14038)
+++ icecast/trunk/icecast/src/connection.c 2007-10-23 22:25:31 UTC (rev 14039)
@@ -22,6 +22,8 @@
#ifdef HAVE_POLL
#include <sys/poll.h>
#endif
+#include <sys/types.h>
+#include <sys/stat.h>
#ifndef _WIN32
#include <sys/time.h>
@@ -93,6 +95,14 @@
struct _thread_queue_tag *next;
} thread_queue_t;
+typedef struct
+{
+ char *filename;
+ time_t file_recheck;
+ time_t file_mtime;
+ avl_tree *contents;
+} cache_file_contents;
+
static mutex_t _connection_mutex;
static volatile unsigned long _current_id = 0;
static int _initialized = 0;
@@ -108,10 +118,29 @@
static SSL_CTX *ssl_ctx;
#endif
+/* filtering client connection based on IP */
+cache_file_contents banned_ip, allowed_ip;
+
rwlock_t _source_shutdown_rwlock;
static void *_handle_connection(void *arg);
+static int compare_ip (void *arg, void *a, void *b)
+{
+ const char *ip = (const char *)a;
+ const char *pattern = (const char *)b;
+
+ return strcmp (pattern, ip);
+}
+
+
+static int free_filtered_ip (void*x)
+{
+ free (x);
+ return 1;
+}
+
+
void connection_initialize(void)
{
if (_initialized) return;
@@ -127,6 +156,12 @@
_con_queue = NULL;
_con_queue_tail = &_con_queue;
+ banned_ip.contents = NULL;
+ banned_ip.file_mtime = 0;
+
+ allowed_ip.contents = NULL;
+ allowed_ip.file_mtime = 0;
+
_initialized = 1;
}
@@ -137,7 +172,9 @@
#ifdef HAVE_OPENSSL
SSL_CTX_free (ssl_ctx);
#endif
-
+ if (banned_ip.contents) avl_tree_free (banned_ip.contents, free_filtered_ip);
+ if (allowed_ip.contents) avl_tree_free (allowed_ip.contents, free_filtered_ip);
+
thread_cond_destroy(&global.shutdown_cond);
thread_rwlock_destroy(&_source_shutdown_rwlock);
thread_mutex_destroy(&_con_queue_mutex);
@@ -275,6 +312,101 @@
}
+/* function to handle the re-populating of the avl tree containing IP addresses
+ * for deciding whether a connection of an incoming request is to be dropped.
+ */
+static void recheck_ip_file (cache_file_contents *cache)
+{
+ time_t now = time(NULL);
+ if (now >= cache->file_recheck)
+ {
+ struct stat file_stat;
+ FILE *file = NULL;
+ int count = 0;
+ avl_tree *new_ips;
+ char line [MAX_LINE_LEN];
+
+ cache->file_recheck = now + 10;
+ if (cache->filename == NULL)
+ {
+ if (cache->contents)
+ {
+ avl_tree_free (cache->contents, free_filtered_ip);
+ cache->contents = NULL;
+ }
+ return;
+ }
+ if (stat (cache->filename, &file_stat) < 0)
+ {
+ WARN2 ("failed to check status of \"%s\": %s", cache->filename, strerror(errno));
+ return;
+ }
+ if (file_stat.st_mtime == cache->file_mtime)
+ return; /* common case, no update to file */
+
+ cache->file_mtime = file_stat.st_mtime;
+
+ file = fopen (cache->filename, "r");
+ if (file == NULL)
+ {
+ WARN2("Failed to open file \"%s\": %s", cache->filename, strerror (errno));
+ return;
+ }
+
+ new_ips = avl_tree_new (compare_ip, NULL);
+
+ while (get_line (file, line, MAX_LINE_LEN))
+ {
+ char *str;
+ if(!line[0] || line[0] == '#')
+ continue;
+ count++;
+ str = strdup (line);
+ if (str)
+ avl_insert (new_ips, str);
+ }
+ fclose (file);
+ INFO2 ("%d entries read from file \"%s\"", count, cache->filename);
+
+ if (cache->contents) avl_tree_free (cache->contents, free_filtered_ip);
+ cache->contents = new_ips;
+ }
+}
+
+
+/* return 0 if the passed ip address is not to be handled by icecast, non-zero otherwise */
+static int accept_ip_address (char *ip)
+{
+ void *result;
+
+ recheck_ip_file (&banned_ip);
+ recheck_ip_file (&allowed_ip);
+
+ if (banned_ip.contents)
+ {
+ if (avl_get_by_key (banned_ip.contents, ip, &result) == 0)
+ {
+ DEBUG1 ("%s is banned", ip);
+ return 0;
+ }
+ }
+ if (allowed_ip.contents)
+ {
+ if (avl_get_by_key (allowed_ip.contents, ip, &result) == 0)
+ {
+ DEBUG1 ("%s is allowed", ip);
+ return 1;
+ }
+ else
+ {
+ DEBUG1 ("%s is not allowed", ip);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
connection_t *connection_create (sock_t sock, sock_t serversock, char *ip)
{
connection_t *con;
@@ -392,7 +524,6 @@
static connection_t *_accept_connection(void)
{
int sock;
- connection_t *con;
char *ip;
int serversock;
@@ -406,11 +537,13 @@
sock = sock_accept(serversock, ip, MAX_ADDR_LEN);
if (sock >= 0)
{
+ connection_t *con = NULL;
/* Make any IPv4 mapped IPv6 address look like a normal IPv4 address */
if (strncmp (ip, "::ffff:", 7) == 0)
memmove (ip, ip+7, strlen (ip+7)+1);
- con = connection_create (sock, serversock, ip);
+ if (accept_ip_address (ip))
+ con = connection_create (sock, serversock, ip);
if (con)
return con;
sock_close (sock);
@@ -1218,6 +1351,11 @@
int count = 0;
listener_t *listener, **prev;
+ free (banned_ip.filename);
+ banned_ip.filename = NULL;
+ free (allowed_ip.filename);
+ allowed_ip.filename = NULL;
+
global_lock();
if (global.serversock)
{
@@ -1232,6 +1370,13 @@
return 0;
}
+ /* setup the banned/allowed IP filenames from the xml */
+ if (config->banfile)
+ banned_ip.filename = strdup (config->banfile);
+
+ if (config->allowfile)
+ allowed_ip.filename = strdup (config->allowfile);
+
count = 0;
global.serversock = calloc (config->listen_sock_count, sizeof (sock_t));
Modified: icecast/trunk/icecast/src/util.c
===================================================================
--- icecast/trunk/icecast/src/util.c 2007-10-23 21:07:21 UTC (rev 14038)
+++ icecast/trunk/icecast/src/util.c 2007-10-23 22:25:31 UTC (rev 14039)
@@ -673,3 +673,18 @@
return ret;
}
+
+int get_line(FILE *file, char *buf, size_t siz)
+{
+ if(fgets(buf, (int)siz, file)) {
+ size_t len = strlen(buf);
+ if(len > 0 && buf[len-1] == '\n') {
+ buf[--len] = 0;
+ if(len > 0 && buf[len-1] == '\r')
+ buf[--len] = 0;
+ }
+ return 1;
+ }
+ return 0;
+}
+
Modified: icecast/trunk/icecast/src/util.h
===================================================================
--- icecast/trunk/icecast/src/util.h 2007-10-23 21:07:21 UTC (rev 14038)
+++ icecast/trunk/icecast/src/util.h 2007-10-23 22:25:31 UTC (rev 14039)
@@ -19,6 +19,8 @@
#define READ_ENTIRE_HEADER 1
#define READ_LINE 0
+#define MAX_LINE_LEN 512
+
int util_timed_wait_for_fd(int fd, int timeout);
int util_read_header(int sock, char *buff, unsigned long len, int entire);
int util_check_valid_extension(const char *uri);
@@ -53,4 +55,5 @@
#endif
char *util_conv_string (const char *string, const char *in_charset, const char *out_charset);
+int get_line(FILE *file, char *buf, size_t siz);
#endif /* __UTIL_H__ */
More information about the commits
mailing list