[xiph-cvs] cvs commit: icecast/src client.c client.h config.c config.h connection.c connection.h global.c slave.c source.c source.h util.c util.h
Michael Smith
msmith at xiph.org
Fri Aug 16 07:26:48 PDT 2002
msmith 02/08/16 10:26:48
Modified: src client.c client.h config.c config.h connection.c
connection.h global.c slave.c source.c source.h
util.c util.h
Log:
HTTP Basic source login support. The old "ice-password" method is still
available, but is deprecated and turned off by default.
Revision Changes Path
1.3 +9 -0 icecast/src/client.c
Index: client.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/client.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- client.c 12 Aug 2002 14:48:31 -0000 1.2
+++ client.c 16 Aug 2002 14:26:47 -0000 1.3
@@ -55,3 +55,12 @@
client_destroy(client);
}
+void client_send_401(client_t *client) {
+ int bytes = sock_write(client->con->sock,
+ "HTTP/1.0 401 Authentication Required\r\n"
+ "WWW-Authenticate: Basic realm=\"Icecast2 Server\"\r\n"
+ "\r\n"
+ "You need to authenticate\r\n");
+ if(bytes > 0) client->con->sent_bytes = bytes;
+ client_destroy(client);
+}
<p><p>1.3 +1 -0 icecast/src/client.h
Index: client.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/client.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- client.h 12 Aug 2002 14:48:31 -0000 1.2
+++ client.h 16 Aug 2002 14:26:47 -0000 1.3
@@ -25,5 +25,6 @@
client_t *client_create(connection_t *con, http_parser_t *parser);
void client_destroy(client_t *client);
void client_send_404(client_t *client, char *message);
+void client_send_401(client_t *client);
#endif /* __CLIENT_H__ */
<p><p>1.17 +6 -0 icecast/src/config.c
Index: config.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/config.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- config.c 11 Aug 2002 14:00:56 -0000 1.16
+++ config.c 16 Aug 2002 14:26:47 -0000 1.17
@@ -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_ICE_LOGIN 0
#define CONFIG_DEFAULT_TOUCH_FREQ 5
#define CONFIG_DEFAULT_HOSTNAME "localhost"
#define CONFIG_DEFAULT_PORT 8888
@@ -156,6 +157,7 @@
_configuration.header_timeout = CONFIG_DEFAULT_HEADER_TIMEOUT;
_configuration.source_timeout = CONFIG_DEFAULT_SOURCE_TIMEOUT;
_configuration.source_password = CONFIG_DEFAULT_SOURCE_PASSWORD;
+ _configuration.ice_login = CONFIG_DEFAULT_ICE_LOGIN;
_configuration.touch_freq = CONFIG_DEFAULT_TOUCH_FREQ;
_configuration.dir_list = NULL;
_configuration.hostname = CONFIG_DEFAULT_HOSTNAME;
@@ -200,6 +202,10 @@
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, "icelogin") == 0) {
+ tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+ _configuration.ice_login = atoi(tmp);
+ if (tmp) xmlFree(tmp);
} else if (strcmp(node->name, "hostname") == 0) {
if (_configuration.hostname && _configuration.hostname != CONFIG_DEFAULT_HOSTNAME) xmlFree(_configuration.hostname);
_configuration.hostname = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
<p><p>1.8 +1 -0 icecast/src/config.h
Index: config.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/config.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- config.h 9 Aug 2002 08:11:37 -0000 1.7
+++ config.h 16 Aug 2002 14:26:47 -0000 1.8
@@ -24,6 +24,7 @@
int client_timeout;
int header_timeout;
int source_timeout;
+ int ice_login;
char *source_password;
<p><p>1.23 +70 -11 icecast/src/connection.c
Index: connection.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/connection.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- connection.c 12 Aug 2002 14:48:31 -0000 1.22
+++ connection.c 16 Aug 2002 14:26:48 -0000 1.23
@@ -286,9 +286,11 @@
return con;
}
-int connection_create_source(connection_t *con, http_parser_t *parser, char *mount) {
+int connection_create_source(client_t *client, connection_t *con, http_parser_t *parser, char *mount) {
source_t *source;
char *contenttype;
+ int bytes;
+
/* check to make sure this source wouldn't
** be over the limit
*/
@@ -311,12 +313,16 @@
WARN1("Content-type \"%s\" not supported, dropping source", contenttype);
goto fail;
} else {
- source = source_create(con, parser, mount, format);
+ source = source_create(client, con, parser, mount, format);
}
} else {
WARN0("No content-type header, cannot handle source");
goto fail;
}
+ bytes = sock_write(client->con->sock,
+ "HTTP/1.0 200 OK\r\n\r\n");
+ if(bytes > 0) client->con->sent_bytes = bytes;
+
source->shutdown_rwlock = &_source_shutdown_rwlock;
sock_set_blocking(con->sock, SOCK_NONBLOCK);
thread_create("Source Thread", source_main, (void *)source, THREAD_DETACHED);
@@ -331,7 +337,46 @@
return 0;
}
-static int _check_source_pass(http_parser_t *parser)
+static int _check_source_pass_http(http_parser_t *parser)
+{
+ /* This will look something like "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" */
+ char *header = httpp_getvar(parser, "authorization");
+ char *userpass, *tmp;
+ char *username, *password;
+ char *correctpass;
+
+ correctpass = config_get_config()->source_password;
+ if(!correctpass)
+ correctpass = "";
+
+ if(header == NULL)
+ return 0;
+
+ if(strncmp(header, "Basic ", 6))
+ return 0;
+
+ userpass = util_base64_decode(header+6);
+ if(userpass == NULL)
+ return 0;
+
+ tmp = strchr(userpass, ':');
+ if(!tmp) {
+ free(userpass);
+ return 0;
+ }
+ *tmp = 0;
+ username = userpass;
+ password = tmp+1;
+
+ if(strcmp(username, "source") || strcmp(password, correctpass)) {
+ free(userpass);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int _check_source_pass_ice(http_parser_t *parser)
{
char *password, *correctpass;
@@ -348,16 +393,27 @@
return 1;
}
+static int _check_source_pass(http_parser_t *parser)
+{
+ if(config_get_config()->ice_login)
+ return _check_source_pass_ice(parser);
+ else
+ return _check_source_pass_http(parser);
+}
+
static void _handle_source_request(connection_t *con,
http_parser_t *parser, char *uri)
{
+ client_t *client;
+
+ client = client_create(con, parser);
+
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);
- connection_close(con);
- httpp_destroy(parser);
+ client_send_401(client);
return;
}
@@ -368,16 +424,14 @@
avl_tree_rlock(global.source_tree);
if (source_find_mount(uri) != NULL) {
INFO1("Source tried to log in as %s, but mountpoint is already used", uri);
- connection_close(con);
- httpp_destroy(parser);
+ client_send_404(client, "Mountpoint in use");
avl_tree_unlock(global.source_tree);
return;
}
avl_tree_unlock(global.source_tree);
- if (!connection_create_source(con, parser, uri)) {
- connection_close(con);
- httpp_destroy(parser);
+ if (!connection_create_source(client, con, parser, uri)) {
+ client_destroy(client);
}
}
@@ -432,6 +486,11 @@
*/
/* 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);
+ client_send_401(client);
+ return;
+ }
DEBUG0("Stats request, sending xml stats");
stats_sendxml(client);
client_destroy(client);
@@ -491,7 +550,7 @@
if (strcmp(uri, "/allstreams.txt") == 0) {
if (!_check_source_pass(parser)) {
INFO0("Client attempted to fetch allstreams.txt with bad password");
- client_send_404(client, "Bad ice-password");
+ client_send_401(client);
} else {
avl_node *node;
source_t *s;
<p><p>1.6 +4 -2 icecast/src/connection.h
Index: connection.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/connection.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- connection.h 5 Aug 2002 14:48:01 -0000 1.5
+++ connection.h 16 Aug 2002 14:26:48 -0000 1.6
@@ -7,6 +7,8 @@
#include "thread.h"
#include "sock.h"
+struct _client_tag;
+
typedef struct connection_tag
{
unsigned long id;
@@ -26,8 +28,8 @@
void connection_accept_loop(void);
void connection_close(connection_t *con);
connection_t *create_connection(sock_t sock, char *ip);
-int connection_create_source(connection_t *con, http_parser_t *parser,
- char *mount);
+int connection_create_source(struct _client_tag *client, connection_t *con,
+ http_parser_t *parser, char *mount);
extern rwlock_t _source_shutdown_rwlock;
<p><p>1.2 +1 -0 icecast/src/global.c
Index: global.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/global.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- global.c 10 Sep 2001 02:21:51 -0000 1.1
+++ global.c 16 Aug 2002 14:26:48 -0000 1.2
@@ -5,6 +5,7 @@
#include "connection.h"
#include "refbuf.h"
#include "format.h"
+#include "client.h"
#include "source.h"
#include "global.h"
<p><p>1.4 +5 -3 icecast/src/slave.c
Index: slave.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/slave.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- slave.c 10 Aug 2002 03:22:44 -0000 1.3
+++ slave.c 16 Aug 2002 14:26:48 -0000 1.4
@@ -70,6 +70,7 @@
char header[4096];
connection_t *con;
http_parser_t *parser;
+ client_t *client;
int interval = config_get_config()->master_update_interval;
while (_initialized) {
@@ -85,6 +86,7 @@
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);
while (sock_read_line(mastersock, buf, sizeof(buf))) {
buf[strlen(buf)] = 0;
@@ -119,10 +121,10 @@
continue;
}
- if (!connection_create_source(con, parser,
+ client = client_create(con, parser);
+ if (!connection_create_source(client, con, parser,
httpp_getvar(parser, HTTPP_VAR_URI))) {
- connection_close(con);
- httpp_destroy(parser);
+ client_destroy(client);
}
continue;
<p><p>1.20 +3 -3 icecast/src/source.c
Index: source.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/source.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- source.c 11 Aug 2002 12:15:40 -0000 1.19
+++ source.c 16 Aug 2002 14:26:48 -0000 1.20
@@ -39,11 +39,12 @@
static int _remove_client(void *key);
static int _free_client(void *key);
-source_t *source_create(connection_t *con, http_parser_t *parser, const char *mount, format_type_t type)
+source_t *source_create(client_t *client, connection_t *con, http_parser_t *parser, const char *mount, format_type_t type)
{
source_t *src;
src = (source_t *)malloc(sizeof(source_t));
+ src->client = client;
src->mount = (char *)strdup(mount);
src->format = format_get_plugin(type, src->mount);
src->con = con;
@@ -94,8 +95,7 @@
source_t *source = (source_t *)key;
free(source->mount);
- connection_close(source->con);
- httpp_destroy(source->parser);
+ client_destroy(source->client);
avl_tree_free(source->pending_tree, _free_client);
avl_tree_free(source->client_tree, _free_client);
source->format->free_plugin(source->format);
<p><p>1.2 +2 -1 icecast/src/source.h
Index: source.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/source.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- source.h 10 Sep 2001 02:21:52 -0000 1.1
+++ source.h 16 Aug 2002 14:26:48 -0000 1.2
@@ -3,6 +3,7 @@
typedef struct source_tag
{
+ client_t *client;
connection_t *con;
http_parser_t *parser;
@@ -15,7 +16,7 @@
rwlock_t *shutdown_rwlock;
} source_t;
-source_t *source_create(connection_t *con, http_parser_t *parser, const char *mount, format_type_t type);
+source_t *source_create(client_t *client, connection_t *con, http_parser_t *parser, const char *mount, format_type_t type);
source_t *source_find_mount(const char *mount);
int source_compare_sources(void *arg, void *a, void *b);
int source_free_source(void *key);
<p><p>1.11 +99 -0 icecast/src/util.c
Index: util.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/util.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- util.c 13 Aug 2002 01:08:15 -0000 1.10
+++ util.c 16 Aug 2002 14:26:48 -0000 1.11
@@ -268,3 +268,102 @@
}
}
+static char base64table[64] = {
+ 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
+ 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
+ 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
+ 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
+};
+
+/* This isn't efficient, but it doesn't need to be */
+char *util_base64_encode(char *data)
+{
+ int len = strlen(data);
+ char *out = malloc(len*4/3 + 4);
+ char *result = out;
+ int chunk;
+
+ while(len > 0) {
+ chunk = (len >3)?3:len;
+ *out++ = base64table[(*data & 0xFC)>>2];
+ *out++ = base64table[((*data & 0x03)<<4) | ((*(data+1) & 0xF0) >> 4)];
+ switch(chunk) {
+ case 3:
+ *out++ = base64table[((*(data+1) & 0x0F)<<2) | ((*(data+2) & 0xC0)>>6)];
+ *out++ = base64table[(*(data+2)) & 0x3F];
+ break;
+ case 2:
+ *out++ = base64table[((*(data+1) & 0x0F)<<2)];
+ *out++ = '=';
+ break;
+ case 1:
+ *out++ = '=';
+ *out++ = '=';
+ break;
+ }
+ data += chunk;
+ len -= chunk;
+ }
+
+ return result;
+}
+
+static int base64chartoval(char input)
+{
+ if(input >= 'A' && input <= 'Z')
+ return input - 'A';
+ else if(input >= 'a' && input <= 'z')
+ return input - 'a' + 26;
+ else if(input >= '0' && input <= '9')
+ return input - '0' + 52;
+ else if(input == '+')
+ return 62;
+ else if(input == '/')
+ return 63;
+ else if(input == '=')
+ return -1;
+ else
+ return -2;
+}
+
+char *util_base64_decode(char *input)
+{
+ int len = strlen(input);
+ char *out = malloc(len*3/4 + 5);
+ char *result = out;
+ signed char vals[4];
+
+ while(len > 0) {
+ if(len < 4)
+ {
+ free(result);
+ return NULL; /* Invalid Base64 data */
+ }
+
+ vals[0] = base64chartoval(*input++);
+ vals[1] = base64chartoval(*input++);
+ vals[2] = base64chartoval(*input++);
+ vals[3] = base64chartoval(*input++);
+
+ if(vals[0] < 0 || vals[1] < 0 || vals[2] < -1 || vals[3] < -1) {
+ continue;
+ }
+
+ *out++ = vals[0]<<2 | vals[1]>>4;
+ if(vals[2] >= 0)
+ *out++ = ((vals[1]&0x0F)<<4) | (vals[2]>>2);
+ else
+ *out++ = 0;
+
+ if(vals[3] >= 0)
+ *out++ = ((vals[2]&0x03)<<6) | (vals[3]);
+ else
+ *out++ = 0;
+
+ len -= 4;
+ }
+ *out = 0;
+
+ return result;
+}
+
<p><p>1.7 +2 -0 icecast/src/util.h
Index: util.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/util.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- util.h 11 Aug 2002 14:23:39 -0000 1.6
+++ util.h 16 Aug 2002 14:26:48 -0000 1.7
@@ -11,5 +11,7 @@
char *util_get_path_from_uri(char *uri);
char *util_get_path_from_normalised_uri(char *uri);
char *util_normalise_uri(char *uri);
+char *util_base64_encode(char *data);
+char *util_base64_decode(char *input);
#endif /* __UTIL_H__ */
<p><p>--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list