1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-12-04 14:46:30 -05:00

Allow for files to be specified that will contain IPs that can be used to

accept or deny client connections.

svn path=/icecast/trunk/icecast/; revision=14039
This commit is contained in:
Karl Heyes 2007-10-23 22:25:31 +00:00
parent 9379e4e051
commit 4b5f00993d
6 changed files with 176 additions and 18 deletions

View File

@ -66,19 +66,6 @@ static void htpasswd_clear(auth_t *self) {
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,8 +82,6 @@ static char *get_hash(const char *data, int len)
return util_bin_to_hex(digest, 16);
}
#define MAX_LINE_LEN 512
static int compare_users (void *arg, void *a, void *b)
{

View File

@ -192,6 +192,8 @@ void config_clear(ice_config_t *c)
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 @@ static void _parse_paths(xmlDocPtr doc, xmlNodePtr node,
} 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);

View File

@ -156,6 +156,8 @@ typedef struct ice_config_tag
char *base_dir;
char *log_dir;
char *pidfile;
char *banfile;
char *allowfile;
char *cert_file;
char *webroot_dir;
char *adminroot_dir;

View File

@ -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 @@ typedef struct _thread_queue_tag {
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 int ssl_ok;
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 @@ void connection_initialize(void)
_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 @@ void connection_shutdown(void)
#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 @@ static int connection_send (connection_t *con, const void *buf, size_t len)
}
/* 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 int wait_for_serversock(int timeout)
static connection_t *_accept_connection(void)
{
int sock;
connection_t *con;
char *ip;
int serversock;
@ -406,11 +537,13 @@ static connection_t *_accept_connection(void)
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 connection_setup_sockets (ice_config_t *config)
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 @@ int connection_setup_sockets (ice_config_t *config)
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));

View File

@ -673,3 +673,18 @@ char *util_conv_string (const char *string, const char *in_charset, const char *
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;
}

View File

@ -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 @@ struct tm *localtime_r (const time_t *timep, struct tm *result);
#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__ */