1
0
Fork 0
mirror of https://repo.or.cz/socat.git synced 2025-05-23 05:12:40 +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.
Test: UDP_LISTEN_BIND4
Protected SSL_connect() from SIGCHLD,SIGUSR1.
Nanosleep() trace output now in decimal form.
Features:
POSIXMQ-RECV now takes option o-nonblock; this, in combination with -T,
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;
Debug1("SSL_connect(%p)", ssl);
result = SSL_connect(ssl);
if (!diag_in_handler) diag_flush();
Debug1("SSL_connect() -> %d", result);
return result;
}

View file

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

32
test.sh
View file

@ -152,7 +152,7 @@ fi
if [ -z "$val_t" ]; then
# Determine the time Socat needs for an empty run
$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
[ -z "$MILLIs" ] && MILLIs=1
[ "$DEFS" ] && echo "MILLIs=\"$MILLIs\" (1)" >&2
@ -5206,11 +5206,12 @@ newport tcp4; PORT3=$PORT
newport tcp4; PORT4=$PORT
newport tcp4; PORT5=$PORT
# 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
# note: the proxy.sh script starts one or two more socat processes without
# 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
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
@ -5238,19 +5239,21 @@ eval "$CMD5 2>\"${te}5\" &"
pid5=$!
waittcp4port $PORT5 1 50 || $PRINTF "$FAILED: port $PORT5\n" >&2 </dev/null
# 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=$!
echo "$da2" |$CMD6 >${tf}_2 2>"${te}6_2" &
relsleep 20
{ echo "$da2"; relsleep 100; } |$CMD6 >${tf}_2 2>"${te}6_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=$!
wait $pid6_1 $pid6_2 $pid6_3
kill $pid1 $pid2 $pid3 $pid4 $pid5 $(childpids $pid5) 2>/dev/null
# (On BSDs a child of pid5 likes to hang)
#
(echo "$da1"; relsleep 2) |diff - "${tf}_1" >"${tdiff}1"
(echo "$da2"; relsleep 2) |diff - "${tf}_2" >"${tdiff}2"
(echo "$da3"; relsleep 2) |diff - "${tf}_3" >"${tdiff}3"
echo "$da1" |diff - "${tf}_1" >"${tdiff}1"
echo "$da2" |diff - "${tf}_2" >"${tdiff}2"
echo "$da3" |diff - "${tf}_3" >"${tdiff}3"
if test -s "${tdiff}1" -o -s "${tdiff}2" -o -s "${tdiff}3"; then
# FAILED only when none of the three transfers succeeded
if test -s "${tdiff}1" -a -s "${tdiff}2" -a -s "${tdiff}3"; then
@ -15565,7 +15568,8 @@ elif ! runsip4 >/dev/null; then
cant
else
# 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"
tk1="$td/test$N.kill1"
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 &
pid2=$!
relsleep 8 # in OpenSSL 1.1.1f DTLS takes two timeouts
if kill $pid2 2>"$tk2"; then
$PRINTF "$FAILED\n"
sleep 0.02 # in OpenSSL 3.0.13 SSL_CTX_clear_mode() needs e.g. 0.02s
kill $pid2 2>"$tk2"
prc2=$?
wait
if [ $prc2 -eq 0 ]; then
$PRINTF "$FAILED (not timeout)\n"
echo "$CMD2" >&2
cat "$te2" >&2
cat "$tk2" >&2

View file

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