diff --git a/conf/icecast.xml b/conf/icecast.xml index 40c21ad0..a39aef74 100644 --- a/conf/icecast.xml +++ b/conf/icecast.xml @@ -12,6 +12,7 @@ hackme + hackme 5 @@ -28,6 +29,7 @@ + /usr/local/icecast diff --git a/src/config.c b/src/config.c index fab97587..6f37f7c4 100644 --- a/src/config.c +++ b/src/config.c @@ -14,6 +14,7 @@ #define CONFIG_DEFAULT_HEADER_TIMEOUT 15 #define CONFIG_DEFAULT_SOURCE_TIMEOUT 10 #define CONFIG_DEFAULT_SOURCE_PASSWORD "changeme" +#define CONFIG_DEFAULT_RELAY_PASSWORD "changeme" #define CONFIG_DEFAULT_ICE_LOGIN 0 #define CONFIG_DEFAULT_TOUCH_FREQ 5 #define CONFIG_DEFAULT_HOSTNAME "localhost" @@ -69,6 +70,8 @@ void config_shutdown(void) xmlFree(c->admin); if (c->source_password && c->source_password != CONFIG_DEFAULT_SOURCE_PASSWORD) xmlFree(c->source_password); + if (c->relay_password && c->relay_password != CONFIG_DEFAULT_SOURCE_PASSWORD) + xmlFree(c->relay_password); if (c->hostname && c->hostname != CONFIG_DEFAULT_HOSTNAME) xmlFree(c->hostname); if (c->base_dir && c->base_dir != CONFIG_DEFAULT_BASE_DIR) @@ -157,6 +160,7 @@ static void _set_defaults(void) _configuration.header_timeout = CONFIG_DEFAULT_HEADER_TIMEOUT; _configuration.source_timeout = CONFIG_DEFAULT_SOURCE_TIMEOUT; _configuration.source_password = CONFIG_DEFAULT_SOURCE_PASSWORD; + _configuration.relay_password = CONFIG_DEFAULT_RELAY_PASSWORD; _configuration.ice_login = CONFIG_DEFAULT_ICE_LOGIN; _configuration.touch_freq = CONFIG_DEFAULT_TOUCH_FREQ; _configuration.dir_list = NULL; @@ -166,6 +170,7 @@ static void _set_defaults(void) _configuration.master_server = NULL; _configuration.master_server_port = CONFIG_DEFAULT_PORT; _configuration.master_update_interval = CONFIG_MASTER_UPDATE_INTERVAL; + _configuration.master_password = NULL; _configuration.base_dir = CONFIG_DEFAULT_BASE_DIR; _configuration.log_dir = CONFIG_DEFAULT_LOG_DIR; _configuration.webroot_dir = CONFIG_DEFAULT_WEBROOT_DIR; @@ -202,6 +207,9 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node) if (_configuration.source_password && _configuration.source_password != CONFIG_DEFAULT_SOURCE_PASSWORD) xmlFree(_configuration.source_password); _configuration.source_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); } + } else if (strcmp(node->name, "relay-password") == 0) { + if (_configuration.relay_password && _configuration.relay_password != CONFIG_DEFAULT_RELAY_PASSWORD) xmlFree(_configuration.relay_password); + _configuration.relay_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); } else if (strcmp(node->name, "icelogin") == 0) { tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); _configuration.ice_login = atoi(tmp); @@ -219,6 +227,9 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node) } else if (strcmp(node->name, "master-server") == 0) { if (_configuration.master_server) xmlFree(_configuration.master_server); _configuration.master_server = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + } else if (strcmp(node->name, "master-password") == 0) { + if (_configuration.master_password) xmlFree(_configuration.master_password); + _configuration.master_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); } else if (strcmp(node->name, "master-server-port") == 0) { tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); _configuration.master_server_port = atoi(tmp); diff --git a/src/config.h b/src/config.h index 4bd0f4c7..d407e421 100644 --- a/src/config.h +++ b/src/config.h @@ -27,6 +27,7 @@ typedef struct ice_config_tag int ice_login; char *source_password; + char *relay_password; int touch_freq; ice_config_dir_t *dir_list; @@ -37,6 +38,7 @@ typedef struct ice_config_tag char *master_server; int master_server_port; int master_update_interval; + char *master_password; char *base_dir; char *log_dir; diff --git a/src/connection.c b/src/connection.c index 5cf0ac38..b3a25f5f 100644 --- a/src/connection.c +++ b/src/connection.c @@ -337,7 +337,7 @@ fail: return 0; } -static int _check_source_pass_http(http_parser_t *parser) +static int _check_source_pass_http(http_parser_t *parser, char *correctuser) { /* This will look something like "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" */ char *header = httpp_getvar(parser, "authorization"); @@ -368,7 +368,7 @@ static int _check_source_pass_http(http_parser_t *parser) username = userpass; password = tmp+1; - if(strcmp(username, "source") || strcmp(password, correctpass)) { + if(strcmp(username, correctuser) || strcmp(password, correctpass)) { free(userpass); return 0; } @@ -393,12 +393,12 @@ static int _check_source_pass_ice(http_parser_t *parser) return 1; } -static int _check_source_pass(http_parser_t *parser) +static int _check_source_pass(http_parser_t *parser, char *user) { if(config_get_config()->ice_login) return _check_source_pass_ice(parser); else - return _check_source_pass_http(parser); + return _check_source_pass_http(parser, user); } static void _handle_source_request(connection_t *con, @@ -411,8 +411,8 @@ static void _handle_source_request(connection_t *con, INFO1("Source logging in at mountpoint \"%s\"", uri); stats_event_inc(NULL, "source_connections"); - if (!_check_source_pass(parser)) { - INFO1("Source (%s) attempted to login with bad password", uri); + if (!_check_source_pass(parser, "source")) { + INFO1("Source (%s) attempted to login with invalid or missing password", uri); client_send_401(client); return; } @@ -442,7 +442,7 @@ static void _handle_stats_request(connection_t *con, stats_event_inc(NULL, "stats_connections"); - if (!_check_source_pass(parser)) { + if (!_check_source_pass(parser, "stats")) { ERROR0("Bad password for stats connection"); connection_close(con); httpp_destroy(parser); @@ -486,8 +486,8 @@ static void _handle_get_request(connection_t *con, */ /* TODO: add GUID-xxxxxx */ if (strcmp(uri, "/stats.xml") == 0) { - if (!_check_source_pass(parser)) { - INFO1("Source (%s) attempted to login with bad password", uri); + if (!_check_source_pass(parser, "stats")) { + INFO0("Request for stats.xml with incorrect or no password"); client_send_401(client); return; } @@ -548,7 +548,7 @@ static void _handle_get_request(connection_t *con, } if (strcmp(uri, "/allstreams.txt") == 0) { - if (!_check_source_pass(parser)) { + if (!_check_source_pass(parser, "relay")) { INFO0("Client attempted to fetch allstreams.txt with bad password"); client_send_401(client); } else { diff --git a/src/slave.c b/src/slave.c index 3450aa92..9902c880 100644 --- a/src/slave.c +++ b/src/slave.c @@ -72,6 +72,9 @@ static void *_slave_thread(void *arg) { http_parser_t *parser; client_t *client; int interval = config_get_config()->master_update_interval; + char *authheader, *data; + int len; + char *username = "relay"; while (_initialized) { if (config_get_config()->master_update_interval > ++interval) { @@ -86,8 +89,15 @@ static void *_slave_thread(void *arg) { WARN0("Relay slave failed to contact master server to fetch stream list"); continue; } - // FIXME: This is now broken... - sock_write(mastersock, "GET /allstreams.txt HTTP/1.0\r\nice-password: %s\r\n\r\n", config_get_config()->source_password); + + len = strlen(username) + strlen(config_get_config()->master_password) + 1; + authheader = malloc(len+1); + strcpy(authheader, username); + strcat(authheader, ":"); + strcat(authheader, config_get_config()->master_password); + data = util_base64_encode(authheader); + sock_write(mastersock, "GET /allstreams.txt HTTP/1.0\r\nAuthorization: Basic %s\r\n\r\n", data); + free(data); while (sock_read_line(mastersock, buf, sizeof(buf))) { buf[strlen(buf)] = 0; avl_tree_rlock(global.source_tree);