diff --git a/daemon/dbus/gkd-secret-service.c b/daemon/dbus/gkd-secret-service.c index 7a4458152243967a8092b378d36aa3143dfbd0f0..090923423b7b41218ae54dc4c2a0d402d19b89d0 100644 --- a/daemon/dbus/gkd-secret-service.c +++ b/daemon/dbus/gkd-secret-service.c @@ -422,18 +422,30 @@ service_method_open_session (GkdExportedService *skeleton, GError *error = NULL; const gchar *caller; GVariant *input_payload; + gboolean opened; caller = g_dbus_method_invocation_get_sender (invocation); /* Now we can create a session with this information */ session = gkd_secret_session_new (self, caller); input_payload = g_variant_get_variant (input); - gkd_secret_session_handle_open (session, algorithm, input_payload, - &output, &result, - &error); + opened = gkd_secret_session_handle_open (session, algorithm, input_payload, + &output, &result, + &error); g_variant_unref (input_payload); - if (error != NULL) { + /* Branch on the return value, not on the error alone: a negotiate helper + * that bails out through g_return_val_if_fail() reports failure without + * ever setting one, and completing the call with a NULL body makes + * g_variant_new() abort the whole daemon. */ + if (!opened || output == NULL || result == NULL) { + if (error == NULL) + g_set_error_literal (&error, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Couldn't open a session for this caller."); + if (output != NULL) + g_variant_unref (g_variant_ref_sink (output)); + g_free (result); g_dbus_method_invocation_take_error (invocation, error); } else { gkd_secret_service_publish_dispatch (self, caller, @@ -1246,7 +1258,16 @@ gkd_secret_service_get_pkcs11_session (GkdSecretService *self, const gchar *call g_return_val_if_fail (caller, NULL); client = g_hash_table_lookup (self->clients, caller); - g_return_val_if_fail (client, NULL); + if (client == NULL) { + /* The record is normally created by a high priority idle queued from + * the message filter, but that idle is not ordered against the method + * call that queued it: a peer which connects and calls straight away + * can reach us first. Create it here instead of failing the call -- + * it is a hash table insert, not I/O. */ + gkd_secret_service_ensure_client (self, caller); + client = g_hash_table_lookup (self->clients, caller); + g_return_val_if_fail (client, NULL); + } /* Open a new session if necessary */ if (!client->pkcs11_session) { @@ -1381,6 +1402,10 @@ gkd_secret_service_publish_dispatch (GkdSecretService *self, const gchar *caller /* Take ownership of the session */ client = g_hash_table_lookup (self->clients, caller); + if (client == NULL) { + gkd_secret_service_ensure_client (self, caller); + 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)); diff --git a/daemon/dbus/gkd-secret-session.c b/daemon/dbus/gkd-secret-session.c index f84076dad3254d3e047c4d022f93ab914c9daf79..74d52982154f9f036b9768d806ddb03d00bcbf66 100644 --- a/daemon/dbus/gkd-secret-session.c +++ b/daemon/dbus/gkd-secret-session.c @@ -183,7 +183,12 @@ aes_negotiate (GkdSecretSession *self, gboolean ret; session = gkd_secret_service_get_pkcs11_session (self->service, self->caller); - g_return_val_if_fail (session, FALSE); + if (session == NULL) { + g_set_error_literal (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Couldn't open a session for this caller."); + return FALSE; + } if (!aes_create_dh_keys (session, "ietf-ike-grp-modp-1024", &pub, &priv)) { g_set_error_literal (error_out, G_DBUS_ERROR, @@ -250,7 +255,12 @@ plain_negotiate (GkdSecretSession *self, GckSession *session; session = gkd_secret_service_get_pkcs11_session (self->service, self->caller); - g_return_val_if_fail (session, FALSE); + if (session == NULL) { + g_set_error_literal (error_out, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Couldn't open a session for this caller."); + return FALSE; + } gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY); gck_builder_add_ulong (&builder, CKA_KEY_TYPE, CKK_G_NULL);