]> granicus.if.org Git - curl/commitdiff
OpenSSL: multi interface handshake could hang
authorDaniel Stenberg <daniel@haxx.se>
Fri, 14 May 2010 20:34:10 +0000 (22:34 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 14 May 2010 20:35:08 +0000 (22:35 +0200)
John-Mark Bell filed bug #3000052 that identified a problem (with
an associated patch) with the OpenSSL handshake state machine
when the multi interface is used:

Performing an https request using a curl multi handle and using
select or epoll to wait for events results in a hang. It appears
that the cause is the fix for bug #2958179, which makes
ossl_connect_common unconditionally return from the step 2 loop
when fetching from a multi handle.

When ossl_connect_step2 has completed, it updates
connssl->connecting_state to ssl_connect_3. ossl_connect_common
will then return to the caller, as a multi handle is in
use. Eventually, the client code will call curl_multi_fdset to
obtain an updated fdset to select or epoll on. For https
requests, curl_multi_fdset will cause https_getsock to be called.
https_getsock will only return a socket handle if the
connecting_state is ssl_connect_2_reading or
ssl_connect_2_writing.  Therefore, the client will never obtain a
valid fdset, and thus not drive the multi handle, resulting in a
hang.

(http://curl.haxx.se/bug/view.cgi?id=3000052)

CHANGES
RELEASE-NOTES
lib/ssluse.c

diff --git a/CHANGES b/CHANGES
index ecb36c437580686bfa0e69d811e848e4c3ba2dfc..d895ebeb6905e3fa76b7ef8846f0a3262658c5a0 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,27 @@
                                   Changelog
 
 Daniel Stenberg (14 May 2010)
+- John-Mark Bell filed bug #3000052 that identified a problem (with an
+  associated patch) with the OpenSSL handshake state machine when the multi
+  interface is used:
+
+  Performing an https request using a curl multi handle and using select or
+  epoll to wait for events results in a hang. It appears that the cause is the
+  fix for bug #2958179, which makes ossl_connect_common unconditionally return
+  from the step 2 loop when fetching from a multi handle.
+
+  When ossl_connect_step2 has completed, it updates connssl->connecting_state
+  to ssl_connect_3. ossl_connect_common will then return to the caller, as a
+  multi handle is in use. Eventually, the client code will call
+  curl_multi_fdset to obtain an updated fdset to select or epoll on. For https
+  requests, curl_multi_fdset will cause https_getsock to be called.
+  https_getsock will only return a socket handle if the connecting_state is
+  ssl_connect_2_reading or ssl_connect_2_writing.  Therefore, the client will
+  never obtain a valid fdset, and thus not drive the multi handle, resulting
+  in a hang.
+
+  (http://curl.haxx.se/bug/view.cgi?id=3000052)
+
 - Sebastian V reported bug #3000056 identifying a problem with redirect
   following. It showed that when curl followed redirects it didn't properly
   ignore the response body of the 30X response if that response was using
index 83b682e9865fd8f11a0ab51e091971a2c36589e8..37348f91f8ddc892d14aa79f36083771cfb144e6 100644 (file)
@@ -29,6 +29,7 @@ This release includes the following bugfixes:
  o multi interface missed storing connection time
  o broken CRL support in libcurl-NSS
  o ignore response-body on redirect even if compressed
+ o OpenSSL handshake state-machine for multi interface
 
 This release includes the following known bugs:
 
@@ -39,6 +40,6 @@ advice from friends like these:
 
  Rainer Canavan, Paul Howarth, Jerome Vouillon, Ruslan Gazizov, Yang Tse,
  Kamil Dudka, Alex Bligh, Ben Greear, Hoi-Ho Chan, Howard Chu, Dirk Manske,
- Pavel Raiskup
+ Pavel Raiskup, John-Mark Bell
 
         Thanks! (and sorry if I forgot to mention someone)
index ce62605e8b616669cf4a9c3ec3477df85609e83e..01eba90db9835aa2aeea0a5629a2a07a07d6663b 100644 (file)
@@ -2425,8 +2425,18 @@ ossl_connect_common(struct connectdata *conn,
       /* socket is readable or writable */
     }
 
+    /* Run transaction, and return to the caller if it failed or if
+     * this connection is part of a multi handle and this loop would
+     * execute again. This permits the owner of a multi handle to
+     * abort a connection attempt before step2 has completed while
+     * ensuring that a client using select() or epoll() will always
+     * have a valid fdset to wait on.
+     */
     retcode = ossl_connect_step2(conn, sockindex);
-    if(retcode || (data->state.used_interface == Curl_if_multi))
+    if(retcode || (data->state.used_interface == Curl_if_multi &&
+                   (ssl_connect_2 == connssl->connecting_state ||
+                    ssl_connect_2_reading == connssl->connecting_state ||
+                    ssl_connect_2_writing == connssl->connecting_state)))
       return retcode;
 
   } /* repeat step2 until all transactions are done. */