1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-01 11:32:48 -05:00

Windows Pageant: establish a named-pipe server.

This reuses all the named-pipe IPC code I set up for connection
sharing a few years ago, to set up a named pipe with a predictable
name and speak the stream-oriented SSH agent protocol over it.

In this commit, we just set up the server, and there's no code that
speaks the client end of the new IPC yet. But my plan is that clients
should switch over to using this interface if possible, because it's
generally better: it doesn't have to be handled synchronously in the
middle of a GUI event loop (either in Pageant itself _or_ in its
client), and it's a better fit to the connection-oriented nature of
forwarded agent connections (so if any features ever appear in the
agent protocol that require state within a connection, we'll now be
able to support them).
This commit is contained in:
Simon Tatham
2020-01-01 15:55:06 +00:00
parent 39248737a4
commit f93b260694
4 changed files with 83 additions and 4 deletions

View File

@ -16,6 +16,7 @@
#include "misc.h"
#include "tree234.h"
#include "winsecur.h"
#include "wincapi.h"
#include "pageant.h"
#include "licence.h"
@ -1125,6 +1126,16 @@ void agent_schedule_callback(void (*callback)(void *, void *, int),
unreachable("all Pageant's own agent requests should be synchronous");
}
void logevent(LogContext *logctx, const char *event)
{
unreachable("Pageant can't create a LogContext, so this can't be called");
}
void noise_ultralight(NoiseSourceId id, unsigned long data)
{
/* Pageant doesn't use random numbers, so we ignore this */
}
void cleanup_exit(int code)
{
shutdown_help();
@ -1279,6 +1290,29 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
return 0;
}
#if !defined NO_SECURITY
/*
* Set up a named-pipe listener.
*/
{
Plug *pl_plug;
struct pageant_listen_state *pl = pageant_listener_new(&pl_plug);
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", pipename,
sk_socket_error(sock));
MessageBox(NULL, err, "Pageant Error", MB_ICONERROR | MB_OK);
return 1;
}
pageant_listener_got_socket(pl, sock);
sfree(pipename);
}
#endif /* !defined NO_SECURITY */
if (!prev) {
wndclass.style = 0;
wndclass.lpfnWndProc = WndProc;
@ -1300,6 +1334,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
WS_OVERLAPPEDWINDOW | WS_VSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT,
100, 100, NULL, NULL, inst, NULL);
winselgui_set_hwnd(hwnd);
/* Set up a system tray icon */
AddTrayIcon(hwnd);
@ -1332,13 +1367,35 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
/*
* Main message loop.
*/
while (GetMessage(&msg, NULL, 0, 0) == 1) {
if (!(IsWindow(keylist) && IsDialogMessage(keylist, &msg)) &&
!(IsWindow(aboutbox) && IsDialogMessage(aboutbox, &msg))) {
while (true) {
HANDLE *handles;
int nhandles, n;
handles = handle_get_events(&nhandles);
n = MsgWaitForMultipleObjects(nhandles, handles, false,
INFINITE, QS_ALLINPUT);
if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)nhandles) {
handle_got_event(handles[n - WAIT_OBJECT_0]);
sfree(handles);
} else
sfree(handles);
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT)
goto finished; /* two-level break */
if (IsWindow(keylist) && IsDialogMessage(keylist, &msg))
continue;
if (IsWindow(aboutbox) && IsDialogMessage(aboutbox, &msg))
continue;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
finished:
/* Clean up the system tray icon */
{

View File

@ -11,6 +11,7 @@
#ifndef NO_SECURITY
#include "winsecur.h"
#include "wincapi.h"
#endif
#define AGENT_COPYDATA_ID 0x804e50ba /* random goop */
@ -136,6 +137,21 @@ agent_pending_query *agent_query(
return NULL;
}
#ifndef NO_SECURITY
char *agent_named_pipe_name(void)
{
char *username, *suffix, *pipename;
username = get_username();
suffix = capi_obfuscate_string("Pageant");
pipename = dupprintf("\\\\.\\pipe\\pageant.%s.%s", username, suffix);
sfree(username);
sfree(suffix);
return pipename;
}
#endif /* NO_SECURITY */
Socket *agent_connect(void *vctx, Plug *plug)
{
unreachable("no agent_connect_ctx can be constructed on this platform");

View File

@ -653,6 +653,11 @@ struct handle_sink {
};
void handle_sink_init(handle_sink *sink, struct handle *h);
/*
* Exports from winpgntc.c.
*/
char *agent_named_pipe_name(void);
/*
* winpgntc.c needs to schedule callbacks for asynchronous agent
* requests. This has to be done differently in GUI and console, so