1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-04-11 08:08:06 -05:00

Windows Pageant: integrate with Windows OpenSSH.

After a discussion with a user recently, I investigated the Windows
native ssh.exe, and found it uses a Windows named pipe to talk to its
ssh-agent, in exactly the same way Pageant does. So if you tell
ssh.exe where to find Pageant's pipe, it can talk directly to Pageant,
and then you can have just one SSH agent.

The slight problem is that Pageant's pipe name is not stable. It's
generated using the same system as connection-sharing pipe names, and
contains a hex hash value whose preimage was fed through
CryptProtectData. And the problem with _that_ is that CryptProtectData
apparently reinitialises its seed between login sessions (though it's
stable within a login session), which I hadn't fully realised when I
reused the same pipe-name construction code.

One possibility, of course, would be to change Pageant so that it uses
a fixed pipe name. But after a bit of thought, I think I actually like
this feature, because the Windows named pipe namespace isn't
segregated into areas writable by only particular users, so anyone
using that namespace on a multiuser Windows box is potentially
vulnerable to someone else squatting on the name you wanted to use.
Using this system makes that harder, because the squatter won't be
able to predict what the name is going to be! (Unless you shut down
Pageant and start it up again within one login session - but there's
only so much we can do. And squatting is at most a DoS, because
PuTTY's named-pipe client code checks ownership of the other end of
the pipe in all cases.)

So instead I've gone for a different approach. Windows Pageant now
supports an extra command-line option to write out a snippet of
OpenSSH config file format on startup, containing an 'IdentityAgent'
directive which points at the location of its named pipe. So you can
use the 'Include' directive in your main .ssh/config to include this
extra snippet, and then ssh.exe invocations will be able to find
wherever the current Pageant has put its pipe.
This commit is contained in:
Simon Tatham 2022-01-15 18:36:22 +00:00
parent 11aa9ab8f3
commit 8a2883933d
2 changed files with 52 additions and 0 deletions

View File

@ -170,6 +170,28 @@ by the command, like this:
\c C:\PuTTY\pageant.exe d:\main.ppk -c C:\PuTTY\putty.exe
\S{pageant-cmdline-openssh} Integrating with Windows OpenSSH
When Pageant starts up, it can optionally write out a file containing
an OpenSSH configuration directive that tells the Windows \c{ssh.exe}
where to find Pageant. If you include this file from your Windows SSH
configuration, then \c{ssh.exe} should automatically use Pageant as
its agent, so that you can keep your keys in one place and have both
SSH clients able to use them.
The option is \c{--openssh-config}, and you follow it with a filename.
To refer to this file from your main OpenSSH configuration, you can
use the \cq{Include} directive. For example, you might run Pageant
like this:
\c pageant --openssh-config C:\Users\Simon\.ssh\pageant.conf
and then add a directive like this to your main \cq{.ssh\\config}
file:
\c Include C:\Users\Simon\.ssh\pageant.conf
\S{pageant-cmdline-keylist} Starting with the key list visible
Start Pageant with the \i\c{--keylist} option to show the main window

View File

@ -1390,6 +1390,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
bool show_keylist_on_startup = false;
int argc;
char **argv, **argstart;
const char *openssh_config_file = NULL;
typedef struct CommandLineKey {
Filename *fn;
@ -1487,6 +1488,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
add_keys_encrypted = true;
} else if (match_opt("-keylist")) {
show_keylist_on_startup = true;
} else if (match_optval("-openssh-config", "-openssh_config")) {
openssh_config_file = val;
} else if (match_opt("-c")) {
/*
* If we see `-c', then the rest of the command line
@ -1554,6 +1557,23 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
return 1;
}
pageant_listener_got_socket(pl, sock);
/*
* If we've been asked to write out an OpenSSH config file
* pointing at the named pipe, do so.
*/
if (openssh_config_file) {
FILE *fp = fopen(openssh_config_file, "w");
if (!fp) {
char *err = dupprintf("Unable to write OpenSSH config file "
"to %s", openssh_config_file);
MessageBox(NULL, err, "Pageant Error", MB_ICONERROR | MB_OK);
return 1;
}
fprintf(fp, "IdentityAgent %s\n", pipename);
fclose(fp);
}
sfree(pipename);
/*
@ -1752,6 +1772,16 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
if (keypath) filereq_free(keypath);
if (openssh_config_file) {
/*
* Leave this file around, but empty it, so that it doesn't
* refer to a pipe we aren't listening on any more.
*/
FILE *fp = fopen(openssh_config_file, "w");
if (fp)
fclose(fp);
}
cleanup_exit(msg.wParam);
return msg.wParam; /* just in case optimiser complains */
}