digest-plugin: add realm check
authorJussi Laako <jussi.laako@linux.intel.com>
Wed, 27 Nov 2013 16:16:30 +0000 (18:16 +0200)
committerJussi Laako <jussi.laako@linux.intel.com>
Thu, 28 Nov 2013 15:23:07 +0000 (17:23 +0200)
include/gsignond/gsignond-utils.h
src/common/gsignond-utils.c
src/plugins/digest/gsignond-digest-plugin.c
test/plugins/digestplugintest.c

index 0d36944..e581638 100644 (file)
@@ -51,6 +51,9 @@ gsignond_sequence_to_array (GSequence *seq);
 GSequence *
 gsignond_array_to_sequence (gchar **items);
 
+GSequence *
+gsignond_copy_array_to_sequence (const gchar **items);
+
 G_END_DECLS
 
 #endif  /* _SGINOND_UTILS_H_ */
index 562df4f..9eab088 100644 (file)
@@ -359,7 +359,7 @@ gsignond_sequence_to_array (GSequence *seq)
 
 /**
  * gsignond_array_to_sequence:
- * @items: Null-terminated array of strings to convert
+ * @items: (transfer full): Null-terminated array of strings to convert
  *
  * Convert null-terminated array of strings to a sequence.
  *
@@ -383,3 +383,28 @@ gsignond_array_to_sequence (gchar **items)
     return seq;
 }
 
+/**
+ * gsignond_copy_array_to_sequence:
+ * @items: Null-terminated array of strings to copy
+ *
+ * Copy null-terminated array of strings to a sequence.
+ *
+ * Returns: (transfer full): #GSequence of strings
+ */
+GSequence *
+gsignond_copy_array_to_sequence (const gchar **items)
+{
+    GSequence *seq = NULL;
+
+    if (!items) return NULL;
+
+    seq = g_sequence_new ((GDestroyNotify) g_free);
+    while (*items) {
+        g_sequence_insert_sorted (seq,
+                                  g_strdup (*items),
+                                  (GCompareDataFunc) _compare_strings,
+                                  NULL);
+        items++;
+    }
+    return seq;
+}
index 325f93b..76df1f4 100644 (file)
@@ -183,16 +183,34 @@ gsignond_digest_plugin_request (
 {
 }
 
+/* difference with g_strcmp0() here is that two NULLs don't compare equal */
+static gint
+_compare_realm (gconstpointer a, gconstpointer b, gpointer user_data)
+{
+    const gchar *realm1 = (const gchar *) a;
+    const gchar *realm2 = (const gchar *) b;
+    (void) user_data;
+    if (realm1 == NULL)
+        return -1;
+    if (realm2 == NULL)
+        return 1;
+
+    return g_strcmp0 (realm1, realm2);
+}
+
 static void
-_gsignond_digest_plugin_return_digest(GSignondPlugin *plugin,
-                                     const gchar *username,
-                                     const gchar *secret,
-                                     GSignondDictionary *session_data)
+_gsignond_digest_plugin_return_digest (GSignondPlugin *plugin,
+                                       const gchar *username,
+                                       const gchar *secret,
+                                       GSignondDictionary *session_data)
 {
     g_return_if_fail (plugin != NULL);
     g_return_if_fail (GSIGNOND_IS_DIGEST_PLUGIN (plugin));
 
     GSignondSessionData *response = NULL;
+    GSequenceIter *iter;
+    GSequence* allowed_realms =
+        gsignond_session_data_get_allowed_realms (session_data);
     const gchar* realm = gsignond_session_data_get_realm (session_data);
     const gchar* algo = gsignond_dictionary_get_string (session_data,
                 "Algo");
@@ -208,10 +226,34 @@ _gsignond_digest_plugin_return_digest(GSignondPlugin *plugin,
                 "DigestUri");
     const gchar* hentity = gsignond_dictionary_get_string (session_data,
                 "HEntity");
+
+    if (!allowed_realms) {
+        GError* error = g_error_new (GSIGNOND_ERROR,
+                                     GSIGNOND_ERROR_MISSING_DATA,
+                                     "Missing realm list");
+        gsignond_plugin_error (plugin, error);
+        g_error_free (error);
+        return;
+    }
+    iter = g_sequence_lookup (allowed_realms,
+                              (gpointer) realm,
+                              _compare_realm,
+                              NULL);
+    g_sequence_free (allowed_realms);
+    if (!iter) {
+        GError* error = g_error_new (GSIGNOND_ERROR,
+                                     GSIGNOND_ERROR_NOT_AUTHORIZED,
+                                     "Unauthorized realm");
+        gsignond_plugin_error (plugin, error);
+        g_error_free (error);
+        return;
+    }
+
     gchar *cnonce = gsignond_generate_nonce ();
     if (!cnonce) {
         GError* error = g_error_new (GSIGNOND_ERROR,
-                       GSIGNOND_ERROR_MISSING_DATA, "Error in generating nonce");
+                                     GSIGNOND_ERROR_MISSING_DATA,
+                                     "Error in generating nonce");
         gsignond_plugin_error (plugin, error);
         g_error_free (error);
         return;
@@ -227,7 +269,7 @@ _gsignond_digest_plugin_return_digest(GSignondPlugin *plugin,
         return;
     }
     gchar *digest = _gsignond_digest_plugin_compute_md5_digest(algo,
-            username,realm, secret, nonce, nonce_count, cnonce, qop, method,
+            username, realm, secret, nonce, nonce_count, cnonce, qop, method,
             digest_uri, hentity);
 
     response = gsignond_dictionary_new();
index 4dfe3c6..5bf8702 100644 (file)
 #include "gsignond/gsignond-error.h"
 #include "gsignond/gsignond-log.h"
 #include "gsignond/gsignond-config.h"
+#include "gsignond/gsignond-utils.h"
 #include "common/gsignond-plugin-loader.h"
 
+static const gchar *realm_list[] = { "realm1", "realm2", "realm3", NULL };
+
 static void check_plugin(GSignondPlugin* plugin)
 {
     gchar* type;
@@ -128,6 +131,9 @@ START_TEST (test_digestplugin_request)
 
     // set all the required stuff so that no ui-action is required
     gsignond_session_data_set_realm(data, "realm1");
+    GSequence *allowed_realms = gsignond_copy_array_to_sequence(realm_list);
+    gsignond_session_data_set_allowed_realms(data, allowed_realms);
+    g_sequence_free(allowed_realms);
     gsignond_dictionary_set_string(data, "Algo", "md5-sess");
     gsignond_dictionary_set_string(data, "Nonce",
             "abg10b1234ee1f0e8b11d0f600bfb0c093");
@@ -237,6 +243,10 @@ START_TEST (test_digestplugin_user_action_finished)
     //correct values
     data = gsignond_dictionary_new ();
     gsignond_session_data_set_username (data, "user1");
+    gsignond_session_data_set_realm(data, "realm1");
+    GSequence *allowed_realms = gsignond_copy_array_to_sequence(realm_list);
+    gsignond_session_data_set_allowed_realms(data, allowed_realms);
+    g_sequence_free(allowed_realms);
     gsignond_session_data_set_realm (data, "realm1");
     gsignond_dictionary_set_string (data, "Algo", "md5-sess");
     gsignond_dictionary_set_string (data, "Nonce",