2 * Copyright (C) 2010 Wim Taymans <wim.taymans at gmail.com>
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.
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.
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.
21 * @short_description: Authentication and authorization
22 * @see_also: #GstRTSPPermissions, #GstRTSPToken
24 * The #GstRTSPAuth object is responsible for checking if the current user is
25 * allowed to perform requested actions. The default implementation has some
26 * reasonable checks but subclasses can implement custom security policies.
28 * A new auth object is made with gst_rtsp_auth_new(). It is usually configured
29 * on the #GstRTSPServer object.
31 * The RTSP server will call gst_rtsp_auth_check() with a string describing the
32 * check to perform. The possible checks are prefixed with
33 * GST_RTSP_AUTH_CHECK_*. Depending on the check, the default implementation
34 * will use the current #GstRTSPToken, #GstRTSPContext and
35 * #GstRTSPPermissions on the object to check if an operation is allowed.
37 * The default #GstRTSPAuth object has support for basic authentication. With
38 * gst_rtsp_auth_add_basic() you can add a basic authentication string together
39 * with the #GstRTSPToken that will become active when successfully
42 * When a TLS certificate has been set with gst_rtsp_auth_set_tls_certificate(),
43 * the default auth object will require the client to connect with a TLS
46 * Last reviewed on 2013-07-16 (1.0.0)
54 #include "rtsp-auth.h"
56 struct _GstRTSPAuthPrivate
60 /* the TLS certificate */
61 GTlsCertificate *certificate;
62 GTlsDatabase *database;
63 GTlsAuthenticationMode mode;
64 GHashTable *basic; /* protected by lock */
65 GHashTable *digest, *nonces; /* protected by lock */
66 guint64 last_nonce_check;
67 GstRTSPToken *default_token;
68 GstRTSPMethod methods;
69 GstRTSPAuthMethod auth_methods;
89 gst_rtsp_digest_entry_free (GstRTSPDigestEntry * entry)
91 gst_rtsp_token_unref (entry->token);
93 g_free (entry->md5_pass);
98 gst_rtsp_digest_nonce_free (GstRTSPDigestNonce * nonce)
100 g_free (nonce->nonce);
113 SIGNAL_ACCEPT_CERTIFICATE,
117 static guint signals[SIGNAL_LAST] = { 0 };
119 GST_DEBUG_CATEGORY_STATIC (rtsp_auth_debug);
120 #define GST_CAT_DEFAULT rtsp_auth_debug
122 static void gst_rtsp_auth_get_property (GObject * object, guint propid,
123 GValue * value, GParamSpec * pspec);
124 static void gst_rtsp_auth_set_property (GObject * object, guint propid,
125 const GValue * value, GParamSpec * pspec);
126 static void gst_rtsp_auth_finalize (GObject * obj);
128 static gboolean default_authenticate (GstRTSPAuth * auth, GstRTSPContext * ctx);
129 static gboolean default_check (GstRTSPAuth * auth, GstRTSPContext * ctx,
130 const gchar * check);
131 static void default_generate_authenticate_header (GstRTSPAuth * auth,
132 GstRTSPContext * ctx);
135 G_DEFINE_TYPE_WITH_PRIVATE (GstRTSPAuth, gst_rtsp_auth, G_TYPE_OBJECT);
138 gst_rtsp_auth_class_init (GstRTSPAuthClass * klass)
140 GObjectClass *gobject_class;
142 gobject_class = G_OBJECT_CLASS (klass);
144 gobject_class->get_property = gst_rtsp_auth_get_property;
145 gobject_class->set_property = gst_rtsp_auth_set_property;
146 gobject_class->finalize = gst_rtsp_auth_finalize;
148 klass->authenticate = default_authenticate;
149 klass->check = default_check;
150 klass->generate_authenticate_header = default_generate_authenticate_header;
152 GST_DEBUG_CATEGORY_INIT (rtsp_auth_debug, "rtspauth", 0, "GstRTSPAuth");
155 * GstRTSPAuth::accept-certificate:
156 * @auth: a #GstRTSPAuth
157 * @connection: a #GTlsConnection
158 * @peer_cert: the peer's #GTlsCertificate
159 * @errors: the problems with @peer_cert.
161 * Emitted during the TLS handshake after the client certificate has
162 * been received. See also gst_rtsp_auth_set_tls_authentication_mode().
164 * Returns: %TRUE to accept @peer_cert (which will also
165 * immediately end the signal emission). %FALSE to allow the signal
166 * emission to continue, which will cause the handshake to fail if
167 * no one else overrides it.
171 signals[SIGNAL_ACCEPT_CERTIFICATE] = g_signal_new ("accept-certificate",
172 G_TYPE_FROM_CLASS (gobject_class),
174 G_STRUCT_OFFSET (GstRTSPAuthClass, accept_certificate),
175 g_signal_accumulator_true_handled, NULL, NULL,
176 G_TYPE_BOOLEAN, 3, G_TYPE_TLS_CONNECTION, G_TYPE_TLS_CERTIFICATE,
177 G_TYPE_TLS_CERTIFICATE_FLAGS);
181 gst_rtsp_auth_init (GstRTSPAuth * auth)
183 GstRTSPAuthPrivate *priv;
185 auth->priv = priv = gst_rtsp_auth_get_instance_private (auth);
187 g_mutex_init (&priv->lock);
189 priv->basic = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
190 (GDestroyNotify) gst_rtsp_token_unref);
191 priv->digest = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
192 (GDestroyNotify) gst_rtsp_digest_entry_free);
193 priv->nonces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
194 (GDestroyNotify) gst_rtsp_digest_nonce_free);
196 /* bitwise or of all methods that need authentication */
198 priv->auth_methods = GST_RTSP_AUTH_BASIC;
199 priv->realm = g_strdup ("GStreamer RTSP Server");
203 gst_rtsp_auth_finalize (GObject * obj)
205 GstRTSPAuth *auth = GST_RTSP_AUTH (obj);
206 GstRTSPAuthPrivate *priv = auth->priv;
208 GST_INFO ("finalize auth %p", auth);
210 if (priv->certificate)
211 g_object_unref (priv->certificate);
213 g_object_unref (priv->database);
214 g_hash_table_unref (priv->basic);
215 g_hash_table_unref (priv->digest);
216 g_hash_table_unref (priv->nonces);
217 if (priv->default_token)
218 gst_rtsp_token_unref (priv->default_token);
219 g_mutex_clear (&priv->lock);
220 g_free (priv->realm);
222 G_OBJECT_CLASS (gst_rtsp_auth_parent_class)->finalize (obj);
226 gst_rtsp_auth_get_property (GObject * object, guint propid,
227 GValue * value, GParamSpec * pspec)
231 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
236 gst_rtsp_auth_set_property (GObject * object, guint propid,
237 const GValue * value, GParamSpec * pspec)
241 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
248 * Create a new #GstRTSPAuth instance.
250 * Returns: (transfer full): a new #GstRTSPAuth
253 gst_rtsp_auth_new (void)
257 result = g_object_new (GST_TYPE_RTSP_AUTH, NULL);
263 * gst_rtsp_auth_set_tls_certificate:
264 * @auth: a #GstRTSPAuth
265 * @cert: (transfer none) (allow-none): a #GTlsCertificate
267 * Set the TLS certificate for the auth. Client connections will only
268 * be accepted when TLS is negotiated.
271 gst_rtsp_auth_set_tls_certificate (GstRTSPAuth * auth, GTlsCertificate * cert)
273 GstRTSPAuthPrivate *priv;
274 GTlsCertificate *old;
276 g_return_if_fail (GST_IS_RTSP_AUTH (auth));
283 g_mutex_lock (&priv->lock);
284 old = priv->certificate;
285 priv->certificate = cert;
286 g_mutex_unlock (&priv->lock);
289 g_object_unref (old);
293 * gst_rtsp_auth_get_tls_certificate:
294 * @auth: a #GstRTSPAuth
296 * Get the #GTlsCertificate used for negotiating TLS @auth.
298 * Returns: (transfer full) (nullable): the #GTlsCertificate of @auth. g_object_unref() after
302 gst_rtsp_auth_get_tls_certificate (GstRTSPAuth * auth)
304 GstRTSPAuthPrivate *priv;
305 GTlsCertificate *result;
307 g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), NULL);
311 g_mutex_lock (&priv->lock);
312 if ((result = priv->certificate))
313 g_object_ref (result);
314 g_mutex_unlock (&priv->lock);
320 * gst_rtsp_auth_set_tls_database:
321 * @auth: a #GstRTSPAuth
322 * @database: (transfer none) (allow-none): a #GTlsDatabase
324 * Sets the certificate database that is used to verify peer certificates.
325 * If set to %NULL (the default), then peer certificate validation will always
326 * set the %G_TLS_CERTIFICATE_UNKNOWN_CA error.
331 gst_rtsp_auth_set_tls_database (GstRTSPAuth * auth, GTlsDatabase * database)
333 GstRTSPAuthPrivate *priv;
336 g_return_if_fail (GST_IS_RTSP_AUTH (auth));
341 g_object_ref (database);
343 g_mutex_lock (&priv->lock);
344 old = priv->database;
345 priv->database = database;
346 g_mutex_unlock (&priv->lock);
349 g_object_unref (old);
353 * gst_rtsp_auth_get_tls_database:
354 * @auth: a #GstRTSPAuth
356 * Get the #GTlsDatabase used for verifying client certificate.
358 * Returns: (transfer full) (nullable): the #GTlsDatabase of @auth. g_object_unref() after
363 gst_rtsp_auth_get_tls_database (GstRTSPAuth * auth)
365 GstRTSPAuthPrivate *priv;
366 GTlsDatabase *result;
368 g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), NULL);
372 g_mutex_lock (&priv->lock);
373 if ((result = priv->database))
374 g_object_ref (result);
375 g_mutex_unlock (&priv->lock);
381 * gst_rtsp_auth_set_tls_authentication_mode:
382 * @auth: a #GstRTSPAuth
383 * @mode: a #GTlsAuthenticationMode
385 * The #GTlsAuthenticationMode to set on the underlying GTlsServerConnection.
386 * When set to another value than %G_TLS_AUTHENTICATION_NONE,
387 * #GstRTSPAuth::accept-certificate signal will be emitted and must be handled.
392 gst_rtsp_auth_set_tls_authentication_mode (GstRTSPAuth * auth,
393 GTlsAuthenticationMode mode)
395 GstRTSPAuthPrivate *priv;
397 g_return_if_fail (GST_IS_RTSP_AUTH (auth));
401 g_mutex_lock (&priv->lock);
403 g_mutex_unlock (&priv->lock);
407 * gst_rtsp_auth_get_tls_authentication_mode:
408 * @auth: a #GstRTSPAuth
410 * Get the #GTlsAuthenticationMode.
412 * Returns: (transfer full): the #GTlsAuthenticationMode.
414 GTlsAuthenticationMode
415 gst_rtsp_auth_get_tls_authentication_mode (GstRTSPAuth * auth)
417 GstRTSPAuthPrivate *priv;
418 GTlsAuthenticationMode result;
420 g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), G_TLS_AUTHENTICATION_NONE);
424 g_mutex_lock (&priv->lock);
426 g_mutex_unlock (&priv->lock);
432 * gst_rtsp_auth_set_default_token:
433 * @auth: a #GstRTSPAuth
434 * @token: (transfer none) (allow-none): a #GstRTSPToken
436 * Set the default #GstRTSPToken to @token in @auth. The default token will
437 * be used for unauthenticated users.
440 gst_rtsp_auth_set_default_token (GstRTSPAuth * auth, GstRTSPToken * token)
442 GstRTSPAuthPrivate *priv;
445 g_return_if_fail (GST_IS_RTSP_AUTH (auth));
450 gst_rtsp_token_ref (token);
452 g_mutex_lock (&priv->lock);
453 old = priv->default_token;
454 priv->default_token = token;
455 g_mutex_unlock (&priv->lock);
458 gst_rtsp_token_unref (old);
462 * gst_rtsp_auth_get_default_token:
463 * @auth: a #GstRTSPAuth
465 * Get the default token for @auth. This token will be used for unauthenticated
468 * Returns: (transfer full) (nullable): the #GstRTSPToken of @auth. gst_rtsp_token_unref() after
472 gst_rtsp_auth_get_default_token (GstRTSPAuth * auth)
474 GstRTSPAuthPrivate *priv;
475 GstRTSPToken *result;
477 g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), NULL);
481 g_mutex_lock (&priv->lock);
482 if ((result = priv->default_token))
483 gst_rtsp_token_ref (result);
484 g_mutex_unlock (&priv->lock);
490 * gst_rtsp_auth_add_basic:
491 * @auth: a #GstRTSPAuth
492 * @basic: the basic token
493 * @token: (transfer none): authorisation token
495 * Add a basic token for the default authentication algorithm that
496 * enables the client with privileges listed in @token.
499 gst_rtsp_auth_add_basic (GstRTSPAuth * auth, const gchar * basic,
500 GstRTSPToken * token)
502 GstRTSPAuthPrivate *priv;
504 g_return_if_fail (GST_IS_RTSP_AUTH (auth));
505 g_return_if_fail (basic != NULL);
506 g_return_if_fail (GST_IS_RTSP_TOKEN (token));
510 g_mutex_lock (&priv->lock);
511 g_hash_table_replace (priv->basic, g_strdup (basic),
512 gst_rtsp_token_ref (token));
513 g_mutex_unlock (&priv->lock);
517 * gst_rtsp_auth_remove_basic:
518 * @auth: a #GstRTSPAuth
519 * @basic: (transfer none): the basic token
521 * Removes @basic authentication token.
524 gst_rtsp_auth_remove_basic (GstRTSPAuth * auth, const gchar * basic)
526 GstRTSPAuthPrivate *priv;
528 g_return_if_fail (GST_IS_RTSP_AUTH (auth));
529 g_return_if_fail (basic != NULL);
533 g_mutex_lock (&priv->lock);
534 g_hash_table_remove (priv->basic, basic);
535 g_mutex_unlock (&priv->lock);
539 * gst_rtsp_auth_add_digest:
540 * @auth: a #GstRTSPAuth
541 * @user: the digest user name
542 * @pass: the digest password
543 * @token: (transfer none): authorisation token
545 * Add a digest @user and @pass for the default authentication algorithm that
546 * enables the client with privileges listed in @token.
551 gst_rtsp_auth_add_digest (GstRTSPAuth * auth, const gchar * user,
552 const gchar * pass, GstRTSPToken * token)
554 GstRTSPAuthPrivate *priv;
555 GstRTSPDigestEntry *entry;
557 g_return_if_fail (GST_IS_RTSP_AUTH (auth));
558 g_return_if_fail (user != NULL);
559 g_return_if_fail (pass != NULL);
560 g_return_if_fail (GST_IS_RTSP_TOKEN (token));
564 entry = g_new0 (GstRTSPDigestEntry, 1);
565 entry->token = gst_rtsp_token_ref (token);
566 entry->pass = g_strdup (pass);
568 g_mutex_lock (&priv->lock);
569 g_hash_table_replace (priv->digest, g_strdup (user), entry);
570 g_mutex_unlock (&priv->lock);
573 /* With auth lock taken */
575 update_digest_cb (gchar * key, GstRTSPDigestEntry * entry, GHashTable * digest)
577 g_hash_table_replace (digest, key, entry);
583 * gst_rtsp_auth_parse_htdigest:
584 * @path: (type filename): Path to the htdigest file
585 * @token: (transfer none): authorisation token
587 * Parse the contents of the file at @path and enable the privileges
588 * listed in @token for the users it describes.
590 * The format of the file is expected to match the format described by
591 * <https://en.wikipedia.org/wiki/Digest_access_authentication#The_.htdigest_file>,
592 * as output by the `htdigest` command.
594 * Returns: %TRUE if the file was successfully parsed, %FALSE otherwise.
599 gst_rtsp_auth_parse_htdigest (GstRTSPAuth * auth, const gchar * path,
600 GstRTSPToken * token)
602 GstRTSPAuthPrivate *priv;
603 gboolean ret = FALSE;
606 gchar *contents = NULL;
607 GError *error = NULL;
608 GHashTable *new_entries =
609 g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
610 (GDestroyNotify) gst_rtsp_digest_entry_free);
613 g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), FALSE);
614 g_return_val_if_fail (path != NULL, FALSE);
615 g_return_val_if_fail (GST_IS_RTSP_TOKEN (token), FALSE);
618 if (!g_file_get_contents (path, &contents, NULL, &error)) {
619 GST_ERROR_OBJECT (auth, "Could not parse htdigest: %s", error->message);
623 for (line = contents; line && *line; line = eol ? eol + 1 : NULL) {
624 GstRTSPDigestEntry *entry;
626 eol = strchr (line, '\n');
631 strv = g_strsplit (line, ":", -1);
633 if (!(strv[0] && strv[1] && strv[2] && !strv[3])) {
634 GST_ERROR_OBJECT (auth, "Invalid htdigest format");
639 if (strlen (strv[2]) != 32) {
640 GST_ERROR_OBJECT (auth,
641 "Invalid htdigest format, hash is expected to be 32 characters long");
646 entry = g_new0 (GstRTSPDigestEntry, 1);
647 entry->token = gst_rtsp_token_ref (token);
648 entry->md5_pass = g_strdup (strv[2]);
649 g_hash_table_replace (new_entries, g_strdup (strv[0]), entry);
655 /* We only update digest if the file was entirely valid */
656 g_mutex_lock (&priv->lock);
657 g_hash_table_foreach_steal (new_entries, (GHRFunc) update_digest_cb,
659 g_mutex_unlock (&priv->lock);
663 g_clear_error (&error);
665 g_hash_table_unref (new_entries);
670 * gst_rtsp_auth_remove_digest:
671 * @auth: a #GstRTSPAuth
672 * @user: (transfer none): the digest user name
674 * Removes a digest user.
679 gst_rtsp_auth_remove_digest (GstRTSPAuth * auth, const gchar * user)
681 GstRTSPAuthPrivate *priv;
683 g_return_if_fail (GST_IS_RTSP_AUTH (auth));
684 g_return_if_fail (user != NULL);
688 g_mutex_lock (&priv->lock);
689 g_hash_table_remove (priv->digest, user);
690 g_mutex_unlock (&priv->lock);
694 * gst_rtsp_auth_set_supported_methods:
695 * @auth: a #GstRTSPAuth
696 * @methods: supported methods
698 * Sets the supported authentication @methods for @auth.
703 gst_rtsp_auth_set_supported_methods (GstRTSPAuth * auth,
704 GstRTSPAuthMethod methods)
706 GstRTSPAuthPrivate *priv;
708 g_return_if_fail (GST_IS_RTSP_AUTH (auth));
712 g_mutex_lock (&priv->lock);
713 priv->auth_methods = methods;
714 g_mutex_unlock (&priv->lock);
718 * gst_rtsp_auth_get_supported_methods:
719 * @auth: a #GstRTSPAuth
721 * Gets the supported authentication methods of @auth.
723 * Returns: The supported authentication methods
728 gst_rtsp_auth_get_supported_methods (GstRTSPAuth * auth)
730 GstRTSPAuthPrivate *priv;
731 GstRTSPAuthMethod methods;
733 g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), 0);
737 g_mutex_lock (&priv->lock);
738 methods = priv->auth_methods;
739 g_mutex_unlock (&priv->lock);
747 GstRTSPDigestNonce *nonce;
751 remove_nonce (gpointer data, GObject * object)
753 RemoveNonceData *remove_nonce_data = data;
755 g_mutex_lock (&remove_nonce_data->auth->priv->lock);
756 g_hash_table_remove (remove_nonce_data->auth->priv->nonces,
757 remove_nonce_data->nonce->nonce);
758 g_mutex_unlock (&remove_nonce_data->auth->priv->lock);
760 g_object_unref (remove_nonce_data->auth);
761 g_free (remove_nonce_data);
765 default_digest_auth (GstRTSPAuth * auth, GstRTSPContext * ctx,
766 GstRTSPAuthParam ** param)
768 const gchar *realm = NULL, *user = NULL, *nonce = NULL;
769 const gchar *response = NULL, *uri = NULL;
770 GstRTSPDigestNonce *nonce_entry = NULL;
771 GstRTSPDigestEntry *digest_entry;
772 gchar *expected_response = NULL;
773 gboolean ret = FALSE;
775 GST_DEBUG_OBJECT (auth, "check Digest auth");
781 if (!realm && strcmp ((*param)->name, "realm") == 0 && (*param)->value)
782 realm = (*param)->value;
783 else if (!user && strcmp ((*param)->name, "username") == 0
785 user = (*param)->value;
786 else if (!nonce && strcmp ((*param)->name, "nonce") == 0 && (*param)->value)
787 nonce = (*param)->value;
788 else if (!response && strcmp ((*param)->name, "response") == 0
790 response = (*param)->value;
791 else if (!uri && strcmp ((*param)->name, "uri") == 0 && (*param)->value)
792 uri = (*param)->value;
797 if (!realm || !user || !nonce || !response || !uri)
800 g_mutex_lock (&auth->priv->lock);
801 digest_entry = g_hash_table_lookup (auth->priv->digest, user);
804 nonce_entry = g_hash_table_lookup (auth->priv->nonces, nonce);
808 if (strcmp (nonce_entry->ip, gst_rtsp_connection_get_ip (ctx->conn)) != 0)
810 if (nonce_entry->client && nonce_entry->client != ctx->client)
813 if (digest_entry->md5_pass) {
814 expected_response = gst_rtsp_generate_digest_auth_response_from_md5 (NULL,
815 gst_rtsp_method_as_text (ctx->method), digest_entry->md5_pass,
819 gst_rtsp_generate_digest_auth_response (NULL,
820 gst_rtsp_method_as_text (ctx->method), realm, user,
821 digest_entry->pass, uri, nonce);
824 if (!expected_response || strcmp (response, expected_response) != 0)
827 ctx->token = digest_entry->token;
831 if (nonce_entry && !nonce_entry->client) {
832 RemoveNonceData *remove_nonce_data = g_new (RemoveNonceData, 1);
834 nonce_entry->client = ctx->client;
835 remove_nonce_data->nonce = nonce_entry;
836 remove_nonce_data->auth = g_object_ref (auth);
837 g_object_weak_ref (G_OBJECT (ctx->client), remove_nonce, remove_nonce_data);
839 g_mutex_unlock (&auth->priv->lock);
841 g_free (expected_response);
847 default_authenticate (GstRTSPAuth * auth, GstRTSPContext * ctx)
849 GstRTSPAuthPrivate *priv = auth->priv;
850 GstRTSPAuthCredential **credentials, **credential;
852 GST_DEBUG_OBJECT (auth, "authenticate");
854 g_mutex_lock (&priv->lock);
855 /* FIXME, need to ref but we have no way to unref when the ctx is
857 ctx->token = priv->default_token;
858 g_mutex_unlock (&priv->lock);
861 gst_rtsp_message_parse_auth_credentials (ctx->request,
862 GST_RTSP_HDR_AUTHORIZATION);
867 credential = credentials;
868 while (*credential) {
869 if ((*credential)->scheme == GST_RTSP_AUTH_BASIC) {
872 GST_DEBUG_OBJECT (auth, "check Basic auth");
873 g_mutex_lock (&priv->lock);
874 if ((*credential)->authorization && (token =
875 g_hash_table_lookup (priv->basic,
876 (*credential)->authorization))) {
877 GST_DEBUG_OBJECT (auth, "setting token %p", token);
879 g_mutex_unlock (&priv->lock);
882 g_mutex_unlock (&priv->lock);
883 } else if ((*credential)->scheme == GST_RTSP_AUTH_DIGEST) {
884 if (default_digest_auth (auth, ctx, (*credential)->params))
891 gst_rtsp_auth_credentials_free (credentials);
896 GST_DEBUG_OBJECT (auth, "no authorization header found");
902 default_generate_authenticate_header (GstRTSPAuth * auth, GstRTSPContext * ctx)
904 if (auth->priv->auth_methods & GST_RTSP_AUTH_BASIC) {
906 g_strdup_printf ("Basic realm=\"%s\"", auth->priv->realm);
907 gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_WWW_AUTHENTICATE,
909 g_free (auth_header);
912 if (auth->priv->auth_methods & GST_RTSP_AUTH_DIGEST) {
913 GstRTSPDigestNonce *nonce;
914 gchar *nonce_value, *auth_header;
917 g_strdup_printf ("%08x%08x", g_random_int (), g_random_int ());
921 ("Digest realm=\"%s\", nonce=\"%s\"", auth->priv->realm, nonce_value);
922 gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_WWW_AUTHENTICATE,
924 g_free (auth_header);
926 nonce = g_new0 (GstRTSPDigestNonce, 1);
927 nonce->nonce = g_strdup (nonce_value);
928 nonce->timestamp = g_get_monotonic_time ();
929 nonce->ip = g_strdup (gst_rtsp_connection_get_ip (ctx->conn));
930 g_mutex_lock (&auth->priv->lock);
931 g_hash_table_replace (auth->priv->nonces, nonce_value, nonce);
933 if (auth->priv->last_nonce_check == 0)
934 auth->priv->last_nonce_check = nonce->timestamp;
936 /* 30 second nonce timeout */
937 if (nonce->timestamp - auth->priv->last_nonce_check >= 30 * G_USEC_PER_SEC) {
941 g_hash_table_iter_init (&iter, auth->priv->nonces);
942 while (g_hash_table_iter_next (&iter, &key, &value)) {
943 GstRTSPDigestNonce *tmp = value;
946 && nonce->timestamp - tmp->timestamp >= 30 * G_USEC_PER_SEC)
947 g_hash_table_iter_remove (&iter);
949 auth->priv->last_nonce_check = nonce->timestamp;
952 g_mutex_unlock (&auth->priv->lock);
957 send_response (GstRTSPAuth * auth, GstRTSPStatusCode code, GstRTSPContext * ctx)
959 gst_rtsp_message_init_response (ctx->response, code,
960 gst_rtsp_status_as_text (code), ctx->request);
962 if (code == GST_RTSP_STS_UNAUTHORIZED) {
963 GstRTSPAuthClass *klass;
965 klass = GST_RTSP_AUTH_GET_CLASS (auth);
967 if (klass->generate_authenticate_header)
968 klass->generate_authenticate_header (auth, ctx);
970 gst_rtsp_client_send_message (ctx->client, ctx->session, ctx->response);
974 ensure_authenticated (GstRTSPAuth * auth, GstRTSPContext * ctx)
976 GstRTSPAuthClass *klass;
978 klass = GST_RTSP_AUTH_GET_CLASS (auth);
980 /* we need a token to check */
981 if (ctx->token == NULL) {
982 if (klass->authenticate) {
983 if (!klass->authenticate (auth, ctx))
984 goto authenticate_failed;
987 if (ctx->token == NULL)
995 GST_DEBUG_OBJECT (auth, "authenticate failed");
996 send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx);
1001 GST_DEBUG_OBJECT (auth, "no authorization token found");
1002 send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx);
1008 accept_certificate_cb (GTlsConnection * conn, GTlsCertificate * peer_cert,
1009 GTlsCertificateFlags errors, GstRTSPAuth * auth)
1011 gboolean ret = FALSE;
1013 g_signal_emit (auth, signals[SIGNAL_ACCEPT_CERTIFICATE], 0,
1014 conn, peer_cert, errors, &ret);
1019 /* new connection */
1021 check_connect (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check)
1023 GstRTSPAuthPrivate *priv = auth->priv;
1024 GTlsConnection *tls;
1026 /* configure the connection */
1028 if (priv->certificate) {
1029 tls = gst_rtsp_connection_get_tls (ctx->conn, NULL);
1030 g_tls_connection_set_certificate (tls, priv->certificate);
1033 if (priv->mode != G_TLS_AUTHENTICATION_NONE) {
1034 tls = gst_rtsp_connection_get_tls (ctx->conn, NULL);
1035 g_tls_connection_set_database (tls, priv->database);
1036 g_object_set (tls, "authentication-mode", priv->mode, NULL);
1037 g_signal_connect (tls, "accept-certificate",
1038 G_CALLBACK (accept_certificate_cb), auth);
1044 /* check url and methods */
1046 check_url (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check)
1048 GstRTSPAuthPrivate *priv = auth->priv;
1050 if ((ctx->method & priv->methods) != 0)
1051 if (!ensure_authenticated (auth, ctx))
1052 goto not_authenticated;
1063 /* check access to media factory */
1065 check_factory (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check)
1068 GstRTSPPermissions *perms;
1070 if (!ensure_authenticated (auth, ctx))
1073 if (!(role = gst_rtsp_token_get_string (ctx->token,
1074 GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE)))
1076 if (!(perms = gst_rtsp_media_factory_get_permissions (ctx->factory)))
1077 goto no_permissions;
1079 if (g_str_equal (check, GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS)) {
1080 if (!gst_rtsp_permissions_is_allowed (perms, role,
1081 GST_RTSP_PERM_MEDIA_FACTORY_ACCESS))
1083 } else if (g_str_equal (check, GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT)) {
1084 if (!gst_rtsp_permissions_is_allowed (perms, role,
1085 GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT))
1089 gst_rtsp_permissions_unref (perms);
1096 GST_DEBUG_OBJECT (auth, "no media factory role found");
1097 send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx);
1102 GST_DEBUG_OBJECT (auth, "no permissions on media factory found");
1103 send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx);
1108 GST_DEBUG_OBJECT (auth, "no permissions to access media factory");
1109 gst_rtsp_permissions_unref (perms);
1110 send_response (auth, GST_RTSP_STS_NOT_FOUND, ctx);
1115 GST_DEBUG_OBJECT (auth, "no permissions to construct media factory");
1116 gst_rtsp_permissions_unref (perms);
1117 send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx);
1123 check_client_settings (GstRTSPAuth * auth, GstRTSPContext * ctx,
1124 const gchar * check)
1126 if (!ensure_authenticated (auth, ctx))
1129 return gst_rtsp_token_is_allowed (ctx->token,
1130 GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS);
1134 default_check (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check)
1136 gboolean res = FALSE;
1138 /* FIXME, use hastable or so */
1139 if (g_str_equal (check, GST_RTSP_AUTH_CHECK_CONNECT)) {
1140 res = check_connect (auth, ctx, check);
1141 } else if (g_str_equal (check, GST_RTSP_AUTH_CHECK_URL)) {
1142 res = check_url (auth, ctx, check);
1143 } else if (g_str_has_prefix (check, "auth.check.media.factory.")) {
1144 res = check_factory (auth, ctx, check);
1145 } else if (g_str_equal (check, GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS)) {
1146 res = check_client_settings (auth, ctx, check);
1152 no_auth_check (const gchar * check)
1156 if (g_str_equal (check, GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS))
1165 * gst_rtsp_auth_check:
1166 * @check: the item to check
1168 * Check if @check is allowed in the current context.
1170 * Returns: FALSE if check failed.
1173 gst_rtsp_auth_check (const gchar * check)
1175 gboolean result = FALSE;
1176 GstRTSPAuthClass *klass;
1177 GstRTSPContext *ctx;
1180 g_return_val_if_fail (check != NULL, FALSE);
1182 if (!(ctx = gst_rtsp_context_get_current ()))
1185 /* no auth, we don't need to check */
1186 if (!(auth = ctx->auth))
1187 return no_auth_check (check);
1189 klass = GST_RTSP_AUTH_GET_CLASS (auth);
1191 GST_DEBUG_OBJECT (auth, "check authorization '%s'", check);
1194 result = klass->check (auth, ctx, check);
1201 GST_ERROR ("no context found");
1207 * gst_rtsp_auth_make_basic:
1211 * Construct a Basic authorisation token from @user and @pass.
1213 * Returns: (transfer full): the base64 encoding of the string @user:@pass.
1214 * g_free() after usage.
1217 gst_rtsp_auth_make_basic (const gchar * user, const gchar * pass)
1222 g_return_val_if_fail (user != NULL, NULL);
1223 g_return_val_if_fail (pass != NULL, NULL);
1225 user_pass = g_strjoin (":", user, pass, NULL);
1226 result = g_base64_encode ((guchar *) user_pass, strlen (user_pass));
1233 * gst_rtsp_auth_set_realm:
1234 * @realm: (nullable): The realm to set
1236 * Set the @realm of @auth
1241 gst_rtsp_auth_set_realm (GstRTSPAuth * auth, const gchar * realm)
1243 g_return_if_fail (GST_IS_RTSP_AUTH (auth));
1244 g_return_if_fail (realm != NULL);
1246 if (auth->priv->realm)
1247 g_free (auth->priv->realm);
1249 auth->priv->realm = g_strdup (realm);
1253 * gst_rtsp_auth_get_realm:
1255 * Returns: (transfer full) (nullable): the @realm of @auth
1260 gst_rtsp_auth_get_realm (GstRTSPAuth * auth)
1262 g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), NULL);
1264 return g_strdup (auth->priv->realm);