mirror of
https://repo.or.cz/socat.git
synced 2025-06-18 14:56:51 +00:00
Protect SSL_connect(); Nanosleep() with decimal output
This commit is contained in:
parent
416fe38e33
commit
ed11b3d2c5
5 changed files with 38 additions and 18 deletions
4
CHANGES
4
CHANGES
|
@ -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.
|
||||||
|
|
1
sslcls.c
1
sslcls.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
4
sycls.c
4
sycls.c
|
@ -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
32
test.sh
|
@ -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
|
||||||
|
|
|
@ -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"); /*!*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue