Browse Source

Detect renegotiation when it actually happens.

The renegotiation callback was called only when the first Application
Data arrived, instead of when the renegotiation took place.

This happened because SSL_read() returns -1 and sets the error to
SSL_ERROR_WANT_READ when a renegotiation happens instead of reading
data [0].

I also added a commented out aggressive assert that I won't enable yet
because I don't feel I understand SSL_ERROR_WANT_READ enough.

[0]: Look at documentation of SSL_read(), SSL_get_error() and
     SSL_CTX_set_mode() (SSL_MODE_AUTO_RETRY section).
George Kadianakis 14 years ago
parent
commit
4fd79f9def
1 changed files with 19 additions and 10 deletions
  1. 19 10
      src/common/tortls.c

+ 19 - 10
src/common/tortls.c

@@ -1606,19 +1606,28 @@ tor_tls_read(tor_tls_t *tls, char *cp, size_t len)
   tor_assert(tls->state == TOR_TLS_ST_OPEN);
   tor_assert(len<INT_MAX);
   r = SSL_read(tls->ssl, cp, (int)len);
-  if (r > 0) {
+  if (r > 0) /* return the number of characters read */
+    return r;
+
+  /* If we got here, SSL_read() did not go as expected. */
+
+  err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_DEBUG, LD_NET);
+
 #ifdef V2_HANDSHAKE_SERVER
-    if (tls->got_renegotiate) {
-      /* Renegotiation happened! */
-      log_info(LD_NET, "Got a TLS renegotiation from %s", ADDR(tls));
-      if (tls->negotiated_callback)
-        tls->negotiated_callback(tls, tls->callback_arg);
-      tls->got_renegotiate = 0;
-    }
-#endif
+  if (tls->got_renegotiate) {
+    tor_assert(tls->server_handshake_count == 2);
+    /* XXX tor_assert(err == TOR_TLS_WANTREAD); */
+
+    /* Renegotiation happened! */
+    log_info(LD_NET, "Got a TLS renegotiation from %s", ADDR(tls));
+    if (tls->negotiated_callback)
+      tls->negotiated_callback(tls, tls->callback_arg);
+    tls->got_renegotiate = 0;
+
     return r;
   }
-  err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_DEBUG, LD_NET);
+#endif
+
   if (err == _TOR_TLS_ZERORETURN || err == TOR_TLS_CLOSE) {
     log_debug(LD_NET,"read returned r=%d; TLS is closed",r);
     tls->state = TOR_TLS_ST_CLOSED;