diff --git a/doc/pageant.but b/doc/pageant.but index 97d41087..8c19633d 100644 --- a/doc/pageant.but +++ b/doc/pageant.but @@ -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 diff --git a/windows/pageant.c b/windows/pageant.c index cb0abb97..63605043 100644 --- a/windows/pageant.c +++ b/windows/pageant.c @@ -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);