rtsp-client: don't use g_object_unref on GstRTSPSessionMedia
[platform/upstream/gstreamer.git] / gst / rtsp-server / rtsp-auth.c
1 /* GStreamer
2  * Copyright (C) 2010 Wim Taymans <wim.taymans at gmail.com>
3  *
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.
8  *
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.
13  *
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., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <string.h>
21
22 #include "rtsp-auth.h"
23
24 enum
25 {
26   PROP_0,
27   PROP_LAST
28 };
29
30 GST_DEBUG_CATEGORY_STATIC (rtsp_auth_debug);
31 #define GST_CAT_DEFAULT rtsp_auth_debug
32
33 static void gst_rtsp_auth_get_property (GObject * object, guint propid,
34     GValue * value, GParamSpec * pspec);
35 static void gst_rtsp_auth_set_property (GObject * object, guint propid,
36     const GValue * value, GParamSpec * pspec);
37 static void gst_rtsp_auth_finalize (GObject * obj);
38
39 static gboolean default_setup_auth (GstRTSPAuth * auth, GstRTSPClient * client,
40     GQuark hint, GstRTSPClientState * state);
41 static gboolean default_check_method (GstRTSPAuth * auth,
42     GstRTSPClient * client, GQuark hint, GstRTSPClientState * state);
43
44 G_DEFINE_TYPE (GstRTSPAuth, gst_rtsp_auth, G_TYPE_OBJECT);
45
46 static void
47 gst_rtsp_auth_class_init (GstRTSPAuthClass * klass)
48 {
49   GObjectClass *gobject_class;
50
51   gobject_class = G_OBJECT_CLASS (klass);
52
53   gobject_class->get_property = gst_rtsp_auth_get_property;
54   gobject_class->set_property = gst_rtsp_auth_set_property;
55   gobject_class->finalize = gst_rtsp_auth_finalize;
56
57   klass->setup_auth = default_setup_auth;
58   klass->check_method = default_check_method;
59
60   GST_DEBUG_CATEGORY_INIT (rtsp_auth_debug, "rtspauth", 0, "GstRTSPAuth");
61 }
62
63 static void
64 gst_rtsp_auth_init (GstRTSPAuth * auth)
65 {
66   /* bitwise or of all methods that need authentication */
67   auth->methods = GST_RTSP_DESCRIBE |
68       GST_RTSP_ANNOUNCE |
69       GST_RTSP_GET_PARAMETER |
70       GST_RTSP_SET_PARAMETER |
71       GST_RTSP_PAUSE |
72       GST_RTSP_PLAY | GST_RTSP_RECORD | GST_RTSP_SETUP | GST_RTSP_TEARDOWN;
73 }
74
75 static void
76 gst_rtsp_auth_finalize (GObject * obj)
77 {
78   GstRTSPAuth *auth = GST_RTSP_AUTH (obj);
79
80   GST_INFO ("finalize auth %p", auth);
81   g_free (auth->basic);
82
83   G_OBJECT_CLASS (gst_rtsp_auth_parent_class)->finalize (obj);
84 }
85
86 static void
87 gst_rtsp_auth_get_property (GObject * object, guint propid,
88     GValue * value, GParamSpec * pspec)
89 {
90   switch (propid) {
91     default:
92       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
93   }
94 }
95
96 static void
97 gst_rtsp_auth_set_property (GObject * object, guint propid,
98     const GValue * value, GParamSpec * pspec)
99 {
100   switch (propid) {
101     default:
102       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
103   }
104 }
105
106 /**
107  * gst_rtsp_auth_new:
108  *
109  * Create a new #GstRTSPAuth instance.
110  *
111  * Returns: a new #GstRTSPAuth
112  */
113 GstRTSPAuth *
114 gst_rtsp_auth_new (void)
115 {
116   GstRTSPAuth *result;
117
118   result = g_object_new (GST_TYPE_RTSP_AUTH, NULL);
119
120   return result;
121 }
122
123 /**
124  * gst_rtsp_auth_set_basic:
125  * @auth: a #GstRTSPAuth
126  * @basic: the basic token
127  *
128  * Set the basic token for the default authentication algorithm.
129  */
130 void
131 gst_rtsp_auth_set_basic (GstRTSPAuth * auth, const gchar * basic)
132 {
133   g_free (auth->basic);
134   auth->basic = g_strdup (basic);
135 }
136
137 static gboolean
138 default_setup_auth (GstRTSPAuth * auth, GstRTSPClient * client,
139     GQuark hint, GstRTSPClientState * state)
140 {
141   if (state->response == NULL)
142     return FALSE;
143
144   /* we only have Basic for now */
145   gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_WWW_AUTHENTICATE,
146       "Basic realm=\"GStreamer RTSP Server\"");
147
148   return TRUE;
149 }
150
151 /**
152  * gst_rtsp_auth_setup_auth:
153  * @auth: a #GstRTSPAuth
154  * @client: the client
155  * @uri: the requested uri
156  * @session: the session
157  * @request: the request
158  * @response: the response
159  *
160  * Add authentication tokens to @response.
161  *
162  * Returns: FALSE if something is wrong.
163  */
164 gboolean
165 gst_rtsp_auth_setup_auth (GstRTSPAuth * auth, GstRTSPClient * client,
166     GQuark hint, GstRTSPClientState * state)
167 {
168   gboolean result = FALSE;
169   GstRTSPAuthClass *klass;
170
171   klass = GST_RTSP_AUTH_GET_CLASS (auth);
172
173   GST_DEBUG_OBJECT (auth, "setup auth");
174
175   if (klass->setup_auth)
176     result = klass->setup_auth (auth, client, hint, state);
177
178   return result;
179 }
180
181 static gboolean
182 default_check_method (GstRTSPAuth * auth, GstRTSPClient * client,
183     GQuark hint, GstRTSPClientState * state)
184 {
185   gboolean result = TRUE;
186   GstRTSPResult res;
187
188   if ((state->method & auth->methods) != 0) {
189     gchar *authorization;
190
191     result = FALSE;
192
193     res =
194         gst_rtsp_message_get_header (state->request, GST_RTSP_HDR_AUTHORIZATION,
195         &authorization, 0);
196     if (res < 0)
197       goto no_auth;
198
199     /* parse type */
200     if (g_ascii_strncasecmp (authorization, "basic ", 6) == 0) {
201       GST_DEBUG_OBJECT (auth, "check Basic auth");
202       if (auth->basic && strcmp (&authorization[6], auth->basic) == 0)
203         result = TRUE;
204     } else if (g_ascii_strncasecmp (authorization, "digest ", 7) == 0) {
205       GST_DEBUG_OBJECT (auth, "check Digest auth");
206       /* not implemented yet */
207       result = FALSE;
208     }
209   }
210   return result;
211
212 no_auth:
213   {
214     GST_DEBUG_OBJECT (auth, "no authorization header found");
215     return FALSE;
216   }
217 }
218
219 /**
220  * gst_rtsp_auth_check:
221  * @auth: a #GstRTSPAuth
222  * @client: the client
223  * @hint: a hint
224  * @state: client state
225  *
226  * Check if @client is allowed to perform the actions of @state.
227  *
228  * Returns: FALSE if the action is not allowed.
229  */
230 gboolean
231 gst_rtsp_auth_check (GstRTSPAuth * auth, GstRTSPClient * client,
232     GQuark hint, GstRTSPClientState * state)
233 {
234   gboolean result = FALSE;
235   GstRTSPAuthClass *klass;
236
237   klass = GST_RTSP_AUTH_GET_CLASS (auth);
238
239   GST_DEBUG_OBJECT (auth, "check state");
240
241   if (klass->check_method)
242     result = klass->check_method (auth, client, hint, state);
243
244   return result;
245 }
246
247 /**
248  * gst_rtsp_auth_make_basic:
249  * @user: a userid
250  * @pass: a password
251  *
252  * Construct a Basic authorisation token from @user and @pass.
253  *
254  * Returns: the base64 encoding of the string @user:@pass. g_free()
255  *    after usage.
256  */
257 gchar *
258 gst_rtsp_auth_make_basic (const gchar * user, const gchar * pass)
259 {
260   gchar *user_pass;
261   gchar *result;
262
263   user_pass = g_strjoin (":", user, pass, NULL);
264   result = g_base64_encode ((guchar *) user_pass, strlen (user_pass));
265   g_free (user_pass);
266
267   return result;
268 }