[gnome-keyring/wip/dueno/secret-portal] dbus: Implement secret portal backend



commit 2e3d8539cd10b676867a17ea6068967f55c50121
Author: Daiki Ueno <dueno src gnome org>
Date:   Sat Jul 27 05:36:41 2019 +0200

    dbus: Implement secret portal backend

 daemon/dbus/Makefile.am                            |  26 +++-
 daemon/dbus/gkd-secret-service.c                   | 151 +++++++++++++++++++++
 daemon/dbus/org.freedesktop.impl.portal.Secret.xml |  65 +++++++++
 3 files changed, 241 insertions(+), 1 deletion(-)
---
diff --git a/daemon/dbus/Makefile.am b/daemon/dbus/Makefile.am
index 9d0b2e1a..13ad3b0b 100644
--- a/daemon/dbus/Makefile.am
+++ b/daemon/dbus/Makefile.am
@@ -32,10 +32,30 @@ daemon/dbus/gkd-internal-generated.h: daemon/dbus/org.gnome.keyring.InternalUnsu
 daemon/dbus/gkd-internal-generated.c: daemon/dbus/gkd-internal-generated.h
        @: # generated as a side-effect
 
+daemon/dbus/gkd-portal-generated.h: daemon/dbus/org.freedesktop.impl.portal.Secret.xml
+       $(AM_V_GEN) gdbus-codegen --interface-prefix org.freedesktop.impl.portal.Secret. \
+       --generate-c-code $(srcdir)/daemon/dbus/gkd-portal-generated \
+       --c-namespace Gkd \
+       --annotate "org.freedesktop.impl.portal.Secret" "org.gtk.GDBus.C.Name" ExportedPortal \
+       $(srcdir)/daemon/dbus/org.freedesktop.impl.portal.Secret.xml
+daemon/dbus/gkd-portal-generated.c: daemon/dbus/gkd-portal-generated.h
+       @: # generated as a side-effect
+
+daemon/dbus/gkd-portal-request-generated.h: daemon/dbus/org.freedesktop.impl.portal.Request.xml
+       $(AM_V_GEN) gdbus-codegen --interface-prefix org.freedesktop.impl.portal.Request. \
+       --generate-c-code $(srcdir)/daemon/dbus/gkd-portal-request-generated \
+       --c-namespace Gkd \
+       --annotate "org.freedesktop.impl.portal.Request" "org.gtk.GDBus.C.Name" ExportedPortalRequest \
+       $(srcdir)/daemon/dbus/org.freedesktop.impl.portal.Request.xml
+daemon/dbus/gkd-portal-request-generated.c: daemon/dbus/gkd-portal-request-generated.h
+       @: # generated as a side-effect
+
 EXTRA_DIST += \
        daemon/dbus/org.freedesktop.Secrets.xml \
        daemon/dbus/org.gnome.keyring.Daemon.xml \
        daemon/dbus/org.gnome.keyring.InternalUnsupportedGuiltRiddenInterface.xml \
+       daemon/dbus/org.freedesktop.impl.portal.Secret.xml \
+       daemon/dbus/org.freedesktop.impl.portal.Request.xml \
        $(NULL)
 
 BUILT_SOURCES += \
@@ -44,7 +64,11 @@ BUILT_SOURCES += \
        daemon/dbus/gkd-internal-generated.c \
        daemon/dbus/gkd-internal-generated.h \
        daemon/dbus/gkd-secrets-generated.c \
-       daemon/dbus/gkd-secrets-generated.h
+       daemon/dbus/gkd-secrets-generated.h \
+       daemon/dbus/gkd-portal-generated.c \
+       daemon/dbus/gkd-portal-generated.h \
+       daemon/dbus/gkd-portal-request-generated.c \
+       daemon/dbus/gkd-portal-request-generated.h
 
 libgkd_dbus_la_SOURCES = \
        $(BUILT_SOURCES) \
diff --git a/daemon/dbus/gkd-secret-service.c b/daemon/dbus/gkd-secret-service.c
index 69a42b4b..8fb7975a 100644
--- a/daemon/dbus/gkd-secret-service.c
+++ b/daemon/dbus/gkd-secret-service.c
@@ -37,6 +37,8 @@
 
 #include "gkd-internal-generated.h"
 #include "gkd-secrets-generated.h"
+#include "gkd-portal-generated.h"
+#include "gkd-portal-request-generated.h"
 
 #include "egg/egg-error.h"
 #include "egg/egg-unix-credentials.h"
@@ -126,6 +128,7 @@ struct _GkdSecretService {
        GDBusConnection *connection;
        GkdExportedService *skeleton;
        GkdExportedInternal *internal_skeleton;
+       GkdExportedPortal *portal_skeleton;
        guint name_owner_id;
        guint filter_id;
 
@@ -911,6 +914,141 @@ service_method_unlock_with_master_password (GkdExportedInternal *skeleton,
        return TRUE;
 }
 
+static gboolean
+service_method_close (GkdExportedPortalRequest *skeleton,
+                     GDBusMethodInvocation *invocation,
+                     GkdSecretService *self)
+{
+       g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (skeleton));
+       return TRUE;
+}
+
+static void
+retrieve_secret_thread (GTask *task,
+                       gpointer source_object,
+                       gpointer task_data,
+                       GCancellable *cancellable)
+{
+}
+
+static gboolean
+service_method_retrieve_secret (GkdExportedPortal *skeleton,
+                               GDBusMethodInvocation *invocation,
+                               GUnixFDList *fd_list,
+                               const gchar *arg_handle,
+                               const gchar *arg_app_id,
+                               GVariant *arg_fd,
+                               GVariant *arg_options,
+                               GkdSecretService *self)
+{
+       GVariantBuilder attributes = G_VARIANT_BUILDER_INIT ("a{sv}");
+       GckBuilder builder = GCK_BUILDER_INIT;
+       GckObject *search;
+       GkdSecretSecret *secret;
+       int idx, fd;
+       gpointer data = NULL;
+       GError *error = NULL;
+
+       request_skeleton = gkd_exported_portal_request_skeleton_new ();
+       if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (request_skeleton),
+                                              g_dbus_method_invocation_get_connection (invocation),
+                                              arg_handle, &error)) {
+               g_warning ("error exporting request: %s\n", error->message);
+               g_clear_error (&error);
+       } else {
+               g_signal_connect (request_skeleton, "handle-close",
+                                 G_CALLBACK (service_method_close), self);
+       }
+
+       g_variant_get (arg_fd, "h", &idx);
+       fd = g_unix_fd_list_get (fd_list, idx, NULL);
+
+       g_variant_builder_add (&attributes, "sv", "app_id", g_variant_new_string (app_id));
+       g_variant_builder_end (&attributes);
+
+       if (!gkd_secret_property_parse_fields (attributes, &builder)) {
+               gck_builder_clear (&builder);
+               g_dbus_method_invocation_return_error_literal (invocation,
+                                                              G_DBUS_ERROR,
+                                                              G_DBUS_ERROR_FAILED,
+                                                              "Invalid data in attributes argument");
+               return TRUE;
+       }
+       
+       /* Find items matching the collection and fields */
+       gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_SEARCH);
+       gck_builder_add_boolean (&builder, CKA_TOKEN, FALSE);
+       gck_builder_add_string (&builder, CKA_G_COLLECTION, "login");
+
+       /* Create the search object */
+       search = gck_session_create_object (session, gck_builder_end (&builder), NULL, &error);
+
+       if (error != NULL) {
+               g_dbus_method_invocation_return_error (invocation,
+                                                      G_DBUS_ERROR,
+                                                      G_DBUS_ERROR_FAILED,
+                                                      "Couldn't search for items: %s",
+                                                      error->message);
+               g_clear_error (&error);
+               return TRUE;
+       }
+
+       /* Get the matched item handles, and delete the search object */
+       data = gck_object_get_data (search, CKA_G_MATCHED, NULL, &n_data, &error);
+       gck_object_destroy (search, NULL, NULL);
+       g_object_unref (search);
+
+       if (error != NULL) {
+               g_dbus_method_invocation_return_error (invocation,
+                                                      G_DBUS_ERROR,
+                                                      G_DBUS_ERROR_FAILED,
+                                                      "Couldn't retrieve matched items: %s",
+                                                      error->message);
+               g_clear_error (&error);
+               return TRUE;
+       }
+
+       if (n_data > 0) {
+               /* Return the first matching item if any */
+               GList *items;
+
+               /* Build a list of object handles */
+               items = gck_objects_from_handle_array (session, data, n_data / sizeof (CK_OBJECT_HANDLE));
+               g_free (data);
+
+               secret = gkd_secret_session_get_item_secret (self->internal_session, items->data, &error);
+               if (secret == NULL) {
+                       g_dbus_method_invocation_take_error (invocation, error);
+                       return TRUE;
+               }
+               
+       } else {
+               /* Otherwise create a new key */
+       }
+
+       if (secret) {
+               gpointer data = secret->value;
+               gsize offset = 0;
+               while (offset < secret->n_value) {
+                       if (write (fd, data + offset, secret->n_value - offset) < 0) {
+                               
+                       }
+               }
+       }
+
+       gkd_exported_portal_complete_retrieve_secret (skeleton,
+                                                     invocation,
+                                                     NULL,
+                                                     0,
+                                                     NULL);
+
+ cleanup:
+       g_free (data);
+       gkd_secret_secret_free (secret);
+
+       return TRUE;
+}
+
 static void
 service_name_owner_changed (GDBusConnection *connection,
                            const gchar *sender_name,
@@ -1034,6 +1172,19 @@ gkd_secret_service_constructor (GType type,
        g_signal_connect (self->internal_skeleton, "handle-unlock-with-master-password",
                          G_CALLBACK (service_method_unlock_with_master_password), self);
 
+       self->portal_skeleton = gkd_exported_portal_skeleton_new ();
+       g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (self->portal_skeleton),
+                                         self->connection,
+                                         SECRET_SERVICE_PATH, &error);
+
+       if (error != NULL) {
+               g_warning ("could not register portal interface service on session bus: %s", error->message);
+               g_clear_error (&error);
+       }
+
+       g_signal_connect (self->portal_skeleton, "handle-retrieve-secret",
+                         G_CALLBACK (service_method_retrieve_secret), self);
+
        self->name_owner_id = g_dbus_connection_signal_subscribe (self->connection,
                                                                  NULL,
                                                                  "org.freedesktop.DBus",
diff --git a/daemon/dbus/org.freedesktop.impl.portal.Secret.xml 
b/daemon/dbus/org.freedesktop.impl.portal.Secret.xml
new file mode 100644
index 00000000..c33d85e2
--- /dev/null
+++ b/daemon/dbus/org.freedesktop.impl.portal.Secret.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0"?>
+<!--
+ Copyright (C) 2019 Red Hat, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+ Author: Daiki Ueno <dueno redhat com>
+-->
+
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd";>
+  <!--
+      org.freedesktop.impl.portal.Secret:
+      @short_description: Secret portal backend interface
+
+      The Secret portal allows sandboxed applications to retrieve a
+      per-application master secret.
+  -->
+  <interface name="org.freedesktop.impl.portal.Secret">
+
+    <!--
+        RetrieveSecret:
+        @handle: Object path for the #org.freedesktop.impl.portal.Request object representing this call
+        @app_id: App id of the application
+        @fd: File descriptor for reading the secret
+        @options: Vardict with optional further information
+        @results: Vardict with the results of the call
+
+        Retrieves a master secret for a sandboxed application.
+
+        Supported keys in the @options vardict include:
+        <variablelist>
+          <varlistentry>
+            <term>token s</term>
+            <listitem><para>
+             An opaque string associated with the retrieve secret.
+            </para></listitem>
+          </varlistentry>
+        </variablelist>
+    -->
+    <method name="RetrieveSecret">
+      <annotation name="org.gtk.GDBus.C.Name" value="retrieve_secret"/>
+      <annotation name="org.gtk.GDBus.C.UnixFD" value="true"/>
+      <arg type="o" name="handle" direction="in"/>
+      <arg type="s" name="app_id" direction="in"/>
+      <arg type="h" name="fd" direction="in"/>
+      <annotation name="org.qtproject.QtDBus.QtTypeName.In3" value="QVariantMap"/>
+      <arg type="a{sv}" name="options" direction="in"/>
+      <arg type="u" name="response" direction="out"/>
+      <annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="QVariantMap"/>
+      <arg type="a{sv}" name="results" direction="out"/>
+    </method>
+    <property name="version" type="u" access="read"/>
+  </interface>
+</node>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]