From c4f569e36782b916cc83183ef275832aa6c1cab9 Mon Sep 17 00:00:00 2001 From: Gerhard Rieger Date: Sat, 24 Aug 2024 14:22:49 +0200 Subject: [PATCH] Socks5 with 3 args and option socksport --- CHANGES | 3 +++ doc/socat.yo | 1 + test.sh | 13 +++++++++++-- xio-socks.c | 49 ++++++++++++++++++++++++++++++------------------- xio-socks.h | 1 + xio-socks5.c | 22 ++++++++++++++++------ xiohelp.c | 2 +- xioopts.h | 2 +- 8 files changed, 64 insertions(+), 29 deletions(-) diff --git a/CHANGES b/CHANGES index 87b6e5c..9c41d85 100644 --- a/CHANGES +++ b/CHANGES @@ -60,6 +60,9 @@ Features: Added option ai-all (sets AI_ALL flag of getaddrinfo() resolver) + Socks5 now also allows syntax without socks port, and supports option + socksport. + Porting: Changes for building and testing on NetBSD diff --git a/doc/socat.yo b/doc/socat.yo index 07f56c8..abfd991 100644 --- a/doc/socat.yo +++ b/doc/socat.yo @@ -1110,6 +1110,7 @@ label(ADDRESS_SOCKS5_CONNECT)dit(bf(tt(SOCKS5-CONNECT::/dev/null 2>&1; then unset SS fi fi -[ "$DEFS" ] && echo " NETSTAT=\"$(type netstat)\"" +[ "$DEFS" ] && echo "NETSTAT=\"$(type netstat 2>/dev/null)\"" # for some tests we need a network interface if type ip >/dev/null 2>&1; then @@ -976,6 +976,8 @@ childprocess () { # return a list of child process pids [killchild] childpids () { + local recursive i + if [ "X$1" = "X-r" ]; then recursive=1; shift; fi case "$UNAME" in AIX) l="$(ps -fade |grep "^........ ...... $(printf %6u $1)" |awk '{print($2);}')" ;; FreeBSD) l="$(ps -fl |grep "^[^ ][^ ]*[ ][ ]*[0-9][0-9]*[ ][ ]*$1[ ]" |awk '{print($2);}')" ;; @@ -992,6 +994,11 @@ childpids () { if [ -z "$l" ]; then return 1; fi + if [ "$recursive" ]; then + for i in $l; do + l="$l $(childpids -r $i)" + done + fi echo "$l" return 0 } @@ -18062,7 +18069,9 @@ printf "test $F_n $TEST... " $N eval $CMD0 >/dev/null 2>"${te}0" & pid0=$! sleep 1 -kill -INT $(childpids $pid0) 2>/dev/null +#echo childpids: $(childpids $pid0) +#echo childpids -r: $(childpids -r $pid0) +kill -INT $(childpids -r $pid0) 2>/dev/null wait 2>/dev/null if grep -q " W waitpid..: child .* exited with status 130" "${te}0"; then $PRINTF "$OK\n" diff --git a/xio-socks.c b/xio-socks.c index 1dc434b..d5234cb 100644 --- a/xio-socks.c +++ b/xio-socks.c @@ -29,12 +29,12 @@ enum { static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc); -const struct optdesc opt_socksport = { "socksport", NULL, OPT_SOCKSPORT, GROUP_IP_SOCKS4, PH_LATE, TYPE_STRING, OFUNC_SPEC }; -const struct optdesc opt_socksuser = { "socksuser", NULL, OPT_SOCKSUSER, GROUP_IP_SOCKS4, PH_LATE, TYPE_NAME, OFUNC_SPEC }; +const struct optdesc opt_socksport = { "socksport", NULL, OPT_SOCKSPORT, GROUP_IP_SOCKS, PH_LATE, TYPE_STRING, OFUNC_SPEC }; +const struct optdesc opt_socksuser = { "socksuser", NULL, OPT_SOCKSUSER, GROUP_IP_SOCKS, PH_LATE, TYPE_NAME, OFUNC_SPEC }; -const struct addrdesc xioaddr_socks4_connect = { "SOCKS4", 3, xioopen_socks4_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_IP_SOCKS4|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":::") }; +const struct addrdesc xioaddr_socks4_connect = { "SOCKS4", 3, xioopen_socks4_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_IP_SOCKS|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":::") }; -const struct addrdesc xioaddr_socks4a_connect = { "SOCKS4A", 3, xioopen_socks4_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_IP_SOCKS4|GROUP_CHILD|GROUP_RETRY, 1, 0, 0 HELP(":::") }; +const struct addrdesc xioaddr_socks4a_connect = { "SOCKS4A", 3, xioopen_socks4_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_IP_SOCKS|GROUP_CHILD|GROUP_RETRY, 1, 0, 0 HELP(":::") }; static int xioopen_socks4_connect( int argc, @@ -230,8 +230,31 @@ static int xioopen_socks4_connect( } -int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **socksport, struct socks4 *sockhead, size_t *headlen) { +int _xioopen_opt_socksport( + struct opt *opts, + char **socksport) +{ struct servent *se; + + if (retropt_string(opts, OPT_SOCKSPORT, socksport) < 0) { + if ((se = getservbyname("socks", "tcp")) != NULL) { + Debug1("\"socks/tcp\" resolves to %u", ntohs(se->s_port)); + if ((*socksport = Malloc(6)) == NULL) { + return STAT_NORETRY; + } + sprintf(*socksport, "%u", ntohs(se->s_port)); + } else { + Debug1("cannot resolve service \"socks/tcp\", using %s", SOCKSPORT); + if ((*socksport = strdup(SOCKSPORT)) == NULL) { + return STAT_NORETRY; + } + } + } + return 0; +} + + +int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **socksport, struct socks4 *sockhead, size_t *headlen) { char *userid; /* generate socks header - points to final target */ @@ -239,20 +262,8 @@ int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **soc sockhead->action = 1; sockhead->port = parseport(targetport, IPPROTO_TCP); /* network byte order */ - - if (retropt_string(opts, OPT_SOCKSPORT, socksport) < 0) { - if ((se = getservbyname("socks", "tcp")) != NULL) { - Debug1("\"socks/tcp\" resolves to %u", ntohs(se->s_port)); - if ((*socksport = Malloc(6)) == NULL) { - return -1; - } - sprintf(*socksport, "%u", ntohs(se->s_port)); - } else { - Debug1("cannot resolve service \"socks/tcp\", using %s", SOCKSPORT); - if ((*socksport = strdup(SOCKSPORT)) == NULL) { - errno = ENOMEM; return -1; - } - } + if (_xioopen_opt_socksport(opts, socksport) < 0) { + return STAT_NORETRY; } if (retropt_string(opts, OPT_SOCKSUSER, &userid) < 0) { diff --git a/xio-socks.h b/xio-socks.h index 4844b4b..b089ec2 100644 --- a/xio-socks.h +++ b/xio-socks.h @@ -20,6 +20,7 @@ extern const struct optdesc opt_socksuser; extern const struct addrdesc xioaddr_socks4_connect; extern const struct addrdesc xioaddr_socks4a_connect; +extern int _xioopen_opt_socksport(struct opt *opts, char **socksport); extern int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **socksport, struct socks4 *sockhead, size_t *headlen); extern int _xioopen_socks4_connect0(struct single *xfd, diff --git a/xio-socks5.c b/xio-socks5.c index d57008d..8543881 100644 --- a/xio-socks5.c +++ b/xio-socks5.c @@ -19,6 +19,7 @@ #include "xio-socket.h" #include "xio-ip.h" #include "xio-ipapp.h" +#include "xio-socks.h" /* _xioopen_opt_socksport() */ #include "xio-socks5.h" @@ -50,9 +51,9 @@ static int xioopen_socks5(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, const struct addrdesc *addrdesc); -const struct addrdesc xioaddr_socks5_connect = { "SOCKS5-CONNECT", 1+XIO_RDWR, xioopen_socks5, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_CHILD|GROUP_RETRY, SOCKS5_COMMAND_CONNECT, 0, 0 HELP("::::") }; +const struct addrdesc xioaddr_socks5_connect = { "SOCKS5-CONNECT", 1+XIO_RDWR, xioopen_socks5, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_IP_SOCKS|GROUP_CHILD|GROUP_RETRY, SOCKS5_COMMAND_CONNECT, 0, 0 HELP(":[:]::") }; -const struct addrdesc xioaddr_socks5_listen = { "SOCKS5-LISTEN", 1+XIO_RDWR, xioopen_socks5, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_CHILD|GROUP_RETRY, SOCKS5_COMMAND_BIND, 0, 0 HELP("::::") }; +const struct addrdesc xioaddr_socks5_listen = { "SOCKS5-LISTEN", 1+XIO_RDWR, xioopen_socks5, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_CHILD|GROUP_RETRY, SOCKS5_COMMAND_BIND, 0, 0 HELP(":[:]::") }; static const char * _xioopen_socks5_strerror(uint8_t r) { @@ -521,15 +522,20 @@ static int xioopen_socks5( Error1("%s: use option --experimental to acknowledge unmature state", argv[0]); return STAT_NORETRY; } - if (argc != 5) { + if (argc < 4 || argc > 5) { xio_syntax(argv[0], 4, argc-1, addrdesc->syntax); return STAT_NORETRY; } socks_server = argv[1]; - socks_port = argv[2]; - target_name = argv[3]; - target_port = argv[4]; + if (argc == 5) { + socks_port = argv[2]; + target_name = argv[3]; + target_port = argv[4]; + } else { + target_name = argv[2]; + target_port = argv[3]; + } if (sfd->howtoend == END_UNSPEC) sfd->howtoend = END_SHUTDOWN; @@ -539,6 +545,10 @@ static int xioopen_socks5( retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_bool(opts, OPT_FORK, &dofork); + if (_xioopen_opt_socksport(opts, (char **)&socks_port) < 0) { + return STAT_NORETRY; + } + result = _xioopen_ipapp_prepare(opts, &opts0, socks_server, socks_port, &pf, ipproto, sfd->para.socket.ip.ai_flags, diff --git a/xiohelp.c b/xiohelp.c index 9db54c4..1ba92a8 100644 --- a/xiohelp.c +++ b/xiohelp.c @@ -46,7 +46,7 @@ static const char *addressgroupnames[] = { "LISTEN", "SHELL", "CHILD", "RETRY", "TERMIOS", "RANGE", "PTY", "PARENT", "UNIX", "IP4", "IP6", "INTERFACE", - "UDP", "TCP", "SOCKS4", "OPENSSL", + "UDP", "TCP", "SOCKS", "OPENSSL", "PROCESS", "APPL", "HTTP", "undef", "POSIXMQ", "SCTP", "DCCP", "UDPLITE" } ; diff --git a/xioopts.h b/xioopts.h index 06fc250..ef3b31c 100644 --- a/xioopts.h +++ b/xioopts.h @@ -182,7 +182,7 @@ enum e_func { #define GROUP_IP_UDP 0x01000000 /* not yet used? */ #define GROUP_IP_TCP 0x02000000 -#define GROUP_IP_SOCKS4 0x04000000 +#define GROUP_IP_SOCKS 0x04000000 /* for socks4(a), socks5 */ #define GROUP_OPENSSL 0x08000000 #define GROUP_PROCESS 0x10000000 /* a process related option */