2 * Copyright (C) 2010 Wim Taymans <wim.taymans at gmail.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
22 #include "rtsp-auth.h"
24 #define GST_RTSP_AUTH_GET_PRIVATE(obj) \
25 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_AUTH, GstRTSPAuthPrivate))
27 struct _GstRTSPAuthPrivate
30 gchar *basic; /* protected by lock */
31 GstRTSPMethod methods;
40 GST_DEBUG_CATEGORY_STATIC (rtsp_auth_debug);
41 #define GST_CAT_DEFAULT rtsp_auth_debug
43 static void gst_rtsp_auth_get_property (GObject * object, guint propid,
44 GValue * value, GParamSpec * pspec);
45 static void gst_rtsp_auth_set_property (GObject * object, guint propid,
46 const GValue * value, GParamSpec * pspec);
47 static void gst_rtsp_auth_finalize (GObject * obj);
49 static gboolean default_setup_auth (GstRTSPAuth * auth, GstRTSPClient * client,
50 GQuark hint, GstRTSPClientState * state);
51 static gboolean default_check_method (GstRTSPAuth * auth,
52 GstRTSPClient * client, GQuark hint, GstRTSPClientState * state);
54 G_DEFINE_TYPE (GstRTSPAuth, gst_rtsp_auth, G_TYPE_OBJECT);
57 gst_rtsp_auth_class_init (GstRTSPAuthClass * klass)
59 GObjectClass *gobject_class;
61 g_type_class_add_private (klass, sizeof (GstRTSPAuthPrivate));
63 gobject_class = G_OBJECT_CLASS (klass);
65 gobject_class->get_property = gst_rtsp_auth_get_property;
66 gobject_class->set_property = gst_rtsp_auth_set_property;
67 gobject_class->finalize = gst_rtsp_auth_finalize;
69 klass->setup_auth = default_setup_auth;
70 klass->check_method = default_check_method;
72 GST_DEBUG_CATEGORY_INIT (rtsp_auth_debug, "rtspauth", 0, "GstRTSPAuth");
76 gst_rtsp_auth_init (GstRTSPAuth * auth)
78 auth->priv = GST_RTSP_AUTH_GET_PRIVATE (auth);
80 g_mutex_init (&auth->priv->lock);
81 /* bitwise or of all methods that need authentication */
82 auth->priv->methods = GST_RTSP_DESCRIBE |
84 GST_RTSP_GET_PARAMETER |
85 GST_RTSP_SET_PARAMETER |
87 GST_RTSP_PLAY | GST_RTSP_RECORD | GST_RTSP_SETUP | GST_RTSP_TEARDOWN;
91 gst_rtsp_auth_finalize (GObject * obj)
93 GstRTSPAuth *auth = GST_RTSP_AUTH (obj);
94 GstRTSPAuthPrivate *priv = auth->priv;
96 GST_INFO ("finalize auth %p", auth);
98 g_mutex_clear (&priv->lock);
100 G_OBJECT_CLASS (gst_rtsp_auth_parent_class)->finalize (obj);
104 gst_rtsp_auth_get_property (GObject * object, guint propid,
105 GValue * value, GParamSpec * pspec)
109 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
114 gst_rtsp_auth_set_property (GObject * object, guint propid,
115 const GValue * value, GParamSpec * pspec)
119 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
126 * Create a new #GstRTSPAuth instance.
128 * Returns: a new #GstRTSPAuth
131 gst_rtsp_auth_new (void)
135 result = g_object_new (GST_TYPE_RTSP_AUTH, NULL);
141 * gst_rtsp_auth_set_basic:
142 * @auth: a #GstRTSPAuth
143 * @basic: the basic token
145 * Set the basic token for the default authentication algorithm.
148 gst_rtsp_auth_set_basic (GstRTSPAuth * auth, const gchar * basic)
150 GstRTSPAuthPrivate *priv;
152 g_return_if_fail (GST_IS_RTSP_AUTH (auth));
156 g_mutex_lock (&priv->lock);
157 g_free (priv->basic);
158 priv->basic = g_strdup (basic);
159 g_mutex_unlock (&priv->lock);
163 default_setup_auth (GstRTSPAuth * auth, GstRTSPClient * client,
164 GQuark hint, GstRTSPClientState * state)
166 if (state->response == NULL)
169 /* we only have Basic for now */
170 gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_WWW_AUTHENTICATE,
171 "Basic realm=\"GStreamer RTSP Server\"");
177 * gst_rtsp_auth_setup_auth:
178 * @auth: a #GstRTSPAuth
179 * @client: the client
183 * Add authentication tokens to @response.
185 * Returns: FALSE if something is wrong.
188 gst_rtsp_auth_setup_auth (GstRTSPAuth * auth, GstRTSPClient * client,
189 GQuark hint, GstRTSPClientState * state)
191 gboolean result = FALSE;
192 GstRTSPAuthClass *klass;
194 g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), FALSE);
195 g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), FALSE);
196 g_return_val_if_fail (state != NULL, FALSE);
198 klass = GST_RTSP_AUTH_GET_CLASS (auth);
200 GST_DEBUG_OBJECT (auth, "setup auth");
202 if (klass->setup_auth)
203 result = klass->setup_auth (auth, client, hint, state);
209 default_check_method (GstRTSPAuth * auth, GstRTSPClient * client,
210 GQuark hint, GstRTSPClientState * state)
212 GstRTSPAuthPrivate *priv = auth->priv;
213 gboolean result = TRUE;
216 if ((state->method & priv->methods) != 0) {
217 gchar *authorization;
222 gst_rtsp_message_get_header (state->request, GST_RTSP_HDR_AUTHORIZATION,
228 if (g_ascii_strncasecmp (authorization, "basic ", 6) == 0) {
229 GST_DEBUG_OBJECT (auth, "check Basic auth");
230 g_mutex_lock (&priv->lock);
231 if (priv->basic && strcmp (&authorization[6], priv->basic) == 0)
233 g_mutex_unlock (&priv->lock);
234 } else if (g_ascii_strncasecmp (authorization, "digest ", 7) == 0) {
235 GST_DEBUG_OBJECT (auth, "check Digest auth");
236 /* not implemented yet */
244 GST_DEBUG_OBJECT (auth, "no authorization header found");
250 * gst_rtsp_auth_check:
251 * @auth: a #GstRTSPAuth
252 * @client: the client
254 * @state: client state
256 * Check if @client is allowed to perform the actions of @state.
258 * Returns: FALSE if the action is not allowed.
261 gst_rtsp_auth_check (GstRTSPAuth * auth, GstRTSPClient * client,
262 GQuark hint, GstRTSPClientState * state)
264 gboolean result = FALSE;
265 GstRTSPAuthClass *klass;
267 g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), FALSE);
268 g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), FALSE);
269 g_return_val_if_fail (state != NULL, FALSE);
271 klass = GST_RTSP_AUTH_GET_CLASS (auth);
273 GST_DEBUG_OBJECT (auth, "check state");
275 if (klass->check_method)
276 result = klass->check_method (auth, client, hint, state);
282 * gst_rtsp_auth_make_basic:
286 * Construct a Basic authorisation token from @user and @pass.
288 * Returns: the base64 encoding of the string @user:@pass. g_free()
292 gst_rtsp_auth_make_basic (const gchar * user, const gchar * pass)
297 g_return_val_if_fail (user != NULL, NULL);
298 g_return_val_if_fail (pass != NULL, NULL);
300 user_pass = g_strjoin (":", user, pass, NULL);
301 result = g_base64_encode ((guchar *) user_pass, strlen (user_pass));