95750488b6cf78819e04f95ea42db9f58d1db0aa
[platform/upstream/gstreamer.git] / gst / rtsp-server / rtsp-permissions.c
1 /* GStreamer
2  * Copyright (C) 2013 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., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 /**
20  * SECTION:rtsp-permissions
21  * @short_description: Roles and associated permissions
22  * @see_also: #GstRTSPToken, #GstRTSPAuth
23  *
24  * The #GstRTSPPermissions object contains an array of roles and associated
25  * permissions. The roles are represented with a string and the permissions with
26  * a generic #GstStructure.
27  *
28  * The permissions are deliberately kept generic. The possible values of the
29  * roles and #GstStructure keys and values are only determined by the #GstRTSPAuth
30  * object that performs the checks on the permissions and the current
31  * #GstRTSPToken.
32  *
33  * As a convenience function, gst_rtsp_permissions_is_allowed() can be used to
34  * check if the permissions contains a role that contains the boolean value
35  * %TRUE for the the given key.
36  *
37  * Last reviewed on 2013-07-15 (1.0.0)
38  */
39
40 #include <string.h>
41
42 #include "rtsp-permissions.h"
43
44 typedef struct _GstRTSPPermissionsImpl
45 {
46   GstRTSPPermissions permissions;
47
48   /* Roles, array of GstStructure */
49   GPtrArray *roles;
50 } GstRTSPPermissionsImpl;
51
52 static void
53 free_structure (GstStructure * structure)
54 {
55   gst_structure_set_parent_refcount (structure, NULL);
56   gst_structure_free (structure);
57 }
58
59 //GST_DEBUG_CATEGORY_STATIC (rtsp_permissions_debug);
60 //#define GST_CAT_DEFAULT rtsp_permissions_debug
61
62 GST_DEFINE_MINI_OBJECT_TYPE (GstRTSPPermissions, gst_rtsp_permissions);
63
64 static void gst_rtsp_permissions_init (GstRTSPPermissionsImpl * permissions);
65
66 static void
67 _gst_rtsp_permissions_free (GstRTSPPermissions * permissions)
68 {
69   GstRTSPPermissionsImpl *impl = (GstRTSPPermissionsImpl *) permissions;
70
71   g_ptr_array_free (impl->roles, TRUE);
72
73   g_slice_free1 (sizeof (GstRTSPPermissionsImpl), permissions);
74 }
75
76 static GstRTSPPermissions *
77 _gst_rtsp_permissions_copy (GstRTSPPermissionsImpl * permissions)
78 {
79   GstRTSPPermissionsImpl *copy;
80   guint i;
81
82   copy = (GstRTSPPermissionsImpl *) gst_rtsp_permissions_new ();
83
84   for (i = 0; i < permissions->roles->len; i++) {
85     GstStructure *entry = g_ptr_array_index (permissions->roles, i);
86     GstStructure *entry_copy = gst_structure_copy (entry);
87
88     gst_structure_set_parent_refcount (entry_copy,
89         &copy->permissions.mini_object.refcount);
90     g_ptr_array_add (copy->roles, entry_copy);
91   }
92
93   return GST_RTSP_PERMISSIONS (copy);
94 }
95
96 static void
97 gst_rtsp_permissions_init (GstRTSPPermissionsImpl * permissions)
98 {
99   gst_mini_object_init (GST_MINI_OBJECT_CAST (permissions), 0,
100       GST_TYPE_RTSP_PERMISSIONS,
101       (GstMiniObjectCopyFunction) _gst_rtsp_permissions_copy, NULL,
102       (GstMiniObjectFreeFunction) _gst_rtsp_permissions_free);
103
104   permissions->roles =
105       g_ptr_array_new_with_free_func ((GDestroyNotify) free_structure);
106 }
107
108 static void
109 add_role_from_structure (GstRTSPPermissionsImpl * impl,
110     GstStructure * structure)
111 {
112   guint i, len;
113   const gchar *role = gst_structure_get_name (structure);
114
115   len = impl->roles->len;
116   for (i = 0; i < len; i++) {
117     GstStructure *entry = g_ptr_array_index (impl->roles, i);
118
119     if (gst_structure_has_name (entry, role)) {
120       g_ptr_array_remove_index_fast (impl->roles, i);
121       break;
122     }
123   }
124
125   gst_structure_set_parent_refcount (structure,
126       &impl->permissions.mini_object.refcount);
127   g_ptr_array_add (impl->roles, structure);
128 }
129
130 /**
131  * gst_rtsp_permissions_new:
132  *
133  * Create a new empty Authorization permissions.
134  *
135  * Returns: (transfer full): a new empty authorization permissions.
136  */
137 GstRTSPPermissions *
138 gst_rtsp_permissions_new (void)
139 {
140   GstRTSPPermissionsImpl *permissions;
141
142   permissions = g_slice_new0 (GstRTSPPermissionsImpl);
143   gst_rtsp_permissions_init (permissions);
144
145   return GST_RTSP_PERMISSIONS (permissions);
146 }
147
148 /**
149  * gst_rtsp_permissions_add_permission_for_role:
150  * @permissions: a #GstRTSPPermissions
151  * @role: a role
152  * @permission: the permission
153  * @allowed: whether the role has this permission or not
154  *
155  * Add a new @permission for @role to @permissions with the access in @allowed.
156  *
157  * Since: 1.14
158  */
159 void
160 gst_rtsp_permissions_add_permission_for_role (GstRTSPPermissions * permissions,
161     const gchar * role, const gchar * permission, gboolean allowed)
162 {
163   GstRTSPPermissionsImpl *impl = (GstRTSPPermissionsImpl *) permissions;
164   guint i, len;
165
166   g_return_if_fail (GST_IS_RTSP_PERMISSIONS (permissions));
167   g_return_if_fail (gst_mini_object_is_writable (&permissions->mini_object));
168   g_return_if_fail (role != NULL);
169   g_return_if_fail (permission != NULL);
170
171   len = impl->roles->len;
172   for (i = 0; i < len; i++) {
173     GstStructure *entry = g_ptr_array_index (impl->roles, i);
174
175     if (gst_structure_has_name (entry, role)) {
176       gst_structure_set (entry, permission, G_TYPE_BOOLEAN, allowed, NULL);
177       return;
178     }
179   }
180
181   gst_rtsp_permissions_add_role (permissions, role,
182       permission, G_TYPE_BOOLEAN, allowed, NULL);
183 }
184
185 /**
186  * gst_rtsp_permissions_add_role_empty: (rename-to gst_rtsp_permissions_add_role)
187  * @permissions: a #GstRTSPPermissions
188  * @role: a role
189  *
190  * Add a new @role to @permissions without any permissions. You can add
191  * permissions for the role with gst_rtsp_permissions_add_permission_for_role().
192  *
193  * Since: 1.14
194  */
195 void
196 gst_rtsp_permissions_add_role_empty (GstRTSPPermissions * permissions,
197     const gchar * role)
198 {
199   gst_rtsp_permissions_add_role (permissions, role, NULL);
200 }
201
202 /**
203  * gst_rtsp_permissions_add_role:
204  * @permissions: a #GstRTSPPermissions
205  * @role: a role
206  * @fieldname: the first field name
207  * @...: additional arguments
208  *
209  * Add a new @role to @permissions with the given variables. The fields
210  * are the same layout as gst_structure_new().
211  */
212 void
213 gst_rtsp_permissions_add_role (GstRTSPPermissions * permissions,
214     const gchar * role, const gchar * fieldname, ...)
215 {
216   va_list var_args;
217
218   va_start (var_args, fieldname);
219   gst_rtsp_permissions_add_role_valist (permissions, role, fieldname, var_args);
220   va_end (var_args);
221 }
222
223 /**
224  * gst_rtsp_permissions_add_role_valist:
225  * @permissions: a #GstRTSPPermissions
226  * @role: a role
227  * @fieldname: the first field name
228  * @var_args: additional fields to add
229  *
230  * Add a new @role to @permissions with the given variables. Structure fields
231  * are set according to the varargs in a manner similar to gst_structure_new().
232  */
233 void
234 gst_rtsp_permissions_add_role_valist (GstRTSPPermissions * permissions,
235     const gchar * role, const gchar * fieldname, va_list var_args)
236 {
237   GstRTSPPermissionsImpl *impl = (GstRTSPPermissionsImpl *) permissions;
238   GstStructure *structure;
239
240   g_return_if_fail (GST_IS_RTSP_PERMISSIONS (permissions));
241   g_return_if_fail (gst_mini_object_is_writable (&permissions->mini_object));
242   g_return_if_fail (role != NULL);
243
244   structure = gst_structure_new_valist (role, fieldname, var_args);
245   g_return_if_fail (structure != NULL);
246
247   add_role_from_structure (impl, structure);
248 }
249
250 /**
251  * gst_rtsp_permissions_add_role_from_structure:
252  *
253  * Add a new role to @permissions based on @structure
254  */
255 void
256 gst_rtsp_permissions_add_role_from_structure (GstRTSPPermissions * permissions,
257     GstStructure * structure)
258 {
259   GstRTSPPermissionsImpl *impl = (GstRTSPPermissionsImpl *) permissions;
260   GstStructure *copy;
261
262   g_return_if_fail (GST_IS_RTSP_PERMISSIONS (permissions));
263   g_return_if_fail (GST_IS_STRUCTURE (structure));
264
265   copy = gst_structure_copy (structure);
266
267   add_role_from_structure (impl, copy);
268 }
269
270 /**
271  * gst_rtsp_permissions_remove_role:
272  * @permissions: a #GstRTSPPermissions
273  * @role: a role
274  *
275  * Remove all permissions for @role in @permissions.
276  */
277 void
278 gst_rtsp_permissions_remove_role (GstRTSPPermissions * permissions,
279     const gchar * role)
280 {
281   GstRTSPPermissionsImpl *impl = (GstRTSPPermissionsImpl *) permissions;
282   guint i, len;
283
284   g_return_if_fail (GST_IS_RTSP_PERMISSIONS (permissions));
285   g_return_if_fail (gst_mini_object_is_writable (&permissions->mini_object));
286   g_return_if_fail (role != NULL);
287
288   len = impl->roles->len;
289   for (i = 0; i < len; i++) {
290     GstStructure *entry = g_ptr_array_index (impl->roles, i);
291
292     if (gst_structure_has_name (entry, role)) {
293       g_ptr_array_remove_index_fast (impl->roles, i);
294       break;
295     }
296   }
297 }
298
299 /**
300  * gst_rtsp_permissions_get_role:
301  * @permissions: a #GstRTSPPermissions
302  * @role: a role
303  *
304  * Get all permissions for @role in @permissions.
305  *
306  * Returns: (transfer none): the structure with permissions for @role. It
307  * remains valid for as long as @permissions is valid.
308  */
309 const GstStructure *
310 gst_rtsp_permissions_get_role (GstRTSPPermissions * permissions,
311     const gchar * role)
312 {
313   GstRTSPPermissionsImpl *impl = (GstRTSPPermissionsImpl *) permissions;
314   guint i, len;
315
316   g_return_val_if_fail (GST_IS_RTSP_PERMISSIONS (permissions), NULL);
317   g_return_val_if_fail (role != NULL, NULL);
318
319   len = impl->roles->len;
320   for (i = 0; i < len; i++) {
321     GstStructure *entry = g_ptr_array_index (impl->roles, i);
322
323     if (gst_structure_has_name (entry, role))
324       return entry;
325   }
326   return NULL;
327 }
328
329 /**
330  * gst_rtsp_permissions_is_allowed:
331  * @permissions: a #GstRTSPPermissions
332  * @role: a role
333  * @permission: a permission
334  *
335  * Check if @role in @permissions is given permission for @permission.
336  *
337  * Returns: %TRUE if @role is allowed @permission.
338  */
339 gboolean
340 gst_rtsp_permissions_is_allowed (GstRTSPPermissions * permissions,
341     const gchar * role, const gchar * permission)
342 {
343   const GstStructure *str;
344   gboolean result;
345
346   g_return_val_if_fail (GST_IS_RTSP_PERMISSIONS (permissions), FALSE);
347   g_return_val_if_fail (role != NULL, FALSE);
348   g_return_val_if_fail (permission != NULL, FALSE);
349
350   str = gst_rtsp_permissions_get_role (permissions, role);
351   if (str == NULL)
352     return FALSE;
353
354   if (!gst_structure_get_boolean (str, permission, &result))
355     result = FALSE;
356
357   return result;
358 }