From 0a285290cba4af9eb37170cf1edcdcda3b35d41b Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 31 May 2013 11:42:36 +0200 Subject: [PATCH] server: add support for TLS Add methods to set and get a TLS certificate. Add vmethod to configure a new connection. By default, configure the TLS certificate in a new connection if needed. --- gst/rtsp-server/rtsp-server.c | 98 ++++++++++++++++++++++++++++++++++++++++++- gst/rtsp-server/rtsp-server.h | 9 +++- 2 files changed, 104 insertions(+), 3 deletions(-) diff --git a/gst/rtsp-server/rtsp-server.c b/gst/rtsp-server/rtsp-server.c index 24f2282..8e3acb3 100644 --- a/gst/rtsp-server/rtsp-server.c +++ b/gst/rtsp-server/rtsp-server.c @@ -51,6 +51,9 @@ struct _GstRTSPServerPrivate /* authentication manager */ GstRTSPAuth *auth; + /* the TLS certificate */ + GTlsCertificate *certificate; + /* the clients that are connected */ GList *clients; GQueue loops; /* the main loops used in the threads */ @@ -106,6 +109,8 @@ static void gst_rtsp_server_finalize (GObject * object); static gpointer do_loop (Loop * loop); 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) @@ -209,6 +214,7 @@ gst_rtsp_server_class_init (GstRTSPServerClass * klass) gst_rtsp_client_get_type ()); klass->create_client = default_create_client; + klass->setup_connection = default_setup_connection; klass->pool = g_thread_pool_new ((GFunc) do_loop, klass, -1, FALSE, NULL); @@ -253,6 +259,9 @@ 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); @@ -678,6 +687,63 @@ gst_rtsp_server_get_max_threads (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, @@ -1087,6 +1153,25 @@ 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 @@ -1165,9 +1250,9 @@ gst_rtsp_server_io_func (GSocket * socket, GIOCondition condition, GstRTSPClient *client = NULL; GstRTSPServerClass *klass; GstRTSPResult res; + GstRTSPConnection *conn = NULL; if (condition & G_IO_IN) { - GstRTSPConnection *conn; klass = GST_RTSP_SERVER_GET_CLASS (server); @@ -1181,6 +1266,10 @@ gst_rtsp_server_io_func (GSocket * socket, GIOCondition condition, 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); @@ -1209,6 +1298,13 @@ accept_failed: g_object_unref (client); return G_SOURCE_CONTINUE; } +setup_failed: + { + GST_ERROR_OBJECT (server, "failed to setup client connection"); + gst_rtsp_connection_free (conn); + g_object_unref (client); + return G_SOURCE_CONTINUE; + } } static void diff --git a/gst/rtsp-server/rtsp-server.h b/gst/rtsp-server/rtsp-server.h index 17e1f61..3d24e0b 100644 --- a/gst/rtsp-server/rtsp-server.h +++ b/gst/rtsp-server/rtsp-server.h @@ -59,7 +59,8 @@ struct _GstRTSPServer { * * @create_client: Create, configure a new GstRTSPClient * object that handles the new connection on @socket. - * @accept_client: accept a new GstRTSPClient + * @setup_connection: Setup the new client connection. The default + * implementation will configure the TLS certificate. * * The RTSP server class structure */ @@ -69,7 +70,8 @@ struct _GstRTSPServerClass { GThreadPool *pool; GstRTSPClient * (*create_client) (GstRTSPServer *server); - + gboolean (*setup_connection) (GstRTSPServer *server, GstRTSPClient *client, + GstRTSPConnection *conn); /* signals */ void (*client_connected) (GstRTSPServer *server, GstRTSPClient *client); }; @@ -101,6 +103,9 @@ GstRTSPAuth * gst_rtsp_server_get_auth (GstRTSPServer *serve void gst_rtsp_server_set_max_threads (GstRTSPServer *server, gint max_threads); gint gst_rtsp_server_get_max_threads (GstRTSPServer *server); +void gst_rtsp_server_set_tls_certificate (GstRTSPServer *server, GTlsCertificate *cert); +GTlsCertificate * gst_rtsp_server_get_tls_certificate (GstRTSPServer *server); + gboolean gst_rtsp_server_transfer_connection (GstRTSPServer * server, GSocket *socket, const gchar * ip, gint port, const gchar *initial_buffer); -- 2.7.4