Auxiliary application: 'psocks', a simple SOCKS server.
This is built more or less entirely out of pieces I already had. The
SOCKS server code is provided by the dynamic forwarding code in
portfwd.c. When that accepts a connection request, it wants to talk to
an SSH ConnectionLayer, which is already a trait with interchangeable
implementations - so I just provide one of my own which only supports
the lportfwd_open() method. And that in turn returns an SshChannel
object, with a special trait implementation all of whose methods
just funnel back to an ordinary Socket.
Result: you get a Socket-to-Socket SOCKS implementation with no SSH
anywhere, and even a minimal amount of need to _pretend_ internally to
be an SSH implementation.
Additional features include the ability to log all the traffic in the
form of diagnostics to standard error, or log each direction of each
connection separately to a file, or for anything more general, to log
each direction of each connection through a pipe to a subcommand that
can filter out whatever you think are the interesting parts. Also, you
can spawn a subcommand after the SOCKS server is set up, and terminate
automatically when that subcommand does - e.g. you might use this to
wrap the execution of a single SOCKS-using program.
This is a modernisation of a diagnostic utility I've had kicking
around out-of-tree for a long time. With all of last year's
refactorings, it now becomes feasible to keep it in-tree without
needing huge amounts of scaffolding. Also, this version runs on
Windows, which is more than the old one did. (On Windows I haven't
implemented the subprocess parts, although there's no reason I
_couldn't_.)
As well as diagnostic uses, this may also be useful in some situations
as a thing to forward ports to: PuTTY doesn't currently support
reverse dynamic port forwarding (in which the remote listening port
acts as a SOCKS server), but you could get the same effect by
forwarding a remote port to a local instance of this. (Although, of
course, that's nothing you couldn't achieve using any other SOCKS
server.)
2020-02-23 16:27:04 +00:00
|
|
|
/*
|
|
|
|
* Main program for Unix psocks.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "putty.h"
|
|
|
|
#include "ssh.h"
|
|
|
|
#include "psocks.h"
|
|
|
|
|
|
|
|
typedef struct PsocksDataSinkPopen {
|
|
|
|
stdio_sink sink[2];
|
|
|
|
PsocksDataSink pds;
|
|
|
|
} PsocksDataSinkPopen;
|
|
|
|
|
|
|
|
static void popen_free(PsocksDataSink *pds)
|
|
|
|
{
|
|
|
|
PsocksDataSinkPopen *pdsp = container_of(pds, PsocksDataSinkPopen, pds);
|
|
|
|
for (size_t i = 0; i < 2; i++)
|
|
|
|
pclose(pdsp->sink[i].fp);
|
|
|
|
sfree(pdsp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PsocksDataSink *open_pipes(
|
|
|
|
const char *cmd, const char *const *direction_args,
|
|
|
|
const char *index_arg, char **err)
|
|
|
|
{
|
|
|
|
FILE *fp[2];
|
|
|
|
char *errmsg = NULL;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < 2; i++) {
|
|
|
|
/* No escaping needed: the provided command is already
|
|
|
|
* shell-quoted, and our extra arguments are simple */
|
|
|
|
char *command = dupprintf("%s %s %s", cmd,
|
|
|
|
direction_args[i], index_arg);
|
|
|
|
|
|
|
|
fp[i] = popen(command, "w");
|
|
|
|
sfree(command);
|
|
|
|
|
|
|
|
if (!fp[i]) {
|
|
|
|
if (!errmsg)
|
|
|
|
errmsg = dupprintf("%s", strerror(errno));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (errmsg) {
|
|
|
|
for (size_t i = 0; i < 2; i++)
|
|
|
|
if (fp[i])
|
|
|
|
pclose(fp[i]);
|
|
|
|
*err = errmsg;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
PsocksDataSinkPopen *pdsp = snew(PsocksDataSinkPopen);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < 2; i++) {
|
|
|
|
setvbuf(fp[i], NULL, _IONBF, 0);
|
|
|
|
stdio_sink_init(&pdsp->sink[i], fp[i]);
|
|
|
|
pdsp->pds.s[i] = BinarySink_UPCAST(&pdsp->sink[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
pdsp->pds.free = popen_free;
|
|
|
|
|
|
|
|
return &pdsp->pds;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int signalpipe[2] = { -1, -1 };
|
|
|
|
static void sigchld(int signum)
|
|
|
|
{
|
|
|
|
if (write(signalpipe[1], "x", 1) <= 0)
|
|
|
|
/* not much we can do about it */;
|
|
|
|
}
|
|
|
|
|
|
|
|
static pid_t subcommand_pid = -1;
|
|
|
|
|
|
|
|
static bool still_running = true;
|
|
|
|
|
New abstraction for command-line arguments.
This begins the process of enabling our Windows applications to handle
Unicode characters on their command lines which don't fit in the
system code page.
Instead of passing plain strings to cmdline_process_param, we now pass
a partially opaque and platform-specific thing called a CmdlineArg.
This has a method that extracts the argument word as a default-encoded
string, and another one that tries to extract it as UTF-8 (though it
may fail if the UTF-8 isn't available).
On Windows, the command line is now constructed by calling
split_into_argv_w on the Unicode command line returned by
GetCommandLineW(), and the UTF-8 method returns text converted
directly from that wide-character form, not going via the system code
page. So it _can_ include UTF-8 characters that wouldn't have
round-tripped via CP_ACP.
This commit introduces the abstraction and switches over the
cross-platform and Windows argv-handling code to use it, with minimal
functional change. Nothing yet tries to call cmdline_arg_get_utf8().
I say 'cross-platform and Windows' because on the Unix side there's
still a lot of use of plain old argv which I haven't converted. That
would be a much larger project, and isn't currently needed: the
_current_ aim of this abstraction is to get the right things to happen
relating to Unicode on Windows, so for code that doesn't run on
Windows anyway, it's not adding value. (Also there's a tension with
GTK, which wants to talk to standard argv and extract arguments _it_
knows about, so at the very least we'd have to let it munge argv
before importing it into this new system.)
2024-09-25 09:18:38 +00:00
|
|
|
static char **exec_args = NULL;
|
|
|
|
|
|
|
|
static void found_subcommand(CmdlineArg *arg)
|
|
|
|
{
|
|
|
|
exec_args = cmdline_arg_remainder(arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void start_subcommand(void)
|
Auxiliary application: 'psocks', a simple SOCKS server.
This is built more or less entirely out of pieces I already had. The
SOCKS server code is provided by the dynamic forwarding code in
portfwd.c. When that accepts a connection request, it wants to talk to
an SSH ConnectionLayer, which is already a trait with interchangeable
implementations - so I just provide one of my own which only supports
the lportfwd_open() method. And that in turn returns an SshChannel
object, with a special trait implementation all of whose methods
just funnel back to an ordinary Socket.
Result: you get a Socket-to-Socket SOCKS implementation with no SSH
anywhere, and even a minimal amount of need to _pretend_ internally to
be an SSH implementation.
Additional features include the ability to log all the traffic in the
form of diagnostics to standard error, or log each direction of each
connection separately to a file, or for anything more general, to log
each direction of each connection through a pipe to a subcommand that
can filter out whatever you think are the interesting parts. Also, you
can spawn a subcommand after the SOCKS server is set up, and terminate
automatically when that subcommand does - e.g. you might use this to
wrap the execution of a single SOCKS-using program.
This is a modernisation of a diagnostic utility I've had kicking
around out-of-tree for a long time. With all of last year's
refactorings, it now becomes feasible to keep it in-tree without
needing huge amounts of scaffolding. Also, this version runs on
Windows, which is more than the old one did. (On Windows I haven't
implemented the subprocess parts, although there's no reason I
_couldn't_.)
As well as diagnostic uses, this may also be useful in some situations
as a thing to forward ports to: PuTTY doesn't currently support
reverse dynamic port forwarding (in which the remote listening port
acts as a SOCKS server), but you could get the same effect by
forwarding a remote port to a local instance of this. (Although, of
course, that's nothing you couldn't achieve using any other SOCKS
server.)
2020-02-23 16:27:04 +00:00
|
|
|
{
|
|
|
|
pid_t pid;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up the pipe we'll use to tell us about SIGCHLD.
|
|
|
|
*/
|
|
|
|
if (pipe(signalpipe) < 0) {
|
|
|
|
perror("pipe");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
putty_signal(SIGCHLD, sigchld);
|
|
|
|
|
|
|
|
pid = fork();
|
|
|
|
if (pid < 0) {
|
|
|
|
perror("fork");
|
|
|
|
exit(1);
|
|
|
|
} else if (pid == 0) {
|
|
|
|
execvp(exec_args[0], exec_args);
|
|
|
|
perror("exec");
|
|
|
|
_exit(127);
|
|
|
|
} else {
|
|
|
|
subcommand_pid = pid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const PsocksPlatform platform = {
|
|
|
|
open_pipes,
|
New abstraction for command-line arguments.
This begins the process of enabling our Windows applications to handle
Unicode characters on their command lines which don't fit in the
system code page.
Instead of passing plain strings to cmdline_process_param, we now pass
a partially opaque and platform-specific thing called a CmdlineArg.
This has a method that extracts the argument word as a default-encoded
string, and another one that tries to extract it as UTF-8 (though it
may fail if the UTF-8 isn't available).
On Windows, the command line is now constructed by calling
split_into_argv_w on the Unicode command line returned by
GetCommandLineW(), and the UTF-8 method returns text converted
directly from that wide-character form, not going via the system code
page. So it _can_ include UTF-8 characters that wouldn't have
round-tripped via CP_ACP.
This commit introduces the abstraction and switches over the
cross-platform and Windows argv-handling code to use it, with minimal
functional change. Nothing yet tries to call cmdline_arg_get_utf8().
I say 'cross-platform and Windows' because on the Unix side there's
still a lot of use of plain old argv which I haven't converted. That
would be a much larger project, and isn't currently needed: the
_current_ aim of this abstraction is to get the right things to happen
relating to Unicode on Windows, so for code that doesn't run on
Windows anyway, it's not adding value. (Also there's a tension with
GTK, which wants to talk to standard argv and extract arguments _it_
knows about, so at the very least we'd have to let it munge argv
before importing it into this new system.)
2024-09-25 09:18:38 +00:00
|
|
|
found_subcommand,
|
Auxiliary application: 'psocks', a simple SOCKS server.
This is built more or less entirely out of pieces I already had. The
SOCKS server code is provided by the dynamic forwarding code in
portfwd.c. When that accepts a connection request, it wants to talk to
an SSH ConnectionLayer, which is already a trait with interchangeable
implementations - so I just provide one of my own which only supports
the lportfwd_open() method. And that in turn returns an SshChannel
object, with a special trait implementation all of whose methods
just funnel back to an ordinary Socket.
Result: you get a Socket-to-Socket SOCKS implementation with no SSH
anywhere, and even a minimal amount of need to _pretend_ internally to
be an SSH implementation.
Additional features include the ability to log all the traffic in the
form of diagnostics to standard error, or log each direction of each
connection separately to a file, or for anything more general, to log
each direction of each connection through a pipe to a subcommand that
can filter out whatever you think are the interesting parts. Also, you
can spawn a subcommand after the SOCKS server is set up, and terminate
automatically when that subcommand does - e.g. you might use this to
wrap the execution of a single SOCKS-using program.
This is a modernisation of a diagnostic utility I've had kicking
around out-of-tree for a long time. With all of last year's
refactorings, it now becomes feasible to keep it in-tree without
needing huge amounts of scaffolding. Also, this version runs on
Windows, which is more than the old one did. (On Windows I haven't
implemented the subprocess parts, although there's no reason I
_couldn't_.)
As well as diagnostic uses, this may also be useful in some situations
as a thing to forward ports to: PuTTY doesn't currently support
reverse dynamic port forwarding (in which the remote listening port
acts as a SOCKS server), but you could get the same effect by
forwarding a remote port to a local instance of this. (Although, of
course, that's nothing you couldn't achieve using any other SOCKS
server.)
2020-02-23 16:27:04 +00:00
|
|
|
start_subcommand,
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool psocks_pw_setup(void *ctx, pollwrapper *pw)
|
|
|
|
{
|
|
|
|
if (signalpipe[0] >= 0)
|
|
|
|
pollwrap_add_fd_rwx(pw, signalpipe[0], SELECT_R);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void psocks_pw_check(void *ctx, pollwrapper *pw)
|
|
|
|
{
|
|
|
|
if (signalpipe[0] >= 0 &&
|
|
|
|
pollwrap_check_fd_rwx(pw, signalpipe[0], SELECT_R)) {
|
|
|
|
while (true) {
|
|
|
|
int status;
|
|
|
|
pid_t pid = waitpid(-1, &status, WNOHANG);
|
|
|
|
if (pid <= 0)
|
|
|
|
break;
|
|
|
|
if (pid == subcommand_pid)
|
|
|
|
still_running = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool psocks_continue(void *ctx, bool found_any_fd,
|
|
|
|
bool ran_any_callback)
|
|
|
|
{
|
|
|
|
return still_running;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
psocks_state *ps = psocks_new(&platform);
|
New abstraction for command-line arguments.
This begins the process of enabling our Windows applications to handle
Unicode characters on their command lines which don't fit in the
system code page.
Instead of passing plain strings to cmdline_process_param, we now pass
a partially opaque and platform-specific thing called a CmdlineArg.
This has a method that extracts the argument word as a default-encoded
string, and another one that tries to extract it as UTF-8 (though it
may fail if the UTF-8 isn't available).
On Windows, the command line is now constructed by calling
split_into_argv_w on the Unicode command line returned by
GetCommandLineW(), and the UTF-8 method returns text converted
directly from that wide-character form, not going via the system code
page. So it _can_ include UTF-8 characters that wouldn't have
round-tripped via CP_ACP.
This commit introduces the abstraction and switches over the
cross-platform and Windows argv-handling code to use it, with minimal
functional change. Nothing yet tries to call cmdline_arg_get_utf8().
I say 'cross-platform and Windows' because on the Unix side there's
still a lot of use of plain old argv which I haven't converted. That
would be a much larger project, and isn't currently needed: the
_current_ aim of this abstraction is to get the right things to happen
relating to Unicode on Windows, so for code that doesn't run on
Windows anyway, it's not adding value. (Also there's a tension with
GTK, which wants to talk to standard argv and extract arguments _it_
knows about, so at the very least we'd have to let it munge argv
before importing it into this new system.)
2024-09-25 09:18:38 +00:00
|
|
|
CmdlineArgList *arglist = cmdline_arg_list_from_argv(argc, argv);
|
|
|
|
psocks_cmdline(ps, arglist);
|
Auxiliary application: 'psocks', a simple SOCKS server.
This is built more or less entirely out of pieces I already had. The
SOCKS server code is provided by the dynamic forwarding code in
portfwd.c. When that accepts a connection request, it wants to talk to
an SSH ConnectionLayer, which is already a trait with interchangeable
implementations - so I just provide one of my own which only supports
the lportfwd_open() method. And that in turn returns an SshChannel
object, with a special trait implementation all of whose methods
just funnel back to an ordinary Socket.
Result: you get a Socket-to-Socket SOCKS implementation with no SSH
anywhere, and even a minimal amount of need to _pretend_ internally to
be an SSH implementation.
Additional features include the ability to log all the traffic in the
form of diagnostics to standard error, or log each direction of each
connection separately to a file, or for anything more general, to log
each direction of each connection through a pipe to a subcommand that
can filter out whatever you think are the interesting parts. Also, you
can spawn a subcommand after the SOCKS server is set up, and terminate
automatically when that subcommand does - e.g. you might use this to
wrap the execution of a single SOCKS-using program.
This is a modernisation of a diagnostic utility I've had kicking
around out-of-tree for a long time. With all of last year's
refactorings, it now becomes feasible to keep it in-tree without
needing huge amounts of scaffolding. Also, this version runs on
Windows, which is more than the old one did. (On Windows I haven't
implemented the subprocess parts, although there's no reason I
_couldn't_.)
As well as diagnostic uses, this may also be useful in some situations
as a thing to forward ports to: PuTTY doesn't currently support
reverse dynamic port forwarding (in which the remote listening port
acts as a SOCKS server), but you could get the same effect by
forwarding a remote port to a local instance of this. (Although, of
course, that's nothing you couldn't achieve using any other SOCKS
server.)
2020-02-23 16:27:04 +00:00
|
|
|
|
|
|
|
sk_init();
|
|
|
|
uxsel_init();
|
|
|
|
psocks_start(ps);
|
New abstraction for command-line arguments.
This begins the process of enabling our Windows applications to handle
Unicode characters on their command lines which don't fit in the
system code page.
Instead of passing plain strings to cmdline_process_param, we now pass
a partially opaque and platform-specific thing called a CmdlineArg.
This has a method that extracts the argument word as a default-encoded
string, and another one that tries to extract it as UTF-8 (though it
may fail if the UTF-8 isn't available).
On Windows, the command line is now constructed by calling
split_into_argv_w on the Unicode command line returned by
GetCommandLineW(), and the UTF-8 method returns text converted
directly from that wide-character form, not going via the system code
page. So it _can_ include UTF-8 characters that wouldn't have
round-tripped via CP_ACP.
This commit introduces the abstraction and switches over the
cross-platform and Windows argv-handling code to use it, with minimal
functional change. Nothing yet tries to call cmdline_arg_get_utf8().
I say 'cross-platform and Windows' because on the Unix side there's
still a lot of use of plain old argv which I haven't converted. That
would be a much larger project, and isn't currently needed: the
_current_ aim of this abstraction is to get the right things to happen
relating to Unicode on Windows, so for code that doesn't run on
Windows anyway, it's not adding value. (Also there's a tension with
GTK, which wants to talk to standard argv and extract arguments _it_
knows about, so at the very least we'd have to let it munge argv
before importing it into this new system.)
2024-09-25 09:18:38 +00:00
|
|
|
cmdline_arg_list_free(arglist);
|
Auxiliary application: 'psocks', a simple SOCKS server.
This is built more or less entirely out of pieces I already had. The
SOCKS server code is provided by the dynamic forwarding code in
portfwd.c. When that accepts a connection request, it wants to talk to
an SSH ConnectionLayer, which is already a trait with interchangeable
implementations - so I just provide one of my own which only supports
the lportfwd_open() method. And that in turn returns an SshChannel
object, with a special trait implementation all of whose methods
just funnel back to an ordinary Socket.
Result: you get a Socket-to-Socket SOCKS implementation with no SSH
anywhere, and even a minimal amount of need to _pretend_ internally to
be an SSH implementation.
Additional features include the ability to log all the traffic in the
form of diagnostics to standard error, or log each direction of each
connection separately to a file, or for anything more general, to log
each direction of each connection through a pipe to a subcommand that
can filter out whatever you think are the interesting parts. Also, you
can spawn a subcommand after the SOCKS server is set up, and terminate
automatically when that subcommand does - e.g. you might use this to
wrap the execution of a single SOCKS-using program.
This is a modernisation of a diagnostic utility I've had kicking
around out-of-tree for a long time. With all of last year's
refactorings, it now becomes feasible to keep it in-tree without
needing huge amounts of scaffolding. Also, this version runs on
Windows, which is more than the old one did. (On Windows I haven't
implemented the subprocess parts, although there's no reason I
_couldn't_.)
As well as diagnostic uses, this may also be useful in some situations
as a thing to forward ports to: PuTTY doesn't currently support
reverse dynamic port forwarding (in which the remote listening port
acts as a SOCKS server), but you could get the same effect by
forwarding a remote port to a local instance of this. (Although, of
course, that's nothing you couldn't achieve using any other SOCKS
server.)
2020-02-23 16:27:04 +00:00
|
|
|
|
|
|
|
cli_main_loop(psocks_pw_setup, psocks_pw_check, psocks_continue, NULL);
|
|
|
|
}
|