Update the mock service to more closely mirror real secret service

This commit is contained in:
Stef Walter 2012-01-31 20:20:31 +01:00
parent 075ca76cc0
commit 3a6cfa697f
16 changed files with 454 additions and 209 deletions

View File

@ -789,6 +789,23 @@ gsecret_collection_create_finish (GAsyncResult *result,
return g_object_ref (closure->collection); return g_object_ref (closure->collection);
} }
/**
* gsecret_collection_create_sync:
* @service: a secret service object
* @label: label for the new collection
* @alias: (allow-none): alias to assign to the collection
* @cancellable: optional cancellation object
* @error: location to place an error on failure
*
* Create a new collection.
* Delete this collection.
*
* This method may block indefinitely. The secret service may prompt the
* user. gsecret_service_prompt() will be used to handle any prompts that
* show up.
*
* Returns: whether the item was successfully deleted or not
*/
GSecretCollection * GSecretCollection *
gsecret_collection_create_sync (GSecretService *service, gsecret_collection_create_sync (GSecretService *service,
const gchar *label, const gchar *label,
@ -821,6 +838,21 @@ gsecret_collection_create_sync (GSecretService *service,
return collection; return collection;
} }
/**
* gsecret_collection_delete:
* @self: a collection
* @cancellable: optional cancellation object
* @callback: called when the operation completes
* @user_data: data to pass to the callback
*
* Delete this collection.
*
* This method returns immediately and completes asynchronously. The secret
* service may prompt the user. gsecret_service_prompt() will be used to handle
* any prompts that show up.
*
* Returns: whether the item was successfully deleted or not
*/
void void
gsecret_collection_delete (GSecretCollection *self, gsecret_collection_delete (GSecretCollection *self,
GCancellable *cancellable, GCancellable *cancellable,
@ -837,6 +869,16 @@ gsecret_collection_delete (GSecretCollection *self,
cancellable, callback, user_data); cancellable, callback, user_data);
} }
/**
* gsecret_collection_delete_finish:
* @self: a collection
* @result: asynchronous result passed to the callback
* @error: location to place an error on failure
*
* Complete operation to delete this collection.
*
* Returns: whether the item was successfully deleted or not
*/
gboolean gboolean
gsecret_collection_delete_finish (GSecretCollection *self, gsecret_collection_delete_finish (GSecretCollection *self,
GAsyncResult *result, GAsyncResult *result,
@ -848,6 +890,20 @@ gsecret_collection_delete_finish (GSecretCollection *self,
return gsecret_service_delete_path_finish (self->pv->service, result, error); return gsecret_service_delete_path_finish (self->pv->service, result, error);
} }
/**
* gsecret_collection_delete_sync:
* @self: a collection
* @cancellable: optional cancellation object
* @error: location to place an error on failure
*
* Delete this collection.
*
* This method may block indefinitely. The secret service may prompt the
* user. gsecret_service_prompt() will be used to handle any prompts that
* show up.
*
* Returns: whether the item was successfully deleted or not
*/
gboolean gboolean
gsecret_collection_delete_sync (GSecretCollection *self, gsecret_collection_delete_sync (GSecretCollection *self,
GCancellable *cancellable, GCancellable *cancellable,
@ -875,6 +931,16 @@ gsecret_collection_delete_sync (GSecretCollection *self,
return ret; return ret;
} }
/**
* gsecret_collection_get_items:
* @self: a collection
*
* Get the list of items in this collection.
*
* Returns: (transfer full) (element-type GSecret.Item): a list of items,
* when done, the list should be freed with g_list_free, and each item should
* be released with g_object_unref()
*/
GList * GList *
gsecret_collection_get_items (GSecretCollection *self) gsecret_collection_get_items (GSecretCollection *self)
{ {
@ -906,6 +972,14 @@ _gsecret_collection_find_item_instance (GSecretCollection *self,
return item; return item;
} }
/**
* gsecret_collection_get_label:
* @self: a collection
*
* Get the label of this collection.
*
* Returns: (transfer full): the label, which should be freed with g_free()
*/
gchar * gchar *
gsecret_collection_get_label (GSecretCollection *self) gsecret_collection_get_label (GSecretCollection *self)
{ {
@ -923,6 +997,18 @@ gsecret_collection_get_label (GSecretCollection *self)
return label; return label;
} }
/**
* gsecret_collection_set_label:
* @self: a collection
* @label: a new label
* @cancellable: optional cancellation object
* @callback: called when the operation completes
* @user_data: data to pass to the callback
*
* Set the label of this collection.
*
* This function returns immediately and completes asynchronously.
*/
void void
gsecret_collection_set_label (GSecretCollection *self, gsecret_collection_set_label (GSecretCollection *self,
const gchar *label, const gchar *label,
@ -939,6 +1025,16 @@ gsecret_collection_set_label (GSecretCollection *self,
cancellable, callback, user_data); cancellable, callback, user_data);
} }
/**
* gsecret_collection_set_label_finish:
* @self: a collection
* @result: asynchronous result passed to callback
* @error: location to place error on failure
*
* Complete asynchronous operation to set the label of this collection.
*
* Returns: whether the change was successful or not
*/
gboolean gboolean
gsecret_collection_set_label_finish (GSecretCollection *self, gsecret_collection_set_label_finish (GSecretCollection *self,
GAsyncResult *result, GAsyncResult *result,
@ -951,6 +1047,20 @@ gsecret_collection_set_label_finish (GSecretCollection *self,
result, error); result, error);
} }
/**
* gsecret_collection_set_label_sync:
* @self: a collection
* @label: a new label
* @cancellable: optional cancellation object
* @error: location to place error on failure
*
* Set the label of this collection.
*
* This function may block indefinetely. Use the asynchronous version
* in user interface threads.
*
* Returns: whether the change was successful or not
*/
gboolean gboolean
gsecret_collection_set_label_sync (GSecretCollection *self, gsecret_collection_set_label_sync (GSecretCollection *self,
const gchar *label, const gchar *label,
@ -965,6 +1075,14 @@ gsecret_collection_set_label_sync (GSecretCollection *self,
cancellable, error); cancellable, error);
} }
/**
* gsecret_collection_get_locked:
* @self: a collection
*
* Get whether the collection is locked or not.
*
* Returns: whether the collection is locked or not
*/
gboolean gboolean
gsecret_collection_get_locked (GSecretCollection *self) gsecret_collection_get_locked (GSecretCollection *self)
{ {
@ -982,6 +1100,15 @@ gsecret_collection_get_locked (GSecretCollection *self)
return locked; return locked;
} }
/**
* gsecret_collection_get_created:
* @self: a collection
*
* Get the created date and time of the collection. The return value is
* the number of seconds since the unix epoch, January 1st 1970.
*
* Returns: the created date and time
*/
guint64 guint64
gsecret_collection_get_created (GSecretCollection *self) gsecret_collection_get_created (GSecretCollection *self)
{ {
@ -999,6 +1126,15 @@ gsecret_collection_get_created (GSecretCollection *self)
return created; return created;
} }
/**
* gsecret_collection_get_modified:
* @self: a collection
*
* Get the modified date and time of the collection. The return value is
* the number of seconds since the unix epoch, January 1st 1970.
*
* Returns: the modified date and time
*/
guint64 guint64
gsecret_collection_get_modified (GSecretCollection *self) gsecret_collection_get_modified (GSecretCollection *self)
{ {

View File

@ -195,7 +195,7 @@ handle_property_changed (GObject *object,
else if (g_str_equal (property_name, "Label")) else if (g_str_equal (property_name, "Label"))
g_object_notify (object, "label"); g_object_notify (object, "label");
else if (g_str_equal (property_name, "Schema")) else if (g_str_equal (property_name, "Type"))
g_object_notify (object, "schema"); g_object_notify (object, "schema");
else if (g_str_equal (property_name, "Locked")) else if (g_str_equal (property_name, "Locked"))
@ -1084,8 +1084,9 @@ gsecret_item_get_schema (GSecretItem *self)
g_return_val_if_fail (GSECRET_IS_ITEM (self), NULL); g_return_val_if_fail (GSECRET_IS_ITEM (self), NULL);
variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Schema"); variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Type");
g_return_val_if_fail (variant != NULL, NULL); if (variant == NULL)
return NULL;
label = g_variant_dup_string (variant, NULL); label = g_variant_dup_string (variant, NULL);
g_variant_unref (variant); g_variant_unref (variant);

View File

@ -312,6 +312,8 @@ on_prompt_dismissed (GObject *source,
g_variant_unref (retval); g_variant_unref (retval);
if (closure->vanished) if (closure->vanished)
g_clear_error (&error); g_clear_error (&error);
if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD))
g_clear_error (&error);
if (error != NULL) { if (error != NULL) {
g_simple_async_result_take_error (res, error); g_simple_async_result_take_error (res, error);

View File

@ -77,7 +77,7 @@ 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-1536", if (!egg_dh_default_params ("ietf-ike-grp-modp-1024",
&session->prime, &base)) &session->prime, &base))
g_return_val_if_reached (NULL); g_return_val_if_reached (NULL);

View File

@ -119,7 +119,7 @@
<property name="Modified" type="t" access="read"/> <property name="Modified" type="t" access="read"/>
<property name="Schema" type="s" access="read"/> <property name="Type" type="s" access="read"/>
<method name="Delete"> <method name="Delete">
<arg name="Prompt" type="o" direction="out"/> <arg name="Prompt" type="o" direction="out"/>

View File

@ -7,11 +7,11 @@ import sys
service = mock.SecretService() service = mock.SecretService()
service.add_standard_objects() service.add_standard_objects()
collection = mock.SecretCollection(service, "to_delete", locked=False) collection = mock.SecretCollection(service, "todelete", locked=False)
mock.SecretItem(collection, "item", attributes={ "number": "1", "string": "one", "even": "false" }, secret="uno") mock.SecretItem(collection, "item", attributes={ "number": "1", "string": "one", "even": "false" }, secret="uno")
mock.SecretItem(collection, "confirm", attributes={ "number": "2", "string": "two", "even": "true" }, secret="dos", confirm=True) mock.SecretItem(collection, "confirm", attributes={ "number": "2", "string": "two", "even": "true" }, secret="dos", confirm=True)
collection = mock.SecretCollection(service, "two_delete", locked=True) collection = mock.SecretCollection(service, "twodelete", locked=True)
mock.SecretItem(collection, "locked", attributes={ "number": "3", "string": "three", "even": "false" }, secret="tres") mock.SecretItem(collection, "locked", attributes={ "number": "3", "string": "three", "even": "false" }, secret="tres")
service.listen() service.listen()

View File

@ -7,11 +7,11 @@ import sys
service = mock.SecretService() service = mock.SecretService()
service.add_standard_objects() service.add_standard_objects()
collection = mock.SecretCollection(service, "lock_one", locked=False, confirm=False) collection = mock.SecretCollection(service, "lockone", locked=False, confirm=False)
mock.SecretItem(collection, "item", attributes={ "number": "1", "string": "one", "even": "false" }, secret="uno") mock.SecretItem(collection, "item", attributes={ "number": "1", "string": "one", "even": "false" }, secret="uno")
mock.SecretItem(collection, "confirm", attributes={ "number": "2", "string": "two", "even": "true" }, secret="dos", confirm=True) mock.SecretItem(collection, "confirm", attributes={ "number": "2", "string": "two", "even": "true" }, secret="dos", confirm=True)
collection = mock.SecretCollection(service, "lock_prompt", locked=True, confirm=True) collection = mock.SecretCollection(service, "lockprompt", locked=True, confirm=True)
mock.SecretItem(collection, "locked", attributes={ "number": "3", "string": "three", "even": "false" }, secret="tres") mock.SecretItem(collection, "locked", attributes={ "number": "3", "string": "three", "even": "false" }, secret="tres")
service.listen() service.listen()

View File

@ -33,7 +33,7 @@ service = mock.SecretService()
service.add_standard_objects() service.add_standard_objects()
mock.SecretPrompt(service, None, "simple") mock.SecretPrompt(service, None, "simple")
mock.SecretPrompt(service, None, "delay", delay=0.5) mock.SecretPrompt(service, None, "delay", delay=0.1)
def prompt_callback(): def prompt_callback():
return dbus.String("Special Result", variant_level=1) return dbus.String("Special Result", variant_level=1)
mock.SecretPrompt(service, None, "result", action=prompt_callback) mock.SecretPrompt(service, None, "result", action=prompt_callback)

View File

@ -634,9 +634,9 @@ def decryptData(key, data, mode=AESModeOfOperation.modeOfOperation["CBC"]):
def generateRandomKey(keysize): def generateRandomKey(keysize):
"""Generates a key from random data of length `keysize`. """Generates a key from random data of length `keysize`.
The returned key is a string of bytes. The returned key is a string of bytes.
""" """
if keysize not in (16, 24, 32): if keysize not in (16, 24, 32):
emsg = 'Invalid keysize, %s. Should be one of (16, 24, 32).' emsg = 'Invalid keysize, %s. Should be one of (16, 24, 32).'

View File

@ -17,7 +17,7 @@
# Some utility functions from tlslite which is public domain # Some utility functions from tlslite which is public domain
# Written by Trevor Perrin <trevp at trevp.net> # Written by Trevor Perrin <trevp at trevp.net>
# http://trevp.net/tlslite/ # http://trevp.net/tlslite/
# #
import math import math
import random import random
@ -26,10 +26,8 @@ PRIME = '\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC9\x0F\xDA\xA2\x21\x68\xC2\x34\xC4\xC
'\x29\x02\x4E\x08\x8A\x67\xCC\x74\x02\x0B\xBE\xA6\x3B\x13\x9B\x22\x51\x4A\x08\x79\x8E\x34\x04\xDD' \ '\x29\x02\x4E\x08\x8A\x67\xCC\x74\x02\x0B\xBE\xA6\x3B\x13\x9B\x22\x51\x4A\x08\x79\x8E\x34\x04\xDD' \
'\xEF\x95\x19\xB3\xCD\x3A\x43\x1B\x30\x2B\x0A\x6D\xF2\x5F\x14\x37\x4F\xE1\x35\x6D\x6D\x51\xC2\x45' \ '\xEF\x95\x19\xB3\xCD\x3A\x43\x1B\x30\x2B\x0A\x6D\xF2\x5F\x14\x37\x4F\xE1\x35\x6D\x6D\x51\xC2\x45' \
'\xE4\x85\xB5\x76\x62\x5E\x7E\xC6\xF4\x4C\x42\xE9\xA6\x37\xED\x6B\x0B\xFF\x5C\xB6\xF4\x06\xB7\xED' \ '\xE4\x85\xB5\x76\x62\x5E\x7E\xC6\xF4\x4C\x42\xE9\xA6\x37\xED\x6B\x0B\xFF\x5C\xB6\xF4\x06\xB7\xED' \
'\xEE\x38\x6B\xFB\x5A\x89\x9F\xA5\xAE\x9F\x24\x11\x7C\x4B\x1F\xE6\x49\x28\x66\x51\xEC\xE4\x5B\x3D' \ '\xEE\x38\x6B\xFB\x5A\x89\x9F\xA5\xAE\x9F\x24\x11\x7C\x4B\x1F\xE6\x49\x28\x66\x51\xEC\xE6\x53\x81' \
'\xC2\x00\x7C\xB8\xA1\x63\xBF\x05\x98\xDA\x48\x36\x1C\x55\xD3\x9A\x69\x16\x3F\xA8\xFD\x24\xCF\x5F' \ '\xFF\xFF\xFF\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' \
'\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:

View File

@ -1,86 +1,86 @@
# Upstream Author: Zooko O'Whielacronx <zooko@zooko.com> # Upstream Author: Zooko O'Whielacronx <zooko@zooko.com>
# #
# Copyright: # Copyright:
# #
# You may use this package under the GNU General Public License, version # You may use this package under the GNU General Public License, version
# 2 or, at your option, any later version. You may use this package # 2 or, at your option, any later version. You may use this package
# under the Transitive Grace Period Public Licence, version 1.0 or, at # under the Transitive Grace Period Public Licence, version 1.0 or, at
# your option, any later version. (You may choose to use this package # your option, any later version. (You may choose to use this package
# under the terms of either licence, at your option.) See the file # under the terms of either licence, at your option.) See the file
# COPYING.GPL for the terms of the GNU General Public License, version 2. # COPYING.GPL for the terms of the GNU General Public License, version 2.
# See the file COPYING.TGPPL.html for the terms of the Transitive Grace # See the file COPYING.TGPPL.html for the terms of the Transitive Grace
# Period Public Licence, version 1.0. # Period Public Licence, version 1.0.
# #
# The following licensing text applies to a subset of the Crypto++ source code # The following licensing text applies to a subset of the Crypto++ source code
# which is included in the pycryptopp source tree under the "embeddedcryptopp" # which is included in the pycryptopp source tree under the "embeddedcryptopp"
# subdirectory. That embedded subset of the Crypto++ source code is not used # subdirectory. That embedded subset of the Crypto++ source code is not used
# when pycryptopp is built for Debian -- instead the --disable-embedded-cryptopp # when pycryptopp is built for Debian -- instead the --disable-embedded-cryptopp
# option to "setup.py build" is used to for pycryptopp to build against the # option to "setup.py build" is used to for pycryptopp to build against the
# system libcryptopp. # system libcryptopp.
import hashlib, hmac import hashlib, hmac
import math import math
from binascii import a2b_hex, b2a_hex from binascii import a2b_hex, b2a_hex
class HKDF(object): class HKDF(object):
def __init__(self, ikm, L, salt=None, info="", digestmod = None): def __init__(self, ikm, L, salt=None, info="", digestmod = None):
self.ikm = ikm self.ikm = ikm
self.keylen = L self.keylen = L
if digestmod is None: if digestmod is None:
digestmod = hashlib.sha256 digestmod = hashlib.sha256
if callable(digestmod): if callable(digestmod):
self.digest_cons = digestmod self.digest_cons = digestmod
else: else:
self.digest_cons = lambda d='':digestmod.new(d) self.digest_cons = lambda d='':digestmod.new(d)
self.hashlen = len(self.digest_cons().digest()) self.hashlen = len(self.digest_cons().digest())
if salt is None: if salt is None:
self.salt = chr(0)*(self.hashlen) self.salt = chr(0)*(self.hashlen)
else: else:
self.salt = salt self.salt = salt
self.info = info self.info = info
#extract PRK #extract PRK
def extract(self): def extract(self):
h = hmac.new(self.salt, self.ikm, self.digest_cons) h = hmac.new(self.salt, self.ikm, self.digest_cons)
self.prk = h.digest() self.prk = h.digest()
return self.prk return self.prk
#expand PRK #expand PRK
def expand(self): def expand(self):
N = math.ceil(float(self.keylen)/self.hashlen) N = math.ceil(float(self.keylen)/self.hashlen)
T = "" T = ""
temp = "" temp = ""
i=0x01 i=0x01
'''while len(T)<2*self.keylen : '''while len(T)<2*self.keylen :
msg = temp msg = temp
msg += self.info msg += self.info
msg += b2a_hex(chr(i)) msg += b2a_hex(chr(i))
h = hmac.new(self.prk, a2b_hex(msg), self.digest_cons) h = hmac.new(self.prk, a2b_hex(msg), self.digest_cons)
temp = b2a_hex(h.digest()) temp = b2a_hex(h.digest())
i += 1 i += 1
T += temp T += temp
''' '''
while len(T)<self.keylen : while len(T)<self.keylen :
msg = temp msg = temp
msg += self.info msg += self.info
msg += chr(i) msg += chr(i)
h = hmac.new(self.prk, msg, self.digest_cons) h = hmac.new(self.prk, msg, self.digest_cons)
temp = h.digest() temp = h.digest()
i += 1 i += 1
T += temp T += temp
self.okm = T[0:self.keylen] self.okm = T[0:self.keylen]
return self.okm return self.okm
def new(ikm, L, salt=None, info="", digestmod = None): def new(ikm, L, salt=None, info="", digestmod = None):
return HKDF(ikm, L,salt,info,digestmod) return HKDF(ikm, L,salt,info,digestmod)
def hkdf(ikm, length, salt=None, info=""): def hkdf(ikm, length, salt=None, info=""):
hk = HKDF(ikm, length ,salt,info) hk = HKDF(ikm, length ,salt,info)
computedprk = hk.extract() computedprk = hk.extract()
return hk.expand() return hk.expand()

View File

@ -44,15 +44,26 @@ class IsLocked(dbus.exceptions.DBusException):
def __init__(self, msg): def __init__(self, msg):
dbus.exceptions.DBusException.__init__(self, msg, name="org.freedesktop.Secret.Error.IsLocked") dbus.exceptions.DBusException.__init__(self, msg, name="org.freedesktop.Secret.Error.IsLocked")
unique_identifier = 0 class NoSuchObject(dbus.exceptions.DBusException):
def next_identifier(prefix='x'): def __init__(self, msg):
dbus.exceptions.DBusException.__init__(self, msg, name="org.freedesktop.Secret.Error.NoSuchObject")
unique_identifier = 111
def next_identifier(prefix=''):
global unique_identifier global unique_identifier
unique_identifier += 1 unique_identifier += 1
return "%s%d" % (prefix, unique_identifier) return "%s%d" % (prefix, unique_identifier)
def encode_identifier(value):
return "".join([(c.isalpha() or c.isdigit()) and c or "_%02x" % ord(c) \
for c in value.encode('utf-8')])
def hex_encode(string): def hex_encode(string):
return "".join([hex(ord(c))[2:].zfill(2) for c in string]) return "".join([hex(ord(c))[2:].zfill(2) for c in string])
def alias_path(name):
return "/org/freedesktop/secrets/aliases/%s" % name
class PlainAlgorithm(): class PlainAlgorithm():
def negotiate(self, service, sender, param): def negotiate(self, service, sender, param):
@ -178,23 +189,37 @@ class SecretSession(dbus.service.Object):
class SecretItem(dbus.service.Object): class SecretItem(dbus.service.Object):
def __init__(self, collection, identifier, label="Item", attributes={ }, SUPPORTS_MULTIPLE_OBJECT_PATHS = True
secret="", confirm=False, content_type="text/plain",
schema="org.freedesktop.Secret.Generic"): def __init__(self, collection, identifier=None, label="Item", attributes={ },
secret="", confirm=False, content_type="text/plain", type=None):
if identifier is None:
identifier = next_identifier()
identifier = encode_identifier(identifier)
self.collection = collection self.collection = collection
self.identifier = identifier self.identifier = identifier
self.label = label or "Unnamed item" self.label = label or "Unnamed item"
self.secret = secret self.secret = secret
self.schema = schema self.type = type or "org.freedesktop.Secret.Generic"
self.attributes = attributes self.attributes = attributes
self.content_type = content_type self.content_type = content_type
self.path = "%s/%s" % (collection.path, identifier) self.path = "%s/%s" % (collection.path, identifier)
self.confirm = confirm self.confirm = confirm
self.created = self.modified = time.time() self.created = self.modified = time.time()
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 self.collection.add_item(self)
objects[self.path] = self objects[self.path] = self
def add_alias(self, name):
path = "%s/%s" % (alias_path(name), self.identifier)
objects[path] = self
self.add_to_connection(self.connection, path)
def remove_alias(self, name):
path = "%s/%s" % (alias_path(name), self.identifier)
del objects[path]
self.remove_from_connection(self.connection, path)
def match_attributes(self, attributes): def match_attributes(self, attributes):
for (key, value) in attributes.items(): for (key, value) in attributes.items():
if not self.attributes.get(key) == value: if not self.attributes.get(key) == value:
@ -208,7 +233,7 @@ class SecretItem(dbus.service.Object):
return self.collection.perform_xlock(lock) return self.collection.perform_xlock(lock)
def perform_delete(self): def perform_delete(self):
del self.collection.items[self.identifier] self.collection.remove_item(self)
del objects[self.path] del objects[self.path]
self.remove_from_connection() self.remove_from_connection()
@ -216,7 +241,7 @@ class SecretItem(dbus.service.Object):
def GetSecret(self, session_path, sender=None): def GetSecret(self, session_path, sender=None):
session = objects.get(session_path, None) session = objects.get(session_path, None)
if not session or session.sender != sender: if not session or session.sender != sender:
raise InvalidArgs("session invalid: %s" % session_path) raise InvalidArgs("session invalid: %s" % session_path)
if self.get_locked(): if self.get_locked():
raise IsLocked("secret is locked: %s" % self.path) raise IsLocked("secret is locked: %s" % self.path)
return session.encode_secret(self.secret, self.content_type) return session.encode_secret(self.secret, self.content_type)
@ -225,7 +250,7 @@ class SecretItem(dbus.service.Object):
def SetSecret(self, secret, sender=None): def SetSecret(self, secret, sender=None):
session = objects.get(secret[0], None) session = objects.get(secret[0], None)
if not session or session.sender != sender: if not session or session.sender != sender:
raise InvalidArgs("session invalid: %s" % secret[0]) raise InvalidArgs("session invalid: %s" % secret[0])
if self.get_locked(): if self.get_locked():
raise IsLocked("secret is locked: %s" % self.path) raise IsLocked("secret is locked: %s" % self.path)
(self.secret, self.content_type) = session.decode_secret(secret) (self.secret, self.content_type) = session.decode_secret(secret)
@ -257,7 +282,7 @@ class SecretItem(dbus.service.Object):
'Label': self.label, 'Label': self.label,
'Created': dbus.UInt64(self.created), 'Created': dbus.UInt64(self.created),
'Modified': dbus.UInt64(self.modified), 'Modified': dbus.UInt64(self.modified),
'Schema': self.schema 'Type': self.type
} }
else: else:
raise InvalidArgs('Unknown %s interface' % interface_name) raise InvalidArgs('Unknown %s interface' % interface_name)
@ -270,8 +295,10 @@ class SecretItem(dbus.service.Object):
self.label = str(new_value) self.label = str(new_value)
elif property_name == "Attributes": elif property_name == "Attributes":
self.attributes = dict(new_value) self.attributes = dict(new_value)
elif property_name == "Type":
self.type = str(new_value)
else: else:
raise InvalidArgs('Unknown %s interface' % property_name) raise InvalidArgs('Not writable %s property' % property_name)
self.PropertiesChanged(interface_name, { property_name: new_value }, []) self.PropertiesChanged(interface_name, { property_name: new_value }, [])
@dbus.service.signal(dbus.PROPERTIES_IFACE, signature='sa{sv}as') @dbus.service.signal(dbus.PROPERTIES_IFACE, signature='sa{sv}as')
@ -280,19 +307,57 @@ class SecretItem(dbus.service.Object):
class SecretCollection(dbus.service.Object): class SecretCollection(dbus.service.Object):
def __init__(self, service, identifier, label="Collection", locked=False, confirm=False): SUPPORTS_MULTIPLE_OBJECT_PATHS = True
def __init__(self, service, identifier=None, label="Collection", locked=False,
confirm=False, master=None):
if identifier is None:
identifier = label
identifier = encode_identifier(identifier)
self.service = service self.service = service
self.identifier = identifier self.identifier = identifier
self.label = label or "Unnamed collection" self.label = label or "Unnamed collection"
self.locked = locked self.locked = locked
self.items = { } self.items = { }
self.confirm = confirm self.confirm = confirm
self.master = None
self.created = self.modified = time.time() self.created = self.modified = time.time()
self.aliased = set()
self.path = "%s%s" % (COLLECTION_PREFIX, 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 self.service.add_collection(self)
objects[self.path] = self objects[self.path] = self
def add_item(self, item):
self.items[item.path] = item
for alias in self.aliased:
item.add_alias(alias)
def remove_item(self, item):
for alias in self.aliased:
item.remove_alias(alias)
del self.items[item.path]
def add_alias(self, name):
if name in self.aliased:
return
self.aliased.add(name)
for item in self.items.values():
item.add_alias(name)
path = alias_path(name)
objects[path] = self
self.add_to_connection(self.connection, path)
def remove_alias(self, name):
if name not in self.aliased:
return
path = alias_path(name)
self.aliased.remove(name)
del objects[path]
self.remove_from_connection(self.connection, path)
for item in self.items.values():
item.remove_alias(name)
def search_items(self, attributes): def search_items(self, attributes):
results = [] results = []
for item in self.items.values(): for item in self.items.values():
@ -312,8 +377,10 @@ class SecretCollection(dbus.service.Object):
def perform_delete(self): def perform_delete(self):
for item in self.items.values(): for item in self.items.values():
item.perform_delete() item.perform_delete()
del self.service.collections[self.identifier]
del objects[self.path] del objects[self.path]
self.service.remove_collection(self)
for alias in list(self.aliased):
self.remove_alias(alias)
self.remove_from_connection() self.remove_from_connection()
@dbus.service.method('org.freedesktop.Secret.Collection', byte_arrays=True, sender_keyword='sender') @dbus.service.method('org.freedesktop.Secret.Collection', byte_arrays=True, sender_keyword='sender')
@ -325,19 +392,20 @@ class SecretCollection(dbus.service.Object):
attributes = properties.get("org.freedesktop.Secret.Item.Attributes", None) attributes = properties.get("org.freedesktop.Secret.Item.Attributes", None)
label = properties.get("org.freedesktop.Secret.Item.Label", None) label = properties.get("org.freedesktop.Secret.Item.Label", None)
schema = properties.get("org.freedesktop.Secret.Item.Schema", None) type = properties.get("org.freedesktop.Secret.Item.Type", None)
(secret, content_type) = session.decode_secret(value) (secret, content_type) = session.decode_secret(value)
item = None item = None
if replace and attributes: if replace:
items = self.search_items(attributes) items = self.search_items(attributes)
if items: if items:
item = items[0] item = items[0]
if item is None: if item is None:
item = SecretItem(self, next_identifier('i'), label, attributes, item = SecretItem(self, next_identifier(), label, attributes, type=type,
secret=secret, confirm=False, content_type=content_type) secret=secret, confirm=False, content_type=content_type)
else: else:
item.label = label item.label = label
item.type = type
item.secret = secret item.secret = secret
item.attributes = attributes item.attributes = attributes
item.content_type = content_type item.content_type = content_type
@ -350,8 +418,8 @@ class SecretCollection(dbus.service.Object):
collection.perform_delete() collection.perform_delete()
return dbus.String("", variant_level=1) return dbus.String("", variant_level=1)
if self.confirm: if self.confirm:
prompt = SecretPrompt(self.collection.service, sender, prompt = SecretPrompt(self.service, sender, dismiss=False,
dismiss=False, action=prompt_callback) action=prompt_callback)
return dbus.ObjectPath(prompt.path) return dbus.ObjectPath(prompt.path)
else: else:
self.perform_delete() self.perform_delete()
@ -405,6 +473,8 @@ class SecretService(dbus.service.Object):
self.sessions = { } self.sessions = { }
self.prompts = { } self.prompts = { }
self.collections = { } self.collections = { }
self.aliases = { }
self.aliased = { }
def on_name_owner_changed(owned, old_owner, new_owner): def on_name_owner_changed(owned, old_owner, new_owner):
if not new_owner: if not new_owner:
@ -417,19 +487,22 @@ class SecretService(dbus.service.Object):
def add_standard_objects(self): def add_standard_objects(self):
collection = SecretCollection(self, "english", label="Collection One", locked=False) collection = SecretCollection(self, "english", label="Collection One", locked=False)
SecretItem(collection, "item_one", label="Item One", SecretItem(collection, "1", label="Item One",
attributes={ "number": "1", "string": "one", "even": "false" }, attributes={ "number": "1", "string": "one", "even": "false" },
secret="111", schema="org.mock.schema.Store") secret="111", type="org.mock.type.Store")
SecretItem(collection, "item_two", attributes={ "number": "2", "string": "two", "even": "true" }, secret="222") SecretItem(collection, "2", attributes={ "number": "2", "string": "two", "even": "true" }, secret="222")
SecretItem(collection, "item_three", attributes={ "number": "3", "string": "three", "even": "false" }, secret="3333") SecretItem(collection, "3", attributes={ "number": "3", "string": "three", "even": "false" }, secret="3333")
self.set_alias('default', collection)
collection = SecretCollection(self, "spanish", locked=True) collection = SecretCollection(self, "spanish", locked=True)
SecretItem(collection, "item_one", attributes={ "number": "1", "string": "uno", "even": "false" }, secret="111") SecretItem(collection, "10", attributes={ "number": "1", "string": "uno", "even": "false" }, secret="111")
SecretItem(collection, "item_two", attributes={ "number": "2", "string": "dos", "even": "true" }, secret="222") SecretItem(collection, "20", attributes={ "number": "2", "string": "dos", "even": "true" }, secret="222")
SecretItem(collection, "item_three", attributes={ "number": "3", "string": "tres", "even": "false" }, secret="3333") SecretItem(collection, "30", attributes={ "number": "3", "string": "tres", "even": "false" }, secret="3333")
collection = SecretCollection(self, "empty", locked=False) collection = SecretCollection(self, "empty", locked=False)
collection = SecretCollection(self, "session", label="Session Keyring", locked=False)
def listen(self): def listen(self):
global ready_pipe global ready_pipe
loop = gobject.MainLoop() loop = gobject.MainLoop()
@ -447,6 +520,25 @@ 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 add_collection(self, collection):
self.collections[collection.path] = collection
def remove_collection(self, collection):
for alias in list(collection.aliased):
self.remove_alias(alias)
del self.collections[collection.path]
def set_alias(self, name, collection):
self.remove_alias(name)
collection.add_alias(name)
self.aliases[name] = collection
def remove_alias(self, name):
if name in self.aliases:
collection = self.aliases[name]
collection.remove_alias(name)
del self.aliases[name]
def add_prompt(self, prompt): def add_prompt(self, prompt):
if prompt.sender not in self.prompts: if prompt.sender not in self.prompts:
self.prompts[prompt.sender] = [] self.prompts[prompt.sender] = []
@ -456,10 +548,9 @@ class SecretService(dbus.service.Object):
self.prompts[prompt.sender].remove(prompt) self.prompts[prompt.sender].remove(prompt)
def find_item(self, object): def find_item(self, object):
if object.startswith(COLLECTION_PREFIX): parts = object.rsplit("/", 1)
parts = object[len(COLLECTION_PREFIX):].split("/", 1) if len(parts) == 2 and parts[0] in self.collections:
if len(parts) == 2 and parts[0] in self.collections: return self.collections[parts[0]].get(parts[1], None)
return self.collections[parts[0]].get(parts[1], None)
return None return None
@dbus.service.method('org.freedesktop.Secret.Service', sender_keyword='sender') @dbus.service.method('org.freedesktop.Secret.Service', sender_keyword='sender')
@ -506,7 +597,7 @@ class SecretService(dbus.service.Object):
label = properties.get("org.freedesktop.Secret.Collection.Label", None) label = properties.get("org.freedesktop.Secret.Collection.Label", None)
service = self service = self
def prompt_callback(): def prompt_callback():
collection = SecretCollection(service, next_identifier('c'), label, locked=False, confirm=True) collection = SecretCollection(service, None, label, locked=False, confirm=True)
return dbus.ObjectPath(collection.path, variant_level=1) return dbus.ObjectPath(collection.path, variant_level=1)
prompt = SecretPrompt(self, sender, dismiss=False, action=prompt_callback) prompt = SecretPrompt(self, sender, dismiss=False, action=prompt_callback)
return (dbus.ObjectPath("/"), dbus.ObjectPath(prompt.path)) return (dbus.ObjectPath("/"), dbus.ObjectPath(prompt.path))
@ -519,16 +610,16 @@ class SecretService(dbus.service.Object):
for collection in self.collections.values(): for collection in self.collections.values():
items = collection.search_items(attributes) items = collection.search_items(attributes)
if collection.get_locked(): if collection.get_locked():
locked.extend(items) locked.extend([item.path for item in items])
else: else:
unlocked.extend(items) unlocked.extend([item.path for item in 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') @dbus.service.method('org.freedesktop.Secret.Service', sender_keyword='sender')
def GetSecrets(self, item_paths, session_path, sender=None): def GetSecrets(self, item_paths, session_path, sender=None):
session = objects.get(session_path, None) session = objects.get(session_path, None)
if not session or session.sender != sender: if not session or session.sender != sender:
raise InvalidArgs("session invalid: %s" % session_path) raise InvalidArgs("session invalid: %s" % session_path)
results = dbus.Dictionary(signature="o(oayays)") results = dbus.Dictionary(signature="o(oayays)")
for item_path in item_paths: for item_path in item_paths:
item = objects.get(item_path, None) item = objects.get(item_path, None)
@ -536,6 +627,18 @@ class SecretService(dbus.service.Object):
results[item_path] = item.GetSecret(session_path, sender) results[item_path] = item.GetSecret(session_path, sender)
return results return results
@dbus.service.method('org.freedesktop.Secret.Service')
def ReadAlias(self, name):
if name not in self.aliases:
return dbus.ObjectPath("/")
return dbus.ObjectPath(self.aliases[name].path)
@dbus.service.method('org.freedesktop.Secret.Service')
def SetAlias(self, name, collection):
if collection not in self.collections:
raise NoSuchObject("no such Collection")
self.set_alias(name, self.collections[collection])
@dbus.service.method(dbus.PROPERTIES_IFACE, in_signature='ss', out_signature='v') @dbus.service.method(dbus.PROPERTIES_IFACE, in_signature='ss', out_signature='v')
def Get(self, interface_name, property_name): def Get(self, interface_name, property_name):
return self.GetAll(interface_name)[property_name] return self.GetAll(interface_name)[property_name]

View File

@ -286,17 +286,17 @@ test_items (Test *test,
items = gsecret_collection_get_items (collection); items = gsecret_collection_get_items (collection);
check_items_equal (items, check_items_equal (items,
"/org/freedesktop/secrets/collection/english/item_one", "/org/freedesktop/secrets/collection/english/1",
"/org/freedesktop/secrets/collection/english/item_two", "/org/freedesktop/secrets/collection/english/2",
"/org/freedesktop/secrets/collection/english/item_three", "/org/freedesktop/secrets/collection/english/3",
NULL); NULL);
g_list_free_full (items, g_object_unref); g_list_free_full (items, g_object_unref);
g_object_get (collection, "items", &items, NULL); g_object_get (collection, "items", &items, NULL);
check_items_equal (items, check_items_equal (items,
"/org/freedesktop/secrets/collection/english/item_one", "/org/freedesktop/secrets/collection/english/1",
"/org/freedesktop/secrets/collection/english/item_two", "/org/freedesktop/secrets/collection/english/2",
"/org/freedesktop/secrets/collection/english/item_three", "/org/freedesktop/secrets/collection/english/3",
NULL); NULL);
g_list_free_full (items, g_object_unref); g_list_free_full (items, g_object_unref);

View File

@ -85,7 +85,7 @@ static void
test_new_sync (Test *test, test_new_sync (Test *test,
gconstpointer unused) gconstpointer unused)
{ {
const gchar *item_path = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *item_path = "/org/freedesktop/secrets/collection/english/1";
GError *error = NULL; GError *error = NULL;
GSecretItem *item; GSecretItem *item;
@ -101,7 +101,7 @@ static void
test_new_sync_noexist (Test *test, test_new_sync_noexist (Test *test,
gconstpointer unused) gconstpointer unused)
{ {
const gchar *item_path = "/org/freedesktop/secrets/collection/english/nonexistant"; const gchar *item_path = "/org/freedesktop/secrets/collection/english/0000";
GError *error = NULL; GError *error = NULL;
GSecretItem *item; GSecretItem *item;
@ -114,7 +114,7 @@ static void
test_new_async (Test *test, test_new_async (Test *test,
gconstpointer unused) gconstpointer unused)
{ {
const gchar *item_path = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *item_path = "/org/freedesktop/secrets/collection/english/1";
GAsyncResult *result = NULL; GAsyncResult *result = NULL;
GError *error = NULL; GError *error = NULL;
GSecretItem *item; GSecretItem *item;
@ -137,7 +137,7 @@ static void
test_new_async_noexist (Test *test, test_new_async_noexist (Test *test,
gconstpointer unused) gconstpointer unused)
{ {
const gchar *item_path = "/org/freedesktop/secrets/collection/english/nonexistant"; const gchar *item_path = "/org/freedesktop/secrets/collection/english/0000";
GAsyncResult *result = NULL; GAsyncResult *result = NULL;
GError *error = NULL; GError *error = NULL;
GSecretItem *item; GSecretItem *item;
@ -240,7 +240,7 @@ static void
test_properties (Test *test, test_properties (Test *test,
gconstpointer unused) gconstpointer unused)
{ {
const gchar *item_path = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *item_path = "/org/freedesktop/secrets/collection/english/1";
GError *error = NULL; GError *error = NULL;
GHashTable *attributes; GHashTable *attributes;
GSecretService *service; GSecretService *service;
@ -259,7 +259,7 @@ test_properties (Test *test,
g_assert_cmpuint (gsecret_item_get_modified (item), <=, time (NULL)); g_assert_cmpuint (gsecret_item_get_modified (item), <=, time (NULL));
schema = gsecret_item_get_schema (item); schema = gsecret_item_get_schema (item);
g_assert_cmpstr (schema, ==, "org.mock.schema.Store"); g_assert_cmpstr (schema, ==, "org.mock.type.Store");
g_free (schema); g_free (schema);
label = gsecret_item_get_label (item); label = gsecret_item_get_label (item);
@ -290,7 +290,7 @@ test_properties (Test *test,
g_assert_cmpstr (label, ==, "Item One"); g_assert_cmpstr (label, ==, "Item One");
g_free (label); g_free (label);
g_assert_cmpstr (schema, ==, "org.mock.schema.Store"); g_assert_cmpstr (schema, ==, "org.mock.type.Store");
g_free (schema); g_free (schema);
g_assert_cmpstr (g_hash_table_lookup (attributes, "string"), ==, "one"); g_assert_cmpstr (g_hash_table_lookup (attributes, "string"), ==, "one");
@ -309,7 +309,7 @@ static void
test_set_label_sync (Test *test, test_set_label_sync (Test *test,
gconstpointer unused) gconstpointer unused)
{ {
const gchar *item_path = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *item_path = "/org/freedesktop/secrets/collection/english/1";
GError *error = NULL; GError *error = NULL;
GSecretItem *item; GSecretItem *item;
gboolean ret; gboolean ret;
@ -337,7 +337,7 @@ static void
test_set_label_async (Test *test, test_set_label_async (Test *test,
gconstpointer unused) gconstpointer unused)
{ {
const gchar *item_path = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *item_path = "/org/freedesktop/secrets/collection/english/1";
GAsyncResult *result = NULL; GAsyncResult *result = NULL;
GError *error = NULL; GError *error = NULL;
GSecretItem *item; GSecretItem *item;
@ -372,7 +372,7 @@ static void
test_set_label_prop (Test *test, test_set_label_prop (Test *test,
gconstpointer unused) gconstpointer unused)
{ {
const gchar *item_path = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *item_path = "/org/freedesktop/secrets/collection/english/1";
GError *error = NULL; GError *error = NULL;
GSecretItem *item; GSecretItem *item;
guint sigs = 2; guint sigs = 2;
@ -402,7 +402,7 @@ static void
test_set_attributes_sync (Test *test, test_set_attributes_sync (Test *test,
gconstpointer unused) gconstpointer unused)
{ {
const gchar *item_path = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *item_path = "/org/freedesktop/secrets/collection/english/1";
GError *error = NULL; GError *error = NULL;
GSecretItem *item; GSecretItem *item;
gboolean ret; gboolean ret;
@ -439,7 +439,7 @@ static void
test_set_attributes_async (Test *test, test_set_attributes_async (Test *test,
gconstpointer unused) gconstpointer unused)
{ {
const gchar *item_path = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *item_path = "/org/freedesktop/secrets/collection/english/1";
GHashTable *attributes; GHashTable *attributes;
GError *error = NULL; GError *error = NULL;
GAsyncResult *result = NULL; GAsyncResult *result = NULL;
@ -482,7 +482,7 @@ static void
test_set_attributes_prop (Test *test, test_set_attributes_prop (Test *test,
gconstpointer unused) gconstpointer unused)
{ {
const gchar *item_path = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *item_path = "/org/freedesktop/secrets/collection/english/1";
GError *error = NULL; GError *error = NULL;
GSecretItem *item; GSecretItem *item;
GHashTable *attributes; GHashTable *attributes;
@ -522,7 +522,7 @@ static void
test_get_secret_sync (Test *test, test_get_secret_sync (Test *test,
gconstpointer unused) gconstpointer unused)
{ {
const gchar *item_path = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *item_path = "/org/freedesktop/secrets/collection/english/1";
GError *error = NULL; GError *error = NULL;
GSecretItem *item; GSecretItem *item;
GSecretValue *value; GSecretValue *value;
@ -548,7 +548,7 @@ static void
test_get_secret_async (Test *test, test_get_secret_async (Test *test,
gconstpointer unused) gconstpointer unused)
{ {
const gchar *item_path = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *item_path = "/org/freedesktop/secrets/collection/english/1";
GAsyncResult *result = NULL; GAsyncResult *result = NULL;
GError *error = NULL; GError *error = NULL;
GSecretItem *item; GSecretItem *item;
@ -581,7 +581,7 @@ static void
test_set_secret_sync (Test *test, test_set_secret_sync (Test *test,
gconstpointer unused) gconstpointer unused)
{ {
const gchar *item_path = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *item_path = "/org/freedesktop/secrets/collection/english/1";
GError *error = NULL; GError *error = NULL;
GSecretItem *item; GSecretItem *item;
gconstpointer data; gconstpointer data;
@ -616,7 +616,7 @@ static void
test_delete_sync (Test *test, test_delete_sync (Test *test,
gconstpointer unused) gconstpointer unused)
{ {
const gchar *item_path = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *item_path = "/org/freedesktop/secrets/collection/english/1";
GError *error = NULL; GError *error = NULL;
GSecretItem *item; GSecretItem *item;
gboolean ret; gboolean ret;
@ -639,7 +639,7 @@ static void
test_delete_async (Test *test, test_delete_async (Test *test,
gconstpointer unused) gconstpointer unused)
{ {
const gchar *item_path = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *item_path = "/org/freedesktop/secrets/collection/english/1";
GAsyncResult *result = NULL; GAsyncResult *result = NULL;
GError *error = NULL; GError *error = NULL;
GSecretItem *item; GSecretItem *item;

View File

@ -37,7 +37,7 @@ static const GSecretSchema DELETE_SCHEMA = {
}; };
static const GSecretSchema STORE_SCHEMA = { static const GSecretSchema STORE_SCHEMA = {
"org.mock.schema.Store", "org.mock.type.Store",
{ {
{ "number", GSECRET_ATTRIBUTE_INTEGER }, { "number", GSECRET_ATTRIBUTE_INTEGER },
{ "string", GSECRET_ATTRIBUTE_STRING }, { "string", GSECRET_ATTRIBUTE_STRING },
@ -122,10 +122,10 @@ test_search_paths_sync (Test *test,
g_assert (ret == TRUE); g_assert (ret == TRUE);
g_assert (locked); g_assert (locked);
g_assert_cmpstr (locked[0], ==, "/org/freedesktop/secrets/collection/spanish/item_one"); g_assert_cmpstr (locked[0], ==, "/org/freedesktop/secrets/collection/spanish/10");
g_assert (unlocked); g_assert (unlocked);
g_assert_cmpstr (unlocked[0], ==, "/org/freedesktop/secrets/collection/english/item_one"); g_assert_cmpstr (unlocked[0], ==, "/org/freedesktop/secrets/collection/english/1");
g_strfreev (unlocked); g_strfreev (unlocked);
g_strfreev (locked); g_strfreev (locked);
@ -159,10 +159,10 @@ test_search_paths_async (Test *test,
g_assert (ret == TRUE); g_assert (ret == TRUE);
g_assert (locked); g_assert (locked);
g_assert_cmpstr (locked[0], ==, "/org/freedesktop/secrets/collection/spanish/item_one"); g_assert_cmpstr (locked[0], ==, "/org/freedesktop/secrets/collection/spanish/10");
g_assert (unlocked); g_assert (unlocked);
g_assert_cmpstr (unlocked[0], ==, "/org/freedesktop/secrets/collection/english/item_one"); g_assert_cmpstr (unlocked[0], ==, "/org/freedesktop/secrets/collection/english/1");
g_strfreev (unlocked); g_strfreev (unlocked);
g_strfreev (locked); g_strfreev (locked);
@ -189,7 +189,7 @@ test_search_paths_nulls (Test *test,
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/english/item_one"); g_assert_cmpstr (paths[0], ==, "/org/freedesktop/secrets/collection/english/1");
g_strfreev (paths); g_strfreev (paths);
ret = gsecret_service_search_for_paths_sync (test->service, attributes, NULL, ret = gsecret_service_search_for_paths_sync (test->service, attributes, NULL,
@ -197,7 +197,7 @@ test_search_paths_nulls (Test *test,
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/spanish/item_one"); g_assert_cmpstr (paths[0], ==, "/org/freedesktop/secrets/collection/spanish/10");
g_strfreev (paths); g_strfreev (paths);
ret = gsecret_service_search_for_paths_sync (test->service, attributes, NULL, ret = gsecret_service_search_for_paths_sync (test->service, attributes, NULL,
@ -214,7 +214,7 @@ test_search_paths_nulls (Test *test,
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/english/item_one"); g_assert_cmpstr (paths[0], ==, "/org/freedesktop/secrets/collection/english/1");
g_strfreev (paths); g_strfreev (paths);
g_clear_object (&result); g_clear_object (&result);
@ -227,7 +227,7 @@ test_search_paths_nulls (Test *test,
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/spanish/item_one"); g_assert_cmpstr (paths[0], ==, "/org/freedesktop/secrets/collection/spanish/10");
g_strfreev (paths); g_strfreev (paths);
g_clear_object (&result); g_clear_object (&result);
@ -263,10 +263,10 @@ test_search_sync (Test *test,
g_assert (ret == TRUE); g_assert (ret == TRUE);
g_assert (locked != NULL); g_assert (locked != NULL);
g_assert_cmpstr (g_dbus_proxy_get_object_path (locked->data), ==, "/org/freedesktop/secrets/collection/spanish/item_one"); g_assert_cmpstr (g_dbus_proxy_get_object_path (locked->data), ==, "/org/freedesktop/secrets/collection/spanish/10");
g_assert (unlocked != NULL); g_assert (unlocked != NULL);
g_assert_cmpstr (g_dbus_proxy_get_object_path (unlocked->data), ==, "/org/freedesktop/secrets/collection/english/item_one"); g_assert_cmpstr (g_dbus_proxy_get_object_path (unlocked->data), ==, "/org/freedesktop/secrets/collection/english/1");
g_list_free_full (unlocked, g_object_unref); g_list_free_full (unlocked, g_object_unref);
g_list_free_full (locked, g_object_unref); g_list_free_full (locked, g_object_unref);
@ -300,10 +300,10 @@ test_search_async (Test *test,
g_assert (ret == TRUE); g_assert (ret == TRUE);
g_assert (locked != NULL); g_assert (locked != NULL);
g_assert_cmpstr (g_dbus_proxy_get_object_path (locked->data), ==, "/org/freedesktop/secrets/collection/spanish/item_one"); g_assert_cmpstr (g_dbus_proxy_get_object_path (locked->data), ==, "/org/freedesktop/secrets/collection/spanish/10");
g_assert (unlocked != NULL); g_assert (unlocked != NULL);
g_assert_cmpstr (g_dbus_proxy_get_object_path (unlocked->data), ==, "/org/freedesktop/secrets/collection/english/item_one"); g_assert_cmpstr (g_dbus_proxy_get_object_path (unlocked->data), ==, "/org/freedesktop/secrets/collection/english/1");
g_list_free_full (unlocked, g_object_unref); g_list_free_full (unlocked, g_object_unref);
g_list_free_full (locked, g_object_unref); g_list_free_full (locked, g_object_unref);
@ -330,7 +330,7 @@ test_search_nulls (Test *test,
g_assert_no_error (error); g_assert_no_error (error);
g_assert (ret == TRUE); g_assert (ret == TRUE);
g_assert (items != NULL); g_assert (items != NULL);
g_assert_cmpstr (g_dbus_proxy_get_object_path (items->data), ==, "/org/freedesktop/secrets/collection/english/item_one"); g_assert_cmpstr (g_dbus_proxy_get_object_path (items->data), ==, "/org/freedesktop/secrets/collection/english/1");
g_list_free_full (items, g_object_unref); g_list_free_full (items, g_object_unref);
ret = gsecret_service_search_sync (test->service, attributes, NULL, ret = gsecret_service_search_sync (test->service, attributes, NULL,
@ -338,7 +338,7 @@ test_search_nulls (Test *test,
g_assert_no_error (error); g_assert_no_error (error);
g_assert (ret == TRUE); g_assert (ret == TRUE);
g_assert (items != NULL); g_assert (items != NULL);
g_assert_cmpstr (g_dbus_proxy_get_object_path (items->data), ==, "/org/freedesktop/secrets/collection/spanish/item_one"); g_assert_cmpstr (g_dbus_proxy_get_object_path (items->data), ==, "/org/freedesktop/secrets/collection/spanish/10");
g_list_free_full (items, g_object_unref); g_list_free_full (items, g_object_unref);
ret = gsecret_service_search_sync (test->service, attributes, NULL, ret = gsecret_service_search_sync (test->service, attributes, NULL,
@ -355,7 +355,7 @@ test_search_nulls (Test *test,
g_assert_no_error (error); g_assert_no_error (error);
g_assert (ret == TRUE); g_assert (ret == TRUE);
g_assert (items != NULL); g_assert (items != NULL);
g_assert_cmpstr (g_dbus_proxy_get_object_path (items->data), ==, "/org/freedesktop/secrets/collection/english/item_one"); g_assert_cmpstr (g_dbus_proxy_get_object_path (items->data), ==, "/org/freedesktop/secrets/collection/english/1");
g_list_free_full (items, g_object_unref); g_list_free_full (items, g_object_unref);
g_clear_object (&result); g_clear_object (&result);
@ -368,7 +368,7 @@ test_search_nulls (Test *test,
g_assert_no_error (error); g_assert_no_error (error);
g_assert (ret == TRUE); g_assert (ret == TRUE);
g_assert (items != NULL); g_assert (items != NULL);
g_assert_cmpstr (g_dbus_proxy_get_object_path (items->data), ==, "/org/freedesktop/secrets/collection/spanish/item_one"); g_assert_cmpstr (g_dbus_proxy_get_object_path (items->data), ==, "/org/freedesktop/secrets/collection/spanish/10");
g_list_free_full (items, g_object_unref); g_list_free_full (items, g_object_unref);
g_clear_object (&result); g_clear_object (&result);
@ -395,7 +395,7 @@ test_secret_for_path_sync (Test *test,
const gchar *password; const gchar *password;
gsize length; gsize length;
path = "/org/freedesktop/secrets/collection/english/item_one"; path = "/org/freedesktop/secrets/collection/english/1";
value = gsecret_service_get_secret_for_path_sync (test->service, path, NULL, &error); value = gsecret_service_get_secret_for_path_sync (test->service, path, NULL, &error);
g_assert_no_error (error); g_assert_no_error (error);
g_assert (value != NULL); g_assert (value != NULL);
@ -421,7 +421,7 @@ test_secret_for_path_async (Test *test,
GAsyncResult *result = NULL; GAsyncResult *result = NULL;
gsize length; gsize length;
path = "/org/freedesktop/secrets/collection/english/item_one"; path = "/org/freedesktop/secrets/collection/english/1";
gsecret_service_get_secret_for_path (test->service, path, NULL, gsecret_service_get_secret_for_path (test->service, path, NULL,
on_complete_get_result, &result); on_complete_get_result, &result);
g_assert (result == NULL); g_assert (result == NULL);
@ -446,14 +446,14 @@ static void
test_secrets_for_paths_sync (Test *test, test_secrets_for_paths_sync (Test *test,
gconstpointer used) gconstpointer used)
{ {
const gchar *path_item_one = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *path_item_one = "/org/freedesktop/secrets/collection/english/1";
const gchar *path_item_two = "/org/freedesktop/secrets/collection/english/item_two"; const gchar *path_item_two = "/org/freedesktop/secrets/collection/english/2";
const gchar *paths[] = { const gchar *paths[] = {
path_item_one, path_item_one,
path_item_two, path_item_two,
/* This one is locked, and not returned */ /* This one is locked, and not returned */
"/org/freedesktop/secrets/collection/spanish/item_one", "/org/freedesktop/secrets/collection/spanish/10",
NULL NULL
}; };
@ -488,14 +488,14 @@ static void
test_secrets_for_paths_async (Test *test, test_secrets_for_paths_async (Test *test,
gconstpointer used) gconstpointer used)
{ {
const gchar *path_item_one = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *path_item_one = "/org/freedesktop/secrets/collection/english/1";
const gchar *path_item_two = "/org/freedesktop/secrets/collection/english/item_two"; const gchar *path_item_two = "/org/freedesktop/secrets/collection/english/2";
const gchar *paths[] = { const gchar *paths[] = {
path_item_one, path_item_one,
path_item_two, path_item_two,
/* This one is locked, and not returned */ /* This one is locked, and not returned */
"/org/freedesktop/secrets/collection/spanish/item_one", "/org/freedesktop/secrets/collection/spanish/10",
NULL NULL
}; };
@ -537,9 +537,9 @@ static void
test_secrets_sync (Test *test, test_secrets_sync (Test *test,
gconstpointer used) gconstpointer used)
{ {
const gchar *path_item_one = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *path_item_one = "/org/freedesktop/secrets/collection/english/1";
const gchar *path_item_two = "/org/freedesktop/secrets/collection/english/item_two"; const gchar *path_item_two = "/org/freedesktop/secrets/collection/english/2";
const gchar *path_item_three = "/org/freedesktop/secrets/collection/spanish/item_one"; const gchar *path_item_three = "/org/freedesktop/secrets/collection/spanish/10";
GSecretValue *value; GSecretValue *value;
GHashTable *values; GHashTable *values;
@ -583,9 +583,9 @@ static void
test_secrets_async (Test *test, test_secrets_async (Test *test,
gconstpointer used) gconstpointer used)
{ {
const gchar *path_item_one = "/org/freedesktop/secrets/collection/english/item_one"; const gchar *path_item_one = "/org/freedesktop/secrets/collection/english/1";
const gchar *path_item_two = "/org/freedesktop/secrets/collection/english/item_two"; const gchar *path_item_two = "/org/freedesktop/secrets/collection/english/2";
const gchar *path_item_three = "/org/freedesktop/secrets/collection/spanish/item_one"; const gchar *path_item_three = "/org/freedesktop/secrets/collection/spanish/10";
GSecretValue *value; GSecretValue *value;
GHashTable *values; GHashTable *values;
@ -597,8 +597,14 @@ test_secrets_async (Test *test,
gsize length; gsize length;
item_one = gsecret_item_new_sync (test->service, path_item_one, NULL, &error); item_one = gsecret_item_new_sync (test->service, path_item_one, NULL, &error);
g_assert_no_error (error);
item_two = gsecret_item_new_sync (test->service, path_item_two, NULL, &error); item_two = gsecret_item_new_sync (test->service, path_item_two, NULL, &error);
g_assert_no_error (error);
item_three = gsecret_item_new_sync (test->service, path_item_three, NULL, &error); item_three = gsecret_item_new_sync (test->service, path_item_three, NULL, &error);
g_assert_no_error (error);
items = g_list_append (items, item_one); items = g_list_append (items, item_one);
items = g_list_append (items, item_two); items = g_list_append (items, item_two);
@ -642,7 +648,7 @@ test_delete_for_path_sync (Test *test,
gconstpointer used) gconstpointer used)
{ {
const gchar *path_item_one = "/org/freedesktop/secrets/collection/to_delete/item"; const gchar *path_item_one = "/org/freedesktop/secrets/collection/todelete/item";
GError *error = NULL; GError *error = NULL;
gboolean ret; gboolean ret;
@ -656,7 +662,7 @@ test_delete_for_path_sync_prompt (Test *test,
gconstpointer used) gconstpointer used)
{ {
const gchar *path_item_one = "/org/freedesktop/secrets/collection/to_delete/confirm"; const gchar *path_item_one = "/org/freedesktop/secrets/collection/todelete/confirm";
GError *error = NULL; GError *error = NULL;
gboolean ret; gboolean ret;
@ -669,7 +675,7 @@ static void
test_lock_paths_sync (Test *test, test_lock_paths_sync (Test *test,
gconstpointer used) gconstpointer used)
{ {
const gchar *collection_path = "/org/freedesktop/secrets/collection/lock_one"; const gchar *collection_path = "/org/freedesktop/secrets/collection/lockone";
const gchar *paths[] = { const gchar *paths[] = {
collection_path, collection_path,
NULL, NULL,
@ -693,7 +699,7 @@ static void
test_lock_prompt_sync (Test *test, test_lock_prompt_sync (Test *test,
gconstpointer used) gconstpointer used)
{ {
const gchar *collection_path = "/org/freedesktop/secrets/collection/lock_prompt"; const gchar *collection_path = "/org/freedesktop/secrets/collection/lockprompt";
const gchar *paths[] = { const gchar *paths[] = {
collection_path, collection_path,
NULL, NULL,
@ -717,7 +723,7 @@ static void
test_lock_sync (Test *test, test_lock_sync (Test *test,
gconstpointer used) gconstpointer used)
{ {
const gchar *collection_path = "/org/freedesktop/secrets/collection/lock_one"; const gchar *collection_path = "/org/freedesktop/secrets/collection/lockone";
GSecretCollection *collection; GSecretCollection *collection;
GError *error = NULL; GError *error = NULL;
GList *locked; GList *locked;
@ -746,7 +752,7 @@ static void
test_unlock_paths_sync (Test *test, test_unlock_paths_sync (Test *test,
gconstpointer used) gconstpointer used)
{ {
const gchar *collection_path = "/org/freedesktop/secrets/collection/lock_one"; const gchar *collection_path = "/org/freedesktop/secrets/collection/lockone";
const gchar *paths[] = { const gchar *paths[] = {
collection_path, collection_path,
NULL, NULL,
@ -770,7 +776,7 @@ static void
test_unlock_prompt_sync (Test *test, test_unlock_prompt_sync (Test *test,
gconstpointer used) gconstpointer used)
{ {
const gchar *collection_path = "/org/freedesktop/secrets/collection/lock_prompt"; const gchar *collection_path = "/org/freedesktop/secrets/collection/lockprompt";
const gchar *paths[] = { const gchar *paths[] = {
collection_path, collection_path,
NULL, NULL,
@ -794,7 +800,7 @@ static void
test_unlock_sync (Test *test, test_unlock_sync (Test *test,
gconstpointer used) gconstpointer used)
{ {
const gchar *collection_path = "/org/freedesktop/secrets/collection/lock_one"; const gchar *collection_path = "/org/freedesktop/secrets/collection/lockone";
GSecretCollection *collection; GSecretCollection *collection;
GError *error = NULL; GError *error = NULL;
GList *unlocked; GList *unlocked;
@ -898,7 +904,7 @@ test_item_sync (Test *test,
g_variant_ref_sink (g_variant_new_string ("Wheeee"))); g_variant_ref_sink (g_variant_new_string ("Wheeee")));
g_hash_table_insert (properties, GSECRET_COLLECTION_INTERFACE ".Attributes", g_hash_table_insert (properties, GSECRET_COLLECTION_INTERFACE ".Attributes",
g_variant_ref_sink (_gsecret_util_variant_for_attributes (attributes))); g_variant_ref_sink (_gsecret_util_variant_for_attributes (attributes)));
g_hash_table_insert (properties, GSECRET_COLLECTION_INTERFACE ".Schema", g_hash_table_insert (properties, GSECRET_COLLECTION_INTERFACE ".Type",
g_variant_ref_sink (g_variant_new_string ("org.gnome.Test"))); g_variant_ref_sink (g_variant_new_string ("org.gnome.Test")));
g_hash_table_unref (attributes); g_hash_table_unref (attributes);
@ -942,7 +948,7 @@ test_item_async (Test *test,
g_variant_ref_sink (g_variant_new_string ("Wheeee"))); g_variant_ref_sink (g_variant_new_string ("Wheeee")));
g_hash_table_insert (properties, GSECRET_COLLECTION_INTERFACE ".Attributes", g_hash_table_insert (properties, GSECRET_COLLECTION_INTERFACE ".Attributes",
g_variant_ref_sink (_gsecret_util_variant_for_attributes (attributes))); g_variant_ref_sink (_gsecret_util_variant_for_attributes (attributes)));
g_hash_table_insert (properties, GSECRET_COLLECTION_INTERFACE ".Schema", g_hash_table_insert (properties, GSECRET_COLLECTION_INTERFACE ".Type",
g_variant_ref_sink (g_variant_new_string ("org.gnome.Test"))); g_variant_ref_sink (g_variant_new_string ("org.gnome.Test")));
g_hash_table_unref (attributes); g_hash_table_unref (attributes);

View File

@ -57,7 +57,6 @@ teardown (Test *test,
mock_service_stop (); mock_service_stop ();
} }
static void static void
on_async_result (GObject *source, on_async_result (GObject *source,
GAsyncResult *result, GAsyncResult *result,
@ -187,11 +186,11 @@ test_perform_cancel (Test *test,
g_assert (ret == TRUE); g_assert (ret == TRUE);
g_object_unref (result); g_object_unref (result);
/* Make sure everything completes */
egg_test_wait_idle ();
g_object_unref (prompt); g_object_unref (prompt);
/* Due to GDBus threading races */
egg_test_wait_until (100);
egg_assert_not_object (prompt); egg_assert_not_object (prompt);
} }