mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00: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:
parent
ca70b1285d
commit
c1ddacf78f
@ -39,6 +39,7 @@ add_library(network STATIC
|
||||
proxy/socks4.c
|
||||
proxy/socks5.c
|
||||
proxy/telnet.c
|
||||
proxy/local.c
|
||||
proxy/interactor.c)
|
||||
|
||||
add_library(keygen STATIC
|
||||
|
266
proxy/local.c
Normal file
266
proxy/local.c
Normal file
@ -0,0 +1,266 @@
|
||||
/*
|
||||
* Implement LocalProxyOpener, a centralised system for setting up the
|
||||
* command string to be run by platform-specific local-subprocess
|
||||
* proxy types.
|
||||
*
|
||||
* The platform-specific local proxy code is expected to use this
|
||||
* system by calling local_proxy_opener() from
|
||||
* platform_new_connection(); then using the resulting
|
||||
* DeferredSocketOpener to make a deferred version of whatever local
|
||||
* socket type is used for talking to subcommands (Unix FdSocket,
|
||||
* Windows HandleSocket); then passing the 'Socket *' back to us via
|
||||
* local_proxy_opener_set_socket().
|
||||
*
|
||||
* The LocalProxyOpener object implemented by this code will set
|
||||
* itself up as an Interactor if possible, so that it can prompt for
|
||||
* the proxy username and/or password if they're referred to in the
|
||||
* command string but not given in the config (exactly as the Telnet
|
||||
* proxy does). Once it knows the exact command it wants to run -
|
||||
* whether that was done immediately or after user interaction - it
|
||||
* calls back to platform_setup_local_proxy() with the full command,
|
||||
* which is expected to actually start the subprocess and fill in the
|
||||
* missing details in the deferred socket, freeing the
|
||||
* LocalProxyOpener as a side effect.
|
||||
*/
|
||||
|
||||
#include "tree234.h"
|
||||
#include "putty.h"
|
||||
#include "network.h"
|
||||
#include "sshcr.h"
|
||||
#include "proxy/proxy.h"
|
||||
|
||||
typedef struct LocalProxyOpener {
|
||||
int crLine;
|
||||
|
||||
Socket *socket;
|
||||
char *formatted_cmd;
|
||||
Plug *plug;
|
||||
SockAddr *addr;
|
||||
int port;
|
||||
Conf *conf;
|
||||
|
||||
Interactor *clientitr;
|
||||
LogPolicy *clientlp;
|
||||
Seat *clientseat;
|
||||
prompts_t *prompts;
|
||||
int username_prompt_index, password_prompt_index;
|
||||
|
||||
Interactor interactor;
|
||||
DeferredSocketOpener opener;
|
||||
} LocalProxyOpener;
|
||||
|
||||
static void local_proxy_opener_free(DeferredSocketOpener *opener)
|
||||
{
|
||||
LocalProxyOpener *lp = container_of(opener, LocalProxyOpener, opener);
|
||||
burnstr(lp->formatted_cmd);
|
||||
if (lp->prompts)
|
||||
free_prompts(lp->prompts);
|
||||
sk_addr_free(lp->addr);
|
||||
conf_free(lp->conf);
|
||||
sfree(lp);
|
||||
}
|
||||
|
||||
static const DeferredSocketOpenerVtable LocalProxyOpener_openervt = {
|
||||
.free = local_proxy_opener_free,
|
||||
};
|
||||
|
||||
static char *local_proxy_opener_description(Interactor *itr)
|
||||
{
|
||||
return dupstr("connection via local command");
|
||||
}
|
||||
|
||||
static LogPolicy *local_proxy_opener_logpolicy(Interactor *itr)
|
||||
{
|
||||
LocalProxyOpener *lp = container_of(itr, LocalProxyOpener, interactor);
|
||||
return lp->clientlp;
|
||||
}
|
||||
|
||||
static Seat *local_proxy_opener_get_seat(Interactor *itr)
|
||||
{
|
||||
LocalProxyOpener *lp = container_of(itr, LocalProxyOpener, interactor);
|
||||
return lp->clientseat;
|
||||
}
|
||||
|
||||
static void local_proxy_opener_set_seat(Interactor *itr, Seat *seat)
|
||||
{
|
||||
LocalProxyOpener *lp = container_of(itr, LocalProxyOpener, interactor);
|
||||
lp->clientseat = seat;
|
||||
}
|
||||
|
||||
static const InteractorVtable LocalProxyOpener_interactorvt = {
|
||||
.description = local_proxy_opener_description,
|
||||
.logpolicy = local_proxy_opener_logpolicy,
|
||||
.get_seat = local_proxy_opener_get_seat,
|
||||
.set_seat = local_proxy_opener_set_seat,
|
||||
};
|
||||
|
||||
static void local_proxy_opener_cleanup_interactor(LocalProxyOpener *lp)
|
||||
{
|
||||
if (lp->clientseat) {
|
||||
interactor_return_seat(lp->clientitr);
|
||||
lp->clientitr = NULL;
|
||||
lp->clientseat = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void local_proxy_opener_coroutine(void *vctx)
|
||||
{
|
||||
LocalProxyOpener *lp = (LocalProxyOpener *)vctx;
|
||||
|
||||
crBegin(lp->crLine);
|
||||
|
||||
/*
|
||||
* Make an initial attempt to figure out the command we want, and
|
||||
* see if it tried to include a username or password that we don't
|
||||
* have.
|
||||
*/
|
||||
{
|
||||
unsigned flags;
|
||||
lp->formatted_cmd = format_telnet_command(
|
||||
lp->addr, lp->port, lp->conf, &flags);
|
||||
|
||||
if (lp->clientseat && (flags & (TELNET_CMD_MISSING_USERNAME |
|
||||
TELNET_CMD_MISSING_PASSWORD))) {
|
||||
burnstr(lp->formatted_cmd);
|
||||
lp->formatted_cmd = NULL;
|
||||
|
||||
/*
|
||||
* We're missing at least one of the two parts, and we
|
||||
* have an Interactor we can use to prompt for them, so
|
||||
* try it.
|
||||
*/
|
||||
lp->prompts = new_prompts();
|
||||
lp->prompts->callback = local_proxy_opener_coroutine;
|
||||
lp->prompts->callback_ctx = lp;
|
||||
lp->prompts->to_server = true;
|
||||
lp->prompts->from_server = false;
|
||||
lp->prompts->name = dupstr("Local proxy authentication");
|
||||
if (flags & TELNET_CMD_MISSING_USERNAME) {
|
||||
lp->username_prompt_index = lp->prompts->n_prompts;
|
||||
add_prompt(lp->prompts, dupstr("Proxy username: "), true);
|
||||
} else {
|
||||
lp->username_prompt_index = -1;
|
||||
}
|
||||
if (flags & TELNET_CMD_MISSING_PASSWORD) {
|
||||
lp->password_prompt_index = lp->prompts->n_prompts;
|
||||
add_prompt(lp->prompts, dupstr("Proxy password: "), false);
|
||||
} else {
|
||||
lp->password_prompt_index = -1;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int prompt_result = seat_get_userpass_input(
|
||||
interactor_announce(&lp->interactor), lp->prompts);
|
||||
if (prompt_result > 0) {
|
||||
break;
|
||||
} else if (prompt_result == 0) {
|
||||
local_proxy_opener_cleanup_interactor(lp);
|
||||
plug_closing_user_abort(lp->plug);
|
||||
/* That will have freed us, so we must just return
|
||||
* without calling any crStop */
|
||||
return;
|
||||
}
|
||||
crReturnV;
|
||||
}
|
||||
|
||||
if (lp->username_prompt_index != -1) {
|
||||
conf_set_str(
|
||||
lp->conf, CONF_proxy_username,
|
||||
prompt_get_result_ref(
|
||||
lp->prompts->prompts[lp->username_prompt_index]));
|
||||
}
|
||||
|
||||
if (lp->password_prompt_index != -1) {
|
||||
conf_set_str(
|
||||
lp->conf, CONF_proxy_password,
|
||||
prompt_get_result_ref(
|
||||
lp->prompts->prompts[lp->password_prompt_index]));
|
||||
}
|
||||
|
||||
free_prompts(lp->prompts);
|
||||
lp->prompts = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now format the command a second time, with the results of
|
||||
* those prompts written into lp->conf.
|
||||
*/
|
||||
lp->formatted_cmd = format_telnet_command(
|
||||
lp->addr, lp->port, lp->conf, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Log the command, with some changes. Firstly, we regenerate it
|
||||
* with the password masked; secondly, we escape control
|
||||
* characters so that the log message is printable.
|
||||
*/
|
||||
conf_set_str(lp->conf, CONF_proxy_password, "*password*");
|
||||
{
|
||||
char *censored_cmd = format_telnet_command(
|
||||
lp->addr, lp->port, lp->conf, NULL);
|
||||
|
||||
strbuf *logmsg = strbuf_new();
|
||||
put_datapl(logmsg, PTRLEN_LITERAL("Starting local proxy command: "));
|
||||
put_c_string_literal(logmsg, ptrlen_from_asciz(censored_cmd));
|
||||
|
||||
plug_log(lp->plug, PLUGLOG_PROXY_MSG, NULL, 0, logmsg->s, 0);
|
||||
strbuf_free(logmsg);
|
||||
sfree(censored_cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we're ready to actually do the platform-specific socket
|
||||
* setup.
|
||||
*/
|
||||
char *cmd = lp->formatted_cmd;
|
||||
lp->formatted_cmd = NULL;
|
||||
|
||||
local_proxy_opener_cleanup_interactor(lp);
|
||||
|
||||
char *error_msg = platform_setup_local_proxy(lp->socket, cmd);
|
||||
burnstr(cmd);
|
||||
|
||||
if (error_msg) {
|
||||
plug_closing_error(lp->plug, error_msg);
|
||||
sfree(error_msg);
|
||||
} else {
|
||||
/* If error_msg was NULL, there was no error in setup,
|
||||
* which means that platform_setup_local_proxy will have
|
||||
* called back to free us. So return without calling any
|
||||
* crStop. */
|
||||
return;
|
||||
}
|
||||
|
||||
crFinishV;
|
||||
}
|
||||
|
||||
DeferredSocketOpener *local_proxy_opener(
|
||||
SockAddr *addr, int port, Plug *plug, Conf *conf, Interactor *itr)
|
||||
{
|
||||
LocalProxyOpener *lp = snew(LocalProxyOpener);
|
||||
memset(lp, 0, sizeof(*lp));
|
||||
lp->plug = plug;
|
||||
lp->opener.vt = &LocalProxyOpener_openervt;
|
||||
lp->interactor.vt = &LocalProxyOpener_interactorvt;
|
||||
lp->addr = sk_addr_dup(addr);
|
||||
lp->port = port;
|
||||
lp->conf = conf_copy(conf);
|
||||
|
||||
if (itr) {
|
||||
lp->clientitr = itr;
|
||||
interactor_set_child(lp->clientitr, &lp->interactor);
|
||||
lp->clientlp = interactor_logpolicy(lp->clientitr);
|
||||
lp->clientseat = interactor_borrow_seat(lp->clientitr);
|
||||
}
|
||||
|
||||
return &lp->opener;
|
||||
}
|
||||
|
||||
void local_proxy_opener_set_socket(DeferredSocketOpener *opener,
|
||||
Socket *socket)
|
||||
{
|
||||
assert(opener->vt == &LocalProxyOpener_openervt);
|
||||
LocalProxyOpener *lp = container_of(opener, LocalProxyOpener, opener);
|
||||
lp->socket = socket;
|
||||
queue_toplevel_callback(local_proxy_opener_coroutine, lp);
|
||||
}
|
@ -105,6 +105,12 @@ prompts_t *proxy_new_prompts(ProxySocket *ps);
|
||||
char *format_telnet_command(SockAddr *addr, int port, Conf *conf,
|
||||
unsigned *flags_out);
|
||||
|
||||
DeferredSocketOpener *local_proxy_opener(
|
||||
SockAddr *addr, int port, Plug *plug, Conf *conf, Interactor *itr);
|
||||
void local_proxy_opener_set_socket(DeferredSocketOpener *opener,
|
||||
Socket *socket);
|
||||
char *platform_setup_local_proxy(Socket *socket, const char *cmd);
|
||||
|
||||
#include "cproxy.h"
|
||||
|
||||
#endif
|
||||
|
@ -14,79 +14,73 @@
|
||||
#include "network.h"
|
||||
#include "proxy/proxy.h"
|
||||
|
||||
char *platform_setup_local_proxy(Socket *socket, const char *cmd)
|
||||
{
|
||||
/*
|
||||
* Create the pipes to the proxy command, and spawn the proxy
|
||||
* command process.
|
||||
*/
|
||||
int to_cmd_pipe[2], from_cmd_pipe[2], cmd_err_pipe[2];
|
||||
if (pipe(to_cmd_pipe) < 0 ||
|
||||
pipe(from_cmd_pipe) < 0 ||
|
||||
pipe(cmd_err_pipe) < 0) {
|
||||
return dupprintf("pipe: %s", strerror(errno));
|
||||
}
|
||||
cloexec(to_cmd_pipe[1]);
|
||||
cloexec(from_cmd_pipe[0]);
|
||||
cloexec(cmd_err_pipe[0]);
|
||||
|
||||
int pid = fork();
|
||||
if (pid == 0) {
|
||||
close(0);
|
||||
close(1);
|
||||
dup2(to_cmd_pipe[0], 0);
|
||||
dup2(from_cmd_pipe[1], 1);
|
||||
close(to_cmd_pipe[0]);
|
||||
close(from_cmd_pipe[1]);
|
||||
dup2(cmd_err_pipe[1], 2);
|
||||
noncloexec(0);
|
||||
noncloexec(1);
|
||||
execl("/bin/sh", "sh", "-c", cmd, (void *)NULL);
|
||||
_exit(255);
|
||||
}
|
||||
|
||||
if (pid < 0) {
|
||||
return dupprintf("fork: %s", strerror(errno));
|
||||
}
|
||||
|
||||
close(to_cmd_pipe[0]);
|
||||
close(from_cmd_pipe[1]);
|
||||
close(cmd_err_pipe[1]);
|
||||
|
||||
setup_fd_socket(socket, from_cmd_pipe[0], to_cmd_pipe[1], cmd_err_pipe[0]);
|
||||
|
||||
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)
|
||||
{
|
||||
char *cmd;
|
||||
switch (conf_get_int(conf, CONF_proxy_type)) {
|
||||
case PROXY_CMD: {
|
||||
DeferredSocketOpener *opener = local_proxy_opener(
|
||||
addr, port, plug, conf, itr);
|
||||
Socket *socket = make_deferred_fd_socket(opener, addr, port, plug);
|
||||
local_proxy_opener_set_socket(opener, socket);
|
||||
return socket;
|
||||
}
|
||||
|
||||
int to_cmd_pipe[2], from_cmd_pipe[2], cmd_err_pipe[2], pid, proxytype;
|
||||
int infd, outfd, inerrfd;
|
||||
|
||||
proxytype = conf_get_int(conf, CONF_proxy_type);
|
||||
if (proxytype != PROXY_CMD && proxytype != PROXY_FUZZ)
|
||||
return NULL;
|
||||
|
||||
if (proxytype == PROXY_CMD) {
|
||||
cmd = format_telnet_command(addr, port, conf, NULL);
|
||||
|
||||
{
|
||||
char *logmsg = dupprintf("Starting local proxy command: %s", cmd);
|
||||
plug_log(plug, PLUGLOG_PROXY_MSG, NULL, 0, logmsg, 0);
|
||||
sfree(logmsg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the pipes to the proxy command, and spawn the proxy
|
||||
* command process.
|
||||
*/
|
||||
if (pipe(to_cmd_pipe) < 0 ||
|
||||
pipe(from_cmd_pipe) < 0 ||
|
||||
pipe(cmd_err_pipe) < 0) {
|
||||
sfree(cmd);
|
||||
return new_error_socket_fmt(plug, "pipe: %s", strerror(errno));
|
||||
}
|
||||
cloexec(to_cmd_pipe[1]);
|
||||
cloexec(from_cmd_pipe[0]);
|
||||
cloexec(cmd_err_pipe[0]);
|
||||
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
close(0);
|
||||
close(1);
|
||||
dup2(to_cmd_pipe[0], 0);
|
||||
dup2(from_cmd_pipe[1], 1);
|
||||
close(to_cmd_pipe[0]);
|
||||
close(from_cmd_pipe[1]);
|
||||
dup2(cmd_err_pipe[1], 2);
|
||||
noncloexec(0);
|
||||
noncloexec(1);
|
||||
execl("/bin/sh", "sh", "-c", cmd, (void *)NULL);
|
||||
_exit(255);
|
||||
}
|
||||
|
||||
sfree(cmd);
|
||||
|
||||
if (pid < 0)
|
||||
return new_error_socket_fmt(plug, "fork: %s", strerror(errno));
|
||||
|
||||
close(to_cmd_pipe[0]);
|
||||
close(from_cmd_pipe[1]);
|
||||
close(cmd_err_pipe[1]);
|
||||
|
||||
outfd = to_cmd_pipe[1];
|
||||
infd = from_cmd_pipe[0];
|
||||
inerrfd = cmd_err_pipe[0];
|
||||
} else {
|
||||
cmd = format_telnet_command(addr, port, conf, NULL);
|
||||
outfd = open("/dev/null", O_WRONLY);
|
||||
case PROXY_FUZZ: {
|
||||
char *cmd = format_telnet_command(addr, port, conf, NULL);
|
||||
int outfd = open("/dev/null", O_WRONLY);
|
||||
if (outfd == -1) {
|
||||
sfree(cmd);
|
||||
return new_error_socket_fmt(
|
||||
plug, "/dev/null: %s", strerror(errno));
|
||||
}
|
||||
infd = open(cmd, O_RDONLY);
|
||||
int infd = open(cmd, O_RDONLY);
|
||||
if (infd == -1) {
|
||||
Socket *toret = new_error_socket_fmt(
|
||||
plug, "%s: %s", cmd, strerror(errno));
|
||||
@ -95,8 +89,10 @@ Socket *platform_new_connection(SockAddr *addr, const char *hostname,
|
||||
return toret;
|
||||
}
|
||||
sfree(cmd);
|
||||
inerrfd = -1;
|
||||
}
|
||||
return make_fd_socket(infd, outfd, -1, addr, port, plug);
|
||||
}
|
||||
|
||||
return make_fd_socket(infd, outfd, inerrfd, addr, port, plug);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user