2003-05-06 19:52:31 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* local-proxy.c: Unix implementation of platform_new_connection(),
|
2003-05-06 19:52:31 +00:00
|
|
|
* supporting an OpenSSH-like proxy command.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
#include "tree234.h"
|
|
|
|
#include "putty.h"
|
|
|
|
#include "network.h"
|
2021-10-30 10:02:28 +00:00
|
|
|
#include "proxy/proxy.h"
|
2003-05-06 19:52:31 +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.
2021-12-22 12:03:28 +00:00
|
|
|
char *platform_setup_local_proxy(Socket *socket, const char *cmd)
|
2003-05-06 19:52:31 +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.
2021-12-22 12:03:28 +00:00
|
|
|
/*
|
|
|
|
* 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]);
|
2015-10-17 13:06:06 +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.
2021-12-22 12:03:28 +00:00
|
|
|
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);
|
|
|
|
}
|
2015-11-22 12:15:52 +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.
2021-12-22 12:03:28 +00:00
|
|
|
if (pid < 0) {
|
|
|
|
return dupprintf("fork: %s", strerror(errno));
|
|
|
|
}
|
2015-10-17 13:06:06 +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.
2021-12-22 12:03:28 +00:00
|
|
|
close(to_cmd_pipe[0]);
|
|
|
|
close(from_cmd_pipe[1]);
|
|
|
|
close(cmd_err_pipe[1]);
|
2003-05-06 19:52:31 +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.
2021-12-22 12:03:28 +00:00
|
|
|
setup_fd_socket(socket, from_cmd_pipe[0], to_cmd_pipe[1], cmd_err_pipe[0]);
|
2009-08-21 21:16:22 +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.
2021-12-22 12:03:28 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2018-10-07 13:55:32 +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.
2021-12-22 12:03:28 +00:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
2003-05-06 19:52:31 +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.
2021-12-22 12:03:28 +00:00
|
|
|
case PROXY_FUZZ: {
|
|
|
|
char *cmd = format_telnet_command(addr, port, conf, NULL);
|
|
|
|
int outfd = open("/dev/null", O_WRONLY);
|
2019-09-08 19:29:00 +00:00
|
|
|
if (outfd == -1) {
|
|
|
|
sfree(cmd);
|
|
|
|
return new_error_socket_fmt(
|
2018-10-07 13:55:32 +00:00
|
|
|
plug, "/dev/null: %s", strerror(errno));
|
2019-09-08 19:29: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.
2021-12-22 12:03:28 +00:00
|
|
|
int infd = open(cmd, O_RDONLY);
|
2019-09-08 19:29:00 +00:00
|
|
|
if (infd == -1) {
|
2019-05-04 14:47:33 +00:00
|
|
|
Socket *toret = new_error_socket_fmt(
|
|
|
|
plug, "%s: %s", cmd, strerror(errno));
|
2019-09-08 19:29:00 +00:00
|
|
|
sfree(cmd);
|
2019-05-04 14:47:33 +00:00
|
|
|
close(outfd);
|
2019-09-08 19:29:00 +00:00
|
|
|
return toret;
|
|
|
|
}
|
|
|
|
sfree(cmd);
|
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.
2021-12-22 12:03:28 +00:00
|
|
|
return make_fd_socket(infd, outfd, -1, addr, port, plug);
|
|
|
|
}
|
2003-05-06 19:52:31 +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.
2021-12-22 12:03:28 +00:00
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
2003-05-06 19:52:31 +00:00
|
|
|
}
|
2022-08-22 17:46:32 +00:00
|
|
|
|
|
|
|
Socket *platform_start_subprocess(const char *cmd, Plug *plug,
|
|
|
|
const char *prefix)
|
|
|
|
{
|
|
|
|
Socket *socket = make_deferred_fd_socket(
|
|
|
|
null_deferred_socket_opener(),
|
|
|
|
sk_nonamelookup("<local command>"), 0, plug);
|
|
|
|
char *err = platform_setup_local_proxy(socket, cmd);
|
|
|
|
fd_socket_set_psb_prefix(socket, prefix);
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
sk_close(socket);
|
|
|
|
socket = new_error_socket_fmt(plug, "%s", err);
|
|
|
|
sfree(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
return socket;
|
|
|
|
}
|