[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