[gcr/wip/dueno/ssh-agent: 5/6] gcr-ssh-agent: Wire up systemd activation




commit 653beaa0e3dc53fb6b2af723f219f7b40451c717
Author: Daiki Ueno <dueno src gnome org>
Date:   Thu Feb 11 18:32:56 2021 +0100

    gcr-ssh-agent: Wire up systemd activation

 gcr/gcr-ssh-agent-service.c  | 70 ++++++++++++++++++++++++++++++++------------
 gcr/gcr-ssh-agent.service.in | 14 +++++++++
 gcr/gcr-ssh-agent.socket     | 11 +++++++
 gcr/meson.build              | 17 +++++++++--
 meson.build                  | 11 +++++++
 meson_options.txt            |  5 ++++
 6 files changed, 108 insertions(+), 20 deletions(-)
---
diff --git a/gcr/gcr-ssh-agent-service.c b/gcr/gcr-ssh-agent-service.c
index d677726..ad89440 100644
--- a/gcr/gcr-ssh-agent-service.c
+++ b/gcr/gcr-ssh-agent-service.c
@@ -39,6 +39,10 @@
 #include <glib/gstdio.h>
 #include <gcr/gcr-base.h>
 
+#ifdef WITH_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
+
 #include <glib/gi18n-lib.h>
 
 EGG_SECURE_DECLARE (ssh_agent);
@@ -370,27 +374,57 @@ on_closed (GcrSshAgentProcess *process,
 gboolean
 gcr_ssh_agent_service_start (GcrSshAgentService *self)
 {
-       gchar *path;
-       GError *error;
+       GError *error = NULL;
 
-       path = g_strdup_printf ("%s/ssh", self->path);
-       g_unlink (path);
-       self->address = g_unix_socket_address_new (path);
-       g_free (path);
+#if WITH_SYSTEMD
+       int ret;
 
-       error = NULL;
-       if (!g_socket_listener_add_address (self->listener,
-                                           self->address,
-                                           G_SOCKET_TYPE_STREAM,
-                                           G_SOCKET_PROTOCOL_DEFAULT,
-                                           NULL,
-                                           NULL,
-                                           &error)) {
-               g_warning ("couldn't listen on %s: %s",
-                          g_unix_socket_address_get_path (G_UNIX_SOCKET_ADDRESS (self->address)),
-                          error->message);
-               g_error_free (error);
+       ret = sd_listen_fds (0);
+       if (ret > 1) {
+               g_warning ("too many file descriptors received");
                return FALSE;
+       } else if (ret == 1) {
+               GSocket *socket;
+
+               socket = g_socket_new_from_fd (SD_LISTEN_FDS_START + 0, &error);
+               if (!socket) {
+                       g_warning ("couldn't create a socket: %s", error->message);
+                       g_error_free (error);
+                       return FALSE;
+               }
+               if (!g_socket_listener_add_socket (self->listener,
+                                                  socket,
+                                                  G_OBJECT (self),
+                                                  &error)) {
+                       g_warning ("couldn't bind socket on %d: %s",
+                                  g_socket_get_fd (socket),
+                                  error->message);
+                       g_object_unref (socket);
+                       g_error_free (error);
+                       return FALSE;
+               }
+       } else
+#endif
+       {
+               gchar *path;
+               path = g_strdup_printf ("%s/ssh", self->path);
+               g_unlink (path);
+               self->address = g_unix_socket_address_new (path);
+               g_free (path);
+
+               if (!g_socket_listener_add_address (self->listener,
+                                                   self->address,
+                                                   G_SOCKET_TYPE_STREAM,
+                                                   G_SOCKET_PROTOCOL_DEFAULT,
+                                                   NULL,
+                                                   NULL,
+                                                   &error)) {
+                       g_warning ("couldn't listen on %s: %s",
+                                  g_unix_socket_address_get_path (G_UNIX_SOCKET_ADDRESS (self->address)),
+                                  error->message);
+                       g_error_free (error);
+                       return FALSE;
+               }
        }
 
        g_signal_connect (self->listener, "run", G_CALLBACK (on_run), self);
diff --git a/gcr/gcr-ssh-agent.service.in b/gcr/gcr-ssh-agent.service.in
new file mode 100644
index 0000000..b2a9819
--- /dev/null
+++ b/gcr/gcr-ssh-agent.service.in
@@ -0,0 +1,14 @@
+[Unit]
+Description=ssh-agent wrapper
+
+Requires=gcr-ssh-agent.socket
+
+[Service]
+Type=simple
+StandardError=journal
+ExecStart=@libexecdir@/gcr-ssh-agent %t/gcr
+Restart=on-failure
+
+[Install]
+Also=gcr-ssh-agent.socket
+WantedBy=default.target
diff --git a/gcr/gcr-ssh-agent.socket b/gcr/gcr-ssh-agent.socket
new file mode 100644
index 0000000..31a3d4c
--- /dev/null
+++ b/gcr/gcr-ssh-agent.socket
@@ -0,0 +1,11 @@
+[Unit]
+Description=p11-kit server
+
+[Socket]
+Priority=6
+Backlog=5
+ListenStream=%t/p11-kit/pkcs11
+SocketMode=0600
+
+[Install]
+WantedBy=sockets.target
diff --git a/gcr/meson.build b/gcr/meson.build
index 87923f3..7a3b69a 100644
--- a/gcr/meson.build
+++ b/gcr/meson.build
@@ -250,7 +250,7 @@ if get_option('ssh_agent')
 
   gcr_ssh_agent = executable('gcr-ssh-agent',
     gcr_ssh_agent_lib_sources + [ 'gcr-ssh-agent.c' ],
-    dependencies: [ gcr_base_deps, gcr_base_dep, libsecret_dep ],
+    dependencies: [ gcr_base_deps, gcr_base_dep, libsecret_dep, libsystemd_deps ],
     c_args: [
       '-DGCR_COMPILATION',
       '-DGCR_API_SUBJECT_TO_CHANGE',
@@ -260,6 +260,19 @@ if get_option('ssh_agent')
     install_dir: get_option('libexecdir'),
   )
 
+  if with_systemd
+    configure_file(
+      input: 'gcr-ssh-agent.service.in',
+      output: '@BASENAME@',
+      configuration: {
+        'libexecdir': gcr_prefix / get_option('libexecdir'),
+      },
+      install_dir: systemduserunitdir,
+    )
+    install_data('gcr-ssh-agent.socket',
+                install_dir: systemduserunitdir)
+  endif
+
   gcr_ssh_agent_test_cflags = [
     '-DSRCDIR="@0@"'.format(source_root),
     '-D_GCR_TEST_SSH_ASKPASS_PATH="@0@"'.format(gcr_ssh_askpass.full_path()),
@@ -267,7 +280,7 @@ if get_option('ssh_agent')
 
   gcr_ssh_agent_test_lib = static_library('gcr-ssh-agent-test',
     sources: gcr_ssh_agent_lib_sources + [ 'gcr-ssh-agent-test.c' ],
-    dependencies: [ gcr_base_deps, gcr_base_dep, libsecret_dep ],
+    dependencies: [ gcr_base_deps, gcr_base_dep, libsecret_dep, libsystemd_deps ],
     c_args: [
       '-DGCR_COMPILATION',
       '-DGCR_API_SUBJECT_TO_CHANGE',
diff --git a/meson.build b/meson.build
index 98b8f35..fa0e3a0 100644
--- a/meson.build
+++ b/meson.build
@@ -55,6 +55,16 @@ libsecret_dep = dependency('libsecret-1', version: '>= 0.20', required: get_opti
 ssh_add_path = find_program('ssh-add', required: get_option('ssh_agent')).path()
 ssh_agent_path = find_program('ssh-agent', required: get_option('ssh_agent')).path()
 
+with_systemd = false
+libsystemd_deps = []
+libsystemd = dependency('libsystemd', required: get_option('systemd'))
+systemd = dependency('systemd', required: get_option('systemd'))
+if libsystemd.found() and systemd.found()
+  systemduserunitdir = systemd.get_pkgconfig_variable('systemduserunitdir')
+  libsystemd_deps += libsystemd
+  with_systemd = true
+endif
+
 if get_option('gtk')
   gtk_min_version = '3.22'
   gtk_dep = dependency('gtk+-3.0', version: '>=' + gtk_min_version)
@@ -74,6 +84,7 @@ conf.set_quoted('GPG_EXECUTABLE', gpg_path)
 conf.set_quoted('LIBGCRYPT_VERSION', libgcrypt_dep.version())
 conf.set_quoted('SSH_ADD_EXECUTABLE', ssh_add_path)
 conf.set_quoted('SSH_AGENT_EXECUTABLE', ssh_agent_path)
+conf.set10('WITH_SYSTEMD', with_systemd)
 config_file = configure_file(
   output: 'config.h',
   configuration: conf,
diff --git a/meson_options.txt b/meson_options.txt
index 17683d9..f96a47c 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -23,3 +23,8 @@ option('ssh_agent',
   value: true,
   description: 'Build ssh-agent binary',
 )
+option('systemd',
+  type: 'feature',
+  value: 'auto',
+  description: 'Use systemd socket activation for server programs'
+)


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