[xiph-commits] r9714 - in icecast/trunk/icecast: . src

karl at svn.xiph.org karl at svn.xiph.org
Sun Aug 7 16:29:16 PDT 2005


Author: karl
Date: 2005-08-07 16:29:12 -0700 (Sun, 07 Aug 2005)
New Revision: 9714

Added:
   icecast/trunk/icecast/src/auth_url.c
   icecast/trunk/icecast/src/auth_url.h
Modified:
   icecast/trunk/icecast/configure.in
   icecast/trunk/icecast/src/Makefile.am
   icecast/trunk/icecast/src/auth.c
Log:
merge URL listener auth


Modified: icecast/trunk/icecast/configure.in
===================================================================
--- icecast/trunk/icecast/configure.in	2005-08-07 23:01:04 UTC (rev 9713)
+++ icecast/trunk/icecast/configure.in	2005-08-07 23:29:12 UTC (rev 9714)
@@ -106,24 +106,27 @@
 XIPH_VAR_APPEND([XIPH_CPPFLAGS],[$PTHREAD_CPPFLAGS])
 XIPH_VAR_PREPEND([XIPH_LIBS],[$PTHREAD_LIBS])
 
-dnl -- YP support --
-AC_ARG_ENABLE([yp],
-        AC_HELP_STRING([--disable-yp],[disable YP directory support]),
-        enable_yp="$enableval",
-        enable_yp="yes")
-if test "x$enable_yp" = "xyes"
-then
 XIPH_PATH_CURL([
     AC_CHECK_DECL([CURLOPT_NOSIGNAL],
-        [ AC_DEFINE([USE_YP], 1, [Define to compile in YP support code])
-        ICECAST_OPTIONAL="$ICECAST_OPTIONAL yp.o"
+        [ AC_DEFINE([HAVE_AUTH_URL], 1, [Define to compile in auth URL support code])
+        ICECAST_OPTIONAL="$ICECAST_OPTIONAL auth_url.o"
+        enable_curl="yes"
         XIPH_VAR_APPEND([XIPH_CPPFLAGS],[$CURL_CFLAGS])
         XIPH_VAR_PREPEND([XIPH_LIBS],[$CURL_LIBS])
         ], [ AC_MSG_NOTICE([Your curl dev files are too old (7.10 or above required), YP disabled])
         ], [#include <curl/curl.h>
         ])
-    ],[ AC_MSG_NOTICE([libcurl not found, YP disabled])
+    ],[ AC_MSG_NOTICE([libcurl not found])
     ])
+dnl -- YP support --
+AC_ARG_ENABLE([yp],
+        AC_HELP_STRING([--disable-yp],[disable YP directory support]),
+        enable_yp="$enableval",
+        enable_yp="yes")
+if test "x$enable_yp" = "xyes" -a "x$enable_curl" = xyes
+then
+    AC_DEFINE([USE_YP], 1, [Define to compile in YP support code])
+    ICECAST_OPTIONAL="$ICECAST_OPTIONAL yp.o"
 else
     AC_MSG_NOTICE([YP support disabled])
 fi

Modified: icecast/trunk/icecast/src/Makefile.am
===================================================================
--- icecast/trunk/icecast/src/Makefile.am	2005-08-07 23:01:04 UTC (rev 9713)
+++ icecast/trunk/icecast/src/Makefile.am	2005-08-07 23:29:12 UTC (rev 9714)
@@ -9,7 +9,7 @@
 noinst_HEADERS = admin.h cfgfile.h os.h logging.h sighandler.h connection.h \
     global.h util.h slave.h source.h stats.h refbuf.h client.h \
     compat.h fserve.h xslt.h yp.h event.h md5.h \
-    auth.h auth_htpasswd.h \
+    auth.h auth_htpasswd.h auth_url.h \
     format.h format_ogg.h format_mp3.h \
     format_vorbis.h format_theora.h format_flac.h format_speex.h format_midi.h
 icecast_SOURCES = cfgfile.c main.c logging.c sighandler.c connection.c global.c \
@@ -18,6 +18,7 @@
     format.c format_ogg.c format_mp3.c format_midi.c format_flac.c \
     auth.c auth_htpasswd.c
 EXTRA_icecast_SOURCES = yp.c \
+    auth_url.c \
     format_vorbis.c format_theora.c format_speex.c
     
 icecast_DEPENDENCIES = @ICECAST_OPTIONAL@ net/libicenet.la thread/libicethread.la \

Modified: icecast/trunk/icecast/src/auth.c
===================================================================
--- icecast/trunk/icecast/src/auth.c	2005-08-07 23:01:04 UTC (rev 9713)
+++ icecast/trunk/icecast/src/auth.c	2005-08-07 23:29:12 UTC (rev 9714)
@@ -25,6 +25,7 @@
 
 #include "auth.h"
 #include "auth_htpasswd.h"
+#include "auth_url.h"
 #include "source.h"
 #include "client.h"
 #include "cfgfile.h"
@@ -423,6 +424,13 @@
     do
     {
         DEBUG1 ("type is %s", auth->type);
+#ifdef HAVE_AUTH_URL
+        if (strcmp (auth->type, "url") == 0)
+        {
+            auth_get_url_auth (auth, options);
+            break;
+        }
+#endif
         if (strcmp (auth->type, "htpasswd") == 0)
         {
             auth_get_htpasswd_auth (auth, options);

Added: icecast/trunk/icecast/src/auth_url.c
===================================================================
--- icecast/trunk/icecast/src/auth_url.c	2005-08-07 23:01:04 UTC (rev 9713)
+++ icecast/trunk/icecast/src/auth_url.c	2005-08-07 23:29:12 UTC (rev 9714)
@@ -0,0 +1,421 @@
+/* Icecast
+ *
+ * This program is distributed under the GNU General Public License, version 2.
+ * A copy of this license is included with this source.
+ *
+ * Copyright 2000-2004, Jack Moffitt <jack at xiph.org>, 
+ *                      Michael Smith <msmith at xiph.org>,
+ *                      oddsock <oddsock at xiph.org>,
+ *                      Karl Heyes <karl at xiph.org>
+ *                      and others (see AUTHORS for details).
+ */
+
+/* 
+ * Client authentication via URL functions
+ *
+ * authenticate user via a URL, this is done via libcurl so https can also
+ * be handled. The request will have POST information about the request in
+ * the form of
+ *
+ * action=auth&client=1&server=host&port=8000&mount=/live&user=fred&pass=mypass&ip=127.0.0.1&agent=""
+ *
+ * For a user to be accecpted the following HTTP header needs
+ * to be returned (the actual string can be specified in the xml file)
+ *
+ * icecast-auth-user: 1
+ *
+ * On client disconnection another request can be sent to a URL with the POST
+ * information of
+ *
+ * action=remove&server=host&port=8000&client=1&mount=/live&user=fred&pass=mypass&duration=3600
+ *
+ * client refers to the icecast client identification number. mount refers
+ * to the mountpoint (beginning with / and may contain query parameters eg ?&
+ * encoded) and duration is the amount of time in seconds. user and pass
+ * setting can be blank
+ *
+ * On stream start and end, another url can be issued to help clear any user
+ * info stored at the auth server. Useful for abnormal outage/termination
+ * cases.
+ *
+ * action=start&mount=/live&server=myserver.com&port=8000
+ * action=end&mount=/live&server=myserver.com&port=8000
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#ifndef _WIN32
+#include <sys/wait.h>
+#include <strings.h>
+#else
+#define snprintf _snprintf
+#define strncasecmp strnicmp
+#endif
+
+#include <curl/curl.h>
+
+#include "auth.h"
+#include "source.h"
+#include "client.h"
+#include "cfgfile.h"
+#include "httpp/httpp.h"
+
+#include "logging.h"
+#define CATMODULE "auth_url"
+
+typedef struct {
+    char *addurl;
+    char *removeurl;
+    char *stream_start;
+    char *stream_end;
+    char *username;
+    char *password;
+    char *auth_header;
+    int  auth_header_len;
+    CURL *handle;
+    char errormsg [CURL_ERROR_SIZE];
+} auth_url;
+
+
+static void auth_url_clear(auth_t *self)
+{
+    auth_url *url = self->state;
+    curl_easy_cleanup (url->handle);
+    free (url->username);
+    free (url->password);
+    free (url->removeurl);
+    free (url->addurl);
+    free (url->stream_start);
+    free (url->stream_end);
+    free (url->auth_header);
+    free (url);
+}
+
+
+static int handle_returned_header (void *ptr, size_t size, size_t nmemb, void *stream)
+{
+    auth_client *auth_user = stream;
+    unsigned bytes = size * nmemb;
+    client_t *client = auth_user->client;
+
+    if (client)
+    {
+        auth_t *auth = client->auth;
+        auth_url *url = auth->state;
+        if (strncasecmp (ptr, url->auth_header, url->auth_header_len) == 0)
+            client->authenticated = 1;
+        if (strncasecmp (ptr, "icecast-auth-message: ", 22) == 0)
+        {
+            char *eol;
+            snprintf (url->errormsg, sizeof (url->errormsg), "%s", (char*)ptr+22);
+            eol = strchr (url->errormsg, '\r');
+            if (eol == NULL)
+                eol = strchr (url->errormsg, '\n');
+            if (eol)
+                *eol = '\0';
+        }
+    }
+
+    return (int)bytes;
+}
+
+/* capture returned data, but don't do anything with it */
+static int handle_returned_data (void *ptr, size_t size, size_t nmemb, void *stream)
+{
+    return (int)(size*nmemb);
+}
+
+
+static auth_result url_remove_client (auth_client *auth_user)
+{
+    client_t *client = auth_user->client;
+    auth_t *auth = client->auth;
+    auth_url *url = auth->state;
+    time_t duration = time(NULL) - client->con->con_time;
+    char *username, *password, *mount, *server;
+    ice_config_t *config;
+    int port;
+    char post [4096];
+
+    config = config_get_config ();
+    server = util_url_escape (config->hostname);
+    port = config->port;
+    config_release_config ();
+
+    if (client->username)
+        username = util_url_escape (client->username);
+    else
+        username = strdup ("");
+
+    if (client->password)
+        password = util_url_escape (client->password);
+    else
+        password = strdup ("");
+
+    /* get the full uri (with query params if available) */
+    mount = httpp_getvar (client->parser, HTTPP_VAR_RAWURI);
+    if (mount == NULL)
+        mount = httpp_getvar (client->parser, HTTPP_VAR_URI);
+    mount = util_url_escape (mount);
+
+    snprintf (post, sizeof (post),
+            "action=remove&server=%s&port=%d&client=%lu&mount=%s"
+            "&user=%s&pass=%s&duration=%lu",
+            server, port, client->con->id, mount, username,
+            password, (long unsigned)duration);
+    free (server);
+    free (mount);
+    free (username);
+    free (password);
+
+    curl_easy_setopt (url->handle, CURLOPT_URL, url->removeurl);
+    curl_easy_setopt (url->handle, CURLOPT_POSTFIELDS, post);
+    curl_easy_setopt (url->handle, CURLOPT_WRITEHEADER, auth_user);
+
+    if (curl_easy_perform (url->handle))
+        WARN2 ("auth to server %s failed with %s", url->removeurl, url->errormsg);
+
+    return AUTH_OK;
+}
+
+
+static auth_result url_add_client (auth_client *auth_user)
+{
+    client_t *client = auth_user->client;
+    auth_t *auth = client->auth;
+    auth_url *url = auth->state;
+    int res = 0, port;
+    char *agent, *user_agent, *username, *password;
+    char *mount, *ipaddr, *server;
+    ice_config_t *config;
+    char post [4096];
+
+    if (url->addurl == NULL)
+        return AUTH_OK;
+
+    config = config_get_config ();
+    server = util_url_escape (config->hostname);
+    port = config->port;
+    config_release_config ();
+    agent = httpp_getvar (client->parser, "user-agent");
+    if (agent == NULL)
+        agent = "-";
+    user_agent = util_url_escape (agent);
+    if (client->username)
+        username  = util_url_escape (client->username);
+    else
+        username = strdup ("");
+    if (client->password)
+        password  = util_url_escape (client->password);
+    else
+        password = strdup ("");
+
+    /* get the full uri (with query params if available) */
+    mount = httpp_getvar (client->parser, HTTPP_VAR_RAWURI);
+    if (mount == NULL)
+        mount = httpp_getvar (client->parser, HTTPP_VAR_URI);
+    mount = util_url_escape (mount);
+    ipaddr = util_url_escape (client->con->ip);
+
+    snprintf (post, sizeof (post),
+            "action=auth&server=%s&port=%d&client=%lu&mount=%s"
+            "&user=%s&pass=%s&ip=%s&agent=%s",
+            server, port, client->con->id, mount, username,
+            password, ipaddr, user_agent);
+    free (server);
+    free (mount);
+    free (user_agent);
+    free (username);
+    free (password);
+    free (ipaddr);
+
+    curl_easy_setopt (url->handle, CURLOPT_URL, url->addurl);
+    curl_easy_setopt (url->handle, CURLOPT_POSTFIELDS, post);
+    curl_easy_setopt (url->handle, CURLOPT_WRITEHEADER, auth_user);
+    url->errormsg[0] = '\0';
+
+    res = curl_easy_perform (url->handle);
+
+    if (res)
+    {
+        WARN2 ("auth to server %s failed with %s", url->addurl, url->errormsg);
+        return AUTH_FAILED;
+    }
+    /* we received a response, lets see what it is */
+    if (client->authenticated)
+        return AUTH_OK;
+    INFO2 ("client auth (%s) failed with \"%s\"", url->addurl, url->errormsg);
+    return AUTH_FAILED;
+}
+
+
+/* called by auth thread when a source starts, there is no client_t in
+ * this case
+ */
+static void url_stream_start (auth_client *auth_user)
+{
+    char *mount, *server;
+    ice_config_t *config = config_get_config ();
+    mount_proxy *mountinfo = config_find_mount (config, auth_user->mount);
+    auth_t *auth = mountinfo->auth;
+    auth_url *url = auth->state;
+    char *stream_start_url;
+    int port;
+    char post [4096];
+
+    if (url->stream_start == NULL)
+    {
+        config_release_config ();
+        return;
+    }
+    server = util_url_escape (config->hostname);
+    port = config->port;
+    stream_start_url = strdup (url->stream_start);
+    /* we don't want this auth disappearing from under us while
+     * the connection is in progress */
+    mountinfo->auth->refcount++;
+    config_release_config ();
+    mount = util_url_escape (auth_user->mount);
+
+    snprintf (post, sizeof (post),
+            "action=start&mount=%s&server=%s&port=%d", mount, server, port);
+    free (server);
+    free (mount);
+
+    curl_easy_setopt (url->handle, CURLOPT_URL, stream_start_url);
+    curl_easy_setopt (url->handle, CURLOPT_POSTFIELDS, post);
+    curl_easy_setopt (url->handle, CURLOPT_WRITEHEADER, auth_user);
+
+    if (curl_easy_perform (url->handle))
+        WARN2 ("auth to server %s failed with %s", stream_start_url, url->errormsg);
+
+    auth_release (auth);
+    free (stream_start_url);
+    return;
+}
+
+
+static void url_stream_end (auth_client *auth_user)
+{
+    char *mount, *server;
+    ice_config_t *config = config_get_config ();
+    mount_proxy *mountinfo = config_find_mount (config, auth_user->mount);
+    auth_t *auth = mountinfo->auth;
+    auth_url *url = auth->state;
+    char *stream_end_url;
+    int port;
+    char post [4096];
+
+    if (url->stream_end == NULL)
+    {
+        config_release_config ();
+        return;
+    }
+    server = util_url_escape (config->hostname);
+    port = config->port;
+    stream_end_url = strdup (url->stream_end);
+    /* we don't want this auth disappearing from under us while
+     * the connection is in progress */
+    mountinfo->auth->refcount++;
+    config_release_config ();
+    mount = util_url_escape (auth_user->mount);
+
+    snprintf (post, sizeof (post),
+            "action=end&mount=%s&server=%s&port=%d", mount, server, port);
+    free (server);
+    free (mount);
+
+    curl_easy_setopt (url->handle, CURLOPT_URL, stream_end_url);
+    curl_easy_setopt (url->handle, CURLOPT_POSTFIELDS, post);
+    curl_easy_setopt (url->handle, CURLOPT_WRITEHEADER, auth_user);
+
+    if (curl_easy_perform (url->handle))
+        WARN2 ("auth to server %s failed with %s", stream_end_url, url->errormsg);
+
+    auth_release (auth);
+    free (stream_end_url);
+    return;
+}
+
+
+static auth_result auth_url_adduser(auth_t *auth, const char *username, const char *password)
+{
+    return AUTH_FAILED;
+}
+
+static auth_result auth_url_deleteuser (auth_t *auth, const char *username)
+{
+    return AUTH_FAILED;
+}
+
+static auth_result auth_url_listuser (auth_t *auth, xmlNodePtr srcnode)
+{
+    return AUTH_FAILED;
+}
+
+int auth_get_url_auth (auth_t *authenticator, config_options_t *options)
+{
+    auth_url *url_info;
+
+    authenticator->authenticate = url_add_client;
+    authenticator->release_client = url_remove_client;
+
+    authenticator->free = auth_url_clear;
+    authenticator->adduser = auth_url_adduser;
+    authenticator->deleteuser = auth_url_deleteuser;
+    authenticator->listuser = auth_url_listuser;
+
+    authenticator->stream_start = url_stream_start;
+    authenticator->stream_end = url_stream_end;
+
+    url_info = calloc(1, sizeof(auth_url));
+    url_info->auth_header = strdup ("icecast-auth-user: 1\r\n");
+
+    while(options) {
+        if(!strcmp(options->name, "username"))
+            url_info->username = strdup (options->value);
+        if(!strcmp(options->name, "password"))
+            url_info->password = strdup (options->value);
+        if(!strcmp(options->name, "add"))
+            url_info->addurl = strdup (options->value);
+        if(!strcmp(options->name, "remove"))
+            url_info->removeurl = strdup (options->value);
+        if(!strcmp(options->name, "start"))
+            url_info->stream_start = strdup (options->value);
+        if(!strcmp(options->name, "end"))
+            url_info->stream_end = strdup (options->value);
+        if(!strcmp(options->name, "auth_header"))
+        {
+            free (url_info->auth_header);
+            url_info->auth_header = strdup (options->value);
+        }
+        options = options->next;
+    }
+    url_info->handle = curl_easy_init ();
+    if (url_info->handle == NULL)
+    {
+        free (url_info);
+        return -1;
+    }
+    if (url_info->auth_header)
+        url_info->auth_header_len = strlen (url_info->auth_header);
+
+    curl_easy_setopt (url_info->handle, CURLOPT_USERAGENT, ICECAST_VERSION_STRING);
+    curl_easy_setopt (url_info->handle, CURLOPT_HEADERFUNCTION, handle_returned_header);
+    curl_easy_setopt (url_info->handle, CURLOPT_WRITEFUNCTION, handle_returned_data);
+    curl_easy_setopt (url_info->handle, CURLOPT_WRITEDATA, url_info->handle);
+    curl_easy_setopt (url_info->handle, CURLOPT_NOSIGNAL, 1L);
+    curl_easy_setopt (url_info->handle, CURLOPT_TIMEOUT, 15L);
+    curl_easy_setopt (url_info->handle, CURLOPT_ERRORBUFFER, &url_info->errormsg[0]);
+
+    authenticator->state = url_info;
+    INFO0("URL based authentication setup");
+    return 0;
+}
+

Added: icecast/trunk/icecast/src/auth_url.h
===================================================================
--- icecast/trunk/icecast/src/auth_url.h	2005-08-07 23:01:04 UTC (rev 9713)
+++ icecast/trunk/icecast/src/auth_url.h	2005-08-07 23:29:12 UTC (rev 9714)
@@ -0,0 +1,24 @@
+/* Icecast
+ *
+ * This program is distributed under the GNU General Public License, version 2.
+ * A copy of this license is included with this source.
+ *
+ * Copyright 2000-2004, Jack Moffitt <jack at xiph.org, 
+ *                      Michael Smith <msmith at xiph.org>,
+ *                      oddsock <oddsock at xiph.org>,
+ *                      Karl Heyes <karl at xiph.org>
+ *                      and others (see AUTHORS for details).
+ */
+
+#ifndef __AUTH_URL_H__
+#define __AUTH_URL_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+int *auth_get_url_auth (auth_t *authenticator, config_options_t *options);
+
+#endif
+
+



More information about the commits mailing list