about summary refs log tree commit diff
path: root/modules/programs
diff options
context:
space:
mode:
Diffstat (limited to 'modules/programs')
-rw-r--r--modules/programs/gnupg/agent-wrapper.c54
-rw-r--r--modules/programs/gnupg/default.nix18
2 files changed, 52 insertions, 20 deletions
diff --git a/modules/programs/gnupg/agent-wrapper.c b/modules/programs/gnupg/agent-wrapper.c
index b5e623bc..d9cb7a0e 100644
--- a/modules/programs/gnupg/agent-wrapper.c
+++ b/modules/programs/gnupg/agent-wrapper.c
@@ -11,21 +11,19 @@
 #include <sys/un.h>
 #include <systemd/sd-daemon.h>
 
+#ifndef SUPERVISOR_SUPPORT
 static int main_fd = 0;
-static int ssh_fd = 0;
 static int scdaemon_fd = 0;
+#endif
 
-/* Get a systemd file descriptor corresponding to the specified socket path.
- *
- * Return values:
- *   -1 Socket path not a systemd socket
- *   -2 Provided socket path is not absolute
- *   -3 No suitable file descriptors in LISTEN_FDS
- *   -4 Error while determining LISTEN_FDS
- */
-static int get_sd_fd(const char *sockpath)
-{
+static int ssh_fd = 0;
+
+static int gather_sd_fds(void) {
+#ifdef SUPERVISOR_SUPPORT
+    if (ssh_fd == 0) {
+#else
     if (main_fd == 0 && ssh_fd == 0 && scdaemon_fd == 0) {
+#endif
         int num_fds;
         char **fdmap = NULL;
         void *libsystemd = NULL;
@@ -55,12 +53,14 @@ static int get_sd_fd(const char *sockpath)
 
         if (fdmap != NULL) {
             for (int i = 0; i < num_fds; i++) {
-                if (strncmp(fdmap[i], "main", 5) == 0)
-                    main_fd = SD_LISTEN_FDS_START + i;
-                else if (strncmp(fdmap[i], "ssh", 4) == 0)
+                if (strncmp(fdmap[i], "ssh", 4) == 0)
                     ssh_fd = SD_LISTEN_FDS_START + i;
+#ifndef SUPERVISOR_SUPPORT
+                else if (strncmp(fdmap[i], "main", 5) == 0)
+                    main_fd = SD_LISTEN_FDS_START + i;
                 else if (strncmp(fdmap[i], "scdaemon", 9) == 0)
                     scdaemon_fd = SD_LISTEN_FDS_START + i;
+#endif
                 free(fdmap[i]);
             }
             free(fdmap);
@@ -70,6 +70,26 @@ static int get_sd_fd(const char *sockpath)
             return -1;
     }
 
+    return 0;
+}
+
+#ifndef SUPERVISOR_SUPPORT
+
+/* Get a systemd file descriptor corresponding to the specified socket path.
+ *
+ * Return values:
+ *   -1 Socket path not a systemd socket
+ *   -2 Provided socket path is not absolute
+ *   -3 No suitable file descriptors in LISTEN_FDS
+ *   -4 Error while determining LISTEN_FDS
+ */
+static int get_sd_fd(const char *sockpath)
+{
+    int ret;
+
+    if ((ret = gather_sd_fds()) != 0)
+        return ret;
+
     char *basename = strrchr(sockpath, '/');
     if (basename == NULL)
         return -2;
@@ -215,6 +235,8 @@ pid_t fork(void)
     return _fork();
 }
 
+#endif /* !SUPERVISOR_SUPPORT */
+
 /* Get the PID of the client connected to the given socket FD. */
 static pid_t get_socket_pid(int sockfd)
 {
@@ -247,6 +269,10 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
 
     last_pid = 0;
 
+#ifdef SUPERVISOR_SUPPORT
+    if (ssh_fd == 0) gather_sd_fds();
+#endif
+
     if (retval != -1 && ssh_fd != 0 && sockfd == ssh_fd) {
         pid_t client_pid = get_socket_pid(retval);
         if (client_pid == -1) {
diff --git a/modules/programs/gnupg/default.nix b/modules/programs/gnupg/default.nix
index d938a184..db9bdc6b 100644
--- a/modules/programs/gnupg/default.nix
+++ b/modules/programs/gnupg/default.nix
@@ -8,6 +8,8 @@ let
   hasXdgSupport = versionAtLeast (getVersion cfg.package) "2.1.13";
   isDefaultHome = cfg.homeDir == ".gnupg";
 
+  hasSupervisorSupport = versionAtLeast (getVersion cfg.package) "2.1.16";
+
   sockDir = if hasXdgSupport && isDefaultHome
             then "%t/gnupg"
             else "%h/${cfg.homeDir}";
@@ -28,11 +30,12 @@ let
       UNIX-CONNECT:"${shellSockDir}/S.scdaemon"
   '';
 
-  agentWrapper = pkgs.runCommandCC "gpg-agent-wrapper" {
+  agentWrapper = withSupervisor: pkgs.runCommandCC "gpg-agent-wrapper" {
     buildInputs = with pkgs; [ pkgconfig systemd ];
     inherit pinentryWrapper;
   } ''
     cc -Wall -shared -std=c11 \
+      ${optionalString withSupervisor "-DSUPERVISOR_SUPPORT=1"} \
       -DLIBSYSTEMD=\"${pkgs.systemd.lib}/lib/libsystemd.so\" \
       -DPINENTRY_WRAPPER=\"$pinentryWrapper\" \
       $(pkg-config --cflags libsystemd) -ldl \
@@ -110,7 +113,7 @@ in {
     (mkIf (cfg.enable && cfg.agent.enable) {
       systemd.user.services.gpg-agent = {
         description = "GnuPG Agent";
-        environment.LD_PRELOAD = agentWrapper;
+        environment.LD_PRELOAD = agentWrapper hasSupervisorSupport;
         environment.GNUPGHOME = "~/${cfg.homeDir}";
 
         serviceConfig.ExecStart = toString ([
@@ -119,8 +122,9 @@ in {
           (if cfg.agent.scdaemon.enable
            then "--scdaemon-program=${scdaemonRedirector}"
            else "--disable-scdaemon")
-          "--no-detach"
-          "--daemon"
+          (if hasSupervisorSupport
+           then "--supervised"
+           else "--no-detach --daemon")
         ] ++ optional cfg.agent.sshSupport "--enable-ssh-support");
 
         serviceConfig.ExecReload = toString [
@@ -134,7 +138,9 @@ in {
         wantedBy = [ "sockets.target" ];
         description = "Main Socket For GnuPG Agent";
         listenStreams = singleton "${sockDir}/S.gpg-agent";
-        socketConfig = agentSocketConfig "main";
+        socketConfig = let
+          sockName = if hasSupervisorSupport then "std" else "main";
+        in agentSocketConfig sockName;
       };
     })
     (mkIf (cfg.enable && cfg.agent.enable && cfg.agent.scdaemon.enable) {
@@ -151,7 +157,7 @@ in {
 
       systemd.user.services.gnupg-scdaemon = {
         description = "GnuPG Smartcard Daemon";
-        environment.LD_PRELOAD = agentWrapper;
+        environment.LD_PRELOAD = agentWrapper false;
         environment.GNUPGHOME = "~/${cfg.homeDir}";
 
         serviceConfig.ExecStart = toString [