Page MenuHome GnuPG

systemd-user: Add service file to create the socketdir
Needs ReviewPublic

Authored by mattst88 on Jun 19 2017, 10:59 PM.

Details

Summary

When forwarding the GnuPG agent to a remote system running systemd over SSH, the /run/user/$UID/gnupg directory does not exist before SSH attempts to place a socket in it, causing agent forwarding to fail.

This systemd user service runs gpgconf --create-socketdir on login, allowing agent forwarding to work successfully.

Test Plan

Configure a local and remote system for GPG agent forwarding over SSH, as described by https://wiki.gnupg.org/AgentForwarding ; The remote system should be running systemd.

SSH to the remote system and see that remote forwarding fails:

Error: remote port forwarding failed for listen path /run/user/1000/gnupg/S.gpg-agent

This is because /run/user/1000/gnupg does not exist when SSH attempt to place the socket. The suggestion in the documentation to run "gpgconf --create-socketdir" from .bashrc/.zshrc does not work, because those are sourced after SSH attempts to place the socket.

Instead, using the proposed systemd user service to create the directory allows forwarding to work.

Diff Detail

Repository
rG GnuPG
Lint
Lint Skipped
Unit
Unit Tests Skipped

Event Timeline

aiui, the point here is to have the user "service" get triggered somehow (through pam's pam_systemd.so's session module?) before ssh goes ahead and forms the socket. is that right? If the pre-launch mechanism is pam, is there a reason to do it as a systemd user service? That won't work for systems that have pam but don't have systemd, whereas a pam module that creates these will work.

as i said in the mailing list thread, i think the right place to fix this is in OpenSSH itself -- it should be willing to try to create the leading directories to the socket path if possible when forwarding a socket.

so in order of preference for resolving this, i'm inclined to say:

  • OpenSSH
  • PAM module
  • *maybe* systemd

Even if systemd gets used, i'm not sure this is the right way to do it. if this wasn't a user service, the right mechanism would be tmpfiles.d (systemd-tmpfiles). But i don't know of a typical per-user analog for systemd-tmpfiles, and i'm not sure just running systemd-tmpfiles as a user service will behave the way we'd want it to. In any case, i thnk the unit file proposed here wants at least Type=oneshot and possibly RemainAfterExit=yes. but i don't think this is the right way to solve the underlying problem.

In D435#3175, @dkg wrote:

aiui, the point here is to have the user "service" get triggered somehow (through pam's pam_systemd.so's session module?) before ssh goes ahead and forms the socket. is that right? If the pre-launch mechanism is pam, is there a reason to do it as a systemd user service? That won't work for systems that have pam but don't have systemd, whereas a pam module that creates these will work.

As far as linux is concerned, today's systems do AFAIK almost all have systemd. For macOS and windows the situation is different.. but on macOS the socketdir is still $HOME/.gnupg (on my mac with gpgtools installed) and I am not sure if ssh socket forwarding works at all on windows as remote.

as i said in the mailing list thread, i think the right place to fix this is in OpenSSH itself -- it should be willing to try to create the leading directories to the socket path if possible when forwarding a socket.

The /run/users/<uid>/gnupg directory has permissions 700. If openssh would handle this and create the directory, it would not have a way to recognize the special permissions assigned to any forwarded sockets that users want. The socket forwarding mechanism is not only used for GnuPG. So there would need to be a generic way to create paths to the forwarded socket, with a generic handling for permissions. And this would make it very complicated, from the point of implementation as well as from the users viewpoint.

Apart from that the situation here is so special that I don't think openssh would (or even should) bother about it at all.

but i don't think this is the right way to solve the underlying problem.

Imho, the underlying problem is that the socketdir is not configurable. If it was, the user could let it point to any existing directory and manage the socket forwarding entirely by himself. And this workaround here wouldn't then be necessary.

My proposal is: make the socketdir configurable and document the issue for ssh socket forwarding.

BTW, I've run into the same issue today and it took me almost the whole day to fix it - by finally finding and applying this workaround. The systemd unit works perfectly, it does exactly the trick. But well, I agree in that I don't think this should be the official way to handle the issue...