mirror of
https://gitlab.gnome.org/GNOME/libsecret.git
synced 2024-12-22 12:48:51 +00:00
Implement gsecret_service_get_secrets_for_paths() and friends
* Lots of testing, fine tuning and other bits too.
This commit is contained in:
parent
09a9d856d2
commit
17fade3173
7
.gitignore
vendored
7
.gitignore
vendored
@ -31,14 +31,13 @@ stamp*
|
|||||||
|
|
||||||
/build/coverage*
|
/build/coverage*
|
||||||
/build/m4
|
/build/m4
|
||||||
/build/valgrind-built.supp
|
/build/valgrind-suppressions
|
||||||
|
|
||||||
/po/POTFILES
|
/po/POTFILES
|
||||||
/po/gsecret.pot
|
/po/gsecret.pot
|
||||||
|
|
||||||
/egg/tests/test-dh
|
/egg/tests/test-*
|
||||||
/egg/tests/test-hkdf
|
!/egg/tests/test-*.c
|
||||||
/egg/tests/test-secmem
|
|
||||||
|
|
||||||
/library/gsecret-dbus-generated.[ch]
|
/library/gsecret-dbus-generated.[ch]
|
||||||
/library/tests/test-*
|
/library/tests/test-*
|
||||||
|
14
Makefile.am
14
Makefile.am
@ -28,17 +28,3 @@ check-memory:
|
|||||||
test -d $(builddir)/$$subdir/tests && \
|
test -d $(builddir)/$$subdir/tests && \
|
||||||
make -C $(builddir)/$$subdir/tests check-memory; \
|
make -C $(builddir)/$$subdir/tests check-memory; \
|
||||||
done
|
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
|
|
||||||
|
@ -1,11 +1,28 @@
|
|||||||
NULL =
|
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 \
|
@for test in $(TEST_PROGS); do \
|
||||||
G_SLICE=always-malloc libtool --mode=execute \
|
G_SLICE=always-malloc libtool --mode=execute \
|
||||||
valgrind --trace-children=no --gen-suppressions=all \
|
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 \
|
--leak-check=full --show-reachable=yes --num-callers=16 \
|
||||||
--quiet --error-exitcode=33 \
|
--quiet --error-exitcode=33 \
|
||||||
$(builddir)/$$test; \
|
$(builddir)/$$test; \
|
||||||
done
|
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
|
||||||
|
|
@ -9,11 +9,11 @@ SUPPRESSIONS = \
|
|||||||
pthread.supp \
|
pthread.supp \
|
||||||
unknown.supp
|
unknown.supp
|
||||||
|
|
||||||
valgrind-built.supp: $(SUPPRESSIONS)
|
valgrind-suppressions: $(SUPPRESSIONS)
|
||||||
$(AM_V_GEN) cat $(SUPPRESSIONS) > $@
|
$(AM_V_GEN) cat $(SUPPRESSIONS) > $@
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
$(VALGRIND_CONTRIB) \
|
$(VALGRIND_CONTRIB) \
|
||||||
$(SUPPRESSIONS)
|
$(SUPPRESSIONS)
|
||||||
|
|
||||||
all-local: valgrind-built.supp
|
all-local: valgrind-suppressions
|
@ -238,6 +238,15 @@
|
|||||||
...
|
...
|
||||||
fun:g_test_run_suite
|
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
|
g_test_run_suite__strconcat
|
||||||
Memcheck:Leak
|
Memcheck:Leak
|
||||||
@ -301,3 +310,10 @@
|
|||||||
...
|
...
|
||||||
fun:g_static_mutex_get_mutex_impl
|
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
|
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
|
endif
|
||||||
|
|
||||||
libegg_la_SOURCES = \
|
libegg_la_SOURCES = \
|
||||||
|
egg-hex.c egg-hex.h \
|
||||||
egg-secure-memory.c egg-secure-memory.h \
|
egg-secure-memory.c egg-secure-memory.h \
|
||||||
egg-testing.c egg-testing.h \
|
egg-testing.c egg-testing.h \
|
||||||
$(ENCRYPTION_SRCS) \
|
$(ENCRYPTION_SRCS) \
|
||||||
$(BUILT_SOURCES)
|
$(BUILT_SOURCES)
|
||||||
|
|
||||||
|
check-memory:
|
||||||
|
make -C tests check-memory
|
150
egg/egg-hex.c
Normal file
150
egg/egg-hex.c
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
46
egg/egg-hex.h
Normal file
46
egg/egg-hex.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
static gboolean
|
||||||
loop_wait_until (int timeout)
|
loop_wait_until (int timeout)
|
||||||
{
|
{
|
||||||
gboolean ret = FALSE;
|
|
||||||
gboolean timed_out = FALSE;
|
gboolean timed_out = FALSE;
|
||||||
guint source;
|
guint source;
|
||||||
|
|
||||||
@ -149,16 +148,10 @@ loop_wait_until (int timeout)
|
|||||||
|
|
||||||
g_main_loop_run (wait_loop);
|
g_main_loop_run (wait_loop);
|
||||||
|
|
||||||
if (timed_out) {
|
g_source_remove (source);
|
||||||
g_source_remove (source);
|
|
||||||
ret = FALSE;
|
|
||||||
} else {
|
|
||||||
ret = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_main_loop_unref (wait_loop);
|
g_main_loop_unref (wait_loop);
|
||||||
wait_loop = NULL;
|
wait_loop = NULL;
|
||||||
return ret;
|
return !timed_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
gint
|
gint
|
||||||
|
@ -12,6 +12,7 @@ LDADD = \
|
|||||||
$(GLIB_LIBS)
|
$(GLIB_LIBS)
|
||||||
|
|
||||||
TEST_PROGS = \
|
TEST_PROGS = \
|
||||||
|
test-hex \
|
||||||
test-secmem
|
test-secmem
|
||||||
|
|
||||||
if WITH_GCRYPT
|
if WITH_GCRYPT
|
||||||
|
121
egg/tests/test-hex.c
Normal file
121
egg/tests/test-hex.c
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/* -*- 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]
|
$(AM_V_GEN) sed -i -e 's/gsecret_gen_/_gsecret_gen_/g' gsecret-dbus-generated.[ch]
|
||||||
|
|
||||||
gsecret-dbus-generated.h: gsecret-dbus-generated.c
|
gsecret-dbus-generated.h: gsecret-dbus-generated.c
|
||||||
|
|
||||||
|
check-memory:
|
||||||
|
make -C tests check-memory
|
@ -20,6 +20,12 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GVariant *in;
|
||||||
|
GVariant *out;
|
||||||
|
GCancellable *cancellable;
|
||||||
|
} GSecretParams;
|
||||||
|
|
||||||
#define GSECRET_SERVICE_PATH "/org/freedesktop/secrets"
|
#define GSECRET_SERVICE_PATH "/org/freedesktop/secrets"
|
||||||
|
|
||||||
#define GSECRET_SERVICE_BUS_NAME "org.freedesktop.Secret.Service"
|
#define GSECRET_SERVICE_BUS_NAME "org.freedesktop.Secret.Service"
|
||||||
@ -28,6 +34,11 @@ G_BEGIN_DECLS
|
|||||||
|
|
||||||
#define GSECRET_COLLECTION_INTERFACE "org.freedesktop.Secret.Collection"
|
#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);
|
gchar * _gsecret_util_parent_path (const gchar *path);
|
||||||
|
|
||||||
GVariant * _gsecret_util_variant_for_attributes (GHashTable *attributes);
|
GVariant * _gsecret_util_variant_for_attributes (GHashTable *attributes);
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "egg/egg-libgcrypt.h"
|
#include "egg/egg-libgcrypt.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "egg/egg-hex.h"
|
||||||
#include "egg/egg-secure-memory.h"
|
#include "egg/egg-secure-memory.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
@ -209,9 +210,18 @@ request_open_session_aes (GSecretSession *session)
|
|||||||
g_assert (session->publi == NULL);
|
g_assert (session->publi == NULL);
|
||||||
|
|
||||||
/* Initialize our local parameters and values */
|
/* 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))
|
&session->prime, &base))
|
||||||
g_return_val_if_reached (NULL);
|
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,
|
if (!egg_dh_gen_pair (session->prime, base, 0,
|
||||||
&session->publi, &session->privat))
|
&session->publi, &session->privat))
|
||||||
g_return_val_if_reached (NULL);
|
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_return_val_if_fail (gcry == 0, FALSE);
|
||||||
g_variant_unref (argument);
|
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);
|
ikm = egg_dh_gen_secret (peer, session->privat, session->prime, &n_ikm);
|
||||||
gcry_mpi_release (peer);
|
gcry_mpi_release (peer);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
g_printerr (" lib ikm: %s\n", egg_hex_encode (ikm, n_ikm));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ikm == NULL) {
|
if (ikm == NULL) {
|
||||||
g_warning ("couldn't negotiate a valid AES session key");
|
g_warning ("couldn't negotiate a valid AES session key");
|
||||||
g_free (session->path);
|
g_free (session->path);
|
||||||
@ -633,9 +655,17 @@ service_decode_aes_secret (GSecretSession *session,
|
|||||||
return NULL;
|
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);
|
gcry = gcry_cipher_setiv (cih, param, n_param);
|
||||||
g_return_val_if_fail (gcry == 0, NULL);
|
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);
|
gcry = gcry_cipher_setkey (cih, session->key, session->n_key);
|
||||||
g_return_val_if_fail (gcry == 0, NULL);
|
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)) {
|
if (!pkcs7_unpad_bytes_in_place (padded, &n_padded)) {
|
||||||
egg_secure_clear (padded, n_padded);
|
egg_secure_clear (padded, n_padded);
|
||||||
egg_secure_free (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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -900,11 +930,11 @@ on_search_items_complete (GObject *source,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gsecret_service_search_paths (GSecretService *self,
|
gsecret_service_search_for_paths (GSecretService *self,
|
||||||
GHashTable *attributes,
|
GHashTable *attributes,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GSimpleAsyncResult *res;
|
GSimpleAsyncResult *res;
|
||||||
|
|
||||||
@ -913,7 +943,7 @@ gsecret_service_search_paths (GSecretService *self,
|
|||||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
|
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_dbus_proxy_call (G_DBUS_PROXY (self), "SearchItems",
|
||||||
g_variant_new ("(@a{ss})",
|
g_variant_new ("(@a{ss})",
|
||||||
@ -925,18 +955,18 @@ gsecret_service_search_paths (GSecretService *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gsecret_service_search_paths_finish (GSecretService *self,
|
gsecret_service_search_for_paths_finish (GSecretService *self,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
gchar ***unlocked,
|
gchar ***unlocked,
|
||||||
gchar ***locked,
|
gchar ***locked,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GVariant *response;
|
GVariant *response;
|
||||||
GSimpleAsyncResult *res;
|
GSimpleAsyncResult *res;
|
||||||
gchar **dummy = NULL;
|
gchar **dummy = NULL;
|
||||||
|
|
||||||
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
|
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
|
||||||
gsecret_service_search_paths), FALSE);
|
gsecret_service_search_for_paths), FALSE);
|
||||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
res = G_SIMPLE_ASYNC_RESULT (result);
|
res = G_SIMPLE_ASYNC_RESULT (result);
|
||||||
@ -957,12 +987,12 @@ gsecret_service_search_paths_finish (GSecretService *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gsecret_service_search_paths_sync (GSecretService *self,
|
gsecret_service_search_for_paths_sync (GSecretService *self,
|
||||||
GHashTable *attributes,
|
GHashTable *attributes,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
gchar ***unlocked,
|
gchar ***unlocked,
|
||||||
gchar ***locked,
|
gchar ***locked,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gchar **dummy = NULL;
|
gchar **dummy = NULL;
|
||||||
GVariant *response;
|
GVariant *response;
|
||||||
@ -993,3 +1023,251 @@ gsecret_service_search_paths_sync (GSecretService *self,
|
|||||||
|
|
||||||
return response != NULL;
|
return response != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_get_secrets_complete (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
GSecretParams *params = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
params->out = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
|
||||||
|
if (error != NULL)
|
||||||
|
g_simple_async_result_take_error (res, error);
|
||||||
|
g_simple_async_result_complete (res);
|
||||||
|
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_get_secrets_session (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
GSecretParams *params = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
GError *error = NULL;
|
||||||
|
const gchar *session;
|
||||||
|
|
||||||
|
session = gsecret_service_ensure_session_finish (GSECRET_SERVICE (source),
|
||||||
|
result, &error);
|
||||||
|
if (error != NULL) {
|
||||||
|
g_simple_async_result_take_error (res, error);
|
||||||
|
g_simple_async_result_complete (res);
|
||||||
|
} else {
|
||||||
|
g_dbus_proxy_call (G_DBUS_PROXY (source), "GetSecrets",
|
||||||
|
g_variant_new ("(@aoo)", params->in, session),
|
||||||
|
G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
|
||||||
|
params->cancellable, on_get_secrets_complete,
|
||||||
|
g_object_ref (res));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsecret_service_get_secret_for_path (GSecretService *self,
|
||||||
|
const gchar *object_path,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res;
|
||||||
|
GSecretParams *params;
|
||||||
|
|
||||||
|
g_return_if_fail (GSECRET_IS_SERVICE (self));
|
||||||
|
g_return_if_fail (object_path != NULL);
|
||||||
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
|
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
|
||||||
|
gsecret_service_get_secret_for_path);
|
||||||
|
|
||||||
|
params = _gsecret_params_new (cancellable, g_variant_new_objv (&object_path, 1));
|
||||||
|
g_simple_async_result_set_op_res_gpointer (res, params, _gsecret_params_free);
|
||||||
|
|
||||||
|
gsecret_service_ensure_session (self, cancellable,
|
||||||
|
on_get_secrets_session,
|
||||||
|
g_object_ref (res));
|
||||||
|
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GSecretValue *
|
||||||
|
service_decode_get_secrets_first (GSecretService *self,
|
||||||
|
GVariant *out)
|
||||||
|
{
|
||||||
|
GVariantIter *iter;
|
||||||
|
GVariant *variant;
|
||||||
|
GSecretValue *value;
|
||||||
|
const gchar *path;
|
||||||
|
|
||||||
|
g_variant_get (out, "(a{o(oayays)})", &iter);
|
||||||
|
while (g_variant_iter_next (iter, "{&o@(oayays)}", &path, &variant)) {
|
||||||
|
value = _gsecret_service_decode_secret (self, variant);
|
||||||
|
g_variant_unref (variant);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_variant_iter_free (iter);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GHashTable *
|
||||||
|
service_decode_get_secrets_all (GSecretService *self,
|
||||||
|
GVariant *out)
|
||||||
|
{
|
||||||
|
GVariantIter *iter;
|
||||||
|
GVariant *variant;
|
||||||
|
GHashTable *values;
|
||||||
|
GSecretValue *value;
|
||||||
|
gchar *path;
|
||||||
|
|
||||||
|
values = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
|
g_free, gsecret_value_unref);
|
||||||
|
g_variant_get (out, "(a{o(oayays)})", &iter);
|
||||||
|
while (g_variant_iter_loop (iter, "{o@(oayays)}", &path, &variant)) {
|
||||||
|
value = _gsecret_service_decode_secret (self, variant);
|
||||||
|
if (value && path)
|
||||||
|
g_hash_table_insert (values, g_strdup (path), value);
|
||||||
|
}
|
||||||
|
g_variant_iter_free (iter);
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
GSecretValue *
|
||||||
|
gsecret_service_get_secret_for_path_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res;
|
||||||
|
GSecretParams *params;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
|
||||||
|
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
|
||||||
|
gsecret_service_get_secret_for_path), NULL);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
|
|
||||||
|
res = G_SIMPLE_ASYNC_RESULT (result);
|
||||||
|
if (g_simple_async_result_propagate_error (res, error))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
params = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
return service_decode_get_secrets_first (self, params->out);
|
||||||
|
}
|
||||||
|
|
||||||
|
GSecretValue *
|
||||||
|
gsecret_service_get_secret_for_path_sync (GSecretService *self,
|
||||||
|
const gchar *object_path,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
const gchar *session;
|
||||||
|
GSecretValue *value;
|
||||||
|
GVariant *out;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
|
||||||
|
g_return_val_if_fail (object_path != NULL, NULL);
|
||||||
|
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
|
|
||||||
|
session = gsecret_service_ensure_session_sync (self, cancellable, error);
|
||||||
|
if (!session)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
out = g_dbus_proxy_call_sync (G_DBUS_PROXY (self), "GetSecrets",
|
||||||
|
g_variant_new ("(@aoo)",
|
||||||
|
g_variant_new_objv (&object_path, 1),
|
||||||
|
session),
|
||||||
|
G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
|
||||||
|
cancellable, error);
|
||||||
|
if (!out)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
value = service_decode_get_secrets_first (self, out);
|
||||||
|
g_variant_unref (out);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsecret_service_get_secrets_for_paths (GSecretService *self,
|
||||||
|
const gchar **object_paths,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res;
|
||||||
|
GSecretParams *params;
|
||||||
|
|
||||||
|
g_return_if_fail (GSECRET_IS_SERVICE (self));
|
||||||
|
g_return_if_fail (object_paths != NULL);
|
||||||
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
|
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
|
||||||
|
gsecret_service_get_secret_for_path);
|
||||||
|
|
||||||
|
params = _gsecret_params_new (cancellable, g_variant_new_objv (object_paths, -1));
|
||||||
|
g_simple_async_result_set_op_res_gpointer (res, params, _gsecret_params_free);
|
||||||
|
|
||||||
|
gsecret_service_ensure_session (self, cancellable,
|
||||||
|
on_get_secrets_session,
|
||||||
|
g_object_ref (res));
|
||||||
|
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
GHashTable *
|
||||||
|
gsecret_service_get_secrets_for_paths_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res;
|
||||||
|
GSecretParams *params;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
|
||||||
|
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
|
||||||
|
gsecret_service_get_secret_for_path), NULL);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
|
|
||||||
|
res = G_SIMPLE_ASYNC_RESULT (result);
|
||||||
|
if (g_simple_async_result_propagate_error (res, error))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
params = g_simple_async_result_get_op_res_gpointer (res);
|
||||||
|
return service_decode_get_secrets_all (self, params->out);
|
||||||
|
}
|
||||||
|
|
||||||
|
GHashTable *
|
||||||
|
gsecret_service_get_secrets_for_paths_sync (GSecretService *self,
|
||||||
|
const gchar **object_paths,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
const gchar *session;
|
||||||
|
GHashTable *values;
|
||||||
|
GVariant *out;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
|
||||||
|
g_return_val_if_fail (object_paths != NULL, NULL);
|
||||||
|
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
|
|
||||||
|
session = gsecret_service_ensure_session_sync (self, cancellable, error);
|
||||||
|
if (!session)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
out = g_dbus_proxy_call_sync (G_DBUS_PROXY (self), "GetSecrets",
|
||||||
|
g_variant_new ("(@aoo)",
|
||||||
|
g_variant_new_objv (object_paths, -1),
|
||||||
|
session),
|
||||||
|
G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
|
||||||
|
cancellable, error);
|
||||||
|
if (!out)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
values = service_decode_get_secrets_all (self, out);
|
||||||
|
g_variant_unref (out);
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include "gsecret-value.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define GSECRET_TYPE_SERVICE (gsecret_service_get_type ())
|
#define GSECRET_TYPE_SERVICE (gsecret_service_get_type ())
|
||||||
@ -110,24 +112,54 @@ gboolean gsecret_service_search_sync (GSecretService *se
|
|||||||
GError **error);
|
GError **error);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void gsecret_service_search_paths (GSecretService *self,
|
void gsecret_service_search_for_paths (GSecretService *self,
|
||||||
GHashTable *attributes,
|
GHashTable *attributes,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
||||||
gboolean gsecret_service_search_paths_finish (GSecretService *self,
|
gboolean gsecret_service_search_for_paths_finish (GSecretService *self,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
gchar ***unlocked,
|
gchar ***unlocked,
|
||||||
gchar ***locked,
|
gchar ***locked,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
gboolean gsecret_service_search_paths_sync (GSecretService *self,
|
gboolean gsecret_service_search_for_paths_sync (GSecretService *self,
|
||||||
GHashTable *attributes,
|
GHashTable *attributes,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
gchar ***unlocked,
|
gchar ***unlocked,
|
||||||
gchar ***locked,
|
gchar ***locked,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
void gsecret_service_get_secret_for_path (GSecretService *self,
|
||||||
|
const gchar *object_path,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
GSecretValue * gsecret_service_get_secret_for_path_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
GSecretValue * gsecret_service_get_secret_for_path_sync (GSecretService *self,
|
||||||
|
const gchar *object_path,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
void gsecret_service_get_secrets_for_paths (GSecretService *self,
|
||||||
|
const gchar **object_paths,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
GHashTable * gsecret_service_get_secrets_for_paths_finish (GSecretService *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
GHashTable * gsecret_service_get_secrets_for_paths_sync (GSecretService *self,
|
||||||
|
const gchar **object_paths,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
void gsecret_service_lock (GSecretService *self,
|
void gsecret_service_lock (GSecretService *self,
|
||||||
|
@ -31,6 +31,32 @@ gsecret_error_get_quark (void)
|
|||||||
return quark;
|
return quark;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GSecretParams *
|
||||||
|
_gsecret_params_new (GCancellable *cancellable,
|
||||||
|
GVariant *in)
|
||||||
|
{
|
||||||
|
GSecretParams *params;
|
||||||
|
|
||||||
|
params = g_slice_new0 (GSecretParams);
|
||||||
|
params->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
||||||
|
params->in = g_variant_ref_sink (in);
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gsecret_params_free (gpointer data)
|
||||||
|
{
|
||||||
|
GSecretParams *params = data;
|
||||||
|
|
||||||
|
g_clear_object (¶ms->cancellable);
|
||||||
|
if (params->in)
|
||||||
|
g_variant_unref (params->in);
|
||||||
|
if (params->out)
|
||||||
|
g_variant_unref (params->out);
|
||||||
|
g_slice_free (GSecretParams, params);
|
||||||
|
}
|
||||||
|
|
||||||
gchar *
|
gchar *
|
||||||
_gsecret_util_parent_path (const gchar *path)
|
_gsecret_util_parent_path (const gchar *path)
|
||||||
{
|
{
|
||||||
|
@ -49,7 +49,7 @@ gsecret_value_new (const gchar *secret, gssize length, const gchar *content_type
|
|||||||
{
|
{
|
||||||
gchar *copy;
|
gchar *copy;
|
||||||
|
|
||||||
g_return_val_if_fail (!secret && length, NULL);
|
g_return_val_if_fail (secret == NULL || length != 0, NULL);
|
||||||
g_return_val_if_fail (content_type, NULL);
|
g_return_val_if_fail (content_type, NULL);
|
||||||
|
|
||||||
if (length < 0)
|
if (length < 0)
|
||||||
@ -67,14 +67,15 @@ gsecret_value_new_full (gchar *secret, gssize length,
|
|||||||
{
|
{
|
||||||
GSecretValue *value;
|
GSecretValue *value;
|
||||||
|
|
||||||
g_return_val_if_fail (!secret && length, NULL);
|
g_return_val_if_fail (secret == NULL || length != 0, NULL);
|
||||||
g_return_val_if_fail (content_type, NULL);
|
g_return_val_if_fail (content_type, NULL);
|
||||||
|
|
||||||
if (length < 0)
|
if (length < 0)
|
||||||
length = strlen (secret);
|
length = strlen (secret);
|
||||||
|
|
||||||
value = g_slice_new0 (GSecretValue);
|
value = g_slice_new0 (GSecretValue);
|
||||||
value->content_type = strdup (content_type);
|
value->refs = 1;
|
||||||
|
value->content_type = g_strdup (content_type);
|
||||||
value->destroy = destroy;
|
value->destroy = destroy;
|
||||||
value->length = length;
|
value->length = length;
|
||||||
value->secret = secret;
|
value->secret = secret;
|
||||||
|
@ -3,15 +3,5 @@
|
|||||||
import mock
|
import mock
|
||||||
|
|
||||||
service = mock.SecretService()
|
service = mock.SecretService()
|
||||||
|
service.add_standard_objects()
|
||||||
collection = mock.SecretCollection(service, "collection", locked=False)
|
|
||||||
mock.SecretItem(collection, "item_one", attributes={ "number": "1", "string": "one", "parity": "odd" })
|
|
||||||
mock.SecretItem(collection, "item_two", attributes={ "number": "2", "string": "two", "parity": "even" })
|
|
||||||
mock.SecretItem(collection, "item_three", attributes={ "number": "3", "string": "three", "parity": "odd" })
|
|
||||||
|
|
||||||
collection = mock.SecretCollection(service, "second", locked=True)
|
|
||||||
mock.SecretItem(collection, "item_one", attributes={ "number": "1", "string": "one", "parity": "odd" })
|
|
||||||
mock.SecretItem(collection, "item_two", attributes={ "number": "2", "string": "two", "parity": "even" })
|
|
||||||
mock.SecretItem(collection, "item_three", attributes={ "number": "3", "string": "three", "parity": "odd" })
|
|
||||||
|
|
||||||
service.listen()
|
service.listen()
|
@ -3,5 +3,6 @@
|
|||||||
import mock
|
import mock
|
||||||
|
|
||||||
service = mock.SecretService()
|
service = mock.SecretService()
|
||||||
|
service.add_standard_objects()
|
||||||
service.algorithms = { "plain": mock.PlainAlgorithm() }
|
service.algorithms = { "plain": mock.PlainAlgorithm() }
|
||||||
service.listen()
|
service.listen()
|
@ -22,14 +22,14 @@
|
|||||||
import math
|
import math
|
||||||
import random
|
import random
|
||||||
|
|
||||||
PRIME = '\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC9\x0F\xDA\xA2\x21\x68\xC2\x34\xC4' \
|
PRIME = '\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC9\x0F\xDA\xA2\x21\x68\xC2\x34\xC4\xC6\x62\x8B\x80\xDC\x1C\xD1' \
|
||||||
'\xC6\x62\x8B\x80\xDC\x1C\xD1\x29\x02\x4E\x08\x8A\x67\xCC\x74\x02\x0B\xBE' \
|
'\x29\x02\x4E\x08\x8A\x67\xCC\x74\x02\x0B\xBE\xA6\x3B\x13\x9B\x22\x51\x4A\x08\x79\x8E\x34\x04\xDD' \
|
||||||
'\xA6\x3B\x13\x9B\x22\x51\x4A\x08\x79\x8E\x34\x04\xDD\xEF\x95\x19\xB3\xCD' \
|
'\xEF\x95\x19\xB3\xCD\x3A\x43\x1B\x30\x2B\x0A\x6D\xF2\x5F\x14\x37\x4F\xE1\x35\x6D\x6D\x51\xC2\x45' \
|
||||||
'\x3A\x43\x1B\x30\x2B\x0A\x6D\xF2\x5F\x14\x37\x4F\xE1\x35\x6D\x6D\x51\xC2' \
|
'\xE4\x85\xB5\x76\x62\x5E\x7E\xC6\xF4\x4C\x42\xE9\xA6\x37\xED\x6B\x0B\xFF\x5C\xB6\xF4\x06\xB7\xED' \
|
||||||
'\x45\xE4\x85\xB5\x76\x62\x5E\x7E\xC6\xF4\x4C\x42\xE9\xA6\x37\xED\x6B\x0B' \
|
'\xEE\x38\x6B\xFB\x5A\x89\x9F\xA5\xAE\x9F\x24\x11\x7C\x4B\x1F\xE6\x49\x28\x66\x51\xEC\xE4\x5B\x3D' \
|
||||||
'\xFF\x5C\xB6\xF4\x06\xB7\xED\xEE\x38\x6B\xFB\x5A\x89\x9F\xA5\xAE\x9F\x24' \
|
'\xC2\x00\x7C\xB8\xA1\x63\xBF\x05\x98\xDA\x48\x36\x1C\x55\xD3\x9A\x69\x16\x3F\xA8\xFD\x24\xCF\x5F' \
|
||||||
'\x11\x7C\x4B\x1F\xE6\x49\x28\x66\x51\xEC\xE6\x53\x81\xFF\xFF\xFF\xFF\xFF' \
|
'\x83\x65\x5D\x23\xDC\xA3\xAD\x96\x1C\x62\xF3\x56\x20\x85\x52\xBB\x9E\xD5\x29\x07\x70\x96\x96\x6D' \
|
||||||
'\xFF\xFF\xFF'
|
'\x67\x0C\x35\x4E\x4A\xBC\x98\x04\xF1\x74\x6C\x08\xCA\x23\x73\x27\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF'
|
||||||
|
|
||||||
def num_bits(number):
|
def num_bits(number):
|
||||||
if number == 0:
|
if number == 0:
|
||||||
@ -67,6 +67,8 @@ def number_to_bytes(number):
|
|||||||
def generate_pair():
|
def generate_pair():
|
||||||
prime = bytes_to_number (PRIME)
|
prime = bytes_to_number (PRIME)
|
||||||
base = 2
|
base = 2
|
||||||
|
# print "mock prime: ", hex(prime)
|
||||||
|
# print " mock base: ", hex(base)
|
||||||
bits = num_bits(prime)
|
bits = num_bits(prime)
|
||||||
privat = 0
|
privat = 0
|
||||||
while privat == 0:
|
while privat == 0:
|
||||||
@ -77,4 +79,5 @@ def generate_pair():
|
|||||||
def derive_key(privat, peer):
|
def derive_key(privat, peer):
|
||||||
prime = bytes_to_number (PRIME)
|
prime = bytes_to_number (PRIME)
|
||||||
key = pow(peer, privat, prime)
|
key = pow(peer, privat, prime)
|
||||||
|
# print " mock ikm2: ", hex(key)
|
||||||
return number_to_bytes(key)
|
return number_to_bytes(key)
|
||||||
|
@ -25,7 +25,10 @@ import dbus.service
|
|||||||
import dbus.glib
|
import dbus.glib
|
||||||
import gobject
|
import gobject
|
||||||
|
|
||||||
|
COLLECTION_PREFIX = "/org/freedesktop/secrets/collection/"
|
||||||
|
|
||||||
bus_name = 'org.freedesktop.Secret.MockService'
|
bus_name = 'org.freedesktop.Secret.MockService'
|
||||||
|
objects = { }
|
||||||
|
|
||||||
class NotSupported(dbus.exceptions.DBusException):
|
class NotSupported(dbus.exceptions.DBusException):
|
||||||
def __init__(self, msg):
|
def __init__(self, msg):
|
||||||
@ -35,38 +38,75 @@ class InvalidArgs(dbus.exceptions.DBusException):
|
|||||||
def __init__(self, msg):
|
def __init__(self, msg):
|
||||||
dbus.exceptions.DBusException.__init__(self, msg, name="org.freedesktop.DBus.Error.InvalidArgs")
|
dbus.exceptions.DBusException.__init__(self, msg, name="org.freedesktop.DBus.Error.InvalidArgs")
|
||||||
|
|
||||||
|
class IsLocked(dbus.exceptions.DBusException):
|
||||||
|
def __init__(self, msg):
|
||||||
|
dbus.exceptions.DBusException.__init__(self, msg, name="org.freedesktop.Secret.Error.IsLocked")
|
||||||
|
|
||||||
unique_identifier = 0
|
unique_identifier = 0
|
||||||
def next_identifier():
|
def next_identifier():
|
||||||
global unique_identifier
|
global unique_identifier
|
||||||
unique_identifier += 1
|
unique_identifier += 1
|
||||||
return unique_identifier
|
return unique_identifier
|
||||||
|
|
||||||
|
def hex_encode(string):
|
||||||
|
return "".join([hex(ord(c))[2:].zfill(2) for c in string])
|
||||||
|
|
||||||
|
|
||||||
class PlainAlgorithm():
|
class PlainAlgorithm():
|
||||||
def negotiate(self, service, sender, param):
|
def negotiate(self, service, sender, param):
|
||||||
if type (param) != dbus.String:
|
if type (param) != dbus.String:
|
||||||
raise InvalidArgs("invalid argument passed to OpenSession")
|
raise InvalidArgs("invalid argument passed to OpenSession")
|
||||||
session = SecretSession(service, sender, None)
|
session = SecretSession(service, sender, self, None)
|
||||||
return (dbus.String("", variant_level=1), session)
|
return (dbus.String("", variant_level=1), session)
|
||||||
|
|
||||||
|
def encrypt(self, key, data):
|
||||||
|
return ("", data)
|
||||||
|
|
||||||
|
|
||||||
class AesAlgorithm():
|
class AesAlgorithm():
|
||||||
def negotiate(self, service, sender, param):
|
def negotiate(self, service, sender, param):
|
||||||
if type (param) != dbus.ByteArray:
|
if type (param) != dbus.ByteArray:
|
||||||
raise InvalidArgs("invalid argument passed to OpenSession")
|
raise InvalidArgs("invalid argument passed to OpenSession")
|
||||||
publi, privat = dh.generate_pair()
|
privat, publi = dh.generate_pair()
|
||||||
peer = dh.bytes_to_number(param)
|
peer = dh.bytes_to_number(param)
|
||||||
|
# print "mock publi: ", hex(publi)
|
||||||
|
# print " mock peer: ", hex(peer)
|
||||||
ikm = dh.derive_key(privat, peer)
|
ikm = dh.derive_key(privat, peer)
|
||||||
|
# print " mock ikm: ", hex_encode(ikm)
|
||||||
key = hkdf.hkdf(ikm, 16)
|
key = hkdf.hkdf(ikm, 16)
|
||||||
session = SecretSession(service, sender, key)
|
# print " mock key: ", hex_encode(key)
|
||||||
|
session = SecretSession(service, sender, self, key)
|
||||||
return (dbus.ByteArray(dh.number_to_bytes(publi), variant_level=1), session)
|
return (dbus.ByteArray(dh.number_to_bytes(publi), variant_level=1), session)
|
||||||
|
|
||||||
|
def encrypt(self, key, data):
|
||||||
|
key = map(ord, key)
|
||||||
|
data = aes.append_PKCS7_padding(data)
|
||||||
|
keysize = len(key)
|
||||||
|
iv = [ord(i) for i in os.urandom(16)]
|
||||||
|
mode = aes.AESModeOfOperation.modeOfOperation["CBC"]
|
||||||
|
moo = aes.AESModeOfOperation()
|
||||||
|
(mode, length, ciph) = moo.encrypt(data, mode, key, keysize, iv)
|
||||||
|
return ("".join([chr(i) for i in iv]),
|
||||||
|
"".join([chr(i) for i in ciph]))
|
||||||
|
|
||||||
|
|
||||||
class SecretSession(dbus.service.Object):
|
class SecretSession(dbus.service.Object):
|
||||||
def __init__(self, service, sender, key):
|
def __init__(self, service, sender, algorithm, key):
|
||||||
self.sender = sender
|
self.sender = sender
|
||||||
self.service = service
|
self.service = service
|
||||||
|
self.algorithm = algorithm
|
||||||
self.key = key
|
self.key = key
|
||||||
self.path = "/org/freedesktop/secrets/sessions/%d" % next_identifier()
|
self.path = "/org/freedesktop/secrets/sessions/%d" % next_identifier()
|
||||||
dbus.service.Object.__init__(self, service.bus_name, self.path)
|
dbus.service.Object.__init__(self, service.bus_name, self.path)
|
||||||
service.add_session(self)
|
service.add_session(self)
|
||||||
|
objects[self.path] = self
|
||||||
|
|
||||||
|
def encode_secret(self, secret, content_type):
|
||||||
|
(params, data) = self.algorithm.encrypt(self.key, secret)
|
||||||
|
# print " mock iv: ", hex_encode(params)
|
||||||
|
# print " mock ciph: ", hex_encode(data)
|
||||||
|
return dbus.Struct((self.path, dbus.ByteArray(params), dbus.ByteArray(data),
|
||||||
|
dbus.String(content_type)), signature="oayays")
|
||||||
|
|
||||||
@dbus.service.method('org.freedesktop.Secret.Session')
|
@dbus.service.method('org.freedesktop.Secret.Session')
|
||||||
def Close(self):
|
def Close(self):
|
||||||
@ -75,15 +115,19 @@ class SecretSession(dbus.service.Object):
|
|||||||
|
|
||||||
|
|
||||||
class SecretItem(dbus.service.Object):
|
class SecretItem(dbus.service.Object):
|
||||||
def __init__(self, collection, identifier, label="Item", attributes={ }, secret=""):
|
def __init__(self, collection, identifier, label="Item", attributes={ },
|
||||||
|
secret="", content_type="text/plain"):
|
||||||
self.collection = collection
|
self.collection = collection
|
||||||
self.identifier = identifier
|
self.identifier = identifier
|
||||||
self.label = label
|
self.label = label
|
||||||
self.secret = secret
|
self.secret = secret
|
||||||
self.attributes = attributes
|
self.attributes = attributes
|
||||||
self.path = "/org/freedesktop/secrets/collection/%s/%s" % (collection.identifier, identifier)
|
self.content_type = content_type
|
||||||
|
self.locked = collection.locked
|
||||||
|
self.path = "%s/%s" % (collection.path, identifier)
|
||||||
dbus.service.Object.__init__(self, collection.service.bus_name, self.path)
|
dbus.service.Object.__init__(self, collection.service.bus_name, self.path)
|
||||||
collection.items[identifier] = self
|
collection.items[identifier] = self
|
||||||
|
objects[self.path] = self
|
||||||
|
|
||||||
def match_attributes(self, attributes):
|
def match_attributes(self, attributes):
|
||||||
for (key, value) in attributes.items():
|
for (key, value) in attributes.items():
|
||||||
@ -91,6 +135,15 @@ class SecretItem(dbus.service.Object):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@dbus.service.method('org.freedesktop.Secret.Item', sender_keyword='sender')
|
||||||
|
def GetSecret(self, session_path, sender=None):
|
||||||
|
session = objects.get(session_path, None)
|
||||||
|
if not session or session.sender != sender:
|
||||||
|
raise InvalidArgs("session invalid: %s" % session_path)
|
||||||
|
if self.locked:
|
||||||
|
raise IsLocked("secret is locked: %s" % self.path)
|
||||||
|
return session.encode_secret(self.secret, self.content_type)
|
||||||
|
|
||||||
|
|
||||||
class SecretCollection(dbus.service.Object):
|
class SecretCollection(dbus.service.Object):
|
||||||
def __init__(self, service, identifier, label="Collection", locked=False):
|
def __init__(self, service, identifier, label="Collection", locked=False):
|
||||||
@ -99,9 +152,10 @@ class SecretCollection(dbus.service.Object):
|
|||||||
self.label = label
|
self.label = label
|
||||||
self.locked = locked
|
self.locked = locked
|
||||||
self.items = { }
|
self.items = { }
|
||||||
self.path = "/org/freedesktop/secrets/collection/%s" % identifier
|
self.path = "%s%s" % (COLLECTION_PREFIX, identifier)
|
||||||
dbus.service.Object.__init__(self, service.bus_name, self.path)
|
dbus.service.Object.__init__(self, service.bus_name, self.path)
|
||||||
service.collections[identifier] = self
|
service.collections[identifier] = self
|
||||||
|
objects[self.path] = self
|
||||||
|
|
||||||
def search_items(self, attributes):
|
def search_items(self, attributes):
|
||||||
results = []
|
results = []
|
||||||
@ -136,6 +190,17 @@ class SecretService(dbus.service.Object):
|
|||||||
'NameOwnerChanged',
|
'NameOwnerChanged',
|
||||||
'org.freedesktop.DBus')
|
'org.freedesktop.DBus')
|
||||||
|
|
||||||
|
def add_standard_objects(self):
|
||||||
|
collection = SecretCollection(self, "collection", locked=False)
|
||||||
|
SecretItem(collection, "item_one", attributes={ "number": "1", "string": "one", "parity": "odd" }, secret="uno")
|
||||||
|
SecretItem(collection, "item_two", attributes={ "number": "2", "string": "two", "parity": "even" }, secret="dos")
|
||||||
|
SecretItem(collection, "item_three", attributes={ "number": "3", "string": "three", "parity": "odd" }, secret="tres")
|
||||||
|
|
||||||
|
collection = SecretCollection(self, "second", locked=True)
|
||||||
|
SecretItem(collection, "item_one", attributes={ "number": "1", "string": "one", "parity": "odd" })
|
||||||
|
SecretItem(collection, "item_two", attributes={ "number": "2", "string": "two", "parity": "even" })
|
||||||
|
SecretItem(collection, "item_three", attributes={ "number": "3", "string": "three", "parity": "odd" })
|
||||||
|
|
||||||
def listen(self):
|
def listen(self):
|
||||||
loop = gobject.MainLoop()
|
loop = gobject.MainLoop()
|
||||||
loop.run()
|
loop.run()
|
||||||
@ -148,6 +213,13 @@ class SecretService(dbus.service.Object):
|
|||||||
def remove_session(self, session):
|
def remove_session(self, session):
|
||||||
self.sessions[session.sender].remove(session)
|
self.sessions[session.sender].remove(session)
|
||||||
|
|
||||||
|
def find_item(self, object):
|
||||||
|
if object.startswith(COLLECTION_PREFIX):
|
||||||
|
parts = object[len(COLLECTION_PREFIX):].split("/", 1)
|
||||||
|
if len(parts) == 2 and parts[0] in self.collections:
|
||||||
|
return self.collections[parts[0]].get(parts[1], None)
|
||||||
|
return None
|
||||||
|
|
||||||
@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
|
||||||
@ -170,6 +242,17 @@ class SecretService(dbus.service.Object):
|
|||||||
unlocked.extend(items)
|
unlocked.extend(items)
|
||||||
return (dbus.Array(unlocked, "o"), dbus.Array(locked, "o"))
|
return (dbus.Array(unlocked, "o"), dbus.Array(locked, "o"))
|
||||||
|
|
||||||
|
@dbus.service.method('org.freedesktop.Secret.Service', sender_keyword='sender')
|
||||||
|
def GetSecrets(self, item_paths, session_path, sender=None):
|
||||||
|
session = objects.get(session_path, None)
|
||||||
|
if not session or session.sender != sender:
|
||||||
|
raise InvalidArgs("session invalid: %s" % session_path)
|
||||||
|
results = dbus.Dictionary(signature="o(oayays)")
|
||||||
|
for item_path in item_paths:
|
||||||
|
item = objects.get(item_path, None)
|
||||||
|
if item and not item.locked:
|
||||||
|
results[item_path] = item.GetSecret(session_path, sender)
|
||||||
|
return results
|
||||||
|
|
||||||
def parse_options(args):
|
def parse_options(args):
|
||||||
global bus_name
|
global bus_name
|
||||||
|
@ -57,7 +57,7 @@ static void
|
|||||||
teardown (Test *test,
|
teardown (Test *test,
|
||||||
gconstpointer unused)
|
gconstpointer unused)
|
||||||
{
|
{
|
||||||
g_clear_object (&test->service);
|
g_object_unref (test->service);
|
||||||
egg_assert_not_object (test->service);
|
egg_assert_not_object (test->service);
|
||||||
|
|
||||||
g_clear_object (&test->connection);
|
g_clear_object (&test->connection);
|
||||||
@ -129,8 +129,8 @@ test_search_paths (Test *test,
|
|||||||
attributes = g_hash_table_new (g_str_hash, g_str_equal);
|
attributes = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
g_hash_table_insert (attributes, "number", "1");
|
g_hash_table_insert (attributes, "number", "1");
|
||||||
|
|
||||||
ret = gsecret_service_search_paths_sync (test->service, attributes, NULL,
|
ret = gsecret_service_search_for_paths_sync (test->service, attributes, NULL,
|
||||||
&unlocked, &locked, &error);
|
&unlocked, &locked, &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
g_assert (ret == TRUE);
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
@ -160,14 +160,14 @@ test_search_paths_async (Test *test,
|
|||||||
attributes = g_hash_table_new (g_str_hash, g_str_equal);
|
attributes = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
g_hash_table_insert (attributes, "number", "1");
|
g_hash_table_insert (attributes, "number", "1");
|
||||||
|
|
||||||
gsecret_service_search_paths (test->service, attributes, NULL,
|
gsecret_service_search_for_paths (test->service, attributes, NULL,
|
||||||
on_complete_get_result, &result);
|
on_complete_get_result, &result);
|
||||||
egg_test_wait ();
|
egg_test_wait ();
|
||||||
|
|
||||||
g_assert (G_IS_ASYNC_RESULT (result));
|
g_assert (G_IS_ASYNC_RESULT (result));
|
||||||
ret = gsecret_service_search_paths_finish (test->service, result,
|
ret = gsecret_service_search_for_paths_finish (test->service, result,
|
||||||
&unlocked, &locked,
|
&unlocked, &locked,
|
||||||
&error);
|
&error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
g_assert (ret == TRUE);
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
@ -197,33 +197,33 @@ test_search_paths_nulls (Test *test,
|
|||||||
attributes = g_hash_table_new (g_str_hash, g_str_equal);
|
attributes = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
g_hash_table_insert (attributes, "number", "1");
|
g_hash_table_insert (attributes, "number", "1");
|
||||||
|
|
||||||
ret = gsecret_service_search_paths_sync (test->service, attributes, NULL,
|
ret = gsecret_service_search_for_paths_sync (test->service, attributes, NULL,
|
||||||
&paths, NULL, &error);
|
&paths, NULL, &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
g_assert (ret == TRUE);
|
g_assert (ret == TRUE);
|
||||||
g_assert (paths != NULL);
|
g_assert (paths != NULL);
|
||||||
g_assert_cmpstr (paths[0], ==, "/org/freedesktop/secrets/collection/collection/item_one");
|
g_assert_cmpstr (paths[0], ==, "/org/freedesktop/secrets/collection/collection/item_one");
|
||||||
g_strfreev (paths);
|
g_strfreev (paths);
|
||||||
|
|
||||||
ret = gsecret_service_search_paths_sync (test->service, attributes, NULL,
|
ret = gsecret_service_search_for_paths_sync (test->service, attributes, NULL,
|
||||||
NULL, &paths, &error);
|
NULL, &paths, &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
g_assert (ret == TRUE);
|
g_assert (ret == TRUE);
|
||||||
g_assert (paths != NULL);
|
g_assert (paths != NULL);
|
||||||
g_assert_cmpstr (paths[0], ==, "/org/freedesktop/secrets/collection/second/item_one");
|
g_assert_cmpstr (paths[0], ==, "/org/freedesktop/secrets/collection/second/item_one");
|
||||||
g_strfreev (paths);
|
g_strfreev (paths);
|
||||||
|
|
||||||
ret = gsecret_service_search_paths_sync (test->service, attributes, NULL,
|
ret = gsecret_service_search_for_paths_sync (test->service, attributes, NULL,
|
||||||
NULL, NULL, &error);
|
NULL, NULL, &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
g_assert (ret == TRUE);
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
gsecret_service_search_paths (test->service, attributes, NULL,
|
gsecret_service_search_for_paths (test->service, attributes, NULL,
|
||||||
on_complete_get_result, &result);
|
on_complete_get_result, &result);
|
||||||
egg_test_wait ();
|
egg_test_wait ();
|
||||||
g_assert (G_IS_ASYNC_RESULT (result));
|
g_assert (G_IS_ASYNC_RESULT (result));
|
||||||
ret = gsecret_service_search_paths_finish (test->service, result,
|
ret = gsecret_service_search_for_paths_finish (test->service, result,
|
||||||
&paths, NULL, &error);
|
&paths, NULL, &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
g_assert (ret == TRUE);
|
g_assert (ret == TRUE);
|
||||||
g_assert (paths != NULL);
|
g_assert (paths != NULL);
|
||||||
@ -231,12 +231,12 @@ test_search_paths_nulls (Test *test,
|
|||||||
g_strfreev (paths);
|
g_strfreev (paths);
|
||||||
g_clear_object (&result);
|
g_clear_object (&result);
|
||||||
|
|
||||||
gsecret_service_search_paths (test->service, attributes, NULL,
|
gsecret_service_search_for_paths (test->service, attributes, NULL,
|
||||||
on_complete_get_result, &result);
|
on_complete_get_result, &result);
|
||||||
egg_test_wait ();
|
egg_test_wait ();
|
||||||
g_assert (G_IS_ASYNC_RESULT (result));
|
g_assert (G_IS_ASYNC_RESULT (result));
|
||||||
ret = gsecret_service_search_paths_finish (test->service, result,
|
ret = gsecret_service_search_for_paths_finish (test->service, result,
|
||||||
NULL, &paths, &error);
|
NULL, &paths, &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
g_assert (ret == TRUE);
|
g_assert (ret == TRUE);
|
||||||
g_assert (paths != NULL);
|
g_assert (paths != NULL);
|
||||||
@ -244,12 +244,12 @@ test_search_paths_nulls (Test *test,
|
|||||||
g_strfreev (paths);
|
g_strfreev (paths);
|
||||||
g_clear_object (&result);
|
g_clear_object (&result);
|
||||||
|
|
||||||
gsecret_service_search_paths (test->service, attributes, NULL,
|
gsecret_service_search_for_paths (test->service, attributes, NULL,
|
||||||
on_complete_get_result, &result);
|
on_complete_get_result, &result);
|
||||||
egg_test_wait ();
|
egg_test_wait ();
|
||||||
g_assert (G_IS_ASYNC_RESULT (result));
|
g_assert (G_IS_ASYNC_RESULT (result));
|
||||||
ret = gsecret_service_search_paths_finish (test->service, result,
|
ret = gsecret_service_search_for_paths_finish (test->service, result,
|
||||||
NULL, NULL, &error);
|
NULL, NULL, &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
g_assert (ret == TRUE);
|
g_assert (ret == TRUE);
|
||||||
g_clear_object (&result);
|
g_clear_object (&result);
|
||||||
@ -257,6 +257,154 @@ test_search_paths_nulls (Test *test,
|
|||||||
g_hash_table_unref (attributes);
|
g_hash_table_unref (attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_secret_for_path (Test *test,
|
||||||
|
gconstpointer used)
|
||||||
|
{
|
||||||
|
GSecretValue *value;
|
||||||
|
GError *error = NULL;
|
||||||
|
const gchar *path;
|
||||||
|
const gchar *password;
|
||||||
|
gsize length;
|
||||||
|
|
||||||
|
path = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
value = gsecret_service_get_secret_for_path_sync (test->service, path, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (value != NULL);
|
||||||
|
|
||||||
|
password = gsecret_value_get (value, &length);
|
||||||
|
g_assert_cmpuint (length, ==, 3);
|
||||||
|
g_assert_cmpstr (password, ==, "uno");
|
||||||
|
|
||||||
|
password = gsecret_value_get (value, NULL);
|
||||||
|
g_assert_cmpstr (password, ==, "uno");
|
||||||
|
|
||||||
|
gsecret_value_unref (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_secret_for_path_async (Test *test,
|
||||||
|
gconstpointer used)
|
||||||
|
{
|
||||||
|
GSecretValue *value;
|
||||||
|
GError *error = NULL;
|
||||||
|
const gchar *path;
|
||||||
|
const gchar *password;
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
gsize length;
|
||||||
|
|
||||||
|
path = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
gsecret_service_get_secret_for_path (test->service, path, NULL,
|
||||||
|
on_complete_get_result, &result);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
value = gsecret_service_get_secret_for_path_finish (test->service, result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (value != NULL);
|
||||||
|
g_object_unref (result);
|
||||||
|
|
||||||
|
password = gsecret_value_get (value, &length);
|
||||||
|
g_assert_cmpuint (length, ==, 3);
|
||||||
|
g_assert_cmpstr (password, ==, "uno");
|
||||||
|
|
||||||
|
password = gsecret_value_get (value, NULL);
|
||||||
|
g_assert_cmpstr (password, ==, "uno");
|
||||||
|
|
||||||
|
gsecret_value_unref (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_secrets_for_paths (Test *test,
|
||||||
|
gconstpointer used)
|
||||||
|
{
|
||||||
|
const gchar *path_item_one = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
const gchar *path_item_two = "/org/freedesktop/secrets/collection/collection/item_two";
|
||||||
|
const gchar *paths[] = {
|
||||||
|
path_item_one,
|
||||||
|
path_item_two,
|
||||||
|
|
||||||
|
/* This one is locked, and not returned */
|
||||||
|
"/org/freedesktop/secrets/collection/second/item_one",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
GSecretValue *value;
|
||||||
|
GHashTable *values;
|
||||||
|
GError *error = NULL;
|
||||||
|
const gchar *password;
|
||||||
|
gsize length;
|
||||||
|
|
||||||
|
values = gsecret_service_get_secrets_for_paths_sync (test->service, paths, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
g_assert (values != NULL);
|
||||||
|
g_assert_cmpuint (g_hash_table_size (values), ==, 2);
|
||||||
|
|
||||||
|
value = g_hash_table_lookup (values, path_item_one);
|
||||||
|
g_assert (value != NULL);
|
||||||
|
password = gsecret_value_get (value, &length);
|
||||||
|
g_assert_cmpuint (length, ==, 3);
|
||||||
|
g_assert_cmpstr (password, ==, "uno");
|
||||||
|
|
||||||
|
value = g_hash_table_lookup (values, path_item_two);
|
||||||
|
g_assert (value != NULL);
|
||||||
|
password = gsecret_value_get (value, &length);
|
||||||
|
g_assert_cmpuint (length, ==, 3);
|
||||||
|
g_assert_cmpstr (password, ==, "dos");
|
||||||
|
|
||||||
|
g_hash_table_unref (values);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_secrets_for_paths_async (Test *test,
|
||||||
|
gconstpointer used)
|
||||||
|
{
|
||||||
|
const gchar *path_item_one = "/org/freedesktop/secrets/collection/collection/item_one";
|
||||||
|
const gchar *path_item_two = "/org/freedesktop/secrets/collection/collection/item_two";
|
||||||
|
const gchar *paths[] = {
|
||||||
|
path_item_one,
|
||||||
|
path_item_two,
|
||||||
|
|
||||||
|
/* This one is locked, and not returned */
|
||||||
|
"/org/freedesktop/secrets/collection/second/item_one",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
GSecretValue *value;
|
||||||
|
GHashTable *values;
|
||||||
|
GError *error = NULL;
|
||||||
|
const gchar *password;
|
||||||
|
GAsyncResult *result = NULL;
|
||||||
|
gsize length;
|
||||||
|
|
||||||
|
gsecret_service_get_secrets_for_paths (test->service, paths, NULL,
|
||||||
|
on_complete_get_result, &result);
|
||||||
|
g_assert (result == NULL);
|
||||||
|
egg_test_wait ();
|
||||||
|
|
||||||
|
values = gsecret_service_get_secrets_for_paths_finish (test->service, result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_object_unref (result);
|
||||||
|
|
||||||
|
g_assert (values != NULL);
|
||||||
|
g_assert_cmpuint (g_hash_table_size (values), ==, 2);
|
||||||
|
|
||||||
|
value = g_hash_table_lookup (values, path_item_one);
|
||||||
|
g_assert (value != NULL);
|
||||||
|
password = gsecret_value_get (value, &length);
|
||||||
|
g_assert_cmpuint (length, ==, 3);
|
||||||
|
g_assert_cmpstr (password, ==, "uno");
|
||||||
|
|
||||||
|
value = g_hash_table_lookup (values, path_item_two);
|
||||||
|
g_assert (value != NULL);
|
||||||
|
password = gsecret_value_get (value, &length);
|
||||||
|
g_assert_cmpuint (length, ==, 3);
|
||||||
|
g_assert_cmpstr (password, ==, "dos");
|
||||||
|
|
||||||
|
g_hash_table_unref (values);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -265,9 +413,14 @@ main (int argc, char **argv)
|
|||||||
g_type_init ();
|
g_type_init ();
|
||||||
|
|
||||||
g_test_add_func ("/service/instance", test_instance);
|
g_test_add_func ("/service/instance", test_instance);
|
||||||
g_test_add ("/service/search-paths", Test, "mock-service-normal.py", setup, test_search_paths, teardown);
|
g_test_add ("/service/search-for-paths", Test, "mock-service-normal.py", setup, test_search_paths, teardown);
|
||||||
g_test_add ("/service/search-paths-async", Test, "mock-service-normal.py", setup, test_search_paths_async, teardown);
|
g_test_add ("/service/search-for-paths-async", Test, "mock-service-normal.py", setup, test_search_paths_async, teardown);
|
||||||
g_test_add ("/service/search-paths-nulls", Test, "mock-service-normal.py", setup, test_search_paths_nulls, teardown);
|
g_test_add ("/service/search-for-paths-nulls", Test, "mock-service-normal.py", setup, test_search_paths_nulls, teardown);
|
||||||
|
g_test_add ("/service/secret-for-path", Test, "mock-service-normal.py", setup, test_secret_for_path, teardown);
|
||||||
|
g_test_add ("/service/secret-for-path-plain", Test, "mock-service-only-plain.py", setup, test_secret_for_path, teardown);
|
||||||
|
g_test_add ("/service/secret-for-path-async", Test, "mock-service-normal.py", setup, test_secret_for_path_async, teardown);
|
||||||
|
g_test_add ("/service/secrets-for-paths", Test, "mock-service-normal.py", setup, test_secrets_for_paths, teardown);
|
||||||
|
g_test_add ("/service/secrets-for-paths-async", Test, "mock-service-normal.py", setup, test_secrets_for_paths_async, teardown);
|
||||||
|
|
||||||
return egg_tests_run_with_loop ();
|
return egg_tests_run_with_loop ();
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,8 @@ teardown (Test *test,
|
|||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
g_clear_object (&test->service);
|
g_object_unref (test->service);
|
||||||
|
egg_assert_not_object (test->service);
|
||||||
|
|
||||||
g_assert (test->pid);
|
g_assert (test->pid);
|
||||||
if (kill (test->pid, SIGTERM) < 0)
|
if (kill (test->pid, SIGTERM) < 0)
|
||||||
@ -69,7 +70,7 @@ teardown (Test *test,
|
|||||||
|
|
||||||
g_dbus_connection_flush_sync (test->connection, NULL, &error);
|
g_dbus_connection_flush_sync (test->connection, NULL, &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
g_clear_object (&test->connection);
|
g_object_unref (test->connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user