mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-03-13 02:23:50 -05:00

On both Unix and Windows, we now redirect the local proxy command's standard error into a third pipe; data received from that pipe is broken up at newlines and logged in the Event Log. So if the proxy command emits any error messages in the course of failing to connect to something, you now have a fighting chance of finding out what went wrong. This feature is disabled in command-line tools like PSFTP and Plink, on the basis that in that situation it seems more likely that the user would expect standard-error output to go to the ordinary standard error in the ordinary way. Only GUI PuTTY catches it and logs it like this, because it either doesn't have a standard error at all (on Windows) or is likely to be pointing it at some completely unhelpful session log file (under X).
116 lines
3.3 KiB
C
116 lines
3.3 KiB
C
/*
|
|
* winproxy.c: Windows implementation of platform_new_connection(),
|
|
* supporting an OpenSSH-like proxy command via the winhandl.c
|
|
* mechanism.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
|
|
#define DEFINE_PLUG_METHOD_MACROS
|
|
#include "tree234.h"
|
|
#include "putty.h"
|
|
#include "network.h"
|
|
#include "proxy.h"
|
|
|
|
Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, Plug plug,
|
|
int overlapped);
|
|
|
|
Socket platform_new_connection(SockAddr addr, const char *hostname,
|
|
int port, int privport,
|
|
int oobinline, int nodelay, int keepalive,
|
|
Plug plug, Conf *conf)
|
|
{
|
|
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;
|
|
SECURITY_ATTRIBUTES sa;
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
|
|
if (conf_get_int(conf, CONF_proxy_type) != PROXY_CMD)
|
|
return NULL;
|
|
|
|
cmd = format_telnet_command(addr, port, conf);
|
|
|
|
/* We are responsible for this and don't need it any more */
|
|
sk_addr_free(addr);
|
|
|
|
{
|
|
char *msg = dupprintf("Starting local proxy command: %s", cmd);
|
|
plug_log(plug, 2, NULL, 0, msg, 0);
|
|
sfree(msg);
|
|
}
|
|
|
|
/*
|
|
* Create the pipes to the proxy command, and spawn the proxy
|
|
* command process.
|
|
*/
|
|
sa.nLength = sizeof(sa);
|
|
sa.lpSecurityDescriptor = NULL; /* default */
|
|
sa.bInheritHandle = TRUE;
|
|
if (!CreatePipe(&us_from_cmd, &cmd_to_us, &sa, 0)) {
|
|
Socket ret =
|
|
new_error_socket("Unable to create pipes for proxy command", plug);
|
|
sfree(cmd);
|
|
return ret;
|
|
}
|
|
|
|
if (!CreatePipe(&cmd_from_us, &us_to_cmd, &sa, 0)) {
|
|
Socket ret =
|
|
new_error_socket("Unable to create pipes for proxy command", plug);
|
|
sfree(cmd);
|
|
CloseHandle(us_from_cmd);
|
|
CloseHandle(cmd_to_us);
|
|
return ret;
|
|
}
|
|
|
|
if (flags & FLAG_STDERR) {
|
|
/* If we have a sensible stderr, the proxy command can send
|
|
* its own standard error there, so we won't interfere. */
|
|
us_from_cmd_err = cmd_err_to_us = NULL;
|
|
} else {
|
|
/* If we don't have a sensible stderr, we should catch the
|
|
* proxy command's standard error to put in our event log. */
|
|
if (!CreatePipe(&us_from_cmd_err, &cmd_err_to_us, &sa, 0)) {
|
|
Socket ret = new_error_socket
|
|
("Unable to create pipes for proxy command", plug);
|
|
sfree(cmd);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
SetHandleInformation(us_to_cmd, HANDLE_FLAG_INHERIT, 0);
|
|
SetHandleInformation(us_from_cmd, HANDLE_FLAG_INHERIT, 0);
|
|
if (us_from_cmd_err != NULL)
|
|
SetHandleInformation(us_from_cmd_err, HANDLE_FLAG_INHERIT, 0);
|
|
|
|
si.cb = sizeof(si);
|
|
si.lpReserved = NULL;
|
|
si.lpDesktop = NULL;
|
|
si.lpTitle = NULL;
|
|
si.dwFlags = STARTF_USESTDHANDLES;
|
|
si.cbReserved2 = 0;
|
|
si.lpReserved2 = NULL;
|
|
si.hStdInput = cmd_from_us;
|
|
si.hStdOutput = cmd_to_us;
|
|
si.hStdError = cmd_err_to_us;
|
|
CreateProcess(NULL, cmd, NULL, NULL, TRUE,
|
|
CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS,
|
|
NULL, NULL, &si, &pi);
|
|
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,
|
|
plug, FALSE);
|
|
}
|