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 GHashTable *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 (GstRTSPAuth * auth, GstRTSPClient * client,
50 GstRTSPClientState * state);
51 static gboolean default_authenticate (GstRTSPAuth * auth,
52 GstRTSPClient * client, GstRTSPClientState * state);
53 static gboolean default_check (GstRTSPAuth * auth, GstRTSPClient * client,
54 GQuark hint, GstRTSPClientState * state);
56 G_DEFINE_TYPE (GstRTSPAuth, gst_rtsp_auth, G_TYPE_OBJECT);
59 gst_rtsp_auth_class_init (GstRTSPAuthClass * klass)
61 GObjectClass *gobject_class;
63 g_type_class_add_private (klass, sizeof (GstRTSPAuthPrivate));
65 gobject_class = G_OBJECT_CLASS (klass);
67 gobject_class->get_property = gst_rtsp_auth_get_property;
68 gobject_class->set_property = gst_rtsp_auth_set_property;
69 gobject_class->finalize = gst_rtsp_auth_finalize;
71 klass->setup = default_setup;
72 klass->authenticate = default_authenticate;
73 klass->check = default_check;
75 GST_DEBUG_CATEGORY_INIT (rtsp_auth_debug, "rtspauth", 0, "GstRTSPAuth");
79 gst_rtsp_auth_init (GstRTSPAuth * auth)
81 GstRTSPAuthPrivate *priv;
83 auth->priv = priv = GST_RTSP_AUTH_GET_PRIVATE (auth);
85 g_mutex_init (&priv->lock);
87 priv->basic = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
88 (GDestroyNotify) gst_rtsp_token_unref);
90 /* bitwise or of all methods that need authentication */
91 priv->methods = GST_RTSP_DESCRIBE |
93 GST_RTSP_GET_PARAMETER |
94 GST_RTSP_SET_PARAMETER |
96 GST_RTSP_PLAY | GST_RTSP_RECORD | GST_RTSP_SETUP | GST_RTSP_TEARDOWN;
100 gst_rtsp_auth_finalize (GObject * obj)
102 GstRTSPAuth *auth = GST_RTSP_AUTH (obj);
103 GstRTSPAuthPrivate *priv = auth->priv;
105 GST_INFO ("finalize auth %p", auth);
106 g_hash_table_unref (priv->basic);
107 g_mutex_clear (&priv->lock);
109 G_OBJECT_CLASS (gst_rtsp_auth_parent_class)->finalize (obj);
113 gst_rtsp_auth_get_property (GObject * object, guint propid,
114 GValue * value, GParamSpec * pspec)
118 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
123 gst_rtsp_auth_set_property (GObject * object, guint propid,
124 const GValue * value, GParamSpec * pspec)
128 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
135 * Create a new #GstRTSPAuth instance.
137 * Returns: a new #GstRTSPAuth
140 gst_rtsp_auth_new (void)
144 result = g_object_new (GST_TYPE_RTSP_AUTH, NULL);
150 * gst_rtsp_auth_add_basic:
151 * @auth: a #GstRTSPAuth
152 * @basic: the basic token
153 * @authgroup: authorisation group
155 * Add a basic token for the default authentication algorithm that
156 * enables the client qith privileges from @authgroup.
159 gst_rtsp_auth_add_basic (GstRTSPAuth * auth, const gchar * basic,
160 GstRTSPToken * token)
162 GstRTSPAuthPrivate *priv;
164 g_return_if_fail (GST_IS_RTSP_AUTH (auth));
165 g_return_if_fail (basic != NULL);
166 g_return_if_fail (GST_IS_RTSP_TOKEN (token));
170 g_mutex_lock (&priv->lock);
171 g_hash_table_replace (priv->basic, g_strdup (basic),
172 gst_rtsp_token_ref (token));
173 g_mutex_unlock (&priv->lock);
177 * gst_rtsp_auth_remove_basic:
178 * @auth: a #GstRTSPAuth
179 * @basic: (transfer none): the basic token
181 * Add a basic token for the default authentication algorithm that
182 * enables the client qith privileges from @authgroup.
185 gst_rtsp_auth_remove_basic (GstRTSPAuth * auth, const gchar * basic)
187 GstRTSPAuthPrivate *priv;
189 g_return_if_fail (GST_IS_RTSP_AUTH (auth));
190 g_return_if_fail (basic != NULL);
194 g_mutex_lock (&priv->lock);
195 g_hash_table_remove (priv->basic, basic);
196 g_mutex_unlock (&priv->lock);
200 default_setup (GstRTSPAuth * auth, GstRTSPClient * client,
201 GstRTSPClientState * state)
203 if (state->response == NULL)
206 /* we only have Basic for now */
207 gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_WWW_AUTHENTICATE,
208 "Basic realm=\"GStreamer RTSP Server\"");
214 * gst_rtsp_auth_setup:
215 * @auth: a #GstRTSPAuth
216 * @client: the client
219 * Add authentication tokens to @response.
221 * Returns: FALSE if something is wrong.
224 gst_rtsp_auth_setup (GstRTSPAuth * auth, GstRTSPClient * client,
225 GstRTSPClientState * state)
227 gboolean result = FALSE;
228 GstRTSPAuthClass *klass;
230 g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), FALSE);
231 g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), FALSE);
232 g_return_val_if_fail (state != NULL, FALSE);
234 klass = GST_RTSP_AUTH_GET_CLASS (auth);
236 GST_DEBUG_OBJECT (auth, "setup auth");
239 result = klass->setup (auth, client, state);
245 default_authenticate (GstRTSPAuth * auth, GstRTSPClient * client,
246 GstRTSPClientState * state)
248 GstRTSPAuthPrivate *priv = auth->priv;
250 gchar *authorization;
252 GST_DEBUG_OBJECT (auth, "authenticate");
255 gst_rtsp_message_get_header (state->request, GST_RTSP_HDR_AUTHORIZATION,
261 if (g_ascii_strncasecmp (authorization, "basic ", 6) == 0) {
264 GST_DEBUG_OBJECT (auth, "check Basic auth");
265 g_mutex_lock (&priv->lock);
266 if ((token = g_hash_table_lookup (priv->basic, &authorization[6]))) {
267 GST_DEBUG_OBJECT (auth, "setting token %p", token);
268 state->token = token;
270 g_mutex_unlock (&priv->lock);
271 } else if (g_ascii_strncasecmp (authorization, "digest ", 7) == 0) {
272 GST_DEBUG_OBJECT (auth, "check Digest auth");
273 /* not implemented yet */
279 GST_DEBUG_OBJECT (auth, "no authorization header found");
285 default_check (GstRTSPAuth * auth, GstRTSPClient * client,
286 GQuark hint, GstRTSPClientState * state)
288 GstRTSPAuthPrivate *priv = auth->priv;
289 GstRTSPAuthClass *klass;
291 klass = GST_RTSP_AUTH_GET_CLASS (auth);
293 if ((state->method & priv->methods) != 0) {
294 /* we need an authgroup to check */
295 if (state->token == NULL) {
296 if (klass->authenticate) {
297 if (!klass->authenticate (auth, client, state))
298 goto authenticate_failed;
302 if (state->token == NULL)
309 GST_DEBUG_OBJECT (auth, "check failed");
314 GST_DEBUG_OBJECT (auth, "no authorization group found");
320 * gst_rtsp_auth_check:
321 * @auth: a #GstRTSPAuth
322 * @client: the client
324 * @state: client state
326 * Check if @client with state is authorized to perform @hint in the
329 * Returns: FALSE if check failed.
332 gst_rtsp_auth_check (GstRTSPAuth * auth, GstRTSPClient * client,
333 GQuark hint, GstRTSPClientState * state)
335 gboolean result = FALSE;
336 GstRTSPAuthClass *klass;
338 g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), FALSE);
339 g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), FALSE);
340 g_return_val_if_fail (state != NULL, FALSE);
342 klass = GST_RTSP_AUTH_GET_CLASS (auth);
344 GST_DEBUG_OBJECT (auth, "check auth");
347 result = klass->check (auth, client, hint, state);
353 * gst_rtsp_auth_make_basic:
357 * Construct a Basic authorisation token from @user and @pass.
359 * Returns: the base64 encoding of the string @user:@pass. g_free()
363 gst_rtsp_auth_make_basic (const gchar * user, const gchar * pass)
368 g_return_val_if_fail (user != NULL, NULL);
369 g_return_val_if_fail (pass != NULL, NULL);
371 user_pass = g_strjoin (":", user, pass, NULL);
372 result = g_base64_encode ((guchar *) user_pass, strlen (user_pass));