c16f7a673275faf8da3b8012f9628dd1b46e30b6
[platform/upstream/gstreamer.git] / subprojects / gst-rtsp-server / gst / rtsp-server / rtsp-auth.c
1 /* GStreamer
2  * Copyright (C) 2010 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-auth
21  * @short_description: Authentication and authorization
22  * @see_also: #GstRTSPPermissions, #GstRTSPToken
23  *
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.
27  *
28  * A new auth object is made with gst_rtsp_auth_new(). It is usually configured
29  * on the #GstRTSPServer object.
30  *
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.
36  *
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
40  * authenticated.
41  *
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
44  * connection.
45  *
46  * Last reviewed on 2013-07-16 (1.0.0)
47  */
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif
51
52 #include <string.h>
53
54 #include "rtsp-auth.h"
55
56 struct _GstRTSPAuthPrivate
57 {
58   GMutex lock;
59
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;
70   gchar *realm;
71 };
72
73 typedef struct
74 {
75   GstRTSPToken *token;
76   gchar *pass;
77   gchar *md5_pass;
78 } GstRTSPDigestEntry;
79
80 typedef struct
81 {
82   gchar *nonce;
83   gchar *ip;
84   guint64 timestamp;
85   gpointer client;
86 } GstRTSPDigestNonce;
87
88 static void
89 gst_rtsp_digest_entry_free (GstRTSPDigestEntry * entry)
90 {
91   gst_rtsp_token_unref (entry->token);
92   g_free (entry->pass);
93   g_free (entry->md5_pass);
94   g_free (entry);
95 }
96
97 static void
98 gst_rtsp_digest_nonce_free (GstRTSPDigestNonce * nonce)
99 {
100   g_free (nonce->nonce);
101   g_free (nonce->ip);
102   g_free (nonce);
103 }
104
105 enum
106 {
107   PROP_0,
108   PROP_LAST
109 };
110
111 enum
112 {
113   SIGNAL_ACCEPT_CERTIFICATE,
114   SIGNAL_LAST
115 };
116
117 static guint signals[SIGNAL_LAST] = { 0 };
118
119 GST_DEBUG_CATEGORY_STATIC (rtsp_auth_debug);
120 #define GST_CAT_DEFAULT rtsp_auth_debug
121
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);
127
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);
133
134
135 G_DEFINE_TYPE_WITH_PRIVATE (GstRTSPAuth, gst_rtsp_auth, G_TYPE_OBJECT);
136
137 static void
138 gst_rtsp_auth_class_init (GstRTSPAuthClass * klass)
139 {
140   GObjectClass *gobject_class;
141
142   gobject_class = G_OBJECT_CLASS (klass);
143
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;
147
148   klass->authenticate = default_authenticate;
149   klass->check = default_check;
150   klass->generate_authenticate_header = default_generate_authenticate_header;
151
152   GST_DEBUG_CATEGORY_INIT (rtsp_auth_debug, "rtspauth", 0, "GstRTSPAuth");
153
154   /**
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.
160    *
161    * Emitted during the TLS handshake after the client certificate has
162    * been received. See also gst_rtsp_auth_set_tls_authentication_mode().
163    *
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.
168    *
169    * Since: 1.6
170    */
171   signals[SIGNAL_ACCEPT_CERTIFICATE] = g_signal_new ("accept-certificate",
172       G_TYPE_FROM_CLASS (gobject_class),
173       G_SIGNAL_RUN_LAST,
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);
178 }
179
180 static void
181 gst_rtsp_auth_init (GstRTSPAuth * auth)
182 {
183   GstRTSPAuthPrivate *priv;
184
185   auth->priv = priv = gst_rtsp_auth_get_instance_private (auth);
186
187   g_mutex_init (&priv->lock);
188
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);
195
196   /* bitwise or of all methods that need authentication */
197   priv->methods = 0;
198   priv->auth_methods = GST_RTSP_AUTH_BASIC;
199   priv->realm = g_strdup ("GStreamer RTSP Server");
200 }
201
202 static void
203 gst_rtsp_auth_finalize (GObject * obj)
204 {
205   GstRTSPAuth *auth = GST_RTSP_AUTH (obj);
206   GstRTSPAuthPrivate *priv = auth->priv;
207
208   GST_INFO ("finalize auth %p", auth);
209
210   if (priv->certificate)
211     g_object_unref (priv->certificate);
212   if (priv->database)
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);
221
222   G_OBJECT_CLASS (gst_rtsp_auth_parent_class)->finalize (obj);
223 }
224
225 static void
226 gst_rtsp_auth_get_property (GObject * object, guint propid,
227     GValue * value, GParamSpec * pspec)
228 {
229   switch (propid) {
230     default:
231       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
232   }
233 }
234
235 static void
236 gst_rtsp_auth_set_property (GObject * object, guint propid,
237     const GValue * value, GParamSpec * pspec)
238 {
239   switch (propid) {
240     default:
241       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
242   }
243 }
244
245 /**
246  * gst_rtsp_auth_new:
247  *
248  * Create a new #GstRTSPAuth instance.
249  *
250  * Returns: (transfer full): a new #GstRTSPAuth
251  */
252 GstRTSPAuth *
253 gst_rtsp_auth_new (void)
254 {
255   GstRTSPAuth *result;
256
257   result = g_object_new (GST_TYPE_RTSP_AUTH, NULL);
258
259   return result;
260 }
261
262 /**
263  * gst_rtsp_auth_set_tls_certificate:
264  * @auth: a #GstRTSPAuth
265  * @cert: (transfer none) (allow-none): a #GTlsCertificate
266  *
267  * Set the TLS certificate for the auth. Client connections will only
268  * be accepted when TLS is negotiated.
269  */
270 void
271 gst_rtsp_auth_set_tls_certificate (GstRTSPAuth * auth, GTlsCertificate * cert)
272 {
273   GstRTSPAuthPrivate *priv;
274   GTlsCertificate *old;
275
276   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
277
278   priv = auth->priv;
279
280   if (cert)
281     g_object_ref (cert);
282
283   g_mutex_lock (&priv->lock);
284   old = priv->certificate;
285   priv->certificate = cert;
286   g_mutex_unlock (&priv->lock);
287
288   if (old)
289     g_object_unref (old);
290 }
291
292 /**
293  * gst_rtsp_auth_get_tls_certificate:
294  * @auth: a #GstRTSPAuth
295  *
296  * Get the #GTlsCertificate used for negotiating TLS @auth.
297  *
298  * Returns: (transfer full) (nullable): the #GTlsCertificate of @auth. g_object_unref() after
299  * usage.
300  */
301 GTlsCertificate *
302 gst_rtsp_auth_get_tls_certificate (GstRTSPAuth * auth)
303 {
304   GstRTSPAuthPrivate *priv;
305   GTlsCertificate *result;
306
307   g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), NULL);
308
309   priv = auth->priv;
310
311   g_mutex_lock (&priv->lock);
312   if ((result = priv->certificate))
313     g_object_ref (result);
314   g_mutex_unlock (&priv->lock);
315
316   return result;
317 }
318
319 /**
320  * gst_rtsp_auth_set_tls_database:
321  * @auth: a #GstRTSPAuth
322  * @database: (transfer none) (allow-none): a #GTlsDatabase
323  *
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.
327  *
328  * Since: 1.6
329  */
330 void
331 gst_rtsp_auth_set_tls_database (GstRTSPAuth * auth, GTlsDatabase * database)
332 {
333   GstRTSPAuthPrivate *priv;
334   GTlsDatabase *old;
335
336   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
337
338   priv = auth->priv;
339
340   if (database)
341     g_object_ref (database);
342
343   g_mutex_lock (&priv->lock);
344   old = priv->database;
345   priv->database = database;
346   g_mutex_unlock (&priv->lock);
347
348   if (old)
349     g_object_unref (old);
350 }
351
352 /**
353  * gst_rtsp_auth_get_tls_database:
354  * @auth: a #GstRTSPAuth
355  *
356  * Get the #GTlsDatabase used for verifying client certificate.
357  *
358  * Returns: (transfer full) (nullable): the #GTlsDatabase of @auth. g_object_unref() after
359  * usage.
360  * Since: 1.6
361  */
362 GTlsDatabase *
363 gst_rtsp_auth_get_tls_database (GstRTSPAuth * auth)
364 {
365   GstRTSPAuthPrivate *priv;
366   GTlsDatabase *result;
367
368   g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), NULL);
369
370   priv = auth->priv;
371
372   g_mutex_lock (&priv->lock);
373   if ((result = priv->database))
374     g_object_ref (result);
375   g_mutex_unlock (&priv->lock);
376
377   return result;
378 }
379
380 /**
381  * gst_rtsp_auth_set_tls_authentication_mode:
382  * @auth: a #GstRTSPAuth
383  * @mode: a #GTlsAuthenticationMode
384  *
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.
388  *
389  * Since: 1.6
390  */
391 void
392 gst_rtsp_auth_set_tls_authentication_mode (GstRTSPAuth * auth,
393     GTlsAuthenticationMode mode)
394 {
395   GstRTSPAuthPrivate *priv;
396
397   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
398
399   priv = auth->priv;
400
401   g_mutex_lock (&priv->lock);
402   priv->mode = mode;
403   g_mutex_unlock (&priv->lock);
404 }
405
406 /**
407  * gst_rtsp_auth_get_tls_authentication_mode:
408  * @auth: a #GstRTSPAuth
409  *
410  * Get the #GTlsAuthenticationMode.
411  *
412  * Returns: (transfer full): the #GTlsAuthenticationMode.
413  */
414 GTlsAuthenticationMode
415 gst_rtsp_auth_get_tls_authentication_mode (GstRTSPAuth * auth)
416 {
417   GstRTSPAuthPrivate *priv;
418   GTlsAuthenticationMode result;
419
420   g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), G_TLS_AUTHENTICATION_NONE);
421
422   priv = auth->priv;
423
424   g_mutex_lock (&priv->lock);
425   result = priv->mode;
426   g_mutex_unlock (&priv->lock);
427
428   return result;
429 }
430
431 /**
432  * gst_rtsp_auth_set_default_token:
433  * @auth: a #GstRTSPAuth
434  * @token: (transfer none) (allow-none): a #GstRTSPToken
435  *
436  * Set the default #GstRTSPToken to @token in @auth. The default token will
437  * be used for unauthenticated users.
438  */
439 void
440 gst_rtsp_auth_set_default_token (GstRTSPAuth * auth, GstRTSPToken * token)
441 {
442   GstRTSPAuthPrivate *priv;
443   GstRTSPToken *old;
444
445   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
446
447   priv = auth->priv;
448
449   if (token)
450     gst_rtsp_token_ref (token);
451
452   g_mutex_lock (&priv->lock);
453   old = priv->default_token;
454   priv->default_token = token;
455   g_mutex_unlock (&priv->lock);
456
457   if (old)
458     gst_rtsp_token_unref (old);
459 }
460
461 /**
462  * gst_rtsp_auth_get_default_token:
463  * @auth: a #GstRTSPAuth
464  *
465  * Get the default token for @auth. This token will be used for unauthenticated
466  * users.
467  *
468  * Returns: (transfer full) (nullable): the #GstRTSPToken of @auth. gst_rtsp_token_unref() after
469  * usage.
470  */
471 GstRTSPToken *
472 gst_rtsp_auth_get_default_token (GstRTSPAuth * auth)
473 {
474   GstRTSPAuthPrivate *priv;
475   GstRTSPToken *result;
476
477   g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), NULL);
478
479   priv = auth->priv;
480
481   g_mutex_lock (&priv->lock);
482   if ((result = priv->default_token))
483     gst_rtsp_token_ref (result);
484   g_mutex_unlock (&priv->lock);
485
486   return result;
487 }
488
489 /**
490  * gst_rtsp_auth_add_basic:
491  * @auth: a #GstRTSPAuth
492  * @basic: the basic token
493  * @token: (transfer none): authorisation token
494  *
495  * Add a basic token for the default authentication algorithm that
496  * enables the client with privileges listed in @token.
497  */
498 void
499 gst_rtsp_auth_add_basic (GstRTSPAuth * auth, const gchar * basic,
500     GstRTSPToken * token)
501 {
502   GstRTSPAuthPrivate *priv;
503
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));
507
508   priv = auth->priv;
509
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);
514 }
515
516 /**
517  * gst_rtsp_auth_remove_basic:
518  * @auth: a #GstRTSPAuth
519  * @basic: (transfer none): the basic token
520  *
521  * Removes @basic authentication token.
522  */
523 void
524 gst_rtsp_auth_remove_basic (GstRTSPAuth * auth, const gchar * basic)
525 {
526   GstRTSPAuthPrivate *priv;
527
528   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
529   g_return_if_fail (basic != NULL);
530
531   priv = auth->priv;
532
533   g_mutex_lock (&priv->lock);
534   g_hash_table_remove (priv->basic, basic);
535   g_mutex_unlock (&priv->lock);
536 }
537
538 /**
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
544  *
545  * Add a digest @user and @pass for the default authentication algorithm that
546  * enables the client with privileges listed in @token.
547  *
548  * Since: 1.12
549  */
550 void
551 gst_rtsp_auth_add_digest (GstRTSPAuth * auth, const gchar * user,
552     const gchar * pass, GstRTSPToken * token)
553 {
554   GstRTSPAuthPrivate *priv;
555   GstRTSPDigestEntry *entry;
556
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));
561
562   priv = auth->priv;
563
564   entry = g_new0 (GstRTSPDigestEntry, 1);
565   entry->token = gst_rtsp_token_ref (token);
566   entry->pass = g_strdup (pass);
567
568   g_mutex_lock (&priv->lock);
569   g_hash_table_replace (priv->digest, g_strdup (user), entry);
570   g_mutex_unlock (&priv->lock);
571 }
572
573 /* With auth lock taken */
574 static gboolean
575 update_digest_cb (gchar * key, GstRTSPDigestEntry * entry, GHashTable * digest)
576 {
577   g_hash_table_replace (digest, key, entry);
578
579   return TRUE;
580 }
581
582 /**
583  * gst_rtsp_auth_parse_htdigest:
584  * @path: (type filename): Path to the htdigest file
585  * @token: (transfer none): authorisation token
586  *
587  * Parse the contents of the file at @path and enable the privileges
588  * listed in @token for the users it describes.
589  *
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.
593  *
594  * Returns: %TRUE if the file was successfully parsed, %FALSE otherwise.
595  *
596  * Since: 1.16
597  */
598 gboolean
599 gst_rtsp_auth_parse_htdigest (GstRTSPAuth * auth, const gchar * path,
600     GstRTSPToken * token)
601 {
602   GstRTSPAuthPrivate *priv;
603   gboolean ret = FALSE;
604   gchar *line = NULL;
605   gchar *eol = NULL;
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);
611
612
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);
616
617   priv = auth->priv;
618   if (!g_file_get_contents (path, &contents, NULL, &error)) {
619     GST_ERROR_OBJECT (auth, "Could not parse htdigest: %s", error->message);
620     goto done;
621   }
622
623   for (line = contents; line && *line; line = eol ? eol + 1 : NULL) {
624     GstRTSPDigestEntry *entry;
625     gchar **strv;
626     eol = strchr (line, '\n');
627
628     if (eol)
629       *eol = '\0';
630
631     strv = g_strsplit (line, ":", -1);
632
633     if (!(strv[0] && strv[1] && strv[2] && !strv[3])) {
634       GST_ERROR_OBJECT (auth, "Invalid htdigest format");
635       g_strfreev (strv);
636       goto done;
637     }
638
639     if (strlen (strv[2]) != 32) {
640       GST_ERROR_OBJECT (auth,
641           "Invalid htdigest format, hash is expected to be 32 characters long");
642       g_strfreev (strv);
643       goto done;
644     }
645
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);
650     g_strfreev (strv);
651   }
652
653   ret = TRUE;
654
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,
658       priv->digest);
659   g_mutex_unlock (&priv->lock);
660
661 done:
662   if (error)
663     g_clear_error (&error);
664   g_free (contents);
665   g_hash_table_unref (new_entries);
666   return ret;
667 }
668
669 /**
670  * gst_rtsp_auth_remove_digest:
671  * @auth: a #GstRTSPAuth
672  * @user: (transfer none): the digest user name
673  *
674  * Removes a digest user.
675  *
676  * Since: 1.12
677  */
678 void
679 gst_rtsp_auth_remove_digest (GstRTSPAuth * auth, const gchar * user)
680 {
681   GstRTSPAuthPrivate *priv;
682
683   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
684   g_return_if_fail (user != NULL);
685
686   priv = auth->priv;
687
688   g_mutex_lock (&priv->lock);
689   g_hash_table_remove (priv->digest, user);
690   g_mutex_unlock (&priv->lock);
691 }
692
693 /**
694  * gst_rtsp_auth_set_supported_methods:
695  * @auth: a #GstRTSPAuth
696  * @methods: supported methods
697  *
698  * Sets the supported authentication @methods for @auth.
699  *
700  * Since: 1.12
701  */
702 void
703 gst_rtsp_auth_set_supported_methods (GstRTSPAuth * auth,
704     GstRTSPAuthMethod methods)
705 {
706   GstRTSPAuthPrivate *priv;
707
708   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
709
710   priv = auth->priv;
711
712   g_mutex_lock (&priv->lock);
713   priv->auth_methods = methods;
714   g_mutex_unlock (&priv->lock);
715 }
716
717 /**
718  * gst_rtsp_auth_get_supported_methods:
719  * @auth: a #GstRTSPAuth
720  *
721  * Gets the supported authentication methods of @auth.
722  *
723  * Returns: The supported authentication methods
724  *
725  * Since: 1.12
726  */
727 GstRTSPAuthMethod
728 gst_rtsp_auth_get_supported_methods (GstRTSPAuth * auth)
729 {
730   GstRTSPAuthPrivate *priv;
731   GstRTSPAuthMethod methods;
732
733   g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), 0);
734
735   priv = auth->priv;
736
737   g_mutex_lock (&priv->lock);
738   methods = priv->auth_methods;
739   g_mutex_unlock (&priv->lock);
740
741   return methods;
742 }
743
744 typedef struct
745 {
746   GstRTSPAuth *auth;
747   GstRTSPDigestNonce *nonce;
748 } RemoveNonceData;
749
750 static void
751 remove_nonce (gpointer data, GObject * object)
752 {
753   RemoveNonceData *remove_nonce_data = data;
754
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);
759
760   g_object_unref (remove_nonce_data->auth);
761   g_free (remove_nonce_data);
762 }
763
764 static gboolean
765 default_digest_auth (GstRTSPAuth * auth, GstRTSPContext * ctx,
766     GstRTSPAuthParam ** param)
767 {
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;
774
775   GST_DEBUG_OBJECT (auth, "check Digest auth");
776
777   if (!param)
778     return ret;
779
780   while (*param) {
781     if (!realm && strcmp ((*param)->name, "realm") == 0 && (*param)->value)
782       realm = (*param)->value;
783     else if (!user && strcmp ((*param)->name, "username") == 0
784         && (*param)->value)
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
789         && (*param)->value)
790       response = (*param)->value;
791     else if (!uri && strcmp ((*param)->name, "uri") == 0 && (*param)->value)
792       uri = (*param)->value;
793
794     param++;
795   }
796
797   if (!realm || !user || !nonce || !response || !uri)
798     return FALSE;
799
800   g_mutex_lock (&auth->priv->lock);
801   digest_entry = g_hash_table_lookup (auth->priv->digest, user);
802   if (!digest_entry)
803     goto out;
804   nonce_entry = g_hash_table_lookup (auth->priv->nonces, nonce);
805   if (!nonce_entry)
806     goto out;
807
808   if (strcmp (nonce_entry->ip, gst_rtsp_connection_get_ip (ctx->conn)) != 0)
809     goto out;
810   if (nonce_entry->client && nonce_entry->client != ctx->client)
811     goto out;
812
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,
816         uri, nonce);
817   } else {
818     expected_response =
819         gst_rtsp_generate_digest_auth_response (NULL,
820         gst_rtsp_method_as_text (ctx->method), realm, user,
821         digest_entry->pass, uri, nonce);
822   }
823
824   if (!expected_response || strcmp (response, expected_response) != 0)
825     goto out;
826
827   ctx->token = digest_entry->token;
828   ret = TRUE;
829
830 out:
831   if (nonce_entry && !nonce_entry->client) {
832     RemoveNonceData *remove_nonce_data = g_new (RemoveNonceData, 1);
833
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);
838   }
839   g_mutex_unlock (&auth->priv->lock);
840
841   g_free (expected_response);
842
843   return ret;
844 }
845
846 static gboolean
847 default_authenticate (GstRTSPAuth * auth, GstRTSPContext * ctx)
848 {
849   GstRTSPAuthPrivate *priv = auth->priv;
850   GstRTSPAuthCredential **credentials, **credential;
851
852   GST_DEBUG_OBJECT (auth, "authenticate");
853
854   g_mutex_lock (&priv->lock);
855   /* FIXME, need to ref but we have no way to unref when the ctx is
856    * popped */
857   ctx->token = priv->default_token;
858   g_mutex_unlock (&priv->lock);
859
860   credentials =
861       gst_rtsp_message_parse_auth_credentials (ctx->request,
862       GST_RTSP_HDR_AUTHORIZATION);
863   if (!credentials)
864     goto no_auth;
865
866   /* parse type */
867   credential = credentials;
868   while (*credential) {
869     if ((*credential)->scheme == GST_RTSP_AUTH_BASIC) {
870       GstRTSPToken *token;
871
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);
878         ctx->token = token;
879         g_mutex_unlock (&priv->lock);
880         break;
881       }
882       g_mutex_unlock (&priv->lock);
883     } else if ((*credential)->scheme == GST_RTSP_AUTH_DIGEST) {
884       if (default_digest_auth (auth, ctx, (*credential)->params))
885         break;
886     }
887
888     credential++;
889   }
890
891   gst_rtsp_auth_credentials_free (credentials);
892   return TRUE;
893
894 no_auth:
895   {
896     GST_DEBUG_OBJECT (auth, "no authorization header found");
897     return TRUE;
898   }
899 }
900
901 static void
902 default_generate_authenticate_header (GstRTSPAuth * auth, GstRTSPContext * ctx)
903 {
904   if (auth->priv->auth_methods & GST_RTSP_AUTH_BASIC) {
905     gchar *auth_header =
906         g_strdup_printf ("Basic realm=\"%s\"", auth->priv->realm);
907     gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_WWW_AUTHENTICATE,
908         auth_header);
909     g_free (auth_header);
910   }
911
912   if (auth->priv->auth_methods & GST_RTSP_AUTH_DIGEST) {
913     GstRTSPDigestNonce *nonce;
914     gchar *nonce_value, *auth_header;
915
916     nonce_value =
917         g_strdup_printf ("%08x%08x", g_random_int (), g_random_int ());
918
919     auth_header =
920         g_strdup_printf
921         ("Digest realm=\"%s\", nonce=\"%s\"", auth->priv->realm, nonce_value);
922     gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_WWW_AUTHENTICATE,
923         auth_header);
924     g_free (auth_header);
925
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);
932
933     if (auth->priv->last_nonce_check == 0)
934       auth->priv->last_nonce_check = nonce->timestamp;
935
936     /* 30 second nonce timeout */
937     if (nonce->timestamp - auth->priv->last_nonce_check >= 30 * G_USEC_PER_SEC) {
938       GHashTableIter iter;
939       gpointer key, value;
940
941       g_hash_table_iter_init (&iter, auth->priv->nonces);
942       while (g_hash_table_iter_next (&iter, &key, &value)) {
943         GstRTSPDigestNonce *tmp = value;
944
945         if (!tmp->client
946             && nonce->timestamp - tmp->timestamp >= 30 * G_USEC_PER_SEC)
947           g_hash_table_iter_remove (&iter);
948       }
949       auth->priv->last_nonce_check = nonce->timestamp;
950     }
951
952     g_mutex_unlock (&auth->priv->lock);
953   }
954 }
955
956 static void
957 send_response (GstRTSPAuth * auth, GstRTSPStatusCode code, GstRTSPContext * ctx)
958 {
959   gst_rtsp_message_init_response (ctx->response, code,
960       gst_rtsp_status_as_text (code), ctx->request);
961
962   if (code == GST_RTSP_STS_UNAUTHORIZED) {
963     GstRTSPAuthClass *klass;
964
965     klass = GST_RTSP_AUTH_GET_CLASS (auth);
966
967     if (klass->generate_authenticate_header)
968       klass->generate_authenticate_header (auth, ctx);
969   }
970   gst_rtsp_client_send_message (ctx->client, ctx->session, ctx->response);
971 }
972
973 static gboolean
974 ensure_authenticated (GstRTSPAuth * auth, GstRTSPContext * ctx)
975 {
976   GstRTSPAuthClass *klass;
977
978   klass = GST_RTSP_AUTH_GET_CLASS (auth);
979
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;
985     }
986   }
987   if (ctx->token == NULL)
988     goto no_auth;
989
990   return TRUE;
991
992 /* ERRORS */
993 authenticate_failed:
994   {
995     GST_DEBUG_OBJECT (auth, "authenticate failed");
996     send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx);
997     return FALSE;
998   }
999 no_auth:
1000   {
1001     GST_DEBUG_OBJECT (auth, "no authorization token found");
1002     send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx);
1003     return FALSE;
1004   }
1005 }
1006
1007 static gboolean
1008 accept_certificate_cb (GTlsConnection * conn, GTlsCertificate * peer_cert,
1009     GTlsCertificateFlags errors, GstRTSPAuth * auth)
1010 {
1011   gboolean ret = FALSE;
1012
1013   g_signal_emit (auth, signals[SIGNAL_ACCEPT_CERTIFICATE], 0,
1014       conn, peer_cert, errors, &ret);
1015
1016   return ret;
1017 }
1018
1019 /* new connection */
1020 static gboolean
1021 check_connect (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check)
1022 {
1023   GstRTSPAuthPrivate *priv = auth->priv;
1024   GTlsConnection *tls;
1025
1026   /* configure the connection */
1027
1028   if (priv->certificate) {
1029     tls = gst_rtsp_connection_get_tls (ctx->conn, NULL);
1030     g_tls_connection_set_certificate (tls, priv->certificate);
1031   }
1032
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);
1039   }
1040
1041   return TRUE;
1042 }
1043
1044 /* check url and methods */
1045 static gboolean
1046 check_url (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check)
1047 {
1048   GstRTSPAuthPrivate *priv = auth->priv;
1049
1050   if ((ctx->method & priv->methods) != 0)
1051     if (!ensure_authenticated (auth, ctx))
1052       goto not_authenticated;
1053
1054   return TRUE;
1055
1056   /* ERRORS */
1057 not_authenticated:
1058   {
1059     return FALSE;
1060   }
1061 }
1062
1063 /* check access to media factory */
1064 static gboolean
1065 check_factory (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check)
1066 {
1067   const gchar *role;
1068   GstRTSPPermissions *perms;
1069
1070   if (!ensure_authenticated (auth, ctx))
1071     return FALSE;
1072
1073   if (!(role = gst_rtsp_token_get_string (ctx->token,
1074               GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE)))
1075     goto no_media_role;
1076   if (!(perms = gst_rtsp_media_factory_get_permissions (ctx->factory)))
1077     goto no_permissions;
1078
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))
1082       goto no_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))
1086       goto no_construct;
1087   }
1088
1089   gst_rtsp_permissions_unref (perms);
1090
1091   return TRUE;
1092
1093   /* ERRORS */
1094 no_media_role:
1095   {
1096     GST_DEBUG_OBJECT (auth, "no media factory role found");
1097     send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx);
1098     return FALSE;
1099   }
1100 no_permissions:
1101   {
1102     GST_DEBUG_OBJECT (auth, "no permissions on media factory found");
1103     send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx);
1104     return FALSE;
1105   }
1106 no_access:
1107   {
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);
1111     return FALSE;
1112   }
1113 no_construct:
1114   {
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);
1118     return FALSE;
1119   }
1120 }
1121
1122 static gboolean
1123 check_client_settings (GstRTSPAuth * auth, GstRTSPContext * ctx,
1124     const gchar * check)
1125 {
1126   if (!ensure_authenticated (auth, ctx))
1127     return FALSE;
1128
1129   return gst_rtsp_token_is_allowed (ctx->token,
1130       GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS);
1131 }
1132
1133 static gboolean
1134 default_check (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check)
1135 {
1136   gboolean res = FALSE;
1137
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);
1147   }
1148   return res;
1149 }
1150
1151 static gboolean
1152 no_auth_check (const gchar * check)
1153 {
1154   gboolean res;
1155
1156   if (g_str_equal (check, GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS))
1157     res = FALSE;
1158   else
1159     res = TRUE;
1160
1161   return res;
1162 }
1163
1164 /**
1165  * gst_rtsp_auth_check:
1166  * @check: the item to check
1167  *
1168  * Check if @check is allowed in the current context.
1169  *
1170  * Returns: FALSE if check failed.
1171  */
1172 gboolean
1173 gst_rtsp_auth_check (const gchar * check)
1174 {
1175   gboolean result = FALSE;
1176   GstRTSPAuthClass *klass;
1177   GstRTSPContext *ctx;
1178   GstRTSPAuth *auth;
1179
1180   g_return_val_if_fail (check != NULL, FALSE);
1181
1182   if (!(ctx = gst_rtsp_context_get_current ()))
1183     goto no_context;
1184
1185   /* no auth, we don't need to check */
1186   if (!(auth = ctx->auth))
1187     return no_auth_check (check);
1188
1189   klass = GST_RTSP_AUTH_GET_CLASS (auth);
1190
1191   GST_DEBUG_OBJECT (auth, "check authorization '%s'", check);
1192
1193   if (klass->check)
1194     result = klass->check (auth, ctx, check);
1195
1196   return result;
1197
1198   /* ERRORS */
1199 no_context:
1200   {
1201     GST_ERROR ("no context found");
1202     return FALSE;
1203   }
1204 }
1205
1206 /**
1207  * gst_rtsp_auth_make_basic:
1208  * @user: a userid
1209  * @pass: a password
1210  *
1211  * Construct a Basic authorisation token from @user and @pass.
1212  *
1213  * Returns: (transfer full): the base64 encoding of the string @user:@pass.
1214  * g_free() after usage.
1215  */
1216 gchar *
1217 gst_rtsp_auth_make_basic (const gchar * user, const gchar * pass)
1218 {
1219   gchar *user_pass;
1220   gchar *result;
1221
1222   g_return_val_if_fail (user != NULL, NULL);
1223   g_return_val_if_fail (pass != NULL, NULL);
1224
1225   user_pass = g_strjoin (":", user, pass, NULL);
1226   result = g_base64_encode ((guchar *) user_pass, strlen (user_pass));
1227   g_free (user_pass);
1228
1229   return result;
1230 }
1231
1232 /**
1233  * gst_rtsp_auth_set_realm:
1234  * @realm: (nullable): The realm to set
1235  *
1236  * Set the @realm of @auth
1237  *
1238  * Since: 1.16
1239  */
1240 void
1241 gst_rtsp_auth_set_realm (GstRTSPAuth * auth, const gchar * realm)
1242 {
1243   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
1244   g_return_if_fail (realm != NULL);
1245
1246   if (auth->priv->realm)
1247     g_free (auth->priv->realm);
1248
1249   auth->priv->realm = g_strdup (realm);
1250 }
1251
1252 /**
1253  * gst_rtsp_auth_get_realm:
1254  *
1255  * Returns: (transfer full) (nullable): the @realm of @auth
1256  *
1257  * Since: 1.16
1258  */
1259 gchar *
1260 gst_rtsp_auth_get_realm (GstRTSPAuth * auth)
1261 {
1262   g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), NULL);
1263
1264   return g_strdup (auth->priv->realm);
1265 }