From e78e911cbb478fdafc90490235faefab5e08fda1 Mon Sep 17 00:00:00 2001 From: Gerhard Rieger Date: Sun, 24 Oct 2021 13:25:36 +0200 Subject: [PATCH] Solve a problem with overlapping socket and openssl parameters --- CHANGES | 8 ++++++++ test.sh | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ xio.h | 46 +++++++++++++++++++++++++++++-------------- 3 files changed, 100 insertions(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index 7822ded..f47b015 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,13 @@  Corrections: + The per address parameters for OpenSSL overlapped in memory with socket + parameters. Magically this did not seem to cause problems except on + MacOS Catalina that reported errors like: + socat[3458] E Select(7, &0x80, NULL, NULL, {140392884396544.000000}): + Invalid argument + Test: OPENSSL_PARA_OVERLAP + Thanks to Ryo Ota for reporting this bug. + Fixed a few minor coding issues Testing: diff --git a/test.sh b/test.sh index 343a66f..6ca21f3 100755 --- a/test.sh +++ b/test.sh @@ -14980,6 +14980,66 @@ PORT=$((PORT+1)) N=$((N+1)) +# Test if the problem with overlapping internal parameters of sockets and +# openssl are fixed +NAME=OPENSSL_PARA_OVERLAP +case "$TESTS" in +*%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%ip4%*|*%tcp%*|*%tcp4%*|*%openssl%*|*%$NAME%*) +TEST="$NAME: test diverse of socket,openssl params" +# That bug had not many effects; the simplest to use is possible SIGSEGV on +# close when option accept-timeout with fractional seconds was applied +if ! eval $NUMCOND; then :; +elif ! testfeats openssl >/dev/null; then + $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N + numCANT=$((numCANT+1)) + listCANT="$listCANT $N" +elif ! type openssl >/dev/null 2>&1; then + $PRINTF "test $F_n $TEST... ${YELLOW}openssl executable not available${NORMAL}\n" $N + numCANT=$((numCANT+1)) + listCANT="$listCANT $N" +elif ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then + $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N + numCANT=$((numCANT+1)) + listCANT="$listCANT $N" +else +gentestcert testsrv +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +trc0="$td/test$N.rc0" +da="test$N $(date) $RANDOM" +CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,accept-timeout=4.5,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 PIPE" +CMD1="$TRACE $SOCAT $opts /dev/null OPENSSL-CONNECT:$LOCALHOST:$PORT,pf=ip4,verify=0,$SOCAT_EGD" +printf "test $F_n $TEST... " $N +$CMD0 >/dev/null 2>"${te}0" || echo $? >$trc0 & +pid0=$! +waittcp4port $PORT 1 +$CMD1 >"${tf}1" 2>"${te}1" +rc1=$? +sleep 0.5 +kill $pid0 2>/dev/null; wait +if [ $rc1 -ne 0 ]; then + $PRINTF "$CANT\n" + numCANT=$((numCANT+1)) +elif [ ! -e $trc0 ]; then + $PRINTF "$OK\n" + numOK=$((numOK+1)) +else + $PRINTF "$FAILED\n" + echo "$CMD0 &" >&2 + cat "${te}0" >&2 + echo "$CMD1" >&2 + cat "${te}1" >&2 + numFAIL=$((numFAIL+1)) + listFAIL="$listFAIL $N" +fi +fi # NUMCOND + ;; +esac +PORT=$((PORT+1)) +N=$((N+1)) + + ################################################################################## #================================================================================= # here come tests that might affect your systems integrity. Put normal tests diff --git a/xio.h b/xio.h index e866053..de4cecc 100644 --- a/xio.h +++ b/xio.h @@ -115,6 +115,23 @@ extern xioopts_t xioopts; #define MAXARGV 8 +#if _WITH_IP4 || _WITH_IP6 +struct para_ip { + unsigned int res_opts[2]; /* bits to be set in _res.options are + at [0], bits to be cleared are at [1] */ + bool dosourceport; /* check the source port of incoming connection or packets */ + uint16_t sourceport; /* host byte order */ + bool lowport; +#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP + bool dolibwrap; + char *libwrapname; + char *tcpwrap_etc; + char *hosts_allow_table; + char *hosts_deny_table; +#endif +} ; +#endif /* _WITH_IP4 || _WITH_IP6 */ + /* a non-dual file descriptor */ typedef struct single { enum xiotag tag; /* see enum xiotag */ @@ -181,6 +198,7 @@ typedef struct single { } bipipe; #if _WITH_SOCKET struct { + /* keep a consistent copy in openssl part !!! */ struct timeval connect_timeout; /* how long to hang in connect() */ #if WITH_LISTEN struct timeval accept_timeout; /* how long to wait for incoming connection */ @@ -190,21 +208,9 @@ typedef struct single { bool dorange; struct xiorange range; /* restrictions for peer address */ #if _WITH_IP4 || _WITH_IP6 - struct { - unsigned int res_opts[2]; /* bits to be set in _res.options are - at [0], bits to be cleared are at [1] */ - bool dosourceport; /* check the source port of incoming connection or packets */ - uint16_t sourceport; /* host byte order */ - bool lowport; -#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP - bool dolibwrap; - char *libwrapname; - char *tcpwrap_etc; - char *hosts_allow_table; - char *hosts_deny_table; -#endif - } ip; + struct para_ip ip; #endif /* _WITH_IP4 || _WITH_IP6 */ + /* up to here, keep consistent copy in openssl part !!! */ #if WITH_UNIX struct { bool tight; @@ -231,7 +237,19 @@ typedef struct single { #endif /* WITH_READLINE */ #if WITH_OPENSSL struct { + /* copy of the para.socket structure without un !!! */ struct timeval connect_timeout; /* how long to hang in connect() */ +#if WITH_LISTEN + struct timeval accept_timeout; /* how long to wait for incoming connection */ +#endif + union sockaddr_union la; /* local socket address */ + bool null_eof; /* with dgram: empty packet means EOF */ + bool dorange; + struct xiorange range; /* restrictions for peer address */ +#if _WITH_IP4 || _WITH_IP6 + struct para_ip ip; +#endif /* _WITH_IP4 || _WITH_IP6 */ + /* end of the para.socket structure copy */ SSL_CTX* ctx; /* for freeing on close */ SSL *ssl; #if HAVE_SSL_CTX_set_min_proto_version || defined(SSL_CTX_set_min_proto_version)