auth: move TLS handling to auth module
authorWim Taymans <wim.taymans@collabora.co.uk>
Fri, 12 Jul 2013 10:41:52 +0000 (12:41 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Fri, 12 Jul 2013 10:41:52 +0000 (12:41 +0200)
Remove the TLS settings on the server and move it to the auth module because
that is where security related bits go.

examples/test-video.c
gst/rtsp-server/rtsp-auth.c
gst/rtsp-server/rtsp-auth.h
gst/rtsp-server/rtsp-server.c
gst/rtsp-server/rtsp-server.h

index 05db5f3..4a8e205 100644 (file)
@@ -22,7 +22,7 @@
 #include <gst/rtsp-server/rtsp-server.h>
 
 /* define this if you want the resource to only be available when using
- * user/admin as the password */
+ * user/password as the password */
 #undef WITH_AUTH
 
 /* define this if you want the server to use TLS */
@@ -52,7 +52,10 @@ main (int argc, char *argv[])
   GstRTSPMediaFactory *factory;
 #ifdef WITH_AUTH
   GstRTSPAuth *auth;
+  GstRTSPToken *token;
+  GstStructure *s;
   gchar *basic;
+  GstRTSPPermissions *permissions;
 #endif
 #ifdef WITH_TLS
   GTlsCertificate *cert;
@@ -64,6 +67,11 @@ main (int argc, char *argv[])
 
   /* create a server instance */
   server = gst_rtsp_server_new ();
+
+#ifdef WITH_AUTH
+  /* make a new authentication manager. it can be added to control access to all
+   * the factories on the server or on individual factories. */
+  auth = gst_rtsp_auth_new ();
 #ifdef WITH_TLS
   cert = g_tls_certificate_new_from_pem ("-----BEGIN CERTIFICATE-----"
       "MIICJjCCAY+gAwIBAgIBBzANBgkqhkiG9w0BAQUFADCBhjETMBEGCgmSJomT8ixk"
@@ -88,25 +96,27 @@ main (int argc, char *argv[])
       "DwIga8PqH5Sf5sHedy2+CiK0V4MRfoU4c3zQ6kArI+bEgSkCIQCLA1vXBiE31B5s"
       "bdHoYa1BXebfZVd+1Hd95IfEM5mbRwIgSkDuQwV55BBlvWph3U8wVIMIb4GStaH8"
       "W535W8UBbEg=" "-----END PRIVATE KEY-----", -1, NULL);
-  gst_rtsp_server_set_tls_certificate (server, cert);
+  gst_rtsp_auth_set_tls_certificate (auth, cert);
   g_object_unref (cert);
 #endif
 
-  /* get the mount points for this server, every server has a default object
-   * that be used to map uri mount points to media factories */
-  mounts = gst_rtsp_server_get_mount_points (server);
-
-#ifdef WITH_AUTH
-  /* make a new authentication manager. it can be added to control access to all
-   * the factories on the server or on individual factories. */
-  auth = gst_rtsp_auth_new ();
-  basic = gst_rtsp_auth_make_basic ("user", "admin");
-  gst_rtsp_auth_set_basic (auth, basic);
+  /* make user token */
+  token = gst_rtsp_token_new ();
+  s = gst_rtsp_token_writable_structure (token);
+  gst_structure_set (s, "media.factory.role", G_TYPE_STRING, "user", NULL);
+  basic = gst_rtsp_auth_make_basic ("user", "password");
+  gst_rtsp_auth_add_basic (auth, basic, token);
   g_free (basic);
+  gst_rtsp_token_unref (token);
+
   /* configure in the server */
   gst_rtsp_server_set_auth (server, auth);
 #endif
 
+  /* get the mount points for this server, every server has a default object
+   * that be used to map uri mount points to media factories */
+  mounts = gst_rtsp_server_get_mount_points (server);
+
   /* make a media factory for a test stream. The default media factory can use
    * gst-launch syntax to create pipelines. 
    * any launch line works as long as it contains elements named pay%d. Each
@@ -117,6 +127,16 @@ main (int argc, char *argv[])
       "x264enc ! rtph264pay name=pay0 pt=96 "
       "audiotestsrc ! audio/x-raw,rate=8000 ! "
       "alawenc ! rtppcmapay name=pay1 pt=97 " ")");
+#ifdef WITH_AUTH
+  /* add permissions for the user media role */
+  permissions = gst_rtsp_permissions_new ();
+  gst_rtsp_permissions_add_role (permissions, "user",
+      gst_structure_new ("user",
+          "media.factory.access", G_TYPE_BOOLEAN, TRUE,
+          "media.factory.construct", G_TYPE_BOOLEAN, TRUE, NULL));
+  gst_rtsp_media_factory_set_permissions (factory, permissions);
+  gst_rtsp_permissions_unref (permissions);
+#endif
 
   /* attach the test factory to the /test url */
   gst_rtsp_mount_points_add_factory (mounts, "/test", factory);
index dc0b2e0..f5afb97 100644 (file)
@@ -34,6 +34,9 @@
 struct _GstRTSPAuthPrivate
 {
   GMutex lock;
+
+  /* the TLS certificate */
+  GTlsCertificate *certificate;
   GHashTable *basic;            /* protected by lock */
   GstRTSPMethod methods;
 };
@@ -109,6 +112,9 @@ gst_rtsp_auth_finalize (GObject * obj)
   GstRTSPAuthPrivate *priv = auth->priv;
 
   GST_INFO ("finalize auth %p", auth);
+
+  if (priv->certificate)
+    g_object_unref (priv->certificate);
   g_hash_table_unref (priv->basic);
   g_mutex_clear (&priv->lock);
 
@@ -153,6 +159,64 @@ gst_rtsp_auth_new (void)
 }
 
 /**
+ * gst_rtsp_auth_set_tls_certificate:
+ * @auth: a #GstRTSPAuth
+ * @cert: (allow none): a #GTlsCertificate
+ *
+ * Set the TLS certificate for the auth. Client connections will only
+ * be accepted when TLS is negotiated.
+ */
+void
+gst_rtsp_auth_set_tls_certificate (GstRTSPAuth * auth, GTlsCertificate * cert)
+{
+  GstRTSPAuthPrivate *priv;
+  GTlsCertificate *old;
+
+  g_return_if_fail (GST_IS_RTSP_AUTH (auth));
+
+  priv = auth->priv;
+
+  if (cert)
+    g_object_ref (cert);
+
+  g_mutex_lock (&priv->lock);
+  old = priv->certificate;
+  priv->certificate = cert;
+  g_mutex_unlock (&priv->lock);
+
+  if (old)
+    g_object_unref (old);
+}
+
+/**
+ * gst_rtsp_auth_get_tls_certificate:
+ * @auth: a #GstRTSPAuth
+ *
+ * Get the #GTlsCertificate used for negotiating TLS @auth.
+ *
+ * Returns: (transfer full): the #GTlsCertificate of @auth. g_object_unref() after
+ * usage.
+ */
+GTlsCertificate *
+gst_rtsp_auth_get_tls_certificate (GstRTSPAuth * auth)
+{
+  GstRTSPAuthPrivate *priv;
+  GTlsCertificate *result;
+
+  g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), NULL);
+
+  priv = auth->priv;
+
+  g_mutex_lock (&priv->lock);
+  if ((result = priv->certificate))
+    g_object_ref (result);
+  g_mutex_unlock (&priv->lock);
+
+  return result;
+}
+
+
+/**
  * gst_rtsp_auth_add_basic:
  * @auth: a #GstRTSPAuth
  * @basic: the basic token
@@ -321,12 +385,24 @@ default_check (GstRTSPAuth * auth, GstRTSPClientState * state,
   GstRTSPAuthPrivate *priv = auth->priv;
   gboolean res = FALSE;
 
-  if (g_str_equal (check, GST_RTSP_AUTH_CHECK_URL)) {
+  if (g_str_equal (check, GST_RTSP_AUTH_CHECK_CONNECT)) {
+    /* new connection */
+    if (priv->certificate) {
+      GTlsConnection *tls;
+
+      /* configure the connection */
+      tls = gst_rtsp_connection_get_tls (state->conn, NULL);
+      g_tls_connection_set_certificate (tls, priv->certificate);
+    }
+    res = TRUE;
+  } else if (g_str_equal (check, GST_RTSP_AUTH_CHECK_URL)) {
+    /* check url and methods */
     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.")) {
+    /* check access to media factory */
     const gchar *role;
     GstRTSPPermissions *perms;
 
index cb8579f..29044de 100644 (file)
@@ -80,6 +80,9 @@ GType               gst_rtsp_auth_get_type          (void);
 
 GstRTSPAuth *       gst_rtsp_auth_new               (void);
 
+void                gst_rtsp_auth_set_tls_certificate (GstRTSPAuth *auth, GTlsCertificate *cert);
+GTlsCertificate *   gst_rtsp_auth_get_tls_certificate (GstRTSPAuth *auth);
+
 void                gst_rtsp_auth_add_basic         (GstRTSPAuth *auth, const gchar * basic,
                                                      GstRTSPToken *token);
 void                gst_rtsp_auth_remove_basic      (GstRTSPAuth *auth, const gchar * basic);
@@ -94,6 +97,12 @@ gchar *             gst_rtsp_auth_make_basic        (const gchar * user, const g
 
 /* checks */
 /**
+ * GST_RTSP_AUTH_CHECK_CONNECT:
+ *
+ * Check a new connection
+ */
+#define GST_RTSP_AUTH_CHECK_CONNECT                  "auth.check.connect"
+/**
  * GST_RTSP_AUTH_CHECK_URL:
  *
  * Check the URL and methods
index 631826a..49d6d51 100644 (file)
@@ -31,7 +31,7 @@
  * network (0.0.0.0) and port 8554.
  *
  * The server will require an SSL connection when a TLS certificate has been
- * set with gst_rtsp_server_set_tls_certificate().
+ * set in the auth object with gst_rtsp_auth_set_tls_certificate().
  *
  * To start the server, use gst_rtsp_server_attach() to attach it to a
  * #GMainContext. For more control, gst_rtsp_server_create_source() and
@@ -89,9 +89,6 @@ struct _GstRTSPServerPrivate
   /* resource manager */
   GstRTSPThreadPool *thread_pool;
 
-  /* the TLS certificate */
-  GTlsCertificate *certificate;
-
   /* the clients that are connected */
   GList *clients;
 };
@@ -144,8 +141,6 @@ static void gst_rtsp_server_set_property (GObject * object, guint propid,
 static void gst_rtsp_server_finalize (GObject * object);
 
 static GstRTSPClient *default_create_client (GstRTSPServer * server);
-static gboolean default_setup_connection (GstRTSPServer * server,
-    GstRTSPClient * client, GstRTSPConnection * conn);
 
 static void
 gst_rtsp_server_class_init (GstRTSPServerClass * klass)
@@ -248,7 +243,6 @@ gst_rtsp_server_class_init (GstRTSPServerClass * klass)
       gst_rtsp_client_get_type ());
 
   klass->create_client = default_create_client;
-  klass->setup_connection = default_setup_connection;
 
   GST_DEBUG_CATEGORY_INIT (rtsp_server_debug, "rtspserver", 0, "GstRTSPServer");
 }
@@ -295,9 +289,6 @@ gst_rtsp_server_finalize (GObject * object)
   if (priv->auth)
     g_object_unref (priv->auth);
 
-  if (priv->certificate)
-    g_object_unref (priv->certificate);
-
   g_mutex_clear (&priv->lock);
 
   G_OBJECT_CLASS (gst_rtsp_server_parent_class)->finalize (object);
@@ -784,64 +775,6 @@ gst_rtsp_server_get_use_client_settings (GstRTSPServer * server)
   return res;
 }
 
-/**
- * gst_rtsp_server_set_tls_certificate:
- * @server: a #GstRTSPServer
- * @cert: (allow none): a #GTlsCertificate
- *
- * Set the TLS certificate for the server. Client connections will only
- * be accepted when TLS is negotiated.
- */
-void
-gst_rtsp_server_set_tls_certificate (GstRTSPServer * server,
-    GTlsCertificate * cert)
-{
-  GstRTSPServerPrivate *priv;
-  GTlsCertificate *old;
-
-  g_return_if_fail (GST_IS_RTSP_SERVER (server));
-
-  priv = server->priv;
-
-  if (cert)
-    g_object_ref (cert);
-
-  GST_RTSP_SERVER_LOCK (server);
-  old = priv->certificate;
-  priv->certificate = cert;
-  GST_RTSP_SERVER_UNLOCK (server);
-
-  if (old)
-    g_object_unref (old);
-}
-
-/**
- * gst_rtsp_server_get_tls_certificate:
- * @server: a #GstRTSPServer
- *
- * Get the #GTlsCertificate used for negotiating TLS @server.
- *
- * Returns: (transfer full): the #GTlsCertificate of @server. g_object_unref() after
- * usage.
- */
-GTlsCertificate *
-gst_rtsp_server_get_tls_certificate (GstRTSPServer * server)
-{
-  GstRTSPServerPrivate *priv;
-  GTlsCertificate *result;
-
-  g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
-
-  priv = server->priv;
-
-  GST_RTSP_SERVER_LOCK (server);
-  if ((result = priv->certificate))
-    g_object_ref (result);
-  GST_RTSP_SERVER_UNLOCK (server);
-
-  return result;
-}
-
 static void
 gst_rtsp_server_get_property (GObject * object, guint propid,
     GValue * value, GParamSpec * pspec)
@@ -1188,25 +1121,6 @@ default_create_client (GstRTSPServer * server)
   return client;
 }
 
-static gboolean
-default_setup_connection (GstRTSPServer * server, GstRTSPClient * client,
-    GstRTSPConnection * conn)
-{
-  GstRTSPServerPrivate *priv = server->priv;
-
-  GST_RTSP_SERVER_LOCK (server);
-  if (priv->certificate) {
-    GTlsConnection *tls;
-
-    /* configure the connection */
-    tls = gst_rtsp_connection_get_tls (conn, NULL);
-    g_tls_connection_set_certificate (tls, priv->certificate);
-  }
-  GST_RTSP_SERVER_UNLOCK (server);
-
-  return TRUE;
-}
-
 /**
  * gst_rtsp_server_transfer_connection:
  * @server: a #GstRTSPServer
@@ -1282,29 +1196,33 @@ gboolean
 gst_rtsp_server_io_func (GSocket * socket, GIOCondition condition,
     GstRTSPServer * server)
 {
+  GstRTSPServerPrivate *priv = server->priv;
   GstRTSPClient *client = NULL;
   GstRTSPServerClass *klass;
   GstRTSPResult res;
   GstRTSPConnection *conn = NULL;
+  GstRTSPClientState state = { NULL };
 
   if (condition & G_IO_IN) {
+    /* a new client connected. */
+    GST_RTSP_CHECK (gst_rtsp_connection_accept (socket, &conn, NULL),
+        accept_failed);
 
-    klass = GST_RTSP_SERVER_GET_CLASS (server);
+    state.server = server;
+    state.conn = conn;
+    state.auth = priv->auth;
+    gst_rtsp_client_state_push_current (&state);
+
+    if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_CONNECT))
+      goto connection_refused;
 
+    klass = GST_RTSP_SERVER_GET_CLASS (server);
     /* a new client connected, create a client object to handle the client. */
     if (klass->create_client)
       client = klass->create_client (server);
     if (client == NULL)
       goto client_failed;
 
-    /* a new client connected. */
-    GST_RTSP_CHECK (gst_rtsp_connection_accept (socket, &conn, NULL),
-        accept_failed);
-
-    if (klass->setup_connection)
-      if (!klass->setup_connection (server, client, conn))
-        goto setup_failed;
-
     /* set connection on the client now */
     gst_rtsp_client_set_connection (client, conn);
 
@@ -1316,29 +1234,31 @@ gst_rtsp_server_io_func (GSocket * socket, GIOCondition condition,
   } else {
     GST_WARNING_OBJECT (server, "received unknown event %08x", condition);
   }
+exit:
+  gst_rtsp_client_state_pop_current (&state);
+
   return G_SOURCE_CONTINUE;
 
   /* ERRORS */
-client_failed:
-  {
-    GST_ERROR_OBJECT (server, "failed to create a client");
-    return G_SOURCE_CONTINUE;
-  }
 accept_failed:
   {
     gchar *str = gst_rtsp_strresult (res);
     GST_ERROR_OBJECT (server, "Could not accept client on socket %p: %s",
         socket, str);
     g_free (str);
-    g_object_unref (client);
-    return G_SOURCE_CONTINUE;
+    goto exit;
   }
-setup_failed:
+connection_refused:
   {
-    GST_ERROR_OBJECT (server, "failed to setup client connection");
+    GST_ERROR_OBJECT (server, "connection refused");
+    gst_rtsp_connection_free (conn);
+    goto exit;
+  }
+client_failed:
+  {
+    GST_ERROR_OBJECT (server, "failed to create a client");
     gst_rtsp_connection_free (conn);
-    g_object_unref (client);
-    return G_SOURCE_CONTINUE;
+    goto exit;
   }
 }
 
index 7140bff..b59482e 100644 (file)
@@ -70,8 +70,7 @@ struct _GstRTSPServerClass {
   GObjectClass  parent_class;
 
   GstRTSPClient * (*create_client)      (GstRTSPServer *server);
-  gboolean        (*setup_connection)   (GstRTSPServer *server, GstRTSPClient *client,
-                                         GstRTSPConnection *conn);
+
   /* signals */
   void            (*client_connected)   (GstRTSPServer *server, GstRTSPClient *client);
 };