Add an object that can check the authorization of requests.
Implement basic authentication.
Add example authentication to test-video
GstRTSPServer *server;
GstRTSPMediaMapping *mapping;
GstRTSPMediaFactory *factory;
+ GstRTSPAuth *auth;
+ gchar *basic;
gst_init (&argc, &argv);
* that be used to map uri mount points to media factories */
mapping = gst_rtsp_server_get_media_mapping (server);
+ /* make a new authentication manager */
+ auth = gst_rtsp_auth_new ();
+ basic = gst_rtsp_auth_make_basic ("user", "admin");
+ gst_rtsp_auth_set_basic (auth, basic);
+ g_free (basic);
+ /* configure in the server */
+ gst_rtsp_server_set_auth (server, auth);
+
/* make a media factory for a test stream. The default media factory can use
* gst-launch syntax to create pipelines.
* any launch line works as long as it contains elements named pay%d. Each
public_headers = \
rtsp-funnel.h \
+ rtsp-auth.h \
rtsp-params.h \
rtsp-sdp.h \
rtsp-media.h \
c_sources = \
rtsp-funnel.c \
+ rtsp-auth.c \
rtsp-params.c \
rtsp-sdp.c \
rtsp-media.c \
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2010 Wim Taymans <wim.taymans at gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+
+#include "rtsp-auth.h"
+
+enum
+{
+ PROP_0,
+ PROP_LAST
+};
+
+GST_DEBUG_CATEGORY_STATIC (rtsp_auth_debug);
+#define GST_CAT_DEFAULT rtsp_auth_debug
+
+static void gst_rtsp_auth_get_property (GObject * object, guint propid,
+ GValue * value, GParamSpec * pspec);
+static void gst_rtsp_auth_set_property (GObject * object, guint propid,
+ const GValue * value, GParamSpec * pspec);
+static void gst_rtsp_auth_finalize (GObject * obj);
+
+static gboolean default_check_method (GstRTSPAuth * auth, GstRTSPMethod method,
+ GstRTSPClient * client, GstRTSPUrl * uri, GstRTSPSession * session,
+ GstRTSPMessage * request);
+
+G_DEFINE_TYPE (GstRTSPAuth, gst_rtsp_auth, G_TYPE_OBJECT);
+
+static void
+gst_rtsp_auth_class_init (GstRTSPAuthClass * klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->get_property = gst_rtsp_auth_get_property;
+ gobject_class->set_property = gst_rtsp_auth_set_property;
+ gobject_class->finalize = gst_rtsp_auth_finalize;
+
+ klass->check_method = default_check_method;
+
+ GST_DEBUG_CATEGORY_INIT (rtsp_auth_debug, "rtspauth", 0, "GstRTSPAuth");
+}
+
+static void
+gst_rtsp_auth_init (GstRTSPAuth * auth)
+{
+ /* bitwise or of all methods that need authentication */
+ auth->methods = GST_RTSP_DESCRIBE |
+ GST_RTSP_ANNOUNCE |
+ GST_RTSP_GET_PARAMETER |
+ GST_RTSP_SET_PARAMETER |
+ GST_RTSP_PAUSE |
+ GST_RTSP_PLAY | GST_RTSP_RECORD | GST_RTSP_SETUP | GST_RTSP_TEARDOWN;
+}
+
+static void
+gst_rtsp_auth_finalize (GObject * obj)
+{
+ GstRTSPAuth *auth = GST_RTSP_AUTH (obj);
+
+ GST_INFO ("finalize auth %p", auth);
+
+ G_OBJECT_CLASS (gst_rtsp_auth_parent_class)->finalize (obj);
+}
+
+static void
+gst_rtsp_auth_get_property (GObject * object, guint propid,
+ GValue * value, GParamSpec * pspec)
+{
+ GstRTSPAuth *auth = GST_RTSP_AUTH (object);
+
+ switch (propid) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
+ }
+}
+
+static void
+gst_rtsp_auth_set_property (GObject * object, guint propid,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstRTSPAuth *auth = GST_RTSP_AUTH (object);
+
+ switch (propid) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
+ }
+}
+
+/**
+ * gst_rtsp_auth_new:
+ *
+ * Create a new #GstRTSPAuth instance.
+ *
+ * Returns: a new #GstRTSPAuth
+ */
+GstRTSPAuth *
+gst_rtsp_auth_new (void)
+{
+ GstRTSPAuth *result;
+
+ result = g_object_new (GST_TYPE_RTSP_AUTH, NULL);
+
+ return result;
+}
+
+/**
+ * gst_rtsp_auth_set_basic:
+ * @auth: a #GstRTSPAuth
+ * @basic: the basic token
+ *
+ * Set the basic token for the default authentication algorithm.
+ */
+void
+gst_rtsp_auth_set_basic (GstRTSPAuth * auth, const gchar * basic)
+{
+ g_free (auth->basic);
+ auth->basic = g_strdup (basic);
+}
+
+static gboolean
+default_check_method (GstRTSPAuth * auth, GstRTSPMethod method,
+ GstRTSPClient * client, GstRTSPUrl * uri, GstRTSPSession * session,
+ GstRTSPMessage * request)
+{
+ gboolean result = TRUE;
+ GstRTSPResult res;
+
+ if (method & auth->methods != 0) {
+ gchar *authorization;
+
+ result = FALSE;
+
+ res =
+ gst_rtsp_message_get_header (request, GST_RTSP_HDR_AUTHORIZATION,
+ &authorization, 0);
+ if (res < 0)
+ goto no_auth;
+
+ /* parse type */
+ if (g_ascii_strncasecmp (authorization, "basic ", 6) == 0) {
+ GST_DEBUG_OBJECT (auth, "check Basic auth");
+ if (auth->basic && strcmp (&authorization[6], auth->basic) == 0)
+ result = TRUE;
+ } else if (g_ascii_strncasecmp (authorization, "digest ", 7) == 0) {
+ GST_DEBUG_OBJECT (auth, "check Digest auth");
+ /* not implemented yet */
+ result = FALSE;
+ }
+ }
+ return result;
+
+no_auth:
+ {
+ GST_DEBUG_OBJECT (auth, "no authorization header found");
+ return FALSE;
+ }
+}
+
+/**
+ * gst_rtsp_auth_check_method:
+ * @auth: a #GstRTSPAuth
+ * @method: method to check
+ * @client: the client
+ * @uri: the requested uri
+ * @session: the session
+ * @request: the request
+ *
+ * Check if @client is allowed to perform @method for the @uri in
+ * @session and with @request.
+ *
+ * Returns: FALSE if the method is not allowed.
+ */
+gboolean
+gst_rtsp_auth_check_method (GstRTSPAuth * auth, GstRTSPMethod method,
+ GstRTSPClient * client, GstRTSPUrl * uri, GstRTSPSession * session,
+ GstRTSPMessage * request)
+{
+ gboolean result = FALSE;
+ GstRTSPAuthClass *klass;
+
+ klass = GST_RTSP_AUTH_GET_CLASS (auth);
+
+ GST_DEBUG_OBJECT (auth, "check method %d", method);
+
+ if (klass->check_method)
+ result = klass->check_method (auth, method, client, uri, session, request);
+
+ return result;
+}
+
+gchar *
+gst_rtsp_auth_make_basic (const gchar * user, const gchar * pass)
+{
+ gchar *user_pass;
+ gchar *result;
+
+ user_pass = g_strjoin (":", user, pass, NULL);
+ result = g_base64_encode ((guchar *) user_pass, strlen (user_pass));
+ g_free (user_pass);
+
+ return result;
+}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2010 Wim Taymans <wim.taymans at gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <gst/gst.h>
+
+#ifndef __GST_RTSP_AUTH_H__
+#define __GST_RTSP_AUTH_H__
+
+typedef struct _GstRTSPAuth GstRTSPAuth;
+typedef struct _GstRTSPAuthClass GstRTSPAuthClass;
+
+#include "rtsp-client.h"
+#include "rtsp-media-mapping.h"
+#include "rtsp-session-pool.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_RTSP_AUTH (gst_rtsp_auth_get_type ())
+#define GST_IS_RTSP_AUTH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_AUTH))
+#define GST_IS_RTSP_AUTH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_AUTH))
+#define GST_RTSP_AUTH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_AUTH, GstRTSPAuthClass))
+#define GST_RTSP_AUTH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_AUTH, GstRTSPAuth))
+#define GST_RTSP_AUTH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_AUTH, GstRTSPAuthClass))
+#define GST_RTSP_AUTH_CAST(obj) ((GstRTSPAuth*)(obj))
+#define GST_RTSP_AUTH_CLASS_CAST(klass) ((GstRTSPAuthClass*)(klass))
+
+/**
+ * GstRTSPAuth:
+ *
+ * The authentication structure.
+ */
+struct _GstRTSPAuth {
+ GObject parent;
+
+ /*< private >*/
+ gchar *basic;
+ GstRTSPMethod methods;
+};
+
+struct _GstRTSPAuthClass {
+ GObjectClass parent_class;
+
+ gboolean (*check_method) (GstRTSPAuth *auth, GstRTSPMethod method,
+ GstRTSPClient * client, GstRTSPUrl * uri,
+ GstRTSPSession * session, GstRTSPMessage * request);
+};
+
+GType gst_rtsp_auth_get_type (void);
+
+GstRTSPAuth * gst_rtsp_auth_new (void);
+
+void gst_rtsp_auth_set_basic (GstRTSPAuth *auth, const gchar * basic);
+
+gboolean gst_rtsp_auth_check_method (GstRTSPAuth *auth, GstRTSPMethod method,
+ GstRTSPClient * client, GstRTSPUrl * uri,
+ GstRTSPSession * session, GstRTSPMessage * request);
+
+/* helpers */
+gchar * gst_rtsp_auth_make_basic (const gchar * user, const gchar * pass);
+
+G_END_DECLS
+
+#endif /* __GST_RTSP_AUTH_H__ */
}
static gboolean
+handle_unauthorized_request (GstRTSPClient * client, GstRTSPUrl * uri,
+ GstRTSPSession * session, GstRTSPMessage * request)
+{
+ GstRTSPMessage response = { 0 };
+
+ gst_rtsp_message_init_response (&response, GST_RTSP_STS_UNAUTHORIZED,
+ gst_rtsp_status_as_text (GST_RTSP_STS_UNAUTHORIZED), request);
+ gst_rtsp_message_add_header (&response, GST_RTSP_HDR_WWW_AUTHENTICATE,
+ "Basic ");
+
+ send_response (client, session, &response);
+ return;
+}
+
+
+static gboolean
compare_uri (const GstRTSPUrl * uri1, const GstRTSPUrl * uri2)
{
if (uri1 == NULL || uri2 == NULL)
} else
session = NULL;
+ if (client->auth) {
+ if (!gst_rtsp_auth_check_method (client->auth, method, client, uri, session,
+ request))
+ goto not_authorized;
+ }
+
/* now see what is asked and dispatch to a dedicated handler */
switch (method) {
case GST_RTSP_OPTIONS:
send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, request);
return;
}
+not_authorized:
+ {
+ handle_unauthorized_request (client, uri, session, request);
+ return;
+ }
}
static void
return result;
}
+/**
+ * gst_rtsp_client_set_auth:
+ * @client: a #GstRTSPClient
+ * @auth: a #GstRTSPAuth
+ *
+ * configure @auth to be used as the authentication manager of @client.
+ */
+void
+gst_rtsp_client_set_auth (GstRTSPClient * client, GstRTSPAuth * auth)
+{
+ GstRTSPAuth *old;
+
+ g_return_if_fail (GST_IS_RTSP_CLIENT (client));
+
+ old = client->auth;
+
+ if (old != auth) {
+ if (auth)
+ g_object_ref (auth);
+ client->auth = auth;
+ if (old)
+ g_object_unref (old);
+ }
+}
+
+
+/**
+ * gst_rtsp_client_get_auth:
+ * @client: a #GstRTSPClient
+ *
+ * Get the #GstRTSPAuth used as the authentication manager of @client.
+ *
+ * Returns: the #GstRTSPAuth of @client. g_object_unref() after
+ * usage.
+ */
+GstRTSPAuth *
+gst_rtsp_client_get_auth (GstRTSPClient * client)
+{
+ GstRTSPAuth *result;
+
+ g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL);
+
+ if ((result = client->auth))
+ g_object_ref (result);
+
+ return result;
+}
+
static GstRTSPResult
message_received (GstRTSPWatch * watch, GstRTSPMessage * message,
gpointer user_data)
typedef struct _GstRTSPClient GstRTSPClient;
typedef struct _GstRTSPClientClass GstRTSPClientClass;
+#include "rtsp-auth.h"
+
/**
* GstRTSPClient:
*
GstRTSPSessionPool *session_pool;
GstRTSPMediaMapping *media_mapping;
+ GstRTSPAuth *auth;
GstRTSPUrl *uri;
GstRTSPMedia *media;
GstRTSPMediaMapping *mapping);
GstRTSPMediaMapping * gst_rtsp_client_get_media_mapping (GstRTSPClient *client);
+void gst_rtsp_client_set_auth (GstRTSPClient *client, GstRTSPAuth *auth);
+GstRTSPAuth * gst_rtsp_client_get_auth (GstRTSPClient *client);
+
+
gboolean gst_rtsp_client_accept (GstRTSPClient *client,
GIOChannel *channel);
* Boston, MA 02111-1307, USA.
*/
+#include <sys/ioctl.h>
+
#include "rtsp-server.h"
#include "rtsp-client.h"
return result;
}
+/**
+ * gst_rtsp_server_set_auth:
+ * @server: a #GstRTSPServer
+ * @auth: a #GstRTSPAuth
+ *
+ * configure @auth to be used as the authentication manager of @server.
+ */
+void
+gst_rtsp_server_set_auth (GstRTSPServer * server, GstRTSPAuth * auth)
+{
+ GstRTSPAuth *old;
+
+ g_return_if_fail (GST_IS_RTSP_SERVER (server));
+
+ old = server->auth;
+
+ if (old != auth) {
+ if (auth)
+ g_object_ref (auth);
+ server->auth = auth;
+ if (old)
+ g_object_unref (old);
+ }
+}
+
+
+/**
+ * gst_rtsp_server_get_auth:
+ * @server: a #GstRTSPServer
+ *
+ * Get the #GstRTSPAuth used as the authentication manager of @server.
+ *
+ * Returns: the #GstRTSPAuth of @server. g_object_unref() after
+ * usage.
+ */
+GstRTSPAuth *
+gst_rtsp_server_get_auth (GstRTSPServer * server)
+{
+ GstRTSPAuth *result;
+
+ g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
+
+ if ((result = server->auth))
+ g_object_ref (result);
+
+ return result;
+}
+
static void
gst_rtsp_server_get_property (GObject * object, guint propid,
GValue * value, GParamSpec * pspec)
gst_rtsp_client_set_session_pool (client, server->session_pool);
/* set the media mapping that this client should use */
gst_rtsp_client_set_media_mapping (client, server->media_mapping);
+ /* set authentication manager */
+ gst_rtsp_client_set_auth (client, server->auth);
/* accept connections for that client, this function returns after accepting
* the connection and will run the remainder of the communication with the
#include "rtsp-media-mapping.h"
#include "rtsp-media-factory-uri.h"
#include "rtsp-client.h"
+#include "rtsp-auth.h"
#ifndef __GST_RTSP_SERVER_H__
#define __GST_RTSP_SERVER_H__
/* media mapper for this server */
GstRTSPMediaMapping *media_mapping;
+
+ /* authentication manager */
+ GstRTSPAuth *auth;
};
/**
void gst_rtsp_server_set_media_mapping (GstRTSPServer *server, GstRTSPMediaMapping *mapping);
GstRTSPMediaMapping * gst_rtsp_server_get_media_mapping (GstRTSPServer *server);
+void gst_rtsp_server_set_auth (GstRTSPServer *server, GstRTSPAuth *auth);
+GstRTSPAuth * gst_rtsp_server_get_auth (GstRTSPServer *server);
+
gboolean gst_rtsp_server_io_func (GIOChannel *channel, GIOCondition condition,
GstRTSPServer *server);