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

Windows Pageant: option to open an AF_UNIX socket.

There's now a command-line option to make Pageant open an AF_UNIX
socket at a pathname of your choice. This allows it to act as an SSH
agent for any client program willing to use a WinSock AF_UNIX socket.

In particular, this allows WSL 1 processes to talk directly to Windows
Pageant without needing any intermediate process, because the AF_UNIX
sockets in the WSL 1 world interoperate with WinSock's ones.

(However, not WSL 2, which isn't very surprising.)
This commit is contained in:
Simon Tatham 2022-01-27 20:37:50 +00:00
parent 82971a3ebb
commit 6f8db22972
2 changed files with 120 additions and 51 deletions

View File

@ -217,6 +217,45 @@ point at a different program. You could point it at
\cw{c:\\Windows\\System32\\OpenSSH\\ssh.exe} once you've done this
setup \dash but it's just as easy to point it at Plink!
\S{pageant-cmdline-unix} Unix-domain sockets: integrating with WSL 1
Pageant can listen on the WinSock implementation of \q{Unix-domain
sockets}. These interoperate with the Unix-domain sockets found in the
original Windows Subsystem for Linux (now known as WSL 1). So if you
ask Pageant to listen on one of these, then your WSL 1 processes can
talk directly to Pageant.
To configure this, run Pageant with the option \c{--unix}, followed
with a pathname. Then, in WSL 1, set the environment variable
\cw{SSH_AUTH_SOCK} to point at the WSL translation of that pathname.
For example, you might run
\c pageant --unix C:\Users\Simon\.ssh\agent.sock
and in WSL 1, set the environment variable
\c SSH_AUTH_SOCK=/mnt/c/Users/Simon/.ssh/agent.sock
Alternatively, you can add a line to your \cw{.ssh/config} file inside
WSL that says
\c IdentityAgent /mnt/c/Users/Simon/.ssh/agent.sock
although doing it like that may mean that \cw{ssh-add} commands won't
find the agent, even though \cw{ssh} itself will.
\s{Security note}: Unix-domain sockets are protected against access by
other users by the file protections on their containing directory. So
if your Windows machine is multiuser, make sure you create the socket
inside a directory that other users can't access at all. (In fact,
that's a good idea on general principles.)
\s{Compatibility note}: WSL 2 processes cannot talk to Pageant by this
mechanism, because WSL 2's Unix-domain sockets are managed by a
separate Linux kernel, and not by the same kernel that WinSock talks
to.
\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

@ -1391,6 +1391,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
{
MSG msg;
const char *command = NULL;
const char *unixsocket = NULL;
bool show_keylist_on_startup = false;
int argc;
char **argv, **argstart;
@ -1494,6 +1495,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
show_keylist_on_startup = true;
} else if (match_optval("-openssh-config", "-openssh_config")) {
openssh_config_file = val;
} else if (match_optval("-unix")) {
unixsocket = val;
} else if (match_opt("-c")) {
/*
* If we see `-c', then the rest of the command line
@ -1538,6 +1541,31 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
* running, so set up all the machinery to answer requests.
*/
if (!already_running) {
/*
* Set up the window class for the hidden window that receives
* all the messages to do with our presence in the system tray.
*/
if (!prev) {
WNDCLASS wndclass;
memset(&wndclass, 0, sizeof(wndclass));
wndclass.lpfnWndProc = TrayWndProc;
wndclass.hInstance = inst;
wndclass.hIcon = LoadIcon(inst, MAKEINTRESOURCE(IDI_MAINICON));
wndclass.lpszClassName = TRAYCLASSNAME;
RegisterClass(&wndclass);
}
keylist = NULL;
traywindow = CreateWindow(TRAYCLASSNAME, TRAYWINTITLE,
WS_OVERLAPPEDWINDOW | WS_VSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT,
100, 100, NULL, NULL, inst, NULL);
winselgui_set_hwnd(traywindow);
/*
* Initialise the cross-platform Pageant code.
*/
@ -1546,39 +1574,66 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
/*
* Set up a named-pipe listener.
*/
Plug *pl_plug;
wpc->plc.vt = &winpgnt_vtable;
wpc->plc.suppress_logging = true;
struct pageant_listen_state *pl =
pageant_listener_new(&pl_plug, &wpc->plc);
char *pipename = agent_named_pipe_name();
Socket *sock = new_named_pipe_listener(pipename, pl_plug);
if (sk_socket_error(sock)) {
char *err = dupprintf("Unable to open named pipe at %s "
"for SSH agent:\n%s", pipename,
sk_socket_error(sock));
MessageBox(NULL, err, "Pageant Error", MB_ICONERROR | MB_OK);
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);
{
Plug *pl_plug;
struct pageant_listen_state *pl =
pageant_listener_new(&pl_plug, &wpc->plc);
char *pipename = agent_named_pipe_name();
Socket *sock = new_named_pipe_listener(pipename, pl_plug);
if (sk_socket_error(sock)) {
char *err = dupprintf("Unable to open named pipe at %s "
"for SSH agent:\n%s", pipename,
sk_socket_error(sock));
MessageBox(NULL, err, "Pageant Error", MB_ICONERROR | MB_OK);
return 1;
}
fprintf(fp, "IdentityAgent %s\n", pipename);
fclose(fp);
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);
}
sfree(pipename);
/*
* Set up an AF_UNIX listener too, if we were asked to.
*/
if (unixsocket) {
sk_init();
/* FIXME: diagnose any error except file-not-found. Also,
* check the file type if possible? */
remove(unixsocket);
Plug *pl_plug;
struct pageant_listen_state *pl =
pageant_listener_new(&pl_plug, &wpc->plc);
Socket *sock = sk_newlistener_unix(unixsocket, pl_plug);
if (sk_socket_error(sock)) {
char *err = dupprintf("Unable to open AF_UNIX socket at %s "
"for SSH agent:\n%s", unixsocket,
sk_socket_error(sock));
MessageBox(NULL, err, "Pageant Error", MB_ICONERROR | MB_OK);
return 1;
}
pageant_listener_got_socket(pl, sock);
}
/*
* Set up the window class for the hidden window that receives
@ -1661,31 +1716,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
return 0;
}
/*
* Set up the window class for the hidden window that receives
* all the messages to do with our presence in the system tray.
*/
if (!prev) {
WNDCLASS wndclass;
memset(&wndclass, 0, sizeof(wndclass));
wndclass.lpfnWndProc = TrayWndProc;
wndclass.hInstance = inst;
wndclass.hIcon = LoadIcon(inst, MAKEINTRESOURCE(IDI_MAINICON));
wndclass.lpszClassName = TRAYCLASSNAME;
RegisterClass(&wndclass);
}
keylist = NULL;
traywindow = CreateWindow(TRAYCLASSNAME, TRAYWINTITLE,
WS_OVERLAPPEDWINDOW | WS_VSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT,
100, 100, NULL, NULL, inst, NULL);
winselgui_set_hwnd(traywindow);
/* Set up a system tray icon */
AddTrayIcon(traywindow);