summaryrefslogtreecommitdiff
path: root/daemon/dbus/gkd-secret-service.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/dbus/gkd-secret-service.c')
-rw-r--r--daemon/dbus/gkd-secret-service.c164
1 files changed, 105 insertions, 59 deletions
diff --git a/daemon/dbus/gkd-secret-service.c b/daemon/dbus/gkd-secret-service.c
index 9c0071c7..198ad65d 100644
--- a/daemon/dbus/gkd-secret-service.c
+++ b/daemon/dbus/gkd-secret-service.c
@@ -59,6 +59,7 @@ struct _GkdSecretService {
GHashTable *clients;
gchar *match_rule;
GkdSecretObjects *objects;
+ GHashTable *aliases;
};
typedef struct _ServiceClient {
@@ -67,8 +68,7 @@ typedef struct _ServiceClient {
pid_t caller_pid;
CK_G_APPLICATION app;
GckSession *pkcs11_session;
- GHashTable *sessions;
- GHashTable *prompts;
+ GHashTable *dispatch;
} ServiceClient;
/* Forward declaration */
@@ -93,9 +93,11 @@ update_default (GkdSecretService *self, gboolean force)
const gchar *identifier;
gchar *path;
- identifier = gkd_secret_objects_get_alias (self->objects, "default");
- if (!force && identifier)
- return;
+ if (!force) {
+ identifier = g_hash_table_lookup (self->aliases, "default");
+ if (identifier)
+ return;
+ }
path = default_path ();
if (g_file_get_contents (path, &contents, NULL, NULL)) {
@@ -107,8 +109,7 @@ update_default (GkdSecretService *self, gboolean force)
}
g_free (path);
- gkd_secret_objects_set_alias (self->objects, "default", contents);
- g_free (contents);
+ g_hash_table_replace (self->aliases, g_strdup ("default"), contents);
}
static void
@@ -118,7 +119,7 @@ store_default (GkdSecretService *self)
const gchar *identifier;
gchar *path;
- identifier = gkd_secret_objects_get_alias (self->objects, "default");
+ identifier = g_hash_table_lookup (self->aliases, "default");
if (!identifier)
return;
@@ -172,8 +173,7 @@ free_client (gpointer data)
}
/* The sessions and prompts the client has open */
- g_hash_table_destroy (client->sessions);
- g_hash_table_destroy (client->prompts);
+ g_hash_table_destroy (client->dispatch);
g_free (client);
}
@@ -237,8 +237,7 @@ on_get_connection_unix_process_id (DBusPendingCall *pending, gpointer user_data)
if (caller_pid != 0)
client->caller_exec = egg_unix_credentials_executable (caller_pid);
client->app.applicationData = client;
- client->sessions = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, dispose_and_unref);
- client->prompts = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, dispose_and_unref);
+ client->dispatch = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, dispose_and_unref);
g_hash_table_replace (self->clients, client->caller_peer, client);
@@ -371,10 +370,8 @@ static DBusMessage*
service_method_open_session (GkdSecretService *self, DBusMessage *message)
{
GkdSecretSession *session;
- ServiceClient *client;
DBusMessage *reply = NULL;
const gchar *caller;
- const gchar *path;
if (!dbus_message_has_signature (message, "sv"))
return NULL;
@@ -385,18 +382,11 @@ service_method_open_session (GkdSecretService *self, DBusMessage *message)
session = gkd_secret_session_new (self, caller);
reply = gkd_secret_session_handle_open (session, message);
- if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN) {
- /* Take ownership of the session */
- client = g_hash_table_lookup (self->clients, caller);
- g_return_val_if_fail (client, NULL);
- path = gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (session));
- g_return_val_if_fail (!g_hash_table_lookup (client->sessions, path), NULL);
- g_hash_table_replace (client->sessions, (gpointer)path, session);
-
- } else {
- g_object_unref (session);
- }
+ if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+ gkd_secret_service_publish_dispatch (self, caller,
+ GKD_SECRET_DISPATCH (session));
+ g_object_unref (session);
return reply;
}
@@ -406,14 +396,14 @@ service_method_create_collection (GkdSecretService *self, DBusMessage *message)
DBusMessageIter iter, array;
GckAttributes *attrs;
GkdSecretCreate *create;
- ServiceClient *client;
DBusMessage *reply;
const gchar *path;
+ const gchar *alias;
const char *caller;
const gchar *coll;
/* Parse the incoming message */
- if (!dbus_message_has_signature (message, "a{sv}"))
+ if (!dbus_message_has_signature (message, "a{sv}s"))
return NULL;
if (!dbus_message_iter_init (message, &iter))
g_return_val_if_reached (NULL);
@@ -424,18 +414,31 @@ service_method_create_collection (GkdSecretService *self, DBusMessage *message)
return dbus_message_new_error_printf (message, DBUS_ERROR_INVALID_ARGS,
"Invalid properties");
}
+ if (!dbus_message_iter_next (&iter))
+ g_return_val_if_reached (NULL);
+ dbus_message_iter_get_basic (&iter, &alias);
+
+ /* Empty alias is no alias */
+ if (alias) {
+ if (!alias[0]) {
+ alias = NULL;
+ } else if (!g_str_equal (alias, "default")) {
+ gck_attributes_unref (attrs);
+ return dbus_message_new_error (message, DBUS_ERROR_NOT_SUPPORTED,
+ "Only the 'default' alias is supported");
+ }
+ }
gck_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
/* Create the prompt object, for the password */
caller = dbus_message_get_sender (message);
- create = gkd_secret_create_new (self, caller, attrs);
+ create = gkd_secret_create_new (self, caller, attrs, alias);
gck_attributes_unref (attrs);
path = gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (create));
- client = g_hash_table_lookup (self->clients, caller);
- g_return_val_if_fail (client, NULL);
- g_hash_table_replace (client->prompts, (gpointer)path, create);
+ gkd_secret_service_publish_dispatch (self, caller,
+ GKD_SECRET_DISPATCH (create));
coll = "/";
reply = dbus_message_new_method_return (message);
@@ -444,6 +447,7 @@ service_method_create_collection (GkdSecretService *self, DBusMessage *message)
DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_INVALID);
+ g_object_unref (create);
return reply;
}
@@ -461,7 +465,6 @@ static DBusMessage*
service_method_unlock (GkdSecretService *self, DBusMessage *message)
{
GkdSecretUnlock *unlock;
- ServiceClient *client;
DBusMessage *reply;
const char *caller;
const gchar *path;
@@ -474,17 +477,16 @@ service_method_unlock (GkdSecretService *self, DBusMessage *message)
return NULL;
caller = dbus_message_get_sender (message);
- unlock = gkd_secret_unlock_new (self, caller);
+ unlock = gkd_secret_unlock_new (self, caller, NULL);
for (i = 0; i < n_objpaths; ++i)
gkd_secret_unlock_queue (unlock, objpaths[i]);
dbus_free_string_array (objpaths);
/* So do we need to prompt? */
if (gkd_secret_unlock_have_queued (unlock)) {
- client = g_hash_table_lookup (self->clients, caller);
- g_return_val_if_fail (client, NULL);
+ gkd_secret_service_publish_dispatch (self, caller,
+ GKD_SECRET_DISPATCH (unlock));
path = gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (unlock));
- g_hash_table_replace (client->prompts, (gpointer)path, g_object_ref (unlock));
/* No need to prompt */
} else {
@@ -546,7 +548,6 @@ static DBusMessage*
service_method_change_lock (GkdSecretService *self, DBusMessage *message)
{
GkdSecretChange *change;
- ServiceClient *client;
DBusMessage *reply;
const char *caller;
const gchar *path;
@@ -564,10 +565,9 @@ service_method_change_lock (GkdSecretService *self, DBusMessage *message)
g_object_unref (collection);
change = gkd_secret_change_new (self, caller, path);
- client = g_hash_table_lookup (self->clients, caller);
- g_return_val_if_fail (client, NULL);
path = gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (change));
- g_hash_table_replace (client->prompts, (gpointer)path, g_object_ref (change));
+ gkd_secret_service_publish_dispatch (self, caller,
+ GKD_SECRET_DISPATCH (change));
reply = dbus_message_new_method_return (message);
dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
@@ -588,9 +588,7 @@ service_method_read_alias (GkdSecretService *self, DBusMessage *message)
if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &alias, DBUS_TYPE_INVALID))
return NULL;
- update_default (self, FALSE);
-
- identifier = gkd_secret_objects_get_alias (self->objects, alias);
+ identifier = gkd_secret_service_get_alias (self, alias);
if (identifier)
path = gkd_secret_util_build_path (SECRET_COLLECTION_PREFIX, identifier, -1);
@@ -647,11 +645,9 @@ service_method_set_alias (GkdSecretService *self, DBusMessage *message)
g_object_unref (collection);
- gkd_secret_objects_set_alias (self->objects, alias, identifier);
+ gkd_secret_service_set_alias (self, alias, identifier);
g_free (identifier);
- store_default (self);
-
return dbus_message_new_method_return (message);
}
@@ -907,17 +903,10 @@ service_dispatch_message (GkdSecretService *self, DBusMessage *message)
path = dbus_message_get_path (message);
g_return_if_fail (path);
- /* Dispatched to a session, find a session in this client */
- if (object_path_has_prefix (path, SECRET_SESSION_PREFIX)) {
- object = g_hash_table_lookup (client->sessions, path);
- if (object == NULL)
- reply = gkd_secret_error_no_such_object (message);
- else
- reply = gkd_secret_dispatch_message (GKD_SECRET_DISPATCH (object), message);
-
- /* Dispatched to a prompt, find a prompt in this client */
- } else if (object_path_has_prefix (path, SECRET_PROMPT_PREFIX)) {
- object = g_hash_table_lookup (client->prompts, path);
+ /* Dispatched to a session or prompt */
+ if (object_path_has_prefix (path, SECRET_SESSION_PREFIX) ||
+ object_path_has_prefix (path, SECRET_PROMPT_PREFIX)) {
+ object = g_hash_table_lookup (client->dispatch, path);
if (object == NULL)
reply = gkd_secret_error_no_such_object (message);
else
@@ -1064,6 +1053,7 @@ static void
gkd_secret_service_init (GkdSecretService *self)
{
self->clients = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_client);
+ self->aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
}
static void
@@ -1106,6 +1096,9 @@ gkd_secret_service_finalize (GObject *obj)
g_hash_table_destroy (self->clients);
self->clients = NULL;
+ g_hash_table_destroy (self->aliases);
+ self->aliases = NULL;
+
G_OBJECT_CLASS (gkd_secret_service_parent_class)->finalize (obj);
}
@@ -1251,6 +1244,7 @@ gkd_secret_service_lookup_session (GkdSecretService *self, const gchar *path,
const gchar *caller)
{
ServiceClient *client;
+ gpointer object;
g_return_val_if_fail (GKD_SECRET_IS_SERVICE (self), NULL);
g_return_val_if_fail (path, NULL);
@@ -1259,7 +1253,11 @@ gkd_secret_service_lookup_session (GkdSecretService *self, const gchar *path,
client = g_hash_table_lookup (self->clients, caller);
g_return_val_if_fail (client, NULL);
- return g_hash_table_lookup (client->sessions, path);
+ object = g_hash_table_lookup (client->dispatch, path);
+ if (object == NULL || !GKD_SECRET_IS_SESSION (object))
+ return NULL;
+
+ return GKD_SECRET_SESSION (object);
}
void
@@ -1277,5 +1275,53 @@ gkd_secret_service_close_session (GkdSecretService *self, GkdSecretSession *sess
g_return_if_fail (client);
path = gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (session));
- g_hash_table_remove (client->sessions, path);
+ g_hash_table_remove (client->dispatch, path);
+}
+
+const gchar*
+gkd_secret_service_get_alias (GkdSecretService *self, const gchar *alias)
+{
+ const gchar *identifier;
+
+ g_return_val_if_fail (GKD_SECRET_IS_SERVICE (self), NULL);
+ g_return_val_if_fail (alias, NULL);
+
+ identifier = g_hash_table_lookup (self->aliases, alias);
+ if (!identifier && g_str_equal (alias, "default")) {
+ update_default (self, TRUE);
+ identifier = g_hash_table_lookup (self->aliases, alias);
+ }
+ return identifier;
+}
+
+void
+gkd_secret_service_set_alias (GkdSecretService *self, const gchar *alias,
+ const gchar *identifier)
+{
+ g_return_if_fail (GKD_SECRET_IS_SERVICE (self));
+ g_return_if_fail (alias);
+
+ g_hash_table_replace (self->aliases, g_strdup (alias), g_strdup (identifier));
+
+ if (g_str_equal (alias, "default"))
+ store_default (self);
+}
+
+void
+gkd_secret_service_publish_dispatch (GkdSecretService *self, const gchar *caller,
+ GkdSecretDispatch *object)
+{
+ ServiceClient *client;
+ const gchar *path;
+
+ g_return_if_fail (GKD_SECRET_IS_SERVICE (self));
+ g_return_if_fail (caller);
+ g_return_if_fail (GKD_SECRET_IS_DISPATCH (object));
+
+ /* Take ownership of the session */
+ client = g_hash_table_lookup (self->clients, caller);
+ g_return_if_fail (client);
+ path = gkd_secret_dispatch_get_object_path (object);
+ g_return_if_fail (!g_hash_table_lookup (client->dispatch, path));
+ g_hash_table_replace (client->dispatch, (gpointer)path, g_object_ref (object));
}