Commit 17fade31 authored by Stef Walter's avatar Stef Walter Committed by Stef Walter
Browse files

Implement gsecret_service_get_secrets_for_paths() and friends

 * Lots of testing, fine tuning and other bits too.
parent 09a9d856
......@@ -31,14 +31,13 @@ stamp*
/build/coverage*
/build/m4
/build/valgrind-built.supp
/build/valgrind-suppressions
/po/POTFILES
/po/gsecret.pot
/egg/tests/test-dh
/egg/tests/test-hkdf
/egg/tests/test-secmem
/egg/tests/test-*
!/egg/tests/test-*.c
/library/gsecret-dbus-generated.[ch]
/library/tests/test-*
......
......@@ -28,17 +28,3 @@ check-memory:
test -d $(builddir)/$$subdir/tests && \
make -C $(builddir)/$$subdir/tests check-memory; \
done
if WITH_COVERAGE
coverage:
mkdir -p $(builddir)/build/coverage
$(LCOV) --directory . --capture --output-file $(builddir)/build/coverage.info
$(GENHTML) --output-directory $(builddir)/build/coverage $(builddir)/build/coverage.info
$(LCOV) --directory . --zerocounters
@echo "file://$(abs_top_builddir)/build/coverage/index.html"
clear-coverage:
$(LCOV) --directory . --zerocounters
.PHONY: coverage
endif
NULL =
perform-memcheck: $(TEST_PROGS) $(top_builddir)/build/valgrind-built.supp
TEST_SUPPRESSIONS = $(top_builddir)/build/valgrind-suppressions
perform-memcheck: $(TEST_PROGS) $(TEST_SUPPRESSIONS)
@for test in $(TEST_PROGS); do \
G_SLICE=always-malloc libtool --mode=execute \
valgrind --trace-children=no --gen-suppressions=all \
--suppressions=$(top_builddir)/build/valgrind-built.supp \
--suppressions=$(TEST_SUPPRESSIONS) \
--leak-check=full --show-reachable=yes --num-callers=16 \
--quiet --error-exitcode=33 \
$(builddir)/$$test; \
done
if WITH_COVERAGE
coverage:
mkdir -p $(top_builddir)/build/coverage
$(LCOV) --directory . --capture --output-file $(top_builddir)/build/coverage.info
$(GENHTML) --output-directory $(top_builddir)/build/coverage $(top_builddir)/build/coverage.info
$(LCOV) --directory . --zerocounters
@echo "file://$(abs_top_builddir)/build/coverage/index.html"
clear-coverage:
$(LCOV) --directory . --zerocounters
.PHONY: coverage
endif
\ No newline at end of file
......@@ -9,11 +9,11 @@ SUPPRESSIONS = \
pthread.supp \
unknown.supp
valgrind-built.supp: $(SUPPRESSIONS)
valgrind-suppressions: $(SUPPRESSIONS)
$(AM_V_GEN) cat $(SUPPRESSIONS) > $@
EXTRA_DIST = \
$(VALGRIND_CONTRIB) \
$(SUPPRESSIONS)
all-local: valgrind-built.supp
\ No newline at end of file
all-local: valgrind-suppressions
\ No newline at end of file
......@@ -238,6 +238,15 @@
...
fun:g_test_run_suite
}
{
g_test_run_suite__timer_new2
Memcheck:Leak
...
fun:g_timer_new
fun:test_case_run_suite_internal
...
fun:g_test_run_suite
}
{
g_test_run_suite__strconcat
Memcheck:Leak
......@@ -301,3 +310,10 @@
...
fun:g_static_mutex_get_mutex_impl
}
{
g_variant_type_info_unref
Memcheck:Leak
...
fun:g_hash_table_remove
fun:g_variant_type_info_unref
}
......@@ -344,3 +344,12 @@
...
fun:gdbus_shared_thread_func
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:g_main_context_add_poll_unlocked
...
fun:g_main_loop_run
fun:gdbus_shared_thread_func
}
......@@ -19,7 +19,11 @@ ENCRYPTION_SRCS =
endif
libegg_la_SOURCES = \
egg-hex.c egg-hex.h \
egg-secure-memory.c egg-secure-memory.h \
egg-testing.c egg-testing.h \
$(ENCRYPTION_SRCS) \
$(BUILT_SOURCES)
check-memory:
make -C tests check-memory
\ No newline at end of file
/*
* gnome-keyring
*
* Copyright (C) 2008 Stefan Walter
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "config.h"
#include "egg-hex.h"
#include <string.h>
static const char HEXC_UPPER[] = "0123456789ABCDEF";
static const char HEXC_LOWER[] = "0123456789abcdef";
gpointer
egg_hex_decode (const gchar *data, gssize n_data, gsize *n_decoded)
{
return egg_hex_decode_full (data, n_data, 0, 1, n_decoded);
}
gpointer
egg_hex_decode_full (const gchar *data, gssize n_data,
gchar delim, guint group, gsize *n_decoded)
{
guchar *result;
guchar *decoded;
gushort j;
gint state = 0;
gint part = 0;
const gchar* pos;
g_return_val_if_fail (data || !n_data, NULL);
g_return_val_if_fail (n_decoded, NULL);
g_return_val_if_fail (group >= 1, NULL);
if (n_data == -1)
n_data = strlen (data);
decoded = result = g_malloc0 ((n_data / 2) + 1);
*n_decoded = 0;
while (n_data > 0 && state == 0) {
if (decoded != result && delim) {
if (*data != delim) {
state = -1;
break;
}
++data;
--n_data;
}
while (part < group && n_data > 0) {
/* Find the position */
pos = strchr (HEXC_UPPER, g_ascii_toupper (*data));
if (pos == 0) {
if (n_data > 0)
state = -1;
break;
}
j = pos - HEXC_UPPER;
if(!state) {
*decoded = (j & 0xf) << 4;
state = 1;
} else {
*decoded |= (j & 0xf);
(*n_decoded)++;
decoded++;
state = 0;
part++;
}
++data;
--n_data;
}
part = 0;
}
/* Parsing error */
if (state != 0) {
g_free (result);
result = NULL;
}
return result;
}
gchar*
egg_hex_encode (gconstpointer data, gsize n_data)
{
return egg_hex_encode_full (data, n_data, TRUE, '\0', 0);
}
gchar*
egg_hex_encode_full (gconstpointer data, gsize n_data,
gboolean upper_case, gchar delim, guint group)
{
GString *result;
const gchar *input;
const char *hexc;
gsize bytes;
guchar j;
g_return_val_if_fail (data || !n_data, NULL);
input = data;
hexc = upper_case ? HEXC_UPPER : HEXC_LOWER;
result = g_string_sized_new (n_data * 2 + 1);
bytes = 0;
while (n_data > 0) {
if (group && bytes && (bytes % group) == 0)
g_string_append_c (result, delim);
j = *(input) >> 4 & 0xf;
g_string_append_c (result, hexc[j]);
j = *(input++) & 0xf;
g_string_append_c (result, hexc[j]);
++bytes;
--n_data;
}
/* Make sure still null terminated */
return g_string_free (result, FALSE);
}
/*
* gnome-keyring
*
* Copyright (C) 2008 Stefan Walter
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef EGG_HEX_H_
#define EGG_HEX_H_
#include <glib.h>
gpointer egg_hex_decode (const gchar *data,
gssize n_data,
gsize *n_decoded);
gpointer egg_hex_decode_full (const gchar *data,
gssize n_data,
gchar delim,
guint group,
gsize *n_decoded);
gchar* egg_hex_encode (gconstpointer data,
gsize n_data);
gchar* egg_hex_encode_full (gconstpointer data,
gsize n_data,
gboolean upper_case,
gchar delim,
guint group);
#endif /* EGG_HEX_H_ */
......@@ -138,7 +138,6 @@ on_loop_wait_timeout (gpointer data)
static gboolean
loop_wait_until (int timeout)
{
gboolean ret = FALSE;
gboolean timed_out = FALSE;
guint source;
......@@ -149,16 +148,10 @@ loop_wait_until (int timeout)
g_main_loop_run (wait_loop);
if (timed_out) {
g_source_remove (source);
ret = FALSE;
} else {
ret = TRUE;
}
g_main_loop_unref (wait_loop);
wait_loop = NULL;
return ret;
return !timed_out;
}
gint
......
......@@ -12,6 +12,7 @@ LDADD = \
$(GLIB_LIBS)
TEST_PROGS = \
test-hex \
test-secmem
if WITH_GCRYPT
......
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* unit-test-util.c: Test gck-util.c
Copyright (C) 2007 Stefan Walter
The Gnome Keyring Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The Gnome Keyring Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the Gnome Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
Author: Stef Walter <stef@memberwebs.com>
*/
#include "config.h"
#include "egg/egg-hex.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static const guchar TEST_DATA[] = { 0x05, 0xD6, 0x95, 0x96, 0x10, 0x12, 0xAE, 0x35 };
static const gchar *TEST_HEX = "05D695961012AE35";
static const gchar *TEST_HEX_DELIM = "05 D6 95 96 10 12 AE 35";
static void
test_encode (void)
{
gchar *hex;
hex = egg_hex_encode (TEST_DATA, sizeof (TEST_DATA));
g_assert (hex);
g_assert_cmpstr (hex, ==, TEST_HEX);
g_free (hex);
}
static void
test_encode_spaces (void)
{
gchar *hex;
/* Encode without spaces */
hex = egg_hex_encode_full (TEST_DATA, sizeof (TEST_DATA), TRUE, 0, 0);
g_assert (hex);
g_assert_cmpstr (hex, ==, TEST_HEX);
g_free (hex);
/* Encode with spaces */
hex = egg_hex_encode_full (TEST_DATA, sizeof (TEST_DATA), TRUE, ' ', 1);
g_assert (hex);
g_assert_cmpstr (hex, ==, TEST_HEX_DELIM);
g_free (hex);
}
static void
test_decode (void)
{
guchar *data;
gsize n_data;
data = egg_hex_decode (TEST_HEX, -1, &n_data);
g_assert (data);
g_assert (n_data == sizeof (TEST_DATA));
g_assert (memcmp (data, TEST_DATA, n_data) == 0);
g_free (data);
/* Nothing in, empty out */
data = egg_hex_decode ("AB", 0, &n_data);
g_assert (data);
g_assert (n_data == 0);
g_free (data);
/* Delimited*/
data = egg_hex_decode_full (TEST_HEX_DELIM, -1, ' ', 1, &n_data);
g_assert (data);
g_assert (n_data == sizeof (TEST_DATA));
g_assert (memcmp (data, TEST_DATA, n_data) == 0);
g_free (data);
}
static void
test_decode_fail (void)
{
guchar *data;
gsize n_data;
/* Invalid input, null out */
data = egg_hex_decode ("AB", 1, &n_data);
g_assert (!data);
/* Bad characters, null out */
data = egg_hex_decode ("ABXX", -1, &n_data);
g_assert (!data);
/* Not Delimited, null out*/
data = egg_hex_decode_full ("ABABAB", -1, ':', 1, &n_data);
g_assert (!data);
}
int
main (int argc, char **argv)
{
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/hex/encode", test_encode);
g_test_add_func ("/hex/encode_spaces", test_encode_spaces);
g_test_add_func ("/hex/decode", test_decode);
g_test_add_func ("/hex/decode_fail", test_decode_fail);
return g_test_run ();
}
......@@ -40,3 +40,6 @@ gsecret-dbus-generated.c: $(DBUS_XML_DEFINITIONS) Makefile.am
$(AM_V_GEN) sed -i -e 's/gsecret_gen_/_gsecret_gen_/g' gsecret-dbus-generated.[ch]
gsecret-dbus-generated.h: gsecret-dbus-generated.c
check-memory:
make -C tests check-memory
\ No newline at end of file
......@@ -20,6 +20,12 @@
G_BEGIN_DECLS
typedef struct {
GVariant *in;
GVariant *out;
GCancellable *cancellable;
} GSecretParams;
#define GSECRET_SERVICE_PATH "/org/freedesktop/secrets"
#define GSECRET_SERVICE_BUS_NAME "org.freedesktop.Secret.Service"
......@@ -28,6 +34,11 @@ G_BEGIN_DECLS
#define GSECRET_COLLECTION_INTERFACE "org.freedesktop.Secret.Collection"
GSecretParams * _gsecret_params_new (GCancellable *cancellable,
GVariant *in);
void _gsecret_params_free (gpointer data);
gchar * _gsecret_util_parent_path (const gchar *path);
GVariant * _gsecret_util_variant_for_attributes (GHashTable *attributes);
......
......@@ -24,6 +24,7 @@
#include "egg/egg-libgcrypt.h"
#endif
#include "egg/egg-hex.h"
#include "egg/egg-secure-memory.h"
#include <glib.h>
......@@ -209,9 +210,18 @@ request_open_session_aes (GSecretSession *session)
g_assert (session->publi == NULL);
/* Initialize our local parameters and values */
if (!egg_dh_default_params ("ietf-ike-grp-modp-1024",
if (!egg_dh_default_params ("ietf-ike-grp-modp-1536",
&session->prime, &base))
g_return_val_if_reached (NULL);
#if 0
g_printerr ("\n lib prime: ");
gcry_mpi_dump (session->prime);
g_printerr ("\n lib base: ");
gcry_mpi_dump (base);
g_printerr ("\n");
#endif
if (!egg_dh_gen_pair (session->prime, base, 0,
&session->publi, &session->privat))
g_return_val_if_reached (NULL);
......@@ -255,9 +265,21 @@ response_open_session_aes (GSecretSession *session,
g_return_val_if_fail (gcry == 0, FALSE);
g_variant_unref (argument);
#if 0
g_printerr (" lib publi: ");
gcry_mpi_dump (session->publi);
g_printerr ("\n lib peer: ");
gcry_mpi_dump (peer);
g_printerr ("\n");
#endif
ikm = egg_dh_gen_secret (peer, session->privat, session->prime, &n_ikm);
gcry_mpi_release (peer);
#if 0
g_printerr (" lib ikm: %s\n", egg_hex_encode (ikm, n_ikm));
#endif
if (ikm == NULL) {
g_warning ("couldn't negotiate a valid AES session key");
g_free (session->path);
......@@ -633,9 +655,17 @@ service_decode_aes_secret (GSecretSession *session,
return NULL;
}
#if 0
g_printerr (" lib iv: %s\n", egg_hex_encode (param, n_param));
#endif
gcry = gcry_cipher_setiv (cih, param, n_param);
g_return_val_if_fail (gcry == 0, NULL);
#if 0
g_printerr (" lib key: %s\n", egg_hex_encode (session->key, session->n_key));
#endif
gcry = gcry_cipher_setkey (cih, session->key, session->n_key);
g_return_val_if_fail (gcry == 0, NULL);
......@@ -656,7 +686,7 @@ service_decode_aes_secret (GSecretSession *session,
if (!pkcs7_unpad_bytes_in_place (padded, &n_padded)) {
egg_secure_clear (padded, n_padded);
egg_secure_free (padded);
g_message ("received an invalid, unencryptable, or non-utf8 secret");
g_message ("received an invalid or unencryptable secret");
return FALSE;
}
......@@ -900,7 +930,7 @@ on_search_items_complete (GObject *source,
}
void
gsecret_service_search_paths (GSecretService *self,
gsecret_service_search_for_paths (GSecretService *self,
GHashTable *attributes,
GCancellable *cancellable,
GAsyncReadyCallback callback,
......@@ -913,7 +943,7 @@ gsecret_service_search_paths (GSecretService *self,
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
gsecret_service_search_paths);
gsecret_service_search_for_paths);
g_dbus_proxy_call (G_DBUS_PROXY (self), "SearchItems",
g_variant_new ("(@a{ss})",
......@@ -925,7 +955,7 @@ gsecret_service_search_paths (GSecretService *self,
}
gboolean
gsecret_service_search_paths_finish (GSecretService *self,
gsecret_service_search_for_paths_finish (GSecretService *self,
GAsyncResult *result,
gchar ***unlocked,
gchar ***locked,
......@@ -936,7 +966,7 @@ gsecret_service_search_paths_finish (GSecretService *self,