Andre Heinecke
2016-Oct-05 19:32 UTC
Socket forwarding with non existent remote directories
Hi openssh dev's, I love an truly appreciate the Socket forwarding feature in OpenSSH 6.7. i use it for forwarding the socket of GnuPG's agent (that handles the secret stuff) to remote machines. Usecase: ===== I am a remote worker and use gnupg agent forwarding to connect to our company infrastructure that makes heavy use of PGP encryption while keeping my key out of the hands of the company on a personal smartcard that is connected to my local system. Problem ==== Now with GnuPG 2.1.13 the socket directory changed from ~/.gnupg to /run/user/<uid>/gnupg on systems where /run/user/<uid> exists, to better accommodate systemd. I now have the problem that my config line: RemoteForward /var/run/user/10118/gnupg/S.gpg-agent /home/aheinecke/.gnupg/S.gpg-agent.extra Does not work if /var/run/user/10118/gnupg/ does not exist. OpenSSH does not create the directory and fails to forward the socket. That it does not exist is the usual case because systemd cleans up this directory on logout if no processes exist that are still accessing it. There are of course workarounds like creating that directory before the agent forwarding connection but they are workarounds and I'd like to have this working smoothly. The gpg-agent forwarding is an awesome feature for us. ( I documented it under https://wiki.gnupg.org/AgentForwarding ) In my opinion OpenSSH should create the parent directories of RemoteForwarded files if possible. Maybe as a configuration option? Do you agree? Or do you think that some other software component in this setup is behaving wrongly? Regards, Andre -- Andre Heinecke | ++49-541-335083-262 | http://www.intevation.de/ Intevation GmbH, Neuer Graben 17, 49074 Osnabr?ck | AG Osnabr?ck, HR B 18998 Gesch?ftsf?hrer: Frank Koormann, Bernhard Reiter, Dr. Jan-Oliver Wagner -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 630 bytes Desc: This is a digitally signed message part. URL: <http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20161005/9387f3ea/attachment.bin>
Daniel Kahn Gillmor
2016-Oct-05 22:31 UTC
Socket forwarding with non existent remote directories
On Wed 2016-10-05 15:32:36 -0400, Andre Heinecke wrote:> In my opinion OpenSSH should create the parent directories of > RemoteForwarded files if possible. Maybe as a configuration option? > Do you agree?fwiw, i think this would be useful. I could probably help Andre assemble a patch if there's no objection to the idea. --dkg -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 930 bytes Desc: not available URL: <http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20161005/50fd1b5a/attachment-0001.bin>
I'm not familiar enough with the syntax of RemoteForward to know which is the local socket and which the remote one, but if it's the remote end's directory that doesn't exist, that can be harder. Edge cases like: - The containing file system usually exists, but is not mounted at the time of login. - There is an error in expansion of the value (for example, the user's home directory was inadvertently reset in /etc/passwd, or the service that backs it gave a bad answer). - The directory exists, but cannot be stat()ed due to permissions (e.g., /var/run/user is mode 0111). Should sshd attempt to create the containing directory in those cases? Perhaps a better approach would be to find a way to use PAM or login scripts to create the needed directory where appropriate? -- jim knoble> On Oct 5, 2016, at 15:31, Daniel Kahn Gillmor <dkg at fifthhorseman.net> wrote: > >> On Wed 2016-10-05 15:32:36 -0400, Andre Heinecke wrote: >> In my opinion OpenSSH should create the parent directories of >> RemoteForwarded files if possible. Maybe as a configuration option? >> Do you agree? > > fwiw, i think this would be useful. I could probably help Andre > assemble a patch if there's no objection to the idea. > > --dkg > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
Daniel Kahn Gillmor
2016-Oct-06 18:56 UTC
Socket forwarding with non existent remote directories
On Thu 2016-10-06 00:57:02 -0400, Jim Knoble wrote:> I'm not familiar enough with the syntax of RemoteForward to know which is the local socket and which the remote one, but if it's the remote end's directory that doesn't exist, that can be harder. Edge cases like: > > - The containing file system usually exists, but is not mounted at the time of login. > - There is an error in expansion of the value (for example, the user's home directory was inadvertently reset in /etc/passwd, or the service that backs it gave a bad answer). > - The directory exists, but cannot be stat()ed due to permissions (e.g., /var/run/user is mode 0111). > > Should sshd attempt to create the containing directory in those cases?Currently, i think sshd tries to create the socket (as the non-priv user), and if that fails it gives up. I think sshd could first try to create the containing directory (as the non-priv user, of course), and ignore any failures. It would then proceed as it currently does. In Andre's case, systemd's PAM session hooks create /run/user/<uid>, but he wants to forward a socket to /run/user/<uid>/gnupg/S.gpg-agent. Arguably, the most "correct" fix would be to recursively try to create every directory component in the tree, but Andre's case would be handled just by creating one level of directory. For example, consider this simple (but untested) patch: diff --git a/misc.c b/misc.c index 9421b4d..a85caca 100644 --- a/misc.c +++ b/misc.c @@ -1153,6 +1153,7 @@ unix_listener(const char *path, int backlog, int unlink_first) { struct sockaddr_un sunaddr; int saved_errno, sock; + const char *parentdir; memset(&sunaddr, 0, sizeof(sunaddr)); sunaddr.sun_family = AF_UNIX; @@ -1174,6 +1175,9 @@ unix_listener(const char *path, int backlog, int unlink_first) if (unlink(path) != 0 && errno != ENOENT) error("unlink(%s): %.100s", path, strerror(errno)); } + parentdir = basename(path); + if (mkdir(parentdir, 0700) != 0 && errno != EEXIST) + error("mkdir(%s): %.100s", parentdir, strerror(errno)); if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) { saved_errno = errno; error("bind: %.100s", strerror(errno));> Perhaps a better approach would be to find a way to use PAM or login > scripts to create the needed directory where appropriate?i don't think login scripts would do the trick; users might forward sockets without initiating a login session, right? So it'd have to be PAM if you take this route. But having to twiddle your pam stack for each new sub-directory you want seems like not a great process. --dkg -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 930 bytes Desc: not available URL: <http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20161006/cd255950/attachment.bin>