Browse Source

Merge commit 'origin/maint-0.2.1'

Conflicts:
	src/common/tortls.c
Nick Mathewson 16 years ago
parent
commit
0a58567ce3
4 changed files with 43 additions and 0 deletions
  1. 6 0
      ChangeLog
  2. 34 0
      src/common/tortls.c
  3. 1 0
      src/common/tortls.h
  4. 2 0
      src/or/connection_or.c

+ 6 - 0
ChangeLog

@@ -311,6 +311,12 @@ Changes in version 0.2.2.1-alpha - 2009-08-26
 
 
 Changes in Version 0.2.1.21 - 20??-??-??
+  o Major bugfixes:
+    - Work around a security feature in OpenSSL 0.9.8l that prevents our
+      handshake from working unless we explicitly tell OpenSSL that we are
+      using SSL renegotiation safely.  We are, of course, but OpenSSL
+      0.9.8l won't work unless we say we are.
+
   o Minor bugfixes:
     - Do not refuse to learn about authority certs and v2 networkstatus
       documents that are older than the latest consensus.  This bug might

+ 34 - 0
src/common/tortls.c

@@ -154,6 +154,7 @@ static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa,
                                         const char *cname,
                                         const char *cname_sign,
                                         unsigned int lifetime);
+static void tor_tls_unblock_renegotiation(tor_tls_t *tls);
 
 /** Global tls context. We keep it here because nobody else needs to
  * touch it. */
@@ -927,6 +928,36 @@ tor_tls_set_renegotiate_callback(tor_tls_t *tls,
 #endif
 }
 
+/** If this version of openssl requires it, turn on renegotiation on
+ * <b>tls</b>.  (Our protocol never requires this for security, but it's nice
+ * to use belt-and-suspenders here.)
+ */
+static void
+tor_tls_unblock_renegotiation(tor_tls_t *tls)
+{
+#ifdef SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
+  /* Yes, we know what we are doing here.  No, we do not treat a renegotiation
+   * as authenticating any earlier-received data. */
+  tls->ssl->s3->flags |= SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
+#else
+  (void)tls;
+#endif
+}
+
+/** If this version of openssl supports it, turn off renegotiation on
+ * <b>tls</b>.  (Our protocol never requires this for security, but it's nice
+ * to use belt-and-suspenders here.)
+ */
+void
+tor_tls_block_renegotiation(tor_tls_t *tls)
+{
+#ifdef SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
+  tls->ssl->s3->flags &= ~SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
+#else
+  (void)tls;
+#endif
+}
+
 /** Return whether this tls initiated the connect (client) or
  * received it (server). */
 int
@@ -1058,6 +1089,9 @@ tor_tls_handshake(tor_tls_t *tls)
   if (oldstate != tls->ssl->state)
     log_debug(LD_HANDSHAKE, "After call, %p was in state %s",
               tls, ssl_state_to_string(tls->ssl->state));
+  /* We need to call this here and not earlier, since OpenSSL has a penchant
+   * for clearing its flags when you say accept or connect. */
+  tor_tls_unblock_renegotiation(tls);
   r = tor_tls_get_error(tls,r,0, "handshaking", LOG_INFO, LD_HANDSHAKE);
   if (ERR_peek_error() != 0) {
     tls_log_errors(tls, tls->isServer ? LOG_INFO : LOG_WARN, LD_HANDSHAKE,

+ 1 - 0
src/common/tortls.h

@@ -65,6 +65,7 @@ int tor_tls_read(tor_tls_t *tls, char *cp, size_t len);
 int tor_tls_write(tor_tls_t *tls, const char *cp, size_t n);
 int tor_tls_handshake(tor_tls_t *tls);
 int tor_tls_renegotiate(tor_tls_t *tls);
+void tor_tls_block_renegotiation(tor_tls_t *tls);
 int tor_tls_shutdown(tor_tls_t *tls);
 int tor_tls_get_pending_bytes(tor_tls_t *tls);
 size_t tor_tls_get_forced_write_size(tor_tls_t *tls);

+ 2 - 0
src/or/connection_or.c

@@ -799,6 +799,7 @@ connection_or_tls_renegotiated_cb(tor_tls_t *tls, void *_conn)
 
   /* Don't invoke this again. */
   tor_tls_set_renegotiate_callback(tls, NULL, NULL);
+  tor_tls_block_renegotiation(tls);
 
   if (connection_tls_finish_handshake(conn) < 0) {
     /* XXXX_TLS double-check that it's ok to do this from inside read. */
@@ -1045,6 +1046,7 @@ connection_tls_finish_handshake(or_connection_t *conn)
       connection_or_init_conn_from_address(conn, &conn->_base.addr,
                                            conn->_base.port, digest_rcvd, 0);
     }
+    tor_tls_block_renegotiation(conn->tls);
     return connection_or_set_state_open(conn);
   } else {
     conn->_base.state = OR_CONN_STATE_OR_HANDSHAKING;