[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