From 1db7a7b1f78743633e3f76fcf578ec7c735a7453 Mon Sep 17 00:00:00 2001 From: Gerhard Rieger Date: Sat, 9 Jan 2010 13:35:24 +0100 Subject: [PATCH] openssl addresses failed with "nonblocking operation did not complete" when the peer performed a renegotiation --- CHANGES | 5 ++++ VERSION | 2 +- test.sh | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++ xio-openssl.c | 7 +++-- 4 files changed, 92 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 8ce1617..53b8813 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,9 @@ +corrections: + socats openssl addresses failed with "nonblocking operation did not + complete" when the peer performed a renegotiation. Thanks to Benjamin + Delpy for reporting this bug. + ####################### V 1.7.1.1: corrections: diff --git a/VERSION b/VERSION index 4026ae1..e4c4aad 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -"1.7.1.1" +"1.7.1.1+reneg" diff --git a/test.sh b/test.sh index 6233520..89cd3fb 100755 --- a/test.sh +++ b/test.sh @@ -10048,6 +10048,88 @@ PORT=$((PORT+1)) N=$((N+1)) +# socat up to 1.7.1.1 (and 2.0.0-b3) terminated with error when an openssl peer +# performed a renegotiation. Test if this is fixed. +NAME=OPENSSLRENEG1 +case "$TESTS" in +*%functions%*|*%bugs%*|*%openssl%*|*%socket%*|*%$NAME%*) +TEST="$NAME: OpenSSL connections survives renogotiation" +# connect with s_client to socat ssl-l; force a renog, then transfer data. When +# data is passed the test succeeded +if ! eval $NUMCOND; then :; else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +da="test$N $(date) $RANDOM" +CMD0="$SOCAT $opts OPENSSL-LISTEN:$PORT,reuseaddr,cert=testsrv.crt,key=testsrv.key,verify=0 PIPE" +CMD1="openssl s_client -port $PORT -verify 0" +printf "test $F_n $TEST... " $N +$CMD0 >/dev/null 2>"${te}0" & +pid0=$! +waittcp4port $PORT 1 +(echo "R"; sleep 1; echo "$da"; sleep 1) |$CMD1 2>"${te}1" |fgrep "$da" >"${tf}1" +rc1=$? +kill $pid0 2>/dev/null; wait +if echo "$da" |diff - ${tf}1 >"$tdiff"; then + $PRINTF "$OK\n" + numOK=$((numOK+1)) +else + $PRINTF "$FAILED\n" + echo "$CMD0 &" + echo "$CMD1" + cat "${te}0" +# cat "${te}1" + cat "$tdiff" + numFAIL=$((numFAIL+1)) +fi +fi # NUMCOND + ;; +esac +N=$((N+1)) + + +# socat up to 1.7.1.1 (and 2.0.0-b3) terminated with error when an openssl peer +# performed a renegotiation. The first temporary fix to this problem might +# leave socat in a blocking ssl-read state. Test if this has been fixed. +NAME=OPENSSLRENEG2 +case "$TESTS" in +*%functions%*|*%bugs%*|*%openssl%*|*%socket%*|*%$NAME%*) +TEST="$NAME: OpenSSL connections do not block after renogotiation" +# connect with s_client to socat ssl-l; force a renog, then transfer data from +# socat to the peer. When data is passed this means that the former ssl read no +# longer blocks and the test succeeds +if ! eval $NUMCOND; then :; else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +da="test$N $(date) $RANDOM" +CMD0="$SOCAT $opts OPENSSL-LISTEN:$PORT,reuseaddr,cert=testsrv.crt,key=testsrv.key,verify=0 SYSTEM:\"sleep 1; echo \\\\\\\"\\\"$da\\\"\\\\\\\"; sleep 1\"!!STDIO" +CMD1="openssl s_client -port $PORT -verify 0" +printf "test $F_n $TEST... " $N +eval "$CMD0 >/dev/null 2>\"${te}0\" &" +pid0=$! +waittcp4port $PORT 1 +(echo "R"; sleep 2) |$CMD1 2>"${te}1" |fgrep "$da" >"${tf}1" +rc1=$? +kill $pid0 2>/dev/null; wait +if echo "$da" |diff - ${tf}1 >"$tdiff"; then + $PRINTF "$OK\n" + numOK=$((numOK+1)) +else + $PRINTF "$FAILED\n" + echo "$CMD0 &" + echo "$CMD1" + cat "${te}0" +# cat "${te}1" + cat "$tdiff" + numFAIL=$((numFAIL+1)) +fi +fi # NUMCOND + ;; +esac +N=$((N+1)) + + echo "summary: $((N-1)) tests; $numOK ok, $numFAIL failed, $numCANT could not be performed" if [ "$numFAIL" -gt 0 ]; then diff --git a/xio-openssl.c b/xio-openssl.c index 3bd8178..e4d37b6 100644 --- a/xio-openssl.c +++ b/xio-openssl.c @@ -1,5 +1,5 @@ /* source: xio-openssl.c */ -/* Copyright Gerhard Rieger 2002-2008 */ +/* Copyright Gerhard Rieger 2002-2009 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the implementation of the openssl addresses */ @@ -1054,8 +1054,9 @@ ssize_t xioread_openssl(struct single *pipe, void *buff, size_t bufsiz) { case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_CONNECT: case SSL_ERROR_WANT_X509_LOOKUP: - Error("nonblocking operation did not complete"); - break; /*!*/ + Info("nonblocking operation did not complete"); + errno = EAGAIN; + return -1; case SSL_ERROR_SYSCALL: if (ERR_peek_error() == 0) { if (ret == 0) {