auth: simplify auth checks
authorWim Taymans <wim.taymans@collabora.co.uk>
Tue, 9 Jul 2013 14:04:35 +0000 (16:04 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Tue, 9 Jul 2013 14:04:35 +0000 (16:04 +0200)
Remove client from methods, it's now in the state
Perform the check specified by the string, use the information from the
thread local context.

gst/rtsp-server/rtsp-auth.c
gst/rtsp-server/rtsp-auth.h
gst/rtsp-server/rtsp-client.c

index ac3fb3e..a6db8a6 100644 (file)
@@ -46,12 +46,11 @@ 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_setup (GstRTSPAuth * auth, GstRTSPClient * client,
-    GstRTSPClientState * state);
+static gboolean default_setup (GstRTSPAuth * auth, GstRTSPClientState * state);
 static gboolean default_authenticate (GstRTSPAuth * auth,
-    GstRTSPClient * client, GstRTSPClientState * state);
-static gboolean default_check (GstRTSPAuth * auth, GstRTSPClient * client,
-    GQuark hint, GstRTSPClientState * state);
+    GstRTSPClientState * state);
+static gboolean default_check (GstRTSPAuth * auth, GstRTSPClientState * state,
+    const gchar * check);
 
 G_DEFINE_TYPE (GstRTSPAuth, gst_rtsp_auth, G_TYPE_OBJECT);
 
@@ -197,8 +196,7 @@ gst_rtsp_auth_remove_basic (GstRTSPAuth * auth, const gchar * basic)
 }
 
 static gboolean
-default_setup (GstRTSPAuth * auth, GstRTSPClient * client,
-    GstRTSPClientState * state)
+default_setup (GstRTSPAuth * auth, GstRTSPClientState * state)
 {
   if (state->response == NULL)
     return FALSE;
@@ -221,14 +219,12 @@ default_setup (GstRTSPAuth * auth, GstRTSPClient * client,
  * Returns: FALSE if something is wrong.
  */
 gboolean
-gst_rtsp_auth_setup (GstRTSPAuth * auth, GstRTSPClient * client,
-    GstRTSPClientState * state)
+gst_rtsp_auth_setup (GstRTSPAuth * auth, GstRTSPClientState * state)
 {
   gboolean result = FALSE;
   GstRTSPAuthClass *klass;
 
   g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), FALSE);
-  g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), FALSE);
   g_return_val_if_fail (state != NULL, FALSE);
 
   klass = GST_RTSP_AUTH_GET_CLASS (auth);
@@ -236,14 +232,13 @@ gst_rtsp_auth_setup (GstRTSPAuth * auth, GstRTSPClient * client,
   GST_DEBUG_OBJECT (auth, "setup auth");
 
   if (klass->setup)
-    result = klass->setup (auth, client, state);
+    result = klass->setup (auth, state);
 
   return result;
 }
 
 static gboolean
-default_authenticate (GstRTSPAuth * auth, GstRTSPClient * client,
-    GstRTSPClientState * state)
+default_authenticate (GstRTSPAuth * auth, GstRTSPClientState * state)
 {
   GstRTSPAuthPrivate *priv = auth->priv;
   GstRTSPResult res;
@@ -282,41 +277,25 @@ no_auth:
 }
 
 static gboolean
-default_check (GstRTSPAuth * auth, GstRTSPClient * client,
-    GstRTSPAuthCheck check, GstRTSPClientState * state)
+ensure_authenticated (GstRTSPAuth * auth, GstRTSPClientState * state)
 {
-  GstRTSPAuthPrivate *priv = auth->priv;
   GstRTSPAuthClass *klass;
-  gboolean need_authorized = FALSE;
-  gboolean res = FALSE;
 
   klass = GST_RTSP_AUTH_GET_CLASS (auth);
 
-  switch (check) {
-    case GST_RTSP_AUTH_CHECK_URL:
-      if ((state->method & priv->methods) != 0)
-        need_authorized = TRUE;
-      else
-        res = TRUE;
-      break;
-    case GST_RTSP_AUTH_CHECK_FACTORY:
-      res = TRUE;
-      break;
-  }
-
-  if (need_authorized) {
-    /* we need a token to check */
-    if (state->token == NULL) {
-      if (klass->authenticate) {
-        if (!klass->authenticate (auth, client, state))
-          goto authenticate_failed;
-      }
+  /* we need a token to check */
+  if (state->token == NULL) {
+    if (klass->authenticate) {
+      if (!klass->authenticate (auth, state))
+        goto authenticate_failed;
     }
-    if (state->token == NULL)
-      goto no_auth;
   }
-  return res;
+  if (state->token == NULL)
+    goto no_auth;
+
+  return TRUE;
 
+/* ERRORS */
 authenticate_failed:
   {
     GST_DEBUG_OBJECT (auth, "authenticate failed");
@@ -329,37 +308,82 @@ no_auth:
   }
 }
 
+static gboolean
+default_check (GstRTSPAuth * auth, GstRTSPClientState * state,
+    const gchar * check)
+{
+  GstRTSPAuthPrivate *priv = auth->priv;
+  gboolean res = FALSE;
+
+  if (g_str_equal (check, GST_RTSP_AUTH_CHECK_URL)) {
+    if ((state->method & priv->methods) != 0)
+      res = ensure_authenticated (auth, state);
+    else
+      res = TRUE;
+  } else if (g_str_has_prefix (check, "auth.check.media.factory.")) {
+    const gchar *role;
+    GstRTSPPermissions *perms;
+
+    if (!(role =
+            gst_rtsp_token_get_string (state->token,
+                GST_RTSP_MEDIA_FACTORY_ROLE)))
+      goto done;
+    if (!(perms = gst_rtsp_media_factory_get_permissions (state->factory)))
+      goto done;
+
+    if (g_str_equal (check, "auth.check.media.factory.access"))
+      res =
+          gst_rtsp_permissions_is_allowed (perms, role,
+          GST_RTSP_MEDIA_FACTORY_PERM_ACCESS);
+    else if (g_str_equal (check, "auth.check.media.factory.construct"))
+      res =
+          gst_rtsp_permissions_is_allowed (perms, role,
+          GST_RTSP_MEDIA_FACTORY_PERM_CONSTRUCT);
+  }
+done:
+  return res;
+}
+
 /**
  * gst_rtsp_auth_check:
- * @auth: a #GstRTSPAuth
- * @client: the client
  * @check: the item to check
- * @state: client state
  *
- * Check if @client with state is authorized to perform @check in the
- * current @state.
+ * Check if @check is allowed in the current context.
  *
  * Returns: FALSE if check failed.
  */
 gboolean
-gst_rtsp_auth_check (GstRTSPAuth * auth, GstRTSPClient * client,
-    GstRTSPAuthCheck check, GstRTSPClientState * state)
+gst_rtsp_auth_check (const gchar * check)
 {
   gboolean result = FALSE;
   GstRTSPAuthClass *klass;
+  GstRTSPClientState *state;
+  GstRTSPAuth *auth;
 
-  g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), FALSE);
-  g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), FALSE);
-  g_return_val_if_fail (state != NULL, FALSE);
+  g_return_val_if_fail (check != NULL, FALSE);
+
+  if (!(state = gst_rtsp_client_state_get_current ()))
+    goto no_state;
+
+  /* no auth, we don't need to check */
+  if (!(auth = state->auth))
+    return TRUE;
 
   klass = GST_RTSP_AUTH_GET_CLASS (auth);
 
   GST_DEBUG_OBJECT (auth, "check auth");
 
   if (klass->check)
-    result = klass->check (auth, client, check, state);
+    result = klass->check (auth, state, check);
 
   return result;
+
+  /* ERRORS */
+no_state:
+  {
+    GST_ERROR ("no clientstate found");
+    return FALSE;
+  }
 }
 
 /**
index 55c5faf..cb8579f 100644 (file)
@@ -41,18 +41,6 @@ G_BEGIN_DECLS
 #define GST_RTSP_AUTH_CLASS_CAST(klass) ((GstRTSPAuthClass*)(klass))
 
 /**
- * GstRTSPAuthCheck:
- * @GST_RTSP_AUTH_CHECK_URL: Check url and method
- * @GST_RTSP_AUTH_CHECK_FACTORY: Check access to factory
- *
- * Different authorization checks
- */
-typedef enum {
-  GST_RTSP_AUTH_CHECK_URL,
-  GST_RTSP_AUTH_CHECK_FACTORY,
-} GstRTSPAuthCheck;
-
-/**
  * GstRTSPAuth:
  *
  * The authentication structure.
@@ -82,12 +70,10 @@ struct _GstRTSPAuth {
 struct _GstRTSPAuthClass {
   GObjectClass  parent_class;
 
-  gboolean           (*setup)        (GstRTSPAuth *auth, GstRTSPClient * client,
-                                      GstRTSPClientState *state);
-  gboolean           (*authenticate) (GstRTSPAuth *auth, GstRTSPClient * client,
-                                      GstRTSPClientState *state);
-  gboolean           (*check)        (GstRTSPAuth *auth, GstRTSPClient * client,
-                                      GstRTSPAuthCheck check, GstRTSPClientState *state);
+  gboolean           (*setup)        (GstRTSPAuth *auth, GstRTSPClientState *state);
+  gboolean           (*authenticate) (GstRTSPAuth *auth, GstRTSPClientState *state);
+  gboolean           (*check)        (GstRTSPAuth *auth, GstRTSPClientState *state,
+                                      const gchar *check);
 };
 
 GType               gst_rtsp_auth_get_type          (void);
@@ -98,15 +84,60 @@ void                gst_rtsp_auth_add_basic         (GstRTSPAuth *auth, const gc
                                                      GstRTSPToken *token);
 void                gst_rtsp_auth_remove_basic      (GstRTSPAuth *auth, const gchar * basic);
 
-gboolean            gst_rtsp_auth_setup             (GstRTSPAuth *auth, GstRTSPClient * client,
-                                                     GstRTSPClientState *state);
+gboolean            gst_rtsp_auth_setup             (GstRTSPAuth *auth, GstRTSPClientState *state);
+
+gboolean            gst_rtsp_auth_check             (const gchar *check);
 
-gboolean            gst_rtsp_auth_check             (GstRTSPAuth *auth, GstRTSPClient * client,
-                                                     GstRTSPAuthCheck check, GstRTSPClientState *state);
 
 /* helpers */
 gchar *             gst_rtsp_auth_make_basic        (const gchar * user, const gchar * pass);
 
+/* checks */
+/**
+ * GST_RTSP_AUTH_CHECK_URL:
+ *
+ * Check the URL and methods
+ */
+#define GST_RTSP_AUTH_CHECK_URL                      "auth.check.url"
+/**
+ * GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS:
+ *
+ * Check if access is allowed to a factory
+ */
+#define GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS     "auth.check.media.factory.access"
+/**
+ * GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT:
+ *
+ * Check if media can be constructed from a media factory
+ */
+#define GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT  "auth.check.media.factory.construct"
+
+
+/* tokens */
+/**
+ * GST_RTSP_MEDIA_FACTORY_ROLE:
+ *
+ * G_TYPE_STRING, the role to use when dealing with media factories
+ */
+#define GST_RTSP_MEDIA_FACTORY_ROLE      "media.factory.role"
+
+/* permissions */
+/**
+ * GST_RTSP_MEDIA_FACTORY_PERM_ACCESS:
+ *
+ * G_TYPE_BOOLEAN, %TRUE if the media can be accessed, %FALSE will
+ * return a 404 Not Found error when trying to access the media.
+ */
+#define GST_RTSP_MEDIA_FACTORY_PERM_ACCESS      "media.factory.access"
+/**
+ * GST_RTSP_MEDIA_FACTORY_PERM_CONSTRUCT:
+ *
+ * G_TYPE_BOOLEAN, %TRUE if the media can be constructed, %FALSE will
+ * return a 404 Not Found error when trying to access the media.
+ */
+#define GST_RTSP_MEDIA_FACTORY_PERM_CONSTRUCT   "media.factory.construct"
+
+
 G_END_DECLS
 
 #endif /* __GST_RTSP_AUTH_H__ */
index 6af4058..50d68cf 100644 (file)
@@ -456,7 +456,7 @@ handle_unauthorized_request (GstRTSPClient * client, GstRTSPAuth * auth,
 
   if (auth) {
     /* and let the authentication manager setup the auth tokens */
-    gst_rtsp_auth_setup (auth, client, state);
+    gst_rtsp_auth_setup (auth, state);
   }
 
   send_message (client, state->session, state->response, FALSE);
@@ -502,8 +502,10 @@ find_media (GstRTSPClient * client, GstRTSPClientState * state, gint * matched)
 
   state->factory = factory;
 
-  if (!gst_rtsp_auth_check (priv->auth, client, GST_RTSP_AUTH_CHECK_FACTORY,
-          state))
+  if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS))
+    goto no_factory_access;
+
+  if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT))
     goto not_authorized;
 
   if (matched)
@@ -563,9 +565,15 @@ no_factory:
     send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
     return NULL;
   }
+no_factory_access:
+  {
+    GST_ERROR ("client %p: not authorized to see factory uri %s", client, path);
+    send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
+    return NULL;
+  }
 not_authorized:
   {
-    GST_ERROR ("client %p: not authorized for factory %p", client, factory);
+    GST_ERROR ("client %p: not authorized for factory uri %s", client, path);
     handle_unauthorized_request (client, priv->auth, state);
     return NULL;
   }
@@ -1858,13 +1866,8 @@ handle_request (GstRTSPClient * client, GstRTSPMessage * request)
   state.uri = uri;
   state.session = session;
 
-  if (priv->auth) {
-    if (!gst_rtsp_auth_check (priv->auth, client, GST_RTSP_AUTH_CHECK_URL,
-            &state))
-      goto not_authorized;
-
-    state.auth = priv->auth;
-  }
+  if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_URL))
+    goto not_authorized;
 
   /* now see what is asked and dispatch to a dedicated handler */
   switch (method) {