mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 07:22:34 +00:00
Added socat-chain.sh for layering protocols
This commit is contained in:
parent
27877ea777
commit
e62f62e5b9
7 changed files with 442 additions and 21 deletions
4
CHANGES
4
CHANGES
|
@ -197,6 +197,10 @@ Features:
|
||||||
reads info from /proc/self/stat and searches for a device with matching
|
reads info from /proc/self/stat and searches for a device with matching
|
||||||
major and minor numbers.
|
major and minor numbers.
|
||||||
|
|
||||||
|
Added socat-chain.sh that makes it possible to stack protocols, e.g. to
|
||||||
|
drive socks through TLS, or to use TLS over a serial line.
|
||||||
|
Tests: SOCAT_CHAIN_SOCKS4 SOCAT_CHAIN_SSL_PTY
|
||||||
|
|
||||||
Corrections:
|
Corrections:
|
||||||
When a sub process (EXEC, SYSTEM) terminated with exit code other than
|
When a sub process (EXEC, SYSTEM) terminated with exit code other than
|
||||||
0, its last sent data might have been lost depending on timing of read/
|
0, its last sent data might have been lost depending on timing of read/
|
||||||
|
|
|
@ -76,7 +76,8 @@ HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.
|
||||||
|
|
||||||
|
|
||||||
DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT doc/socat.yo doc/socat.1 doc/socat.html FAQ BUGREPORTS COPYING COPYING.OpenSSL doc/dest-unreach.css doc/socat-openssltunnel.html doc/socat-multicast.html doc/socat-tun.html doc/socat-genericsocket.html
|
DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT doc/socat.yo doc/socat.1 doc/socat.html FAQ BUGREPORTS COPYING COPYING.OpenSSL doc/dest-unreach.css doc/socat-openssltunnel.html doc/socat-multicast.html doc/socat-tun.html doc/socat-genericsocket.html
|
||||||
SHFILES = daemon.sh mail.sh ftp.sh readline.sh \
|
SHFILES = socat-chain.sh \
|
||||||
|
daemon.sh mail.sh ftp.sh readline.sh \
|
||||||
socat_buildscript_for_android.sh
|
socat_buildscript_for_android.sh
|
||||||
TESTFILES = test.sh socks4echo.sh proxyecho.sh readline-test.sh \
|
TESTFILES = test.sh socks4echo.sh proxyecho.sh readline-test.sh \
|
||||||
proxy.sh socks4a-echo.sh
|
proxy.sh socks4a-echo.sh
|
||||||
|
@ -131,6 +132,7 @@ install: progs $(srcdir)/doc/socat.1
|
||||||
mkdir -p $(DESTDIR)$(BINDEST)
|
mkdir -p $(DESTDIR)$(BINDEST)
|
||||||
$(INSTALL) -m 755 socat $(DESTDIR)$(BINDEST)/socat1
|
$(INSTALL) -m 755 socat $(DESTDIR)$(BINDEST)/socat1
|
||||||
ln -s socat1 $(DESTDIR)$(BINDEST)/socat
|
ln -s socat1 $(DESTDIR)$(BINDEST)/socat
|
||||||
|
$(INSTALL) -m 755 socat-chain.sh $(DESTDIR)$(BINDEST)
|
||||||
$(INSTALL) -m 755 procan $(DESTDIR)$(BINDEST)
|
$(INSTALL) -m 755 procan $(DESTDIR)$(BINDEST)
|
||||||
$(INSTALL) -m 755 filan $(DESTDIR)$(BINDEST)
|
$(INSTALL) -m 755 filan $(DESTDIR)$(BINDEST)
|
||||||
mkdir -p $(DESTDIR)$(MANDEST)/man1
|
mkdir -p $(DESTDIR)$(MANDEST)/man1
|
||||||
|
@ -140,6 +142,7 @@ install: progs $(srcdir)/doc/socat.1
|
||||||
uninstall:
|
uninstall:
|
||||||
rm -f $(DESTDIR)$(BINDEST)/socat
|
rm -f $(DESTDIR)$(BINDEST)/socat
|
||||||
rm -f $(DESTDIR)$(BINDEST)/socat1
|
rm -f $(DESTDIR)$(BINDEST)/socat1
|
||||||
|
rm -f $(DESTDIR)$(BINDEST)/socat-chain.sh
|
||||||
rm -f $(DESTDIR)$(BINDEST)/procan
|
rm -f $(DESTDIR)$(BINDEST)/procan
|
||||||
rm -f $(DESTDIR)$(BINDEST)/filan
|
rm -f $(DESTDIR)$(BINDEST)/filan
|
||||||
rm -f $(DESTDIR)$(MANDEST)/man1/socat.1
|
rm -f $(DESTDIR)$(MANDEST)/man1/socat.1
|
||||||
|
|
264
socat-chain.sh
Executable file
264
socat-chain.sh
Executable file
|
@ -0,0 +1,264 @@
|
||||||
|
#! /usr/bin/env bash
|
||||||
|
# Copyright Gerhard Rieger and contributors (see file CHANGES)
|
||||||
|
# Published under the GNU General Public License V.2, see file COPYING
|
||||||
|
|
||||||
|
# Shell script to build a chain of Socat instances connected via TCP sockets.
|
||||||
|
# This allows to drive, e.g., PROXY-CONNECT over SSL, or SSL over serial.
|
||||||
|
# Currently only a chain made from 3 addresses, resulting in two instances, is
|
||||||
|
# implemented.
|
||||||
|
# The 2nd address must be one of OPENSSL (SSL), PROXY-CONNECT (PROXY),
|
||||||
|
# SOCKS4, SOCKS4A, SOCKS5
|
||||||
|
|
||||||
|
# This is beta!
|
||||||
|
|
||||||
|
# Examples:
|
||||||
|
|
||||||
|
# Drive HTTP CONNECT (PROXY) over SSL
|
||||||
|
# (establish an SSL tunnel to a proxy server, request being forwarded to a
|
||||||
|
# telnet server):
|
||||||
|
# socat-chain.sh \
|
||||||
|
# STDIO \
|
||||||
|
# PROXY::<telnet-server>:23 \
|
||||||
|
# OPENSSL:<proxy-server>:8443
|
||||||
|
|
||||||
|
# Accept connections that arrive on port 7777, encrypt the data, and send it
|
||||||
|
# via socks server to final target:
|
||||||
|
# socat-chain.sh \
|
||||||
|
# TCP-L:7777,reuseaddr,fork \
|
||||||
|
# OPENSSL,verify=0 \
|
||||||
|
# SOCKS4:<socks-server>:<ssl-server>:8443
|
||||||
|
|
||||||
|
# Receive SSL coming from a serial lie
|
||||||
|
# socat-chain.sh \
|
||||||
|
# /dev/ttyS0,cfmakeraw \
|
||||||
|
# SSL-L,cafile=server.pem,verify=0 \
|
||||||
|
# TCP4:localhost:80
|
||||||
|
|
||||||
|
# Formally, this is what happens:
|
||||||
|
# socat-chain.sh addr1 addr2 addr3
|
||||||
|
# results in something like:
|
||||||
|
# socat TCP-L:RANDOM addr3 &
|
||||||
|
# socat addr1 addr2:localhost:RANDOM
|
||||||
|
# or on passive/listening addr2:
|
||||||
|
# socat addr2:RANDOM addr3 &
|
||||||
|
# socat addr1 TCP:localhost:RANDOM
|
||||||
|
|
||||||
|
ECHO="echo -e"
|
||||||
|
|
||||||
|
usage () {
|
||||||
|
$ECHO "Usage: $0 <options> <address1> <address2> <address3>"
|
||||||
|
$ECHO " <address1> is typically a passive (listening) address like"
|
||||||
|
$ECHO " TCP-L:1234"
|
||||||
|
$ECHO " <address2> must be one of OPENSSL, PROXY, SOCK4, SOCKS4A, or SOCKS5,"
|
||||||
|
$ECHO " or SSL-L (passive/listening)"
|
||||||
|
$ECHO " Given server hostname and port are ignored and replaced by internal"
|
||||||
|
$ECHO " communication point"
|
||||||
|
$ECHO " <address3> is typically a client address with protocol like OPENSSL"
|
||||||
|
$ECHO " <options>:"
|
||||||
|
$ECHO " -d* -S <sigmask> -t <timeout> -T <timeout> are passed to socat"
|
||||||
|
$ECHO " -V prints the socat commands before starting them"
|
||||||
|
$ECHO "Example to drive SOCKS over TLS:"
|
||||||
|
$ECHO " $0 \\"
|
||||||
|
$ECHO " TCP4-L:1234,reuseaddr,fork \\"
|
||||||
|
$ECHO " SOCKS::<server>:<port> \\"
|
||||||
|
$ECHO " OPENSSL:10.2.3.4:12345,cafile=..."
|
||||||
|
$ECHO " Clients that connect to port 1234 will be forwarded to <server>:<port> using socks"
|
||||||
|
$ECHO " over TLS"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOCALHOST=127.0.0.1
|
||||||
|
|
||||||
|
VERBOSE= QUIET= OPTS=
|
||||||
|
while [ "$1" ]; do
|
||||||
|
case "X$1" in
|
||||||
|
X-h) usage; exit ;;
|
||||||
|
X-V) VERBOSE=1 ;;
|
||||||
|
X-q) QUIET=1; OPTS="-d0" ;;
|
||||||
|
X-d*|X-l?*) OPTS="$OPTS $1" ;;
|
||||||
|
X-b|X-S|X-t|X-T|X-l) OPT=$1; shift; OPTS="$OPTS $OPT $1" ;;
|
||||||
|
X-) break ;;
|
||||||
|
X-*) echo "$0: Unknown option \"$1\"" >&2
|
||||||
|
usage >&2
|
||||||
|
exit 1 ;;
|
||||||
|
*) break ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
ARG0="$1"
|
||||||
|
ARG1="$2"
|
||||||
|
ARG2="$3"
|
||||||
|
|
||||||
|
if [ -z "$ARG0" -o -z "$ARG1" -o -z "$ARG2" ]; then
|
||||||
|
echo "$0: Three addresses required" >&2
|
||||||
|
usage >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
mkprogname () {
|
||||||
|
ARG="$1"
|
||||||
|
if [[ "$ARG" =~ .*[:].* ]]; then
|
||||||
|
NAME="${ARG%%:*}"
|
||||||
|
elif [[ "$ARG" =~ .*[,].* ]]; then
|
||||||
|
NAME="${ARG%%,*}"
|
||||||
|
elif [ "X$ARG" = X- ]; then
|
||||||
|
NAME=stdio
|
||||||
|
else
|
||||||
|
NAME="$ARG"
|
||||||
|
fi
|
||||||
|
NAME="${NAME,,*}"
|
||||||
|
echo $NAME
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# You may place a fork option in the first address
|
||||||
|
# in which case the following internal listeners do fork too
|
||||||
|
FORK=
|
||||||
|
case "$ARG0" in
|
||||||
|
*,fork,*|*,fork) FORK=fork ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Split middle address for insertion of additional parts
|
||||||
|
if [[ "$ARG1" =~ .*,.* ]]; then
|
||||||
|
ARG1A="${ARG1%%,*}"
|
||||||
|
ARG1B="${ARG1#*,}"
|
||||||
|
else
|
||||||
|
ARG1A="$ARG1"
|
||||||
|
ARG1B=
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$0" in
|
||||||
|
*/*) SOCAT=${0%/*}/socat ;;
|
||||||
|
*) SOCAT=socat ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
PORT=$($SOCAT -d -d TCP4-L:0,accept-timeout=0.000001 /dev/null 2>&1 |grep listening |sed 's/.*:\([1-9][0-9]*\)$/\1/')
|
||||||
|
if [ -z "$PORT" ]; then
|
||||||
|
echo "$0: Failed to determine free TCP port" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PASSIVE= # is the second address passive/listening/server?
|
||||||
|
case "${ARG1A^^*}" in
|
||||||
|
OPENSSL|OPENSSL:*|SSL|SSL:.*)
|
||||||
|
OPTS1A=
|
||||||
|
#if [[ $ARG1A =~ ^\([^:]*\):\([^:]*\):\([^,]*\)\(.*\) ]]; then # bash 3
|
||||||
|
if [[ $ARG1A =~ ^([^:]*):([^:]*):([^,]*)(.*) ]]; then
|
||||||
|
OPTS1A="${BASH_REMATCH[4]}"
|
||||||
|
#elif [[ $ARG1A =~ ^\([^,]*\)\(.*\) ]]; then # bash 3
|
||||||
|
elif [[ $ARG1A =~ ^([^,]*)(.*) ]]; then
|
||||||
|
OPTS1A="${BASH_REMATCH[2]}"
|
||||||
|
else
|
||||||
|
echo "$0: \"$ARG1A\": invalid arguments" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
PROG1="${BASH_REMATCH[1]}"
|
||||||
|
NAME1=$(mkprogname "${BASH_REMATCH[1]}")
|
||||||
|
NAME2=$(mkprogname "$ARG2")
|
||||||
|
ARG1A=$PROG1:$LOCALHOST:$PORT$OPTS1A ;;
|
||||||
|
PROXY-CONNECT:*|PROXY:*)
|
||||||
|
#if ! [[ $ARG1A =~ ^\([^:]*\):\([^:]*\):\([^:]*\):\([^,]*\)\(.*\) ]]; then # bash 3
|
||||||
|
if ! [[ $ARG1A =~ ^([^:]*):([^:]*):([^:]*):([^,]*)(.*) ]]; then
|
||||||
|
echo "$0: \"$ARG1A\": invalid arguments" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
#echo "0:\"${BASH_REMATCH[0]}\" 1:\"${BASH_REMATCH[1]}\" 2:\"${BASH_REMATCH[2]}\" 3:\"${BASH_REMATCH[3]}\" 4:\"${BASH_REMATCH[4]}\""
|
||||||
|
PROG1="${BASH_REMATCH[1]}"
|
||||||
|
NAME1=$(mkprogname "${PROG1,,*}")
|
||||||
|
NAME2=$(mkprogname "$ARG2")
|
||||||
|
OPTS1A="${BASH_REMATCH[5]}"
|
||||||
|
ARG1A="$PROG1:$LOCALHOST:${BASH_REMATCH[3]}:${BASH_REMATCH[4]},proxyport=$PORT,$OPTS1A" ;;
|
||||||
|
SOCKS:*|SOCKS4:*|SOCKS4A*)
|
||||||
|
#if ! [[ $ARG1A =~ ^\([^:]*\):\([^:]*\):\([^:]*\):\([^:,]*\),* ]]; then # bash 3
|
||||||
|
if ! [[ $ARG1A =~ ^([^:]*):([^:]*):([^:]*):([^:,]*),* ]]; then
|
||||||
|
echo "$0: \"$ARG1A\": invalid arguments" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
PROG1="${BASH_REMATCH[1]}"
|
||||||
|
NAME1=$(mkprogname "${PROG1,,*}")
|
||||||
|
NAME2=$(mkprogname "$ARG2")
|
||||||
|
OPTS1A="${BASH_REMATCH[5]}"
|
||||||
|
ARG1A="$PROG1:$LOCALHOST:${BASH_REMATCH[3]}:${BASH_REMATCH[4]},socksport=$PORT,$OPTS1A" ;;
|
||||||
|
SOCKS5:*|SOCKS5-CONNECT*)
|
||||||
|
#if ! [[ $ARG1A =~ ^\([^:]*\):\([^:]*\):\([^:]*\):\([^:,]*\):\([^:,]*\),* ]]; then # bash 3
|
||||||
|
if ! [[ $ARG1A =~ ^([^:]*):([^:]*):([^:]*):([^:,]*):([^:,]*),* ]]; then
|
||||||
|
echo "$0: \"$ARG1A\": invalid arguments" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
PROG1="${BASH_REMATCH[1]}"
|
||||||
|
NAME1=$(mkprogname "${PROG1,,*}")
|
||||||
|
NAME2=$(mkprogname "$ARG2")
|
||||||
|
OPTS1A="${BASH_REMATCH[6]}"
|
||||||
|
ARG1A="$PROG1:$LOCALHOST:$PORT:${BASH_REMATCH[4]}:${BASH_REMATCH[5]},$OPTS1A" ;;
|
||||||
|
# Passive (server) addresses
|
||||||
|
OPENSSL-LISTEN|OPENSSL-LISTEN:*|SSL-L|SSL-L:.*)
|
||||||
|
PASSIVE=1
|
||||||
|
OPTS1A=
|
||||||
|
#if [[ $ARG1A =~ ^\([^:]*\):\([^,]*\)\(.*\) ]]; then # bash 3
|
||||||
|
if [[ $ARG1A =~ ^([^:]*):([^,]*)(.*) ]]; then
|
||||||
|
OPTS1A="${BASH_REMATCH[3]}"
|
||||||
|
#elif [[ $ARG1A =~ ^\([^,]*\)\(.*\) ]]; then # bash 3
|
||||||
|
elif [[ $ARG1A =~ ^([^,]*)(.*) ]]; then
|
||||||
|
OPTS1A="${BASH_REMATCH[2]}"
|
||||||
|
else
|
||||||
|
echo "$0: \"$ARG1A\": invalid arguments" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
PROG1="${BASH_REMATCH[1]}"
|
||||||
|
NAME1=$(mkprogname "$ARG0")
|
||||||
|
NAME2=$(mkprogname "${BASH_REMATCH[1]}")
|
||||||
|
ARG1A=$PROG1:$PORT$OPTS1A ;;
|
||||||
|
*) echo "$0: Unsupported address \"$ARG1A\"" >&2
|
||||||
|
usage >&2
|
||||||
|
exit 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
ADDR1A="$ARG0"
|
||||||
|
if [ -z "$PASSIVE" ]; then
|
||||||
|
ADDR1B="$ARG1A,bind=$LOCALHOST,$ARG1B"
|
||||||
|
ADDR2A="TCP4-L:$PORT,reuseaddr,$FORK,bind=$LOCALHOST,range=$LOCALHOST/32"
|
||||||
|
else
|
||||||
|
ADDR1B="TCP4:$LOCALHOST:$PORT,bind=$LOCALHOST"
|
||||||
|
ADDR2A="$ARG1A,reuseaddr,$FORK,bind=$LOCALHOST,range=$LOCALHOST/32,$ARG1B"
|
||||||
|
fi
|
||||||
|
ADDR2B="$ARG2"
|
||||||
|
|
||||||
|
|
||||||
|
pid1= pid2=
|
||||||
|
trap '[ "$pid1" ] && kill $pid1 2>/dev/null; [ "$pid2" ] && kill $pid2 2>/dev/null' EXIT
|
||||||
|
|
||||||
|
set -bm
|
||||||
|
trap 'rc=$?; if ! kill -n 0 $pid2 2>/dev/null; then [ -z "$QUIET" -a $rc -ne 0 ] && echo "$0: socat-$NAME2 exited with rc=$rc" >&2; exit $rc; fi' SIGCHLD
|
||||||
|
|
||||||
|
# Start instance 2 first, because instance 1 ("left") connects to 2
|
||||||
|
if [ "$VERBOSE" ]; then
|
||||||
|
$ECHO "$SOCAT $OPTS -lp socat-$NAME2 \\
|
||||||
|
\"$ADDR2A\" \\
|
||||||
|
\"$ADDR2B\" &"
|
||||||
|
fi
|
||||||
|
$SOCAT $OPTS -lp socat-$NAME2 \
|
||||||
|
"$ADDR2A" \
|
||||||
|
"$ADDR2B" &
|
||||||
|
pid2=$!
|
||||||
|
sleep 0.1
|
||||||
|
|
||||||
|
#trap 'if ! kill -n 0 $pid1 2>/dev/null; then [ -z "$QUIET" ] && echo "$0: socat-$NAME1 exited with rc=$?" >&2; kill $pid2 2>/dev/null; exit 1; elif ! kill -n 0 $pid2 2>/dev/null; then [ -z "$QUIET" ] && echo "$0: socat-$NAME2 exited with rc=$?" >&2; kill $pid1 2>/dev/null; exit 1; fi' SIGCHLD
|
||||||
|
|
||||||
|
if [ "$VERBOSE" ]; then
|
||||||
|
$ECHO "$SOCAT $OPTS -lp socat-$NAME1 \\
|
||||||
|
\"$ADDR1A\" \\
|
||||||
|
\"$ADDR1B\""
|
||||||
|
fi
|
||||||
|
$SOCAT $OPTS -lp socat-$NAME1 \
|
||||||
|
"$ADDR1A" \
|
||||||
|
"$ADDR1B"
|
||||||
|
#pid1=$!
|
||||||
|
rc1=$?
|
||||||
|
|
||||||
|
kill $pid2 2>/dev/null
|
||||||
|
wait 2>/dev/null
|
||||||
|
#wait -f
|
||||||
|
|
||||||
|
exit $rc1
|
|
@ -91,7 +91,7 @@ else
|
||||||
fi
|
fi
|
||||||
if [ "$u" != "nobody" ]; then
|
if [ "$u" != "nobody" ]; then
|
||||||
$ECHO "$SOCKSREPLY_FAILED"
|
$ECHO "$SOCKSREPLY_FAILED"
|
||||||
echo "wrong socks user requested" >&2
|
echo "wrong socks user requested (expected \"nobody\")" >&2
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
152
test.sh
152
test.sh
|
@ -1044,7 +1044,7 @@ checkconds() {
|
||||||
local uname="$(echo $UNAME |tr 'A-Z' 'a-z')"
|
local uname="$(echo $UNAME |tr 'A-Z' 'a-z')"
|
||||||
for i in $unames; do
|
for i in $unames; do
|
||||||
if [ "$uname" = "$(echo "$i" |tr 'A-Z,' 'a-z ')" ]; then
|
if [ "$uname" = "$(echo "$i" |tr 'A-Z,' 'a-z ')" ]; then
|
||||||
# good, mark as passed
|
# good, mark as passed
|
||||||
i=
|
i=
|
||||||
break;
|
break;
|
||||||
fi
|
fi
|
||||||
|
@ -18838,6 +18838,154 @@ esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
|
# Test the socat-chain.sh script with SOCKS4 over UNIX-socket
|
||||||
|
NAME=SOCAT_CHAIN_SOCKS4
|
||||||
|
case "$TESTS" in
|
||||||
|
*%$N%*|*%functions%*|*%scripts%*|*%socat-chain%*|*%listen%*|*%fork%*|*%ip4%*|*%tcp4%*|*%unix%*|*%socks4%*|*%socket%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: test socat-chain.sh with SOCKS4 over UNIX-socket"
|
||||||
|
# Run a socks4 server on UNIX-listen
|
||||||
|
# Connect with socat-chein.sh; check if data transfer is correct
|
||||||
|
if ! eval $NUMCOND; then :
|
||||||
|
# Remove unneeded checks, adapt lists of the remaining ones
|
||||||
|
elif ! cond=$(checkconds \
|
||||||
|
"" \
|
||||||
|
"" \
|
||||||
|
"" \
|
||||||
|
"IP4 TCP LISTEN STDIO UNIX" \
|
||||||
|
"TCP4-LISTEN PIPE STDIN STDOUT TCP4 UNIX UNIX-LISTEN" \
|
||||||
|
"so-reuseaddr" \
|
||||||
|
"tcp4 unix" ); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
namesCANT="$namesCANT $NAME"
|
||||||
|
else
|
||||||
|
ts="$td/test$N.sock"
|
||||||
|
tf="$td/test$N.stdout"
|
||||||
|
te="$td/test$N.stderr"
|
||||||
|
tdiff="$td/test$N.diff"
|
||||||
|
da="test$N $(date) $RANDOM"
|
||||||
|
CMD0="$TRACE $SOCAT $opts UNIX-LISTEN:$ts,reuseaddr EXEC:./socks4echo.sh"
|
||||||
|
CMD1="$TRACE ./socat-chain.sh $opts - SOCKS4::32.98.76.54:32109,socksuser=nobody UNIX:$ts"
|
||||||
|
printf "test $F_n $TEST... " $N
|
||||||
|
$CMD0 >/dev/null 2>"${te}0" &
|
||||||
|
pid0=$!
|
||||||
|
waitunixport $ts 1
|
||||||
|
#relsleep 1 # if no matching wait*port function
|
||||||
|
echo "$da" |$CMD1 >"${tf}1" 2>"${te}1"
|
||||||
|
rc1=$?
|
||||||
|
kill $pid0 2>/dev/null; wait
|
||||||
|
if [ "$rc1" -ne 0 ]; then
|
||||||
|
$PRINTF "$FAILED (rc1=$rc1)\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
echo "$CMD1"
|
||||||
|
cat "${te}1" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
namesFAIL="$namesFAIL $NAME"
|
||||||
|
elif ! echo "$da" |diff - "${tf}1" >$tdiff; then
|
||||||
|
$PRINTF "$FAILED (diff)\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
echo "$CMD1"
|
||||||
|
cat "${te}1" >&2
|
||||||
|
echo "// diff:" >&2
|
||||||
|
cat "$tdiff" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
namesFAIL="$namesFAIL $NAME"
|
||||||
|
else
|
||||||
|
$PRINTF "$OK\n"
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD1"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
|
||||||
|
numOK=$((numOK+1))
|
||||||
|
fi
|
||||||
|
fi # NUMCOND
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
# Test the socat-chain.sh script by driving SSL over serial
|
||||||
|
NAME=SOCAT_CHAIN_SSL_PTY
|
||||||
|
case "$TESTS" in
|
||||||
|
*%$N%*|*%functions%*|*%scripts%*|*%socat-chain%*|*%listen%*|*%fork%*|*%ip4%*|*%tcp4%*|*%unix%*|*%socket%*|*%socket%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: test socat-chain.sh with SSL over PTY"
|
||||||
|
# Run a socat-chain.sh instance with SSL listening behind a PTY;
|
||||||
|
# open the PTY with socat-chein.sh using SSL;
|
||||||
|
# check if data transfer is correct
|
||||||
|
if ! eval $NUMCOND; then :
|
||||||
|
# Remove unneeded checks, adapt lists of the remaining ones
|
||||||
|
elif ! cond=$(checkconds \
|
||||||
|
"" \
|
||||||
|
"" \
|
||||||
|
"" \
|
||||||
|
"IP4 TCP LISTEN OPENSSL STDIO PTY" \
|
||||||
|
"TCP4-LISTEN SOCKETPAIR STDIN STDOUT TCP4 SSL SSL-L" \
|
||||||
|
"so-reuseaddr" \
|
||||||
|
"tcp4" ); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
namesCANT="$namesCANT $NAME"
|
||||||
|
elif [[ $BASH_VERSION =~ ^[1-3]\. ]]; then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}requires bash 4 or higher${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
namesCANT="$namesCANT $NAME"
|
||||||
|
else
|
||||||
|
gentestcert testsrv
|
||||||
|
tp="$td/test$N.pty"
|
||||||
|
tf="$td/test$N.stdout"
|
||||||
|
te="$td/test$N.stderr"
|
||||||
|
tdiff="$td/test$N.diff"
|
||||||
|
da="test$N $(date) $RANDOM"
|
||||||
|
CMD0="$TRACE ./socat-chain.sh $opts PTY,link=$tp SSL-L,cert=testsrv.pem,verify=0 SOCKETPAIR"
|
||||||
|
CMD1="$TRACE ./socat-chain.sh $opts - SSL,cafile=testsrv.crt,commonname=localhost $tp,cfmakeraw"
|
||||||
|
printf "test $F_n $TEST... " $N
|
||||||
|
$CMD0 >/dev/null 2>"${te}0" &
|
||||||
|
pid0=$!
|
||||||
|
waitfile $tp 1
|
||||||
|
echo "$da" |$CMD1 >"${tf}1" 2>"${te}1"
|
||||||
|
rc1=$?
|
||||||
|
kill $pid0 2>/dev/null
|
||||||
|
wait 2>/dev/null
|
||||||
|
if [ "$rc1" -ne 0 ]; then
|
||||||
|
$PRINTF "$FAILED (rc1=$rc1)\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
echo "$CMD1"
|
||||||
|
cat "${te}1" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
namesFAIL="$namesFAIL $NAME"
|
||||||
|
elif ! echo "$da" |diff - "${tf}1" >$tdiff; then
|
||||||
|
$PRINTF "$FAILED (diff)\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
echo "$CMD1"
|
||||||
|
cat "${te}1" >&2
|
||||||
|
echo "// diff:" >&2
|
||||||
|
cat "$tdiff" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
namesFAIL="$namesFAIL $NAME"
|
||||||
|
else
|
||||||
|
$PRINTF "$OK\n"
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD1"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
|
||||||
|
numOK=$((numOK+1))
|
||||||
|
fi
|
||||||
|
fi # NUMCOND
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
# end of common tests
|
# end of common tests
|
||||||
|
|
||||||
##################################################################################
|
##################################################################################
|
||||||
|
@ -19015,7 +19163,7 @@ else
|
||||||
numFAIL=$((numFAIL+1))
|
numFAIL=$((numFAIL+1))
|
||||||
listFAIL="$listFAIL $N"
|
listFAIL="$listFAIL $N"
|
||||||
namesFAIL="$namesFAIL $NAME"
|
namesFAIL="$namesFAIL $NAME"
|
||||||
elif ! echo "$da" |diff "${tf}1" - >$tdiff; then
|
elif ! echo "$da" |diff - "${tf}1" >$tdiff; then
|
||||||
$PRINTF "$FAILED (diff)\n"
|
$PRINTF "$FAILED (diff)\n"
|
||||||
echo "$CMD0 &"
|
echo "$CMD0 &"
|
||||||
cat "${te}0" >&2
|
cat "${te}0" >&2
|
||||||
|
|
32
xio-pty.c
32
xio-pty.c
|
@ -38,7 +38,8 @@ static int xioopen_pty(
|
||||||
{
|
{
|
||||||
/* we expect the form: filename */
|
/* we expect the form: filename */
|
||||||
struct single *sfd = &xfd->stream;
|
struct single *sfd = &xfd->stream;
|
||||||
int ptyfd = -1, ttyfd = -1;
|
int ptyfd = -1; /* master */
|
||||||
|
int ttyfd = -1; /* slave */
|
||||||
#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
|
#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
|
||||||
bool useptmx = false; /* use /dev/ptmx or equivalent */
|
bool useptmx = false; /* use /dev/ptmx or equivalent */
|
||||||
#endif
|
#endif
|
||||||
|
@ -101,6 +102,18 @@ static int xioopen_pty(
|
||||||
if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
|
||||||
applyopts2(sfd, -1, opts, PH_INIT, PH_EARLY);
|
applyopts2(sfd, -1, opts, PH_INIT, PH_EARLY);
|
||||||
|
|
||||||
|
#if HAVE_OPENPTY
|
||||||
|
if (ptyfd < 0) {
|
||||||
|
int result;
|
||||||
|
if ((result = Openpty(&ptyfd, &ttyfd, ptyname, NULL, NULL)) < 0) {
|
||||||
|
Error4("openpty(%p, %p, %p, NULL, NULL): %s",
|
||||||
|
&ptyfd, &ttyfd, ptyname, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Notice1("PTY is %s", ptyname);
|
||||||
|
}
|
||||||
|
#endif /* HAVE_OPENPTY */
|
||||||
|
|
||||||
applyopts(sfd, -1, opts, PH_PREBIGEN);
|
applyopts(sfd, -1, opts, PH_PREBIGEN);
|
||||||
|
|
||||||
#if defined(HAVE_DEV_PTMX)
|
#if defined(HAVE_DEV_PTMX)
|
||||||
|
@ -109,7 +122,7 @@ static int xioopen_pty(
|
||||||
# define PTMX "/dev/ptc" /* AIX 4.3.3 */
|
# define PTMX "/dev/ptc" /* AIX 4.3.3 */
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_DEV_PTMX || HAVE_DEV_PTC
|
#if HAVE_DEV_PTMX || HAVE_DEV_PTC
|
||||||
if (useptmx) {
|
if (useptmx || ptyfd < 0) {
|
||||||
if ((ptyfd = Open(PTMX, O_RDWR|O_NOCTTY, 0620)) < 0) {
|
if ((ptyfd = Open(PTMX, O_RDWR|O_NOCTTY, 0620)) < 0) {
|
||||||
Warn1("open(\""PTMX"\", O_RDWR|O_NOCTTY, 0620): %s",
|
Warn1("open(\""PTMX"\", O_RDWR|O_NOCTTY, 0620): %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
@ -117,7 +130,7 @@ static int xioopen_pty(
|
||||||
} else {
|
} else {
|
||||||
;/*0 Info1("open(\""PTMX"\", O_RDWR|O_NOCTTY, 0620) -> %d", ptyfd);*/
|
;/*0 Info1("open(\""PTMX"\", O_RDWR|O_NOCTTY, 0620) -> %d", ptyfd);*/
|
||||||
}
|
}
|
||||||
if (ptyfd >= 0 && ttyfd < 0) {
|
if (ptyfd >= 0) {
|
||||||
/* we used PTMX before forking */
|
/* we used PTMX before forking */
|
||||||
/*0 extern char *ptsname(int);*/
|
/*0 extern char *ptsname(int);*/
|
||||||
#if HAVE_GRANTPT /* AIX, not Linux */
|
#if HAVE_GRANTPT /* AIX, not Linux */
|
||||||
|
@ -146,17 +159,6 @@ static int xioopen_pty(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* HAVE_DEV_PTMX || HAVE_DEV_PTC */
|
#endif /* HAVE_DEV_PTMX || HAVE_DEV_PTC */
|
||||||
#if HAVE_OPENPTY
|
|
||||||
if (ptyfd < 0) {
|
|
||||||
int result;
|
|
||||||
if ((result = Openpty(&ptyfd, &ttyfd, ptyname, NULL, NULL)) < 0) {
|
|
||||||
Error4("openpty(%p, %p, %p, NULL, NULL): %s",
|
|
||||||
&ptyfd, &ttyfd, ptyname, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
Notice1("PTY is %s", ptyname);
|
|
||||||
}
|
|
||||||
#endif /* HAVE_OPENPTY */
|
|
||||||
|
|
||||||
if (!retropt_string(opts, OPT_SYMBOLIC_LINK, &linkname)) {
|
if (!retropt_string(opts, OPT_SYMBOLIC_LINK, &linkname)) {
|
||||||
xio_unlink(linkname, E_ERROR);
|
xio_unlink(linkname, E_ERROR);
|
||||||
|
@ -178,7 +180,7 @@ static int xioopen_pty(
|
||||||
applyopts_cloexec(ptyfd, opts);/*!*/
|
applyopts_cloexec(ptyfd, opts);/*!*/
|
||||||
sfd->dtype = XIODATA_PTY;
|
sfd->dtype = XIODATA_PTY;
|
||||||
|
|
||||||
applyopts(sfd, ptyfd, opts, PH_FD);
|
applyopts(sfd, ttyfd, opts, PH_FD);
|
||||||
|
|
||||||
{
|
{
|
||||||
/* special handling of user-late etc.; with standard behaviour (up to
|
/* special handling of user-late etc.; with standard behaviour (up to
|
||||||
|
|
|
@ -225,8 +225,8 @@ int xiohelp_syntax(
|
||||||
int isnum,
|
int isnum,
|
||||||
const char *syntax)
|
const char *syntax)
|
||||||
{
|
{
|
||||||
Error4("%s: wrong number of parameters (%d instead of %d): usage: %s",
|
Error5("%s: wrong number of parameters (%d instead of %d): usage: %s%s",
|
||||||
addr, isnum, expectnum, syntax);
|
addr, isnum, expectnum, addr, syntax);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue