rtsp-auth: Add support for Digest authentication
[platform/upstream/gstreamer.git] / 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
49 #include <string.h>
50
51 #include "rtsp-auth.h"
52
53 #define GST_RTSP_AUTH_GET_PRIVATE(obj)  \
54    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_AUTH, GstRTSPAuthPrivate))
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 };
71
72 typedef struct
73 {
74   GstRTSPToken *token;
75   gchar *pass;
76 } GstRTSPDigestEntry;
77
78 typedef struct
79 {
80   gchar *nonce;
81   gchar *ip;
82   guint64 timestamp;
83   gpointer client;
84 } GstRTSPDigestNonce;
85
86 static void
87 gst_rtsp_digest_entry_free (GstRTSPDigestEntry * entry)
88 {
89   gst_rtsp_token_unref (entry->token);
90   g_free (entry->pass);
91   g_free (entry);
92 }
93
94 static void
95 gst_rtsp_digest_nonce_free (GstRTSPDigestNonce * nonce)
96 {
97   g_free (nonce->nonce);
98   g_free (nonce->ip);
99   g_free (nonce);
100 }
101
102 enum
103 {
104   PROP_0,
105   PROP_LAST
106 };
107
108 enum
109 {
110   SIGNAL_ACCEPT_CERTIFICATE,
111   SIGNAL_LAST
112 };
113
114 static guint signals[SIGNAL_LAST] = { 0 };
115
116 GST_DEBUG_CATEGORY_STATIC (rtsp_auth_debug);
117 #define GST_CAT_DEFAULT rtsp_auth_debug
118
119 static void gst_rtsp_auth_get_property (GObject * object, guint propid,
120     GValue * value, GParamSpec * pspec);
121 static void gst_rtsp_auth_set_property (GObject * object, guint propid,
122     const GValue * value, GParamSpec * pspec);
123 static void gst_rtsp_auth_finalize (GObject * obj);
124
125 static gboolean default_authenticate (GstRTSPAuth * auth, GstRTSPContext * ctx);
126 static gboolean default_check (GstRTSPAuth * auth, GstRTSPContext * ctx,
127     const gchar * check);
128 static void default_generate_authenticate_header (GstRTSPAuth * auth,
129     GstRTSPContext * ctx);
130
131
132 G_DEFINE_TYPE (GstRTSPAuth, gst_rtsp_auth, G_TYPE_OBJECT);
133
134 static void
135 gst_rtsp_auth_class_init (GstRTSPAuthClass * klass)
136 {
137   GObjectClass *gobject_class;
138
139   g_type_class_add_private (klass, sizeof (GstRTSPAuthPrivate));
140
141   gobject_class = G_OBJECT_CLASS (klass);
142
143   gobject_class->get_property = gst_rtsp_auth_get_property;
144   gobject_class->set_property = gst_rtsp_auth_set_property;
145   gobject_class->finalize = gst_rtsp_auth_finalize;
146
147   klass->authenticate = default_authenticate;
148   klass->check = default_check;
149   klass->generate_authenticate_header = default_generate_authenticate_header;
150
151   GST_DEBUG_CATEGORY_INIT (rtsp_auth_debug, "rtspauth", 0, "GstRTSPAuth");
152
153   /**
154    * GstRTSPAuth::accept-certificate:
155    * @auth: a #GstRTSPAuth
156    * @connection: a #GTlsConnection
157    * @peer_cert: the peer's #GTlsCertificate
158    * @errors: the problems with @peer_cert.
159    *
160    * Emitted during the TLS handshake after the client certificate has
161    * been received. See also gst_rtsp_auth_set_tls_authentication_mode().
162    *
163    * Returns: %TRUE to accept @peer_cert (which will also
164    * immediately end the signal emission). %FALSE to allow the signal
165    * emission to continue, which will cause the handshake to fail if
166    * no one else overrides it.
167    *
168    * Since: 1.6
169    */
170   signals[SIGNAL_ACCEPT_CERTIFICATE] = g_signal_new ("accept-certificate",
171       G_TYPE_FROM_CLASS (gobject_class),
172       G_SIGNAL_RUN_LAST,
173       G_STRUCT_OFFSET (GstRTSPAuthClass, accept_certificate),
174       g_signal_accumulator_true_handled, NULL, g_cclosure_marshal_generic,
175       G_TYPE_BOOLEAN, 3, G_TYPE_TLS_CONNECTION, G_TYPE_TLS_CERTIFICATE,
176       G_TYPE_TLS_CERTIFICATE_FLAGS);
177 }
178
179 static void
180 gst_rtsp_auth_init (GstRTSPAuth * auth)
181 {
182   GstRTSPAuthPrivate *priv;
183
184   auth->priv = priv = GST_RTSP_AUTH_GET_PRIVATE (auth);
185
186   g_mutex_init (&priv->lock);
187
188   priv->basic = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
189       (GDestroyNotify) gst_rtsp_token_unref);
190   priv->digest = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
191       (GDestroyNotify) gst_rtsp_digest_entry_free);
192   priv->nonces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
193       (GDestroyNotify) gst_rtsp_digest_nonce_free);
194
195   /* bitwise or of all methods that need authentication */
196   priv->methods = 0;
197   priv->auth_methods = GST_RTSP_AUTH_BASIC;
198 }
199
200 static void
201 gst_rtsp_auth_finalize (GObject * obj)
202 {
203   GstRTSPAuth *auth = GST_RTSP_AUTH (obj);
204   GstRTSPAuthPrivate *priv = auth->priv;
205
206   GST_INFO ("finalize auth %p", auth);
207
208   if (priv->certificate)
209     g_object_unref (priv->certificate);
210   if (priv->database)
211     g_object_unref (priv->database);
212   g_hash_table_unref (priv->basic);
213   g_hash_table_unref (priv->digest);
214   g_hash_table_unref (priv->nonces);
215   g_mutex_clear (&priv->lock);
216
217   G_OBJECT_CLASS (gst_rtsp_auth_parent_class)->finalize (obj);
218 }
219
220 static void
221 gst_rtsp_auth_get_property (GObject * object, guint propid,
222     GValue * value, GParamSpec * pspec)
223 {
224   switch (propid) {
225     default:
226       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
227   }
228 }
229
230 static void
231 gst_rtsp_auth_set_property (GObject * object, guint propid,
232     const GValue * value, GParamSpec * pspec)
233 {
234   switch (propid) {
235     default:
236       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
237   }
238 }
239
240 /**
241  * gst_rtsp_auth_new:
242  *
243  * Create a new #GstRTSPAuth instance.
244  *
245  * Returns: (transfer full): a new #GstRTSPAuth
246  */
247 GstRTSPAuth *
248 gst_rtsp_auth_new (void)
249 {
250   GstRTSPAuth *result;
251
252   result = g_object_new (GST_TYPE_RTSP_AUTH, NULL);
253
254   return result;
255 }
256
257 /**
258  * gst_rtsp_auth_set_tls_certificate:
259  * @auth: a #GstRTSPAuth
260  * @cert: (transfer none) (allow-none): a #GTlsCertificate
261  *
262  * Set the TLS certificate for the auth. Client connections will only
263  * be accepted when TLS is negotiated.
264  */
265 void
266 gst_rtsp_auth_set_tls_certificate (GstRTSPAuth * auth, GTlsCertificate * cert)
267 {
268   GstRTSPAuthPrivate *priv;
269   GTlsCertificate *old;
270
271   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
272
273   priv = auth->priv;
274
275   if (cert)
276     g_object_ref (cert);
277
278   g_mutex_lock (&priv->lock);
279   old = priv->certificate;
280   priv->certificate = cert;
281   g_mutex_unlock (&priv->lock);
282
283   if (old)
284     g_object_unref (old);
285 }
286
287 /**
288  * gst_rtsp_auth_get_tls_certificate:
289  * @auth: a #GstRTSPAuth
290  *
291  * Get the #GTlsCertificate used for negotiating TLS @auth.
292  *
293  * Returns: (transfer full): the #GTlsCertificate of @auth. g_object_unref() after
294  * usage.
295  */
296 GTlsCertificate *
297 gst_rtsp_auth_get_tls_certificate (GstRTSPAuth * auth)
298 {
299   GstRTSPAuthPrivate *priv;
300   GTlsCertificate *result;
301
302   g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), NULL);
303
304   priv = auth->priv;
305
306   g_mutex_lock (&priv->lock);
307   if ((result = priv->certificate))
308     g_object_ref (result);
309   g_mutex_unlock (&priv->lock);
310
311   return result;
312 }
313
314 /**
315  * gst_rtsp_auth_set_tls_database:
316  * @auth: a #GstRTSPAuth
317  * @database: (transfer none) (allow-none): a #GTlsDatabase
318  *
319  * Sets the certificate database that is used to verify peer certificates.
320  * If set to %NULL (the default), then peer certificate validation will always
321  * set the %G_TLS_CERTIFICATE_UNKNOWN_CA error.
322  *
323  * Since 1.6
324  */
325 void
326 gst_rtsp_auth_set_tls_database (GstRTSPAuth * auth, GTlsDatabase * database)
327 {
328   GstRTSPAuthPrivate *priv;
329   GTlsDatabase *old;
330
331   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
332
333   priv = auth->priv;
334
335   if (database)
336     g_object_ref (database);
337
338   g_mutex_lock (&priv->lock);
339   old = priv->database;
340   priv->database = database;
341   g_mutex_unlock (&priv->lock);
342
343   if (old)
344     g_object_unref (old);
345 }
346
347 /**
348  * gst_rtsp_auth_get_tls_database:
349  * @auth: a #GstRTSPAuth
350  *
351  * Get the #GTlsDatabase used for verifying client certificate.
352  *
353  * Returns: (transfer full): the #GTlsDatabase of @auth. g_object_unref() after
354  * usage.
355  * Since: 1.6
356  */
357 GTlsDatabase *
358 gst_rtsp_auth_get_tls_database (GstRTSPAuth * auth)
359 {
360   GstRTSPAuthPrivate *priv;
361   GTlsDatabase *result;
362
363   g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), NULL);
364
365   priv = auth->priv;
366
367   g_mutex_lock (&priv->lock);
368   if ((result = priv->database))
369     g_object_ref (result);
370   g_mutex_unlock (&priv->lock);
371
372   return result;
373 }
374
375 /**
376  * gst_rtsp_auth_set_tls_authentication_mode:
377  * @auth: a #GstRTSPAuth
378  * @mode: (transfer none) (allow-none): a #GTlsAuthenticationMode
379  *
380  * The #GTlsAuthenticationMode to set on the underlying GTlsServerConnection.
381  * When set to another value than %G_TLS_AUTHENTICATION_NONE,
382  * #GstRTSPAuth::accept-certificate signal will be emitted and must be handled.
383  *
384  * Since: 1.6
385  */
386 void
387 gst_rtsp_auth_set_tls_authentication_mode (GstRTSPAuth * auth,
388     GTlsAuthenticationMode mode)
389 {
390   GstRTSPAuthPrivate *priv;
391
392   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
393
394   priv = auth->priv;
395
396   g_mutex_lock (&priv->lock);
397   priv->mode = mode;
398   g_mutex_unlock (&priv->lock);
399 }
400
401 /**
402  * gst_rtsp_auth_get_tls_authentication_mode:
403  * @auth: a #GstRTSPAuth
404  *
405  * Get the #GTlsAuthenticationMode.
406  *
407  * Returns: (transfer full): the #GTlsAuthenticationMode.
408  */
409 GTlsAuthenticationMode
410 gst_rtsp_auth_get_tls_authentication_mode (GstRTSPAuth * auth)
411 {
412   GstRTSPAuthPrivate *priv;
413   GTlsAuthenticationMode result;
414
415   g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), G_TLS_AUTHENTICATION_NONE);
416
417   priv = auth->priv;
418
419   g_mutex_lock (&priv->lock);
420   result = priv->mode;
421   g_mutex_unlock (&priv->lock);
422
423   return result;
424 }
425
426 /**
427  * gst_rtsp_auth_set_default_token:
428  * @auth: a #GstRTSPAuth
429  * @token: (transfer none) (allow-none): a #GstRTSPToken
430  *
431  * Set the default #GstRTSPToken to @token in @auth. The default token will
432  * be used for unauthenticated users.
433  */
434 void
435 gst_rtsp_auth_set_default_token (GstRTSPAuth * auth, GstRTSPToken * token)
436 {
437   GstRTSPAuthPrivate *priv;
438   GstRTSPToken *old;
439
440   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
441
442   priv = auth->priv;
443
444   if (token)
445     gst_rtsp_token_ref (token);
446
447   g_mutex_lock (&priv->lock);
448   old = priv->default_token;
449   priv->default_token = token;
450   g_mutex_unlock (&priv->lock);
451
452   if (old)
453     gst_rtsp_token_unref (old);
454 }
455
456 /**
457  * gst_rtsp_auth_get_default_token:
458  * @auth: a #GstRTSPAuth
459  *
460  * Get the default token for @auth. This token will be used for unauthenticated
461  * users.
462  *
463  * Returns: (transfer full): the #GstRTSPToken of @auth. gst_rtsp_token_unref() after
464  * usage.
465  */
466 GstRTSPToken *
467 gst_rtsp_auth_get_default_token (GstRTSPAuth * auth)
468 {
469   GstRTSPAuthPrivate *priv;
470   GstRTSPToken *result;
471
472   g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), NULL);
473
474   priv = auth->priv;
475
476   g_mutex_lock (&priv->lock);
477   if ((result = priv->default_token))
478     gst_rtsp_token_ref (result);
479   g_mutex_unlock (&priv->lock);
480
481   return result;
482 }
483
484 /**
485  * gst_rtsp_auth_add_basic:
486  * @auth: a #GstRTSPAuth
487  * @basic: the basic token
488  * @token: (transfer none): authorisation token
489  *
490  * Add a basic token for the default authentication algorithm that
491  * enables the client with privileges listed in @token.
492  */
493 void
494 gst_rtsp_auth_add_basic (GstRTSPAuth * auth, const gchar * basic,
495     GstRTSPToken * token)
496 {
497   GstRTSPAuthPrivate *priv;
498
499   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
500   g_return_if_fail (basic != NULL);
501   g_return_if_fail (GST_IS_RTSP_TOKEN (token));
502
503   priv = auth->priv;
504
505   g_mutex_lock (&priv->lock);
506   g_hash_table_replace (priv->basic, g_strdup (basic),
507       gst_rtsp_token_ref (token));
508   g_mutex_unlock (&priv->lock);
509 }
510
511 /**
512  * gst_rtsp_auth_remove_basic:
513  * @auth: a #GstRTSPAuth
514  * @basic: (transfer none): the basic token
515  *
516  * Removes @basic authentication token.
517  */
518 void
519 gst_rtsp_auth_remove_basic (GstRTSPAuth * auth, const gchar * basic)
520 {
521   GstRTSPAuthPrivate *priv;
522
523   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
524   g_return_if_fail (basic != NULL);
525
526   priv = auth->priv;
527
528   g_mutex_lock (&priv->lock);
529   g_hash_table_remove (priv->basic, basic);
530   g_mutex_unlock (&priv->lock);
531 }
532
533 /**
534  * gst_rtsp_auth_add_digest:
535  * @auth: a #GstRTSPAuth
536  * @user: the digest user name
537  * @pass: the digest password
538  * @token: (transfer none): authorisation token
539  *
540  * Add a digest @user and @pass for the default authentication algorithm that
541  * enables the client with privileges listed in @token.
542  *
543  * Since: 1.12
544  */
545 void
546 gst_rtsp_auth_add_digest (GstRTSPAuth * auth, const gchar * user,
547     const gchar * pass, GstRTSPToken * token)
548 {
549   GstRTSPAuthPrivate *priv;
550   GstRTSPDigestEntry *entry;
551
552   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
553   g_return_if_fail (user != NULL);
554   g_return_if_fail (pass != NULL);
555   g_return_if_fail (GST_IS_RTSP_TOKEN (token));
556
557   priv = auth->priv;
558
559   entry = g_new0 (GstRTSPDigestEntry, 1);
560   entry->token = gst_rtsp_token_ref (token);
561   entry->pass = g_strdup (pass);
562
563   g_mutex_lock (&priv->lock);
564   g_hash_table_replace (priv->digest, g_strdup (user), entry);
565   g_mutex_unlock (&priv->lock);
566 }
567
568 /**
569  * gst_rtsp_auth_remove_digest:
570  * @auth: a #GstRTSPAuth
571  * @user: (transfer none): the digest user name
572  *
573  * Removes a digest user.
574  *
575  * Since: 1.12
576  */
577 void
578 gst_rtsp_auth_remove_digest (GstRTSPAuth * auth, const gchar * user)
579 {
580   GstRTSPAuthPrivate *priv;
581
582   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
583   g_return_if_fail (user != NULL);
584
585   priv = auth->priv;
586
587   g_mutex_lock (&priv->lock);
588   g_hash_table_remove (priv->digest, user);
589   g_mutex_unlock (&priv->lock);
590 }
591
592 /**
593  * gst_rtsp_auth_set_supported_methods:
594  * @auth: a #GstRTSPAuth
595  * @methods: supported methods
596  *
597  * Sets the supported authentication @methods for @auth.
598  *
599  * Since: 1.12
600  */
601 void
602 gst_rtsp_auth_set_supported_methods (GstRTSPAuth * auth,
603     GstRTSPAuthMethod methods)
604 {
605   GstRTSPAuthPrivate *priv;
606
607   g_return_if_fail (GST_IS_RTSP_AUTH (auth));
608
609   priv = auth->priv;
610
611   g_mutex_lock (&priv->lock);
612   priv->auth_methods = methods;
613   g_mutex_unlock (&priv->lock);
614 }
615
616 /**
617  * gst_rtsp_auth_get_supported_methods:
618  * @auth: a #GstRTSPAuth
619  *
620  * Gets the supported authentication methods of @auth.
621  *
622  * Returns: The supported authentication methods
623  *
624  * Since: 1.12
625  */
626 GstRTSPAuthMethod
627 gst_rtsp_auth_get_supported_methods (GstRTSPAuth * auth)
628 {
629   GstRTSPAuthPrivate *priv;
630   GstRTSPAuthMethod methods;
631
632   g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), 0);
633
634   priv = auth->priv;
635
636   g_mutex_lock (&priv->lock);
637   methods = priv->auth_methods;
638   g_mutex_unlock (&priv->lock);
639
640   return methods;
641 }
642
643 typedef struct
644 {
645   GstRTSPAuth *auth;
646   GstRTSPDigestNonce *nonce;
647 } RemoveNonceData;
648
649 static void
650 remove_nonce (gpointer data, GObject * object)
651 {
652   RemoveNonceData *remove_nonce_data = data;
653
654   g_mutex_lock (&remove_nonce_data->auth->priv->lock);
655   g_hash_table_remove (remove_nonce_data->auth->priv->nonces,
656       remove_nonce_data->nonce->nonce);
657   g_mutex_unlock (&remove_nonce_data->auth->priv->lock);
658
659   g_object_unref (remove_nonce_data->auth);
660   g_free (remove_nonce_data);
661 }
662
663 static gboolean
664 default_digest_auth (GstRTSPAuth * auth, GstRTSPContext * ctx,
665     GstRTSPAuthParam ** param)
666 {
667   const gchar *realm = NULL, *user = NULL, *nonce = NULL;
668   const gchar *response = NULL, *uri = NULL;
669   GstRTSPDigestNonce *nonce_entry = NULL;
670   GstRTSPDigestEntry *digest_entry;
671   gchar *expected_response = NULL;
672   gboolean ret = FALSE;
673
674   GST_DEBUG_OBJECT (auth, "check Digest auth");
675
676   if (!param)
677     return ret;
678
679   while (*param) {
680     if (!realm && strcmp ((*param)->name, "realm") == 0 && (*param)->value)
681       realm = (*param)->value;
682     else if (!user && strcmp ((*param)->name, "username") == 0
683         && (*param)->value)
684       user = (*param)->value;
685     else if (!nonce && strcmp ((*param)->name, "nonce") == 0 && (*param)->value)
686       nonce = (*param)->value;
687     else if (!response && strcmp ((*param)->name, "response") == 0
688         && (*param)->value)
689       response = (*param)->value;
690     else if (!uri && strcmp ((*param)->name, "uri") == 0 && (*param)->value)
691       uri = (*param)->value;
692
693     param++;
694   }
695
696   if (!realm || !user || !nonce || !response || !uri)
697     return FALSE;
698
699   g_mutex_lock (&auth->priv->lock);
700   digest_entry = g_hash_table_lookup (auth->priv->digest, user);
701   if (!digest_entry)
702     goto out;
703   nonce_entry = g_hash_table_lookup (auth->priv->nonces, nonce);
704   if (!nonce_entry)
705     goto out;
706
707   if (strcmp (nonce_entry->ip, gst_rtsp_connection_get_ip (ctx->conn)) != 0)
708     goto out;
709   if (nonce_entry->client && nonce_entry->client != ctx->client)
710     goto out;
711
712   expected_response =
713       gst_rtsp_generate_digest_auth_response (NULL,
714       gst_rtsp_method_as_text (ctx->method), "GStreamer RTSP Server", user,
715       digest_entry->pass, uri, nonce);
716   if (!expected_response || strcmp (response, expected_response) != 0)
717     goto out;
718
719   ctx->token = digest_entry->token;
720   ret = TRUE;
721
722 out:
723   if (nonce_entry && !nonce_entry->client) {
724     RemoveNonceData *remove_nonce_data = g_new (RemoveNonceData, 1);
725
726     nonce_entry->client = ctx->client;
727     remove_nonce_data->nonce = nonce_entry;
728     remove_nonce_data->auth = g_object_ref (auth);
729     g_object_weak_ref (G_OBJECT (ctx->client), remove_nonce, remove_nonce_data);
730   }
731   g_mutex_unlock (&auth->priv->lock);
732
733   g_free (expected_response);
734
735   return ret;
736 }
737
738 static gboolean
739 default_authenticate (GstRTSPAuth * auth, GstRTSPContext * ctx)
740 {
741   GstRTSPAuthPrivate *priv = auth->priv;
742   GstRTSPAuthCredential **credentials, **credential;
743
744   GST_DEBUG_OBJECT (auth, "authenticate");
745
746   g_mutex_lock (&priv->lock);
747   /* FIXME, need to ref but we have no way to unref when the ctx is
748    * popped */
749   ctx->token = priv->default_token;
750   g_mutex_unlock (&priv->lock);
751
752   credentials =
753       gst_rtsp_message_parse_auth_credentials (ctx->request,
754       GST_RTSP_HDR_AUTHORIZATION);
755   if (!credentials)
756     goto no_auth;
757
758   /* parse type */
759   credential = credentials;
760   while (*credential) {
761     if ((*credential)->scheme == GST_RTSP_AUTH_BASIC) {
762       GstRTSPToken *token;
763
764       GST_DEBUG_OBJECT (auth, "check Basic auth");
765       g_mutex_lock (&priv->lock);
766       if ((token =
767               g_hash_table_lookup (priv->basic,
768                   (*credential)->authorization))) {
769         GST_DEBUG_OBJECT (auth, "setting token %p", token);
770         ctx->token = token;
771         g_mutex_unlock (&priv->lock);
772         break;
773       }
774       g_mutex_unlock (&priv->lock);
775     } else if ((*credential)->scheme == GST_RTSP_AUTH_DIGEST) {
776       if (default_digest_auth (auth, ctx, (*credential)->params))
777         break;
778     }
779
780     credential++;
781   }
782
783   gst_rtsp_auth_credentials_free (credentials);
784   return TRUE;
785
786 no_auth:
787   {
788     GST_DEBUG_OBJECT (auth, "no authorization header found");
789     return TRUE;
790   }
791 }
792
793 static void
794 default_generate_authenticate_header (GstRTSPAuth * auth, GstRTSPContext * ctx)
795 {
796   if (auth->priv->auth_methods & GST_RTSP_AUTH_BASIC) {
797     gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_WWW_AUTHENTICATE,
798         "Basic realm=\"GStreamer RTSP Server\"");
799   }
800
801   if (auth->priv->auth_methods & GST_RTSP_AUTH_DIGEST) {
802     GstRTSPDigestNonce *nonce;
803     gchar *nonce_value, *auth_header;
804
805     nonce_value =
806         g_strdup_printf ("%08x%08x", g_random_int (), g_random_int ());
807
808     auth_header =
809         g_strdup_printf
810         ("Digest realm=\"GStreamer RTSP Server\", nonce=\"%s\"", nonce_value);
811     gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_WWW_AUTHENTICATE,
812         auth_header);
813     g_free (auth_header);
814
815     nonce = g_new0 (GstRTSPDigestNonce, 1);
816     nonce->nonce = g_strdup (nonce_value);
817     nonce->timestamp = g_get_monotonic_time ();
818     nonce->ip = g_strdup (gst_rtsp_connection_get_ip (ctx->conn));
819     g_mutex_lock (&auth->priv->lock);
820     g_hash_table_replace (auth->priv->nonces, nonce_value, nonce);
821
822     if (auth->priv->last_nonce_check == 0)
823       auth->priv->last_nonce_check = nonce->timestamp;
824
825     /* 30 second nonce timeout */
826     if (nonce->timestamp - auth->priv->last_nonce_check >= 30 * G_USEC_PER_SEC) {
827       GHashTableIter iter;
828       gpointer key, value;
829
830       g_hash_table_iter_init (&iter, auth->priv->nonces);
831       while (g_hash_table_iter_next (&iter, &key, &value)) {
832         GstRTSPDigestNonce *tmp = value;
833
834         if (nonce->timestamp - tmp->timestamp >= 30 * G_USEC_PER_SEC)
835           g_hash_table_iter_remove (&iter);
836       }
837       auth->priv->last_nonce_check = nonce->timestamp;
838     }
839
840     g_mutex_unlock (&auth->priv->lock);
841   }
842 }
843
844 static void
845 send_response (GstRTSPAuth * auth, GstRTSPStatusCode code, GstRTSPContext * ctx)
846 {
847   gst_rtsp_message_init_response (ctx->response, code,
848       gst_rtsp_status_as_text (code), ctx->request);
849
850   if (code == GST_RTSP_STS_UNAUTHORIZED) {
851     GstRTSPAuthClass *klass;
852
853     klass = GST_RTSP_AUTH_GET_CLASS (auth);
854
855     if (klass->generate_authenticate_header)
856       klass->generate_authenticate_header (auth, ctx);
857   }
858   gst_rtsp_client_send_message (ctx->client, ctx->session, ctx->response);
859 }
860
861 static gboolean
862 ensure_authenticated (GstRTSPAuth * auth, GstRTSPContext * ctx)
863 {
864   GstRTSPAuthClass *klass;
865
866   klass = GST_RTSP_AUTH_GET_CLASS (auth);
867
868   /* we need a token to check */
869   if (ctx->token == NULL) {
870     if (klass->authenticate) {
871       if (!klass->authenticate (auth, ctx))
872         goto authenticate_failed;
873     }
874   }
875   if (ctx->token == NULL)
876     goto no_auth;
877
878   return TRUE;
879
880 /* ERRORS */
881 authenticate_failed:
882   {
883     GST_DEBUG_OBJECT (auth, "authenticate failed");
884     send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx);
885     return FALSE;
886   }
887 no_auth:
888   {
889     GST_DEBUG_OBJECT (auth, "no authorization token found");
890     send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx);
891     return FALSE;
892   }
893 }
894
895 static gboolean
896 accept_certificate_cb (GTlsConnection * conn, GTlsCertificate * peer_cert,
897     GTlsCertificateFlags errors, GstRTSPAuth * auth)
898 {
899   gboolean ret = FALSE;
900
901   g_signal_emit (auth, signals[SIGNAL_ACCEPT_CERTIFICATE], 0,
902       conn, peer_cert, errors, &ret);
903
904   return ret;
905 }
906
907 /* new connection */
908 static gboolean
909 check_connect (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check)
910 {
911   GstRTSPAuthPrivate *priv = auth->priv;
912   GTlsConnection *tls;
913
914   /* configure the connection */
915
916   if (priv->certificate) {
917     tls = gst_rtsp_connection_get_tls (ctx->conn, NULL);
918     g_tls_connection_set_certificate (tls, priv->certificate);
919   }
920
921   if (priv->mode != G_TLS_AUTHENTICATION_NONE) {
922     tls = gst_rtsp_connection_get_tls (ctx->conn, NULL);
923     g_tls_connection_set_database (tls, priv->database);
924     g_object_set (tls, "authentication-mode", priv->mode, NULL);
925     g_signal_connect (tls, "accept-certificate",
926         G_CALLBACK (accept_certificate_cb), auth);
927   }
928
929   return TRUE;
930 }
931
932 /* check url and methods */
933 static gboolean
934 check_url (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check)
935 {
936   GstRTSPAuthPrivate *priv = auth->priv;
937
938   if ((ctx->method & priv->methods) != 0)
939     if (!ensure_authenticated (auth, ctx))
940       goto not_authenticated;
941
942   return TRUE;
943
944   /* ERRORS */
945 not_authenticated:
946   {
947     return FALSE;
948   }
949 }
950
951 /* check access to media factory */
952 static gboolean
953 check_factory (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check)
954 {
955   const gchar *role;
956   GstRTSPPermissions *perms;
957
958   if (!ensure_authenticated (auth, ctx))
959     return FALSE;
960
961   if (!(role = gst_rtsp_token_get_string (ctx->token,
962               GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE)))
963     goto no_media_role;
964   if (!(perms = gst_rtsp_media_factory_get_permissions (ctx->factory)))
965     goto no_permissions;
966
967   if (g_str_equal (check, GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS)) {
968     if (!gst_rtsp_permissions_is_allowed (perms, role,
969             GST_RTSP_PERM_MEDIA_FACTORY_ACCESS))
970       goto no_access;
971   } else if (g_str_equal (check, GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT)) {
972     if (!gst_rtsp_permissions_is_allowed (perms, role,
973             GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT))
974       goto no_construct;
975   }
976
977   gst_rtsp_permissions_unref (perms);
978
979   return TRUE;
980
981   /* ERRORS */
982 no_media_role:
983   {
984     GST_DEBUG_OBJECT (auth, "no media factory role found");
985     send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx);
986     return FALSE;
987   }
988 no_permissions:
989   {
990     GST_DEBUG_OBJECT (auth, "no permissions on media factory found");
991     send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx);
992     return FALSE;
993   }
994 no_access:
995   {
996     GST_DEBUG_OBJECT (auth, "no permissions to access media factory");
997     gst_rtsp_permissions_unref (perms);
998     send_response (auth, GST_RTSP_STS_NOT_FOUND, ctx);
999     return FALSE;
1000   }
1001 no_construct:
1002   {
1003     GST_DEBUG_OBJECT (auth, "no permissions to construct media factory");
1004     gst_rtsp_permissions_unref (perms);
1005     send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx);
1006     return FALSE;
1007   }
1008 }
1009
1010 static gboolean
1011 check_client_settings (GstRTSPAuth * auth, GstRTSPContext * ctx,
1012     const gchar * check)
1013 {
1014   if (!ensure_authenticated (auth, ctx))
1015     return FALSE;
1016
1017   return gst_rtsp_token_is_allowed (ctx->token,
1018       GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS);
1019 }
1020
1021 static gboolean
1022 default_check (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check)
1023 {
1024   gboolean res = FALSE;
1025
1026   /* FIXME, use hastable or so */
1027   if (g_str_equal (check, GST_RTSP_AUTH_CHECK_CONNECT)) {
1028     res = check_connect (auth, ctx, check);
1029   } else if (g_str_equal (check, GST_RTSP_AUTH_CHECK_URL)) {
1030     res = check_url (auth, ctx, check);
1031   } else if (g_str_has_prefix (check, "auth.check.media.factory.")) {
1032     res = check_factory (auth, ctx, check);
1033   } else if (g_str_equal (check, GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS)) {
1034     res = check_client_settings (auth, ctx, check);
1035   }
1036   return res;
1037 }
1038
1039 static gboolean
1040 no_auth_check (const gchar * check)
1041 {
1042   gboolean res;
1043
1044   if (g_str_equal (check, GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS))
1045     res = FALSE;
1046   else
1047     res = TRUE;
1048
1049   return res;
1050 }
1051
1052 /**
1053  * gst_rtsp_auth_check:
1054  * @check: the item to check
1055  *
1056  * Check if @check is allowed in the current context.
1057  *
1058  * Returns: FALSE if check failed.
1059  */
1060 gboolean
1061 gst_rtsp_auth_check (const gchar * check)
1062 {
1063   gboolean result = FALSE;
1064   GstRTSPAuthClass *klass;
1065   GstRTSPContext *ctx;
1066   GstRTSPAuth *auth;
1067
1068   g_return_val_if_fail (check != NULL, FALSE);
1069
1070   if (!(ctx = gst_rtsp_context_get_current ()))
1071     goto no_context;
1072
1073   /* no auth, we don't need to check */
1074   if (!(auth = ctx->auth))
1075     return no_auth_check (check);
1076
1077   klass = GST_RTSP_AUTH_GET_CLASS (auth);
1078
1079   GST_DEBUG_OBJECT (auth, "check authorization '%s'", check);
1080
1081   if (klass->check)
1082     result = klass->check (auth, ctx, check);
1083
1084   return result;
1085
1086   /* ERRORS */
1087 no_context:
1088   {
1089     GST_ERROR ("no context found");
1090     return FALSE;
1091   }
1092 }
1093
1094 /**
1095  * gst_rtsp_auth_make_basic:
1096  * @user: a userid
1097  * @pass: a password
1098  *
1099  * Construct a Basic authorisation token from @user and @pass.
1100  *
1101  * Returns: (transfer full): the base64 encoding of the string @user:@pass.
1102  * g_free() after usage.
1103  */
1104 gchar *
1105 gst_rtsp_auth_make_basic (const gchar * user, const gchar * pass)
1106 {
1107   gchar *user_pass;
1108   gchar *result;
1109
1110   g_return_val_if_fail (user != NULL, NULL);
1111   g_return_val_if_fail (pass != NULL, NULL);
1112
1113   user_pass = g_strjoin (":", user, pass, NULL);
1114   result = g_base64_encode ((guchar *) user_pass, strlen (user_pass));
1115   g_free (user_pass);
1116
1117   return result;
1118 }