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

Rewrite local-proxy system to allow interactive prompts.

This fills in the remaining gap in the interactive prompt rework of
the proxy system in general. If you used the Telnet proxy with a
command containing %user or %pass, and hadn't filled in those
variables in the PuTTY config, then proxy/telnet.c would prompt you at
run time to enter the proxy auth details. But the local proxy command,
which uses the same format_telnet_command function, would not do that.
Now it does!

I've implemented this by moving the formatting of the proxy command
into a new module proxy/local.c, shared between both the Unix and
Windows local-proxy implementations. That module implements a
DeferredSocketOpener, which constructs the proxy command (prompting
first if necessary), and once it's constructed, hands it to a
per-platform function platform_setup_local_proxy().

So each platform-specific proxy function, instead of starting a
subprocess there and then and passing its details to make_fd_socket or
make_handle_socket, now returns a _deferred_ version of one of those
sockets, with the DeferredSocketOpener being the thing in
proxy/local.c. When that calls back to platform_setup_local_proxy(),
we actually start the subprocess and pass the resulting fds/handles to
the deferred socket to un-defer it.

A side effect of the rewrite is that when proxy commands are logged in
the Event Log, they now get the same amenities as in the Telnet proxy
type: the proxy password is sanitised out, and any difficult
characters are escaped.
This commit is contained in:
Simon Tatham
2021-12-22 12:03:28 +00:00
parent ca70b1285d
commit c1ddacf78f
5 changed files with 363 additions and 98 deletions

View File

@ -12,12 +12,8 @@
#include "network.h"
#include "proxy/proxy.h"
Socket *platform_new_connection(SockAddr *addr, const char *hostname,
int port, bool privport,
bool oobinline, bool nodelay, bool keepalive,
Plug *plug, Conf *conf, Interactor *itr)
char *platform_setup_local_proxy(Socket *socket, const char *cmd)
{
char *cmd;
HANDLE us_to_cmd, cmd_from_us;
HANDLE us_from_cmd, cmd_to_us;
HANDLE us_from_cmd_err, cmd_err_to_us;
@ -25,17 +21,6 @@ Socket *platform_new_connection(SockAddr *addr, const char *hostname,
STARTUPINFO si;
PROCESS_INFORMATION pi;
if (conf_get_int(conf, CONF_proxy_type) != PROXY_CMD)
return NULL;
cmd = format_telnet_command(addr, port, conf, NULL);
{
char *msg = dupprintf("Starting local proxy command: %s", cmd);
plug_log(plug, PLUGLOG_PROXY_MSG, NULL, 0, msg, 0);
sfree(msg);
}
/*
* Create the pipes to the proxy command, and spawn the proxy
* command process.
@ -44,30 +29,24 @@ Socket *platform_new_connection(SockAddr *addr, const char *hostname,
sa.lpSecurityDescriptor = NULL; /* default */
sa.bInheritHandle = true;
if (!CreatePipe(&us_from_cmd, &cmd_to_us, &sa, 0)) {
sfree(cmd);
return new_error_socket_fmt(
plug, "Unable to create pipes for proxy command: %s",
win_strerror(GetLastError()));
return dupprintf("Unable to create pipes for proxy command: %s",
win_strerror(GetLastError()));
}
if (!CreatePipe(&cmd_from_us, &us_to_cmd, &sa, 0)) {
sfree(cmd);
CloseHandle(us_from_cmd);
CloseHandle(cmd_to_us);
return new_error_socket_fmt(
plug, "Unable to create pipes for proxy command: %s",
win_strerror(GetLastError()));
return dupprintf("Unable to create pipes for proxy command: %s",
win_strerror(GetLastError()));
}
if (!CreatePipe(&us_from_cmd_err, &cmd_err_to_us, &sa, 0)) {
sfree(cmd);
CloseHandle(us_from_cmd);
CloseHandle(cmd_to_us);
CloseHandle(us_to_cmd);
CloseHandle(cmd_from_us);
return new_error_socket_fmt(
plug, "Unable to create pipes for proxy command: %s",
win_strerror(GetLastError()));
return dupprintf("Unable to create pipes for proxy command: %s",
win_strerror(GetLastError()));
}
SetHandleInformation(us_to_cmd, HANDLE_FLAG_INHERIT, 0);
@ -85,20 +64,37 @@ Socket *platform_new_connection(SockAddr *addr, const char *hostname,
si.hStdInput = cmd_from_us;
si.hStdOutput = cmd_to_us;
si.hStdError = cmd_err_to_us;
CreateProcess(NULL, cmd, NULL, NULL, true,
char *cmd_mutable = dupstr(cmd); /* CreateProcess needs non-const char * */
CreateProcess(NULL, cmd_mutable, NULL, NULL, true,
CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS,
NULL, NULL, &si, &pi);
sfree(cmd_mutable);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
sfree(cmd);
CloseHandle(cmd_from_us);
CloseHandle(cmd_to_us);
if (cmd_err_to_us != NULL)
CloseHandle(cmd_err_to_us);
return make_handle_socket(us_to_cmd, us_from_cmd, us_from_cmd_err,
addr, port, plug, false);
setup_handle_socket(socket, us_to_cmd, us_from_cmd, us_from_cmd_err,
false);
return NULL;
}
Socket *platform_new_connection(SockAddr *addr, const char *hostname,
int port, bool privport,
bool oobinline, bool nodelay, bool keepalive,
Plug *plug, Conf *conf, Interactor *itr)
{
if (conf_get_int(conf, CONF_proxy_type) != PROXY_CMD)
return NULL;
DeferredSocketOpener *opener = local_proxy_opener(
addr, port, plug, conf, itr);
Socket *socket = make_deferred_handle_socket(opener, addr, port, plug);
local_proxy_opener_set_socket(opener, socket);
return socket;
}