1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
4 * This file is part of gsignond
6 * Copyright (C) 2012 Intel Corporation.
8 * Contact: Alexander Kanavin <alex.kanavin@gmail.com>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
28 #include <glib-object.h>
31 #include "gsignond-plugin-proxy.h"
32 #include "gsignond-plugin-proxy-factory.h"
33 #include "gsignond-plugin-remote.h"
34 #include "gsignond/gsignond-error.h"
35 #include "gsignond/gsignond-log.h"
37 static GMainLoop *main_loop = NULL;
43 g_main_loop_quit (main_loop);
50 g_main_loop_run (main_loop);
57 #if !GLIB_CHECK_VERSION (2, 36, 0)
60 if (main_loop == NULL) {
61 main_loop = g_main_loop_new (NULL, FALSE);
70 g_main_loop_unref (main_loop);
75 struct _GSignondAuthSession
81 struct _GSignondAuthSessionClass
83 GObjectClass parent_class;
86 G_DEFINE_TYPE (GSignondAuthSession, gsignond_auth_session, G_TYPE_OBJECT);
89 gsignond_auth_session_init (
90 GSignondAuthSession *self)
95 gsignond_auth_session_class_init (
96 GSignondAuthSessionClass *klass)
98 // GObjectClass *object_class = G_OBJECT_CLASS (klass);
101 gboolean testing_proxy_process = FALSE;
102 gboolean testing_proxy_process_cancel = FALSE;
103 gboolean testing_proxy_process_queue = FALSE;
104 gint proxy_process_queue_results = 0;
105 gboolean testing_proxy_process_queue_cancel = FALSE;
106 gint proxy_process_queue_cancel_results = 0;
107 gboolean testing_proxy_process_cancel_triggered = FALSE;
110 gsignond_auth_session_notify_process_result (
111 GSignondAuthSession *iface,
112 GSignondSessionData *result,
119 if (testing_proxy_process) {
120 testing_proxy_process = FALSE;
122 gsignond_session_data_get_username(result), "megauser") != 0);
124 gsignond_session_data_get_secret(result), "megapassword") != 0);
127 } else if (testing_proxy_process_queue) {
128 proxy_process_queue_results++;
129 if (proxy_process_queue_results == 1) {
130 GSignondPluginProxy* proxy = GSIGNOND_PLUGIN_PROXY(user_data);
131 GSignondSessionData* data = gsignond_dictionary_new();
132 fail_if(data == NULL);
133 gsignond_session_data_set_username(data, "megauser");
134 gsignond_session_data_set_secret(data, "megapassword");
136 gsignond_plugin_proxy_process(proxy, iface, data, NULL, "password",
139 gsignond_plugin_proxy_process(proxy, iface, data, NULL, "password",
142 gsignond_dictionary_unref(data);
144 if (proxy_process_queue_results == 3) {
145 testing_proxy_process_queue = FALSE;
148 } else if (testing_proxy_process_queue_cancel) {
149 proxy_process_queue_cancel_results++;
150 if (proxy_process_queue_cancel_results == 1) {
151 GSignondPluginProxy* proxy = GSIGNOND_PLUGIN_PROXY(user_data);
152 GSignondSessionData* data = gsignond_dictionary_new();
153 fail_if(data == NULL);
155 for (i = 0; i < 9; i++) {
156 gsignond_plugin_proxy_process(proxy, iface, data, NULL, "mech1",
159 gsignond_dictionary_unref(data);
161 if (proxy_process_queue_cancel_results == 10) {
162 testing_proxy_process_queue_cancel = FALSE;
170 gsignond_auth_session_notify_process_error (
171 GSignondAuthSession *iface,
177 if (testing_proxy_process_cancel) {
178 fail_if(error->code != GSIGNOND_ERROR_SESSION_CANCELED);
179 testing_proxy_process_cancel = FALSE;
181 } else if (testing_proxy_process_queue_cancel) {
182 fail_if(error->code != GSIGNOND_ERROR_SESSION_CANCELED);
183 proxy_process_queue_cancel_results++;
189 gsignond_auth_session_notify_store (
190 GSignondAuthSession *self,
191 GSignondSessionData *session_data)
198 gsignond_auth_session_notify_user_action_required (
199 GSignondAuthSession *self,
200 GSignondSignonuiData *session_data)
207 gsignond_auth_session_notify_refreshed (
208 GSignondAuthSession *self,
209 GSignondSignonuiData *session_data)
216 gsignond_auth_session_notify_state_changed (
217 GSignondAuthSession *self,
219 const gchar *message,
222 if (testing_proxy_process_cancel &&
223 !testing_proxy_process_cancel_triggered &&
224 state == GSIGNOND_PLUGIN_STATE_WAITING) {
225 GSignondPluginProxy* proxy = GSIGNOND_PLUGIN_PROXY(user_data);
226 gsignond_plugin_proxy_cancel(proxy, self);
227 testing_proxy_process_cancel_triggered = TRUE;
228 } else if (testing_proxy_process_queue_cancel &&
229 state == GSIGNOND_PLUGIN_STATE_WAITING &&
230 proxy_process_queue_cancel_results == 5) {
231 GSignondPluginProxy* proxy = GSIGNOND_PLUGIN_PROXY(user_data);
232 gsignond_plugin_proxy_cancel(proxy, self);
238 GSignondPluginProxy* proxy,
243 gchar** pmechanisms = NULL;
246 fail_if(proxy == NULL);
248 g_object_get(proxy, "type", &ptype, "mechanisms", &pmechanisms, NULL);
249 fail_unless(g_strcmp0(ptype, type) == 0);
252 guint len = g_strv_length (pmechanisms);
253 fail_unless (len == g_strv_length (mechanisms));
255 for (i=0; i<len; i++) {
256 fail_unless(g_strcmp0(pmechanisms[i], mechanisms[i]) == 0);
259 g_strfreev(pmechanisms);
263 static GSignondPluginProxy* _make_plugin_proxy(GSignondConfig* config, const gchar* plugin_type)
265 gchar* loader_path = g_build_filename (g_getenv("SSO_BIN_DIR"), "gsignond-plugind", NULL);
267 GSignondPluginProxy* proxy = gsignond_plugin_proxy_new(loader_path, plugin_type,
268 gsignond_config_get_integer (config, GSIGNOND_CONFIG_PLUGIN_TIMEOUT));
273 START_TEST (test_pluginproxy_create)
275 DBG("test_pluginproxy_create\n");
277 gchar *pass_mechs[] = {"password", NULL};
279 GSignondConfig* config = gsignond_config_new();
280 fail_if(config == NULL);
282 GSignondPluginProxy* proxy2 = _make_plugin_proxy(config,
284 fail_if (proxy2 != NULL);
286 GSignondPluginProxy* proxy = _make_plugin_proxy(config, "password");
287 fail_if (proxy == NULL);
288 check_plugin_proxy(proxy, "password", pass_mechs);
290 g_object_unref(proxy);
291 g_object_unref(config);
295 START_TEST (test_pluginproxy_process)
297 DBG("test_pluginproxy_process\n");
299 GSignondConfig* config = gsignond_config_new();
300 fail_if(config == NULL);
302 GSignondPluginProxy* proxy = _make_plugin_proxy(config, "password");
303 fail_if (proxy == NULL);
305 GSignondSessionData* data = gsignond_dictionary_new();
306 fail_if(data == NULL);
307 gsignond_session_data_set_username(data, "megauser");
308 gsignond_session_data_set_secret(data, "megapassword");
310 GSignondAuthSession* test_auth_session =
311 g_object_new(gsignond_auth_session_get_type(), NULL);
313 testing_proxy_process = TRUE;
315 gsignond_plugin_proxy_process(proxy, test_auth_session, data, NULL, "password",
320 fail_if(testing_proxy_process);
322 gsignond_dictionary_unref(data);
323 g_object_unref(test_auth_session);
324 g_object_unref(proxy);
325 g_object_unref(config);
329 START_TEST (test_pluginproxy_process_cancel)
331 DBG("test_pluginproxy_process_cancel\n");
333 GSignondConfig* config = gsignond_config_new();
334 fail_if(config == NULL);
336 GSignondPluginProxy* proxy = _make_plugin_proxy(config, "ssotest");
337 fail_if (proxy == NULL);
339 GSignondSessionData* data = gsignond_dictionary_new();
340 fail_if(data == NULL);
342 GSignondAuthSession* test_auth_session = g_object_new(
343 gsignond_auth_session_get_type(), NULL);
345 testing_proxy_process_cancel = TRUE;
347 gsignond_plugin_proxy_process(proxy, test_auth_session, data, NULL, "mech1",
352 fail_if(testing_proxy_process_cancel);
354 gsignond_dictionary_unref(data);
355 g_object_unref(test_auth_session);
356 g_object_unref(proxy);
357 g_object_unref(config);
361 START_TEST (test_pluginproxy_process_queue)
363 DBG("test_pluginproxy_process_queue\n");
365 GSignondConfig* config = gsignond_config_new();
366 fail_if(config == NULL);
368 GSignondPluginProxy* proxy = _make_plugin_proxy(config, "password");
369 fail_if (proxy == NULL);
371 GSignondSessionData* data = gsignond_dictionary_new();
372 fail_if(data == NULL);
373 gsignond_session_data_set_username(data, "megauser");
374 gsignond_session_data_set_secret(data, "megapassword");
376 GSignondAuthSession* test_auth_session = g_object_new(
377 gsignond_auth_session_get_type(), NULL);
379 testing_proxy_process_queue = TRUE;
381 gsignond_plugin_proxy_process(proxy, test_auth_session, data, NULL, "password",
385 fail_if(testing_proxy_process_queue);
386 fail_if(proxy_process_queue_results < 3);
388 gsignond_dictionary_unref(data);
389 g_object_unref(test_auth_session);
390 g_object_unref(proxy);
391 g_object_unref(config);
395 START_TEST (test_pluginproxy_process_queue_cancel)
397 GSignondConfig* config = gsignond_config_new();
398 fail_if(config == NULL);
400 GSignondPluginProxy* proxy = _make_plugin_proxy(config, "ssotest");
401 fail_if (proxy == NULL);
403 GSignondSessionData* data = gsignond_dictionary_new();
404 fail_if(data == NULL);
406 GSignondAuthSession* test_auth_session = g_object_new(
407 gsignond_auth_session_get_type(), NULL);
409 testing_proxy_process_queue_cancel = TRUE;
411 gsignond_plugin_proxy_process(proxy, test_auth_session, data, NULL, "mech1",
416 fail_if(testing_proxy_process_queue_cancel);
417 fail_if(proxy_process_queue_cancel_results != 10);
419 gsignond_dictionary_unref(data);
420 g_object_unref(test_auth_session);
421 g_object_unref(proxy);
422 g_object_unref(config);
426 START_TEST (test_pluginproxyfactory_methods_and_mechanisms)
429 GSignondConfig* config = gsignond_config_new();
430 fail_if(config == NULL);
432 GSignondPluginProxyFactory* factory = gsignond_plugin_proxy_factory_new(
434 fail_if(factory == NULL);
435 const gchar *pass_method = NULL;
436 const gchar** pmethods = NULL;
438 const gchar** methods = gsignond_plugin_proxy_factory_get_plugin_types(
440 fail_if(methods == NULL);
442 while (pmethods[0] != NULL) {
443 DBG ("Method %s", pmethods[0]);
444 if (g_strcmp0 (pmethods[0], "password") == 0) {
445 pass_method = pmethods[0];
449 const gchar** mechanisms =
450 gsignond_plugin_proxy_factory_get_plugin_mechanisms(factory,
452 fail_if(mechanisms == NULL);
453 fail_if(strcmp(mechanisms[0], "password") != 0);
454 fail_if(mechanisms[1] != NULL);
456 g_object_unref(factory);
457 g_object_unref(config);
461 START_TEST (test_pluginproxyfactory_get)
464 gchar *pass_mechs[] = {"password", NULL};
465 GSignondConfig* config = gsignond_config_new();
466 fail_if(config == NULL);
468 GSignondPluginProxyFactory* factory = gsignond_plugin_proxy_factory_new(
470 fail_if(factory == NULL);
472 fail_if(gsignond_plugin_proxy_factory_get_plugin(factory, "absentplugin")
475 GSignondPluginProxy* proxy1 = gsignond_plugin_proxy_factory_get_plugin(
476 factory, "password");
477 GSignondPluginProxy* proxy2 = gsignond_plugin_proxy_factory_get_plugin(
478 factory, "password");
479 GSignondPluginProxy* proxy3 = gsignond_plugin_proxy_factory_get_plugin(
480 factory, "password");
481 fail_if(proxy1 == NULL || proxy2 == NULL || proxy3 == NULL);
482 fail_if(proxy1 != proxy3 || proxy1 != proxy2);
483 check_plugin_proxy(proxy1, "password", pass_mechs);
485 g_object_unref(proxy1);
486 g_object_unref(proxy2);
487 g_object_unref(proxy3);
489 g_object_unref(factory);
490 g_object_unref(config);
495 GSignondPluginProxyFactory *factory;
496 GSignondPluginProxy *proxy;
500 _validate_new_proxy(gpointer userdata)
502 ProxyTimeoutData *data = (ProxyTimeoutData *)userdata;
503 fail_if (data == NULL);
505 fail_if(g_hash_table_size(data->factory->plugins) != 0);
507 GSignondPluginProxy *proxy = gsignond_plugin_proxy_factory_get_plugin (data->factory, "ssotest");
508 fail_if (proxy == NULL);
509 fail_if(g_hash_table_size(data->factory->plugins) != 1);
511 // This is unreliable: the proxy object may be allocated to the same location
512 // as the old object!
513 //fail_if (proxy == data->proxy, "expected new proxy object, but got cached object");
514 g_object_unref(proxy);
524 _validate_cached_proxy (gpointer userdata)
526 ProxyTimeoutData *data = (ProxyTimeoutData *)userdata;
527 fail_if (data == NULL);
529 fail_if(g_hash_table_size(data->factory->plugins) != 1);
530 GSignondPluginProxy *proxy = gsignond_plugin_proxy_factory_get_plugin (data->factory, "ssotest");
531 fail_if (proxy == NULL);
532 fail_if(g_hash_table_size(data->factory->plugins) != 1);
534 fail_unless (proxy == data->proxy, "expected cached proxy object, but got new object");
536 g_object_unref (proxy);
538 g_timeout_add (2200, _validate_new_proxy, userdata);
543 START_TEST (test_pluginproxyfactory_proxy_timeout)
545 DBG("test_pluginproxyfactory_proxy_timeout\n");
546 GSignondPluginProxyFactory *factory = NULL;
547 GSignondPluginProxy *proxy1 = NULL, *proxy2 = NULL;
548 GSignondConfig *config = NULL;
550 /* CASE 1: proxy timeout disabled */
551 config = gsignond_config_new();
552 fail_if(config == NULL);
553 gsignond_config_set_integer (config, GSIGNOND_CONFIG_PLUGIN_TIMEOUT, 0);
555 factory = gsignond_plugin_proxy_factory_new (config);
556 fail_if (factory == NULL);
558 proxy1 = gsignond_plugin_proxy_factory_get_plugin (factory, "ssotest");
559 fail_if (proxy1 == NULL);
560 g_object_unref (proxy1);
561 fail_if(g_hash_table_size(factory->plugins) != 1);
563 proxy2 = gsignond_plugin_proxy_factory_get_plugin (factory, "ssotest");
564 fail_if (proxy2 == NULL);
565 fail_if(g_hash_table_size(factory->plugins) != 1);
567 fail_unless (proxy1 == proxy2, "got new plugin proxy object, "
568 "where expected cached object(%p,%p)",
570 g_object_unref (proxy2);
572 g_object_unref (config);
573 g_object_unref (factory);
575 /* CASE 2: proxy timeout enbled */
576 config = gsignond_config_new();
577 fail_if(config == NULL);
578 gsignond_config_set_integer (config, GSIGNOND_CONFIG_PLUGIN_TIMEOUT, 1);
580 factory = gsignond_plugin_proxy_factory_new (config);
581 fail_if (factory == NULL);
583 proxy1 = gsignond_plugin_proxy_factory_get_plugin (factory, "ssotest");
584 fail_if (proxy1 == NULL);
585 g_object_unref (proxy1);
586 ProxyTimeoutData *data = g_new0(ProxyTimeoutData, 1);
587 data->factory = factory;
588 data->proxy = proxy1;
589 g_timeout_add_seconds (2, _validate_new_proxy, (gpointer)data);
593 g_object_unref(config);
594 g_object_unref(factory);
596 /* CASE 3: proxy timeout enable - request recently closed plugin */
597 config = gsignond_config_new ();
598 fail_if (config == NULL);
599 gsignond_config_set_integer (config, GSIGNOND_CONFIG_PLUGIN_TIMEOUT, 2);
601 factory = gsignond_plugin_proxy_factory_new(config);
602 fail_if (factory == NULL);
604 proxy1 = gsignond_plugin_proxy_factory_get_plugin(factory, "ssotest");
605 fail_if (proxy1 == NULL);
606 g_object_unref (proxy1);
608 ProxyTimeoutData *data1 = g_new0(ProxyTimeoutData, 1);
609 data1->factory = factory;
610 data1->proxy = proxy1;
612 g_timeout_add_seconds (1, _validate_cached_proxy, (gpointer)data1);
616 g_object_unref(config);
617 g_object_unref(factory);
621 Suite* pluginproxy_suite (void)
623 Suite *s = suite_create ("Plugin proxy");
626 TCase *tc_core = tcase_create ("Tests");
627 tcase_add_checked_fixture (tc_core, _setup, _teardown);
629 tcase_set_timeout (tc_core, 10);
630 tcase_add_test (tc_core, test_pluginproxy_create);
631 tcase_add_test (tc_core, test_pluginproxy_process);
632 tcase_add_test (tc_core, test_pluginproxy_process_cancel);
633 tcase_add_test (tc_core, test_pluginproxy_process_queue);
634 tcase_add_test (tc_core, test_pluginproxy_process_queue_cancel);
635 tcase_add_test (tc_core, test_pluginproxyfactory_methods_and_mechanisms);
636 tcase_add_test (tc_core, test_pluginproxyfactory_get);
637 tcase_add_test (tc_core, test_pluginproxyfactory_proxy_timeout);
639 suite_add_tcase (s, tc_core);
647 Suite *s = pluginproxy_suite();
648 SRunner *sr = srunner_create(s);
649 srunner_run_all(sr, CK_NORMAL);
650 number_failed = srunner_ntests_failed(sr);
652 return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;