1
0
Fork 0
mirror of https://repo.or.cz/socat.git synced 2025-06-18 06:46:51 +00:00

Protect SSL_connect(); Nanosleep() with decimal output

This commit is contained in:
Gerhard 2025-02-08 20:53:35 +01:00
parent 416fe38e33
commit ed11b3d2c5
5 changed files with 38 additions and 18 deletions

View file

@ -52,6 +52,10 @@ Corrections:
Thanks to Brian Woo for reporting this issue. Thanks to Brian Woo for reporting this issue.
Test: UDP_LISTEN_BIND4 Test: UDP_LISTEN_BIND4
Protected SSL_connect() from SIGCHLD,SIGUSR1.
Nanosleep() trace output now in decimal form.
Features: Features:
POSIXMQ-RECV now takes option o-nonblock; this, in combination with -T, POSIXMQ-RECV now takes option o-nonblock; this, in combination with -T,
makes it possible to terminate Socat in case the queue is empty. makes it possible to terminate Socat in case the queue is empty.

View file

@ -368,6 +368,7 @@ int sycSSL_connect(SSL *ssl) {
int result; int result;
Debug1("SSL_connect(%p)", ssl); Debug1("SSL_connect(%p)", ssl);
result = SSL_connect(ssl); result = SSL_connect(ssl);
if (!diag_in_handler) diag_flush();
Debug1("SSL_connect() -> %d", result); Debug1("SSL_connect() -> %d", result);
return result; return result;
} }

View file

@ -1421,11 +1421,11 @@ unsigned int Sleep(unsigned int seconds) {
#if HAVE_NANOSLEEP #if HAVE_NANOSLEEP
unsigned int Nanosleep(const struct timespec *req, struct timespec *rem) { unsigned int Nanosleep(const struct timespec *req, struct timespec *rem) {
int retval, _errno; int retval, _errno;
Debug3("nanosleep({"F_time",%ld},%p)", req->tv_sec, req->tv_nsec, rem); Debug3("nanosleep({"F_time".%09ld}, %p)", req->tv_sec, req->tv_nsec, rem);
retval = nanosleep(req, rem); retval = nanosleep(req, rem);
_errno = errno; _errno = errno;
if (rem) { if (rem) {
Debug3("nanosleep(,{"F_time",%ld}) -> %d", Debug3("nanosleep(,{"F_time".%09ld}) -> %d",
rem->tv_sec, rem->tv_nsec, retval); rem->tv_sec, rem->tv_nsec, retval);
} else { } else {
Debug1("nanosleep() -> %d", retval); Debug1("nanosleep() -> %d", retval);

32
test.sh
View file

@ -152,7 +152,7 @@ fi
if [ -z "$val_t" ]; then if [ -z "$val_t" ]; then
# Determine the time Socat needs for an empty run # Determine the time Socat needs for an empty run
$SOCAT /dev/null /dev/null # populate caches $SOCAT /dev/null /dev/null # populate caches
MILLIs=$(bash -c 'time $SOCAT /dev/null /dev/null' 2>&1 |grep ^real |sed 's/.*m\(.*\)s.*/\1/' |tr -d ,.) MILLIs=$(bash -c 'time $SOCAT $opts /dev/null /dev/null' 2>&1 |grep ^real |sed 's/.*m\(.*\)s.*/\1/' |tr -d ,.)
while [ "${MILLIs:0:1}" = '0' ]; do MILLIs=${MILLIs##0}; done # strip leading '0' to avoid octal while [ "${MILLIs:0:1}" = '0' ]; do MILLIs=${MILLIs##0}; done # strip leading '0' to avoid octal
[ -z "$MILLIs" ] && MILLIs=1 [ -z "$MILLIs" ] && MILLIs=1
[ "$DEFS" ] && echo "MILLIs=\"$MILLIs\" (1)" >&2 [ "$DEFS" ] && echo "MILLIs=\"$MILLIs\" (1)" >&2
@ -5206,11 +5206,12 @@ newport tcp4; PORT3=$PORT
newport tcp4; PORT4=$PORT newport tcp4; PORT4=$PORT
newport tcp4; PORT5=$PORT newport tcp4; PORT5=$PORT
# this is the server in the protected network that we want to reach # this is the server in the protected network that we want to reach
CMD1="$TRACE $SOCAT $opts -lpserver -t$(reltime 10) TCP4-L:$PORT1,reuseaddr,bind=$LOCALHOST,fork ECHO" CMD1="$TRACE $SOCAT $opts -lpserver -t$(reltime 100) TCP4-L:$PORT1,reuseaddr,bind=$LOCALHOST,fork ECHO"
# this is the proxy in the protected network that provides a way out # this is the proxy in the protected network that provides a way out
# note: the proxy.sh script starts one or two more socat processes without # note: the proxy.sh script starts one or two more socat processes without
# setting the program name # setting the program name
CMD2="$TRACE $SOCAT $opts -lpproxy -t$(reltime 10) TCP4-L:$PORT2,reuseaddr,bind=$LOCALHOST,fork EXEC:./proxy.sh" export SOCAT_OPTS="$OPTS" # for proxy.sh
CMD2="$TRACE $SOCAT $opts -lpproxy -t$(reltime 100) TCP4-L:$PORT2,reuseaddr,bind=$LOCALHOST,fork EXEC:./proxy.sh"
# this is our proxy connect wrapper in the protected network # this is our proxy connect wrapper in the protected network
CMD3="$TRACE $SOCAT $opts -lpwrapper -t$(reltime 30) TCP4-L:$PORT3,reuseaddr,bind=$LOCALHOST,fork PROXY:$LOCALHOST:$LOCALHOST:$PORT4,pf=ip4,proxyport=$PORT2,resolve" CMD3="$TRACE $SOCAT $opts -lpwrapper -t$(reltime 30) TCP4-L:$PORT3,reuseaddr,bind=$LOCALHOST,fork PROXY:$LOCALHOST:$LOCALHOST:$PORT4,pf=ip4,proxyport=$PORT2,resolve"
# this is our double client in the protected network using SSL # this is our double client in the protected network using SSL
@ -5238,19 +5239,21 @@ eval "$CMD5 2>\"${te}5\" &"
pid5=$! pid5=$!
waittcp4port $PORT5 1 50 || $PRINTF "$FAILED: port $PORT5\n" >&2 </dev/null waittcp4port $PORT5 1 50 || $PRINTF "$FAILED: port $PORT5\n" >&2 </dev/null
# and this is the outside client: # and this is the outside client:
echo "$da1" |$CMD6 >${tf}_1 2>"${te}6_1" & { echo "$da1"; relsleep 100; } |$CMD6 >${tf}_1 2>"${te}6_1" &
pid6_1=$! pid6_1=$!
echo "$da2" |$CMD6 >${tf}_2 2>"${te}6_2" & relsleep 20
{ echo "$da2"; relsleep 100; } |$CMD6 >${tf}_2 2>"${te}6_2" &
pid6_2=$! pid6_2=$!
echo "$da3" |$CMD6 >${tf}_3 2>"${te}6_3" & relsleep 20
{ echo "$da3"; relsleep 100; } |$CMD6 >${tf}_3 2>"${te}6_3" &
pid6_3=$! pid6_3=$!
wait $pid6_1 $pid6_2 $pid6_3 wait $pid6_1 $pid6_2 $pid6_3
kill $pid1 $pid2 $pid3 $pid4 $pid5 $(childpids $pid5) 2>/dev/null kill $pid1 $pid2 $pid3 $pid4 $pid5 $(childpids $pid5) 2>/dev/null
# (On BSDs a child of pid5 likes to hang) # (On BSDs a child of pid5 likes to hang)
# #
(echo "$da1"; relsleep 2) |diff - "${tf}_1" >"${tdiff}1" echo "$da1" |diff - "${tf}_1" >"${tdiff}1"
(echo "$da2"; relsleep 2) |diff - "${tf}_2" >"${tdiff}2" echo "$da2" |diff - "${tf}_2" >"${tdiff}2"
(echo "$da3"; relsleep 2) |diff - "${tf}_3" >"${tdiff}3" echo "$da3" |diff - "${tf}_3" >"${tdiff}3"
if test -s "${tdiff}1" -o -s "${tdiff}2" -o -s "${tdiff}3"; then if test -s "${tdiff}1" -o -s "${tdiff}2" -o -s "${tdiff}3"; then
# FAILED only when none of the three transfers succeeded # FAILED only when none of the three transfers succeeded
if test -s "${tdiff}1" -a -s "${tdiff}2" -a -s "${tdiff}3"; then if test -s "${tdiff}1" -a -s "${tdiff}2" -a -s "${tdiff}3"; then
@ -15565,7 +15568,8 @@ elif ! runsip4 >/dev/null; then
cant cant
else else
# We need a hanging connection attempt, guess an address for this # We need a hanging connection attempt, guess an address for this
HANGIP=0.0.0.1 #HANGIP=0.0.0.1 # some OSes refuse to end to this address
HANGIP=8.8.8.9 # 2025 this hangs...
te1="$td/test$N.stderr1" te1="$td/test$N.stderr1"
tk1="$td/test$N.kill1" tk1="$td/test$N.kill1"
te2="$td/test$N.stderr2" te2="$td/test$N.stderr2"
@ -15590,8 +15594,12 @@ CMD2="$TRACE $SOCAT $opts - DTLS:$HANGIP:1,verify=0,so-rcvtimeo=$(reltime 1)"
$CMD2 >"$te1" 2>$te2 </dev/null & $CMD2 >"$te1" 2>$te2 </dev/null &
pid2=$! pid2=$!
relsleep 8 # in OpenSSL 1.1.1f DTLS takes two timeouts relsleep 8 # in OpenSSL 1.1.1f DTLS takes two timeouts
if kill $pid2 2>"$tk2"; then sleep 0.02 # in OpenSSL 3.0.13 SSL_CTX_clear_mode() needs e.g. 0.02s
$PRINTF "$FAILED\n" kill $pid2 2>"$tk2"
prc2=$?
wait
if [ $prc2 -eq 0 ]; then
$PRINTF "$FAILED (not timeout)\n"
echo "$CMD2" >&2 echo "$CMD2" >&2
cat "$te2" >&2 cat "$te2" >&2
cat "$tk2" >&2 cat "$tk2" >&2

View file

@ -26,7 +26,6 @@
(not only tcp, but also pipes, stdin, files...) (not only tcp, but also pipes, stdin, files...)
for tcp we want to provide support for socks and proxy. for tcp we want to provide support for socks and proxy.
read and write functions must use the openssl crypt versions. read and write functions must use the openssl crypt versions.
but currently only plain tcp4 is implemented.
*/ */
/* Linux: "man 3 ssl" */ /* Linux: "man 3 ssl" */
@ -1976,12 +1975,20 @@ static int xioSSL_set_fd(struct single *sfd, int level) {
should not retry for any reason. */ should not retry for any reason. */
static int xioSSL_connect(struct single *sfd, const char *opt_commonname, static int xioSSL_connect(struct single *sfd, const char *opt_commonname,
bool opt_ver, int level) { bool opt_ver, int level) {
sigset_t masksigs, oldsigs;
char error_string[256]; char error_string[256];
int errint, status, ret; int errint, status, _errno, ret;
unsigned long err; unsigned long err;
sigemptyset(&masksigs);
sigaddset(&masksigs, SIGCHLD);
sigaddset(&masksigs, SIGUSR1);
Sigprocmask(SIG_BLOCK, &masksigs, &oldsigs);
/* connect via SSL by performing handshake */ /* connect via SSL by performing handshake */
if ((ret = sycSSL_connect(sfd->para.openssl.ssl)) <= 0) { ret = sycSSL_connect(sfd->para.openssl.ssl);
_errno = errno;
Sigprocmask(SIG_SETMASK, &oldsigs, NULL);
if (ret <= 0) {
/*if (ERR_peek_error() == 0) Msg(level, "SSL_connect() failed");*/ /*if (ERR_peek_error() == 0) Msg(level, "SSL_connect() failed");*/
errint = SSL_get_error(sfd->para.openssl.ssl, ret); errint = SSL_get_error(sfd->para.openssl.ssl, ret);
switch (errint) { switch (errint) {
@ -2005,7 +2012,7 @@ static int xioSSL_connect(struct single *sfd, const char *opt_commonname,
if (ret == 0) { if (ret == 0) {
Msg(level, "SSL_connect(): socket closed by peer"); Msg(level, "SSL_connect(): socket closed by peer");
} else if (ret == -1) { } else if (ret == -1) {
Msg1(level, "SSL_connect(): %s", strerror(errno)); Msg1(level, "SSL_connect(): %s", strerror(_errno));
} }
} else { } else {
Msg(level, "I/O error"); /*!*/ Msg(level, "I/O error"); /*!*/