Explorar o código

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 %!s(int64=14) %!d(string=hai) anos
pai
achega
4fd79f9def
Modificáronse 1 ficheiros con 19 adicións e 10 borrados
  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;