Testing of gsecret_service_ensure and friends

This commit is contained in:
Stef Walter 2011-09-25 22:59:43 +02:00 committed by Stef Walter
parent 51896081f0
commit 6b4d7b6484
7 changed files with 204 additions and 28 deletions

View File

@ -24,16 +24,15 @@ dist-hook:
fi fi
if WITH_COVERAGE if WITH_COVERAGE
check-coverage: clear-coverage check coverage
coverage: coverage:
mkdir -p coverage mkdir -p coverage
$(LCOV) --directory . --capture --output-file coverage/coverage.info $(LCOV) --directory . --capture --output-file coverage/coverage.info
$(GENHTML) --output-directory coverage/coverage coverage/coverage.info $(GENHTML) --output-directory coverage coverage/coverage.info
$(LCOV) --directory . --zerocounters $(LCOV) --directory . --zerocounters
@echo "file://$(abs_top_builddir)/coverage/index.html" @echo "file://$(abs_top_builddir)/coverage/index.html"
clear-coverage: clear-coverage:
$(LCOV) --directory . --zerocounters $(LCOV) --directory . --zerocounters
.PHONY: coverage
endif endif

View File

@ -34,8 +34,12 @@ EGG_SECURE_GLIB_DEFINITIONS ();
EGG_SECURE_DECLARE (secret_service); EGG_SECURE_DECLARE (secret_service);
#define ALGORITHMS_AES "dh-ietf1024-sha256-aes128-cbc-pkcs7"
#define ALGORITHMS_PLAIN "plain"
typedef struct { typedef struct {
gchar *path; gchar *path;
const gchar *algorithms;
#ifdef WITH_GCRYPT #ifdef WITH_GCRYPT
gcry_mpi_t prime; gcry_mpi_t prime;
gcry_mpi_t privat; gcry_mpi_t privat;
@ -156,6 +160,28 @@ _gsecret_service_bare_instance (GDBusConnection *connection,
return service; return service;
} }
const gchar *
gsecret_service_get_session_algorithms (GSecretService *self)
{
GSecretSession *session;
g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
session = g_atomic_pointer_get (&self->pv->session);
return session ? session->algorithms : NULL;
}
const gchar *
gsecret_service_get_session_path (GSecretService *self)
{
GSecretSession *session;
g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
session = g_atomic_pointer_get (&self->pv->session);
return session ? session->path : NULL;
}
#ifdef WITH_GCRYPT #ifdef WITH_GCRYPT
static GVariant * static GVariant *
@ -186,7 +212,7 @@ request_open_session_aes (GSecretSession *session)
buffer, n_buffer, TRUE, buffer, n_buffer, TRUE,
gcry_free, buffer); gcry_free, buffer);
return g_variant_new ("sv", "dh-ietf1024-sha256-aes128-cbc-pkcs7", argument); return g_variant_new ("(sv)", ALGORITHMS_AES, argument);
} }
static gboolean static gboolean
@ -195,20 +221,23 @@ response_open_session_aes (GSecretSession *session,
{ {
gconstpointer buffer; gconstpointer buffer;
GVariant *argument; GVariant *argument;
const gchar *sig;
gsize n_buffer; gsize n_buffer;
gcry_mpi_t peer; gcry_mpi_t peer;
gcry_error_t gcry; gcry_error_t gcry;
gpointer ikm; gpointer ikm;
gsize n_ikm; gsize n_ikm;
if (G_VARIANT_TYPE ("vo") != g_variant_get_type (response)) { sig = g_variant_get_type_string (response);
g_warning ("invalid OpenSession() response from daemon with signature: %s", g_return_val_if_fail (sig != NULL, FALSE);
g_variant_get_type_string (response));
if (!g_str_equal (sig, "(vo)")) {
g_warning ("invalid OpenSession() response from daemon with signature: %s", sig);
return FALSE; return FALSE;
} }
g_assert (session->path == NULL); g_assert (session->path == NULL);
g_variant_get (response, "vo", &argument, &session->path); g_variant_get (response, "(vo)", &argument, &session->path);
buffer = g_variant_get_fixed_array (argument, &n_buffer, sizeof (guchar)); buffer = g_variant_get_fixed_array (argument, &n_buffer, sizeof (guchar));
gcry = gcry_mpi_scan (&peer, GCRYMPI_FMT_USG, buffer, n_buffer, NULL); gcry = gcry_mpi_scan (&peer, GCRYMPI_FMT_USG, buffer, n_buffer, NULL);
@ -232,6 +261,7 @@ response_open_session_aes (GSecretSession *session,
g_return_val_if_reached (FALSE); g_return_val_if_reached (FALSE);
egg_secure_free (ikm); egg_secure_free (ikm);
session->algorithms = ALGORITHMS_AES;
return TRUE; return TRUE;
} }
@ -241,7 +271,7 @@ static GVariant *
request_open_session_plain (GSecretSession *session) request_open_session_plain (GSecretSession *session)
{ {
GVariant *argument = g_variant_new_string (""); GVariant *argument = g_variant_new_string ("");
return g_variant_new ("sv", "plain", argument); return g_variant_new ("(sv)", "plain", argument);
} }
static gboolean static gboolean
@ -249,20 +279,25 @@ response_open_session_plain (GSecretSession *session,
GVariant *response) GVariant *response)
{ {
GVariant *argument; GVariant *argument;
const gchar *sig;
if (G_VARIANT_TYPE ("vo") != g_variant_get_type (response)) { sig = g_variant_get_type_string (response);
g_return_val_if_fail (sig != NULL, FALSE);
if (!g_str_equal (sig, "(vo)")) {
g_warning ("invalid OpenSession() response from daemon with signature: %s", g_warning ("invalid OpenSession() response from daemon with signature: %s",
g_variant_get_type_string (response)); g_variant_get_type_string (response));
return FALSE; return FALSE;
} }
g_assert (session->path == NULL); g_assert (session->path == NULL);
g_variant_get (response, "vo", &argument, &session->path); g_variant_get (response, "(vo)", &argument, &session->path);
g_variant_unref (argument); g_variant_unref (argument);
g_assert (session->key == NULL); g_assert (session->key == NULL);
g_assert (session->n_key == 0); g_assert (session->n_key == 0);
session->algorithms = ALGORITHMS_PLAIN;
return TRUE; return TRUE;
} }
@ -395,7 +430,7 @@ gsecret_service_ensure_session (GSecretService *self,
closure = g_new (OpenSessionClosure, 1); closure = g_new (OpenSessionClosure, 1);
closure->cancellable = cancellable ? g_object_ref (cancellable) : cancellable; closure->cancellable = cancellable ? g_object_ref (cancellable) : cancellable;
closure->session = g_new (GSecretSession, 1); closure->session = g_new0 (GSecretSession, 1);
g_simple_async_result_set_op_res_gpointer (res, closure, open_session_closure_free); g_simple_async_result_set_op_res_gpointer (res, closure, open_session_closure_free);
g_dbus_proxy_call (G_DBUS_PROXY (self), "OpenSession", g_dbus_proxy_call (G_DBUS_PROXY (self), "OpenSession",

View File

@ -72,6 +72,10 @@ GSecretService * gsecret_service_instance_sync (GDBusConnection *c
GError **error); GError **error);
#endif #endif
const gchar * gsecret_service_get_session_algorithms (GSecretService *self);
const gchar * gsecret_service_get_session_path (GSecretService *self);
void gsecret_service_ensure_session (GSecretService *self, void gsecret_service_ensure_session (GSecretService *self,
GCancellable *cancellable, GCancellable *cancellable,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,

View File

@ -0,0 +1,7 @@
#!/usr/bin/env python
import mock
service = mock.SecretService()
service.algorithms = { "plain": mock.PlainAlgorithm() }
service.listen()

View File

@ -31,6 +31,10 @@ class NotSupported(dbus.exceptions.DBusException):
def __init__(self, msg): def __init__(self, msg):
dbus.exceptions.DBusException.__init__(self, msg, name="org.freedesktop.DBus.Error.NotSupported") dbus.exceptions.DBusException.__init__(self, msg, name="org.freedesktop.DBus.Error.NotSupported")
class InvalidArgs(dbus.exceptions.DBusException):
def __init__(self, msg):
dbus.exceptions.DBusException.__init__(self, msg, name="org.freedesktop.DBus.Error.InvalidArgs")
unique_identifier = 0 unique_identifier = 0
def next_identifier(): def next_identifier():
global unique_identifier global unique_identifier
@ -39,11 +43,15 @@ def next_identifier():
class PlainAlgorithm(): class PlainAlgorithm():
def negotiate(self, service, sender, param): def negotiate(self, service, sender, param):
if type (param) != dbus.String:
raise InvalidArgs("invalid argument passed to OpenSession")
session = SecretSession(service, sender, None) session = SecretSession(service, sender, None)
return (dbus.String("", variant_level=1), session) return (dbus.String("", variant_level=1), session)
class AesAlgorithm(): class AesAlgorithm():
def negotiate(self, service, sender, param): def negotiate(self, service, sender, param):
if type (param) != dbus.ByteArray:
raise InvalidArgs("invalid argument passed to OpenSession")
publi, privat = dh.generate_pair() publi, privat = dh.generate_pair()
peer = dh.bytes_to_number(param) peer = dh.bytes_to_number(param)
ikm = dh.derive_key(privat, peer) ikm = dh.derive_key(privat, peer)
@ -72,9 +80,11 @@ class SecretService(dbus.service.Object):
"dh-ietf1024-sha256-aes128-cbc-pkcs7": AesAlgorithm(), "dh-ietf1024-sha256-aes128-cbc-pkcs7": AesAlgorithm(),
} }
def __init__(self, name=bus_name): def __init__(self, name=None):
bus = bus = dbus.SessionBus() if name == None:
self.bus_name = dbus.service.BusName(name) name = bus_name
bus = dbus.SessionBus()
self.bus_name = dbus.service.BusName(name, allow_replacement=True, replace_existing=True)
dbus.service.Object.__init__(self, self.bus_name, '/org/freedesktop/secrets') dbus.service.Object.__init__(self, self.bus_name, '/org/freedesktop/secrets')
self.sessions = { } self.sessions = { }
@ -102,7 +112,6 @@ class SecretService(dbus.service.Object):
@dbus.service.method('org.freedesktop.Secret.Service', byte_arrays=True, sender_keyword='sender') @dbus.service.method('org.freedesktop.Secret.Service', byte_arrays=True, sender_keyword='sender')
def OpenSession(self, algorithm, param, sender=None): def OpenSession(self, algorithm, param, sender=None):
assert type(algorithm) == dbus.String assert type(algorithm) == dbus.String
assert type(param) == dbus.ByteArray
if algorithm not in self.algorithms: if algorithm not in self.algorithms:
raise NotSupported("algorithm %s is not supported" % algorithm) raise NotSupported("algorithm %s is not supported" % algorithm)

View File

@ -17,6 +17,8 @@
#include "gsecret-service.h" #include "gsecret-service.h"
#include "gsecret-private.h" #include "gsecret-private.h"
#include "egg/egg-testing.h"
#include <glib.h> #include <glib.h>
#include <errno.h> #include <errno.h>
@ -31,18 +33,20 @@ typedef struct {
} Test; } Test;
static void static void
setup_normal (Test *test, setup (Test *test,
gconstpointer unused) gconstpointer data)
{ {
GError *error = NULL; GError *error = NULL;
const gchar *mock_script = data;
gchar *argv[] = { gchar *argv[] = {
"python", "./mock-service-normal.py", "python", (gchar *)mock_script,
"--name", MOCK_NAME, "--name", MOCK_NAME,
NULL NULL
}; };
g_spawn_async (SRCDIR, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &test->pid, &error); g_spawn_async (SRCDIR, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &test->pid, &error);
g_assert_no_error (error); g_assert_no_error (error);
g_usleep (100 * 1000);
test->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); test->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
g_assert_no_error (error); g_assert_no_error (error);
@ -64,16 +68,130 @@ teardown (Test *test,
} }
static void static void
test_ensure_sync (Test *test, test_ensure (Test *test,
gconstpointer unused) gconstpointer unused)
{ {
GError *error = NULL; GError *error = NULL;
const gchar *path; const gchar *path;
g_assert_cmpstr (gsecret_service_get_session_path (test->service), ==, NULL);
g_assert_cmpstr (gsecret_service_get_session_algorithms (test->service), ==, NULL);
path = gsecret_service_ensure_session_sync (test->service, NULL, &error); path = gsecret_service_ensure_session_sync (test->service, NULL, &error);
g_assert_no_error (error); g_assert_no_error (error);
g_assert (path != NULL); g_assert (path != NULL);
g_printerr ("%s", path); g_assert_cmpstr (gsecret_service_get_session_path (test->service), ==, path);
g_assert_cmpstr (gsecret_service_get_session_algorithms (test->service), ==, "dh-ietf1024-sha256-aes128-cbc-pkcs7");
}
static void
test_ensure_twice (Test *test,
gconstpointer unused)
{
GError *error = NULL;
const gchar *path;
g_assert_cmpstr (gsecret_service_get_session_path (test->service), ==, NULL);
g_assert_cmpstr (gsecret_service_get_session_algorithms (test->service), ==, NULL);
path = gsecret_service_ensure_session_sync (test->service, NULL, &error);
g_assert_no_error (error);
g_assert (path != NULL);
g_assert_cmpstr (gsecret_service_get_session_path (test->service), ==, path);
g_assert_cmpstr (gsecret_service_get_session_algorithms (test->service), ==, "dh-ietf1024-sha256-aes128-cbc-pkcs7");
path = gsecret_service_ensure_session_sync (test->service, NULL, &error);
g_assert_no_error (error);
g_assert (path != NULL);
g_assert_cmpstr (gsecret_service_get_session_path (test->service), ==, path);
g_assert_cmpstr (gsecret_service_get_session_algorithms (test->service), ==, "dh-ietf1024-sha256-aes128-cbc-pkcs7");
}
static void
test_ensure_plain (Test *test,
gconstpointer unused)
{
GError *error = NULL;
const gchar *path;
g_assert_cmpstr (gsecret_service_get_session_path (test->service), ==, NULL);
g_assert_cmpstr (gsecret_service_get_session_algorithms (test->service), ==, NULL);
path = gsecret_service_ensure_session_sync (test->service, NULL, &error);
g_assert_no_error (error);
g_assert (path != NULL);
g_assert_cmpstr (gsecret_service_get_session_path (test->service), ==, path);
g_assert_cmpstr (gsecret_service_get_session_algorithms (test->service), ==, "plain");
}
static void
on_complete_get_result (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
GAsyncResult **ret = user_data;
g_assert (ret != NULL);
g_assert (*ret == NULL);
*ret = g_object_ref (result);
}
static void
test_ensure_async (Test *test,
gconstpointer unused)
{
GAsyncResult *result = NULL;
GError *error = NULL;
const gchar *path;
gsecret_service_ensure_session (test->service, NULL, on_complete_get_result, &result);
egg_test_wait_until (500);
g_assert (G_IS_ASYNC_RESULT (result));
path = gsecret_service_ensure_session_finish (test->service, result, &error);
g_assert_no_error (error);
g_assert (path != NULL);
g_assert_cmpstr (gsecret_service_get_session_path (test->service), ==, path);
g_assert_cmpstr (gsecret_service_get_session_algorithms (test->service), ==, "plain");
g_object_unref (result);
}
static void
test_ensure_async_twice (Test *test,
gconstpointer unused)
{
GAsyncResult *result = NULL;
GError *error = NULL;
const gchar *path;
gsecret_service_ensure_session (test->service, NULL, on_complete_get_result, &result);
egg_test_wait_until (500);
g_assert (G_IS_ASYNC_RESULT (result));
path = gsecret_service_ensure_session_finish (test->service, result, &error);
g_assert_no_error (error);
g_assert (path != NULL);
g_assert_cmpstr (gsecret_service_get_session_path (test->service), ==, path);
g_assert_cmpstr (gsecret_service_get_session_algorithms (test->service), ==, "plain");
g_object_unref (result);
result = NULL;
gsecret_service_ensure_session (test->service, NULL, on_complete_get_result, &result);
egg_test_wait_until (500);
g_assert (G_IS_ASYNC_RESULT (result));
path = gsecret_service_ensure_session_finish (test->service, result, &error);
g_assert_no_error (error);
g_assert (path != NULL);
g_assert_cmpstr (gsecret_service_get_session_path (test->service), ==, path);
g_assert_cmpstr (gsecret_service_get_session_algorithms (test->service), ==, "plain");
g_object_unref (result);
} }
int int
@ -83,7 +201,11 @@ main (int argc, char **argv)
g_set_prgname ("test-session"); g_set_prgname ("test-session");
g_type_init (); g_type_init ();
g_test_add ("/session/ensure-sync", Test, NULL, setup_normal, test_ensure_sync, teardown); g_test_add ("/session/ensure-aes", Test, "mock-service-normal.py", setup, test_ensure, teardown);
g_test_add ("/session/ensure-twice", Test, "mock-service-normal.py", setup, test_ensure_twice, teardown);
g_test_add ("/session/ensure-plain", Test, "mock-service-only-plain.py", setup, test_ensure_plain, teardown);
g_test_add ("/session/ensure-async", Test, "mock-service-only-plain.py", setup, test_ensure_async, teardown);
g_test_add ("/session/ensure-async-twice", Test, "mock-service-only-plain.py", setup, test_ensure_async_twice, teardown);
return g_test_run (); return egg_tests_run_in_thread_with_loop ();
} }

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-09-25 21:16+0200\n" "POT-Creation-Date: 2011-09-25 22:56+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -22,8 +22,8 @@ msgstr ""
msgid "Received invalid secret from the secret storage" msgid "Received invalid secret from the secret storage"
msgstr "" msgstr ""
#: ../library/gsecret-service.c:308 ../library/gsecret-service.c:348 #: ../library/gsecret-service.c:343 ../library/gsecret-service.c:383
#: ../library/gsecret-service.c:508 #: ../library/gsecret-service.c:543
#, c-format #, c-format
msgid "Couldn't communicate with the secret storage" msgid "Couldn't communicate with the secret storage"
msgstr "" msgstr ""