Ver código fonte

Decide whether to use SSL flags based on runtime OpenSSL version.

We need to do this because Apple doesn't update its dev-tools headers
when it updates its libraries in a security patch.  On the bright
side, this might get us out of shipping a statically linked OpenSSL on
OSX.

May fix bug 1225.

[backported]
Nick Mathewson 15 anos atrás
pai
commit
1744e447a1
2 arquivos alterados com 52 adições e 15 exclusões
  1. 6 0
      ChangeLog
  2. 46 15
      src/common/tortls.c

+ 6 - 0
ChangeLog

@@ -8,6 +8,12 @@ Changes in version 0.2.1.23 - 2010-0?-??
       automatically discard guards picked using the old algorithm. Fixes
       automatically discard guards picked using the old algorithm. Fixes
       bug 1217; bugfix on 0.2.1.3-alpha. Found by Mike Perry.
       bug 1217; bugfix on 0.2.1.3-alpha. Found by Mike Perry.
 
 
+  o Minor bugfixes:
+    - When deciding whether to use strange flags to turn TLS renegotiation
+      on, detect the OpenSSL version at run-time, not compile time.  We
+      need to do this because Apple doesn't update its dev-tools headers
+      when it updates its libraries in a security patch.
+
   o Minor features:
   o Minor features:
     - Avoid a mad rush at the beginning of each month when each client
     - Avoid a mad rush at the beginning of each month when each client
       rotates half of its guards. Instead we spread the rotation out
       rotates half of its guards. Instead we spread the rotation out

+ 46 - 15
src/common/tortls.c

@@ -53,6 +53,24 @@
 
 
 #define ADDR(tls) (((tls) && (tls)->address) ? tls->address : "peer")
 #define ADDR(tls) (((tls) && (tls)->address) ? tls->address : "peer")
 
 
+/* We redefine these so that we can run correctly even if the vendor gives us
+ * a version of OpenSSL that does not match its header files.  (Apple: I am
+ * looking at you.)
+ */
+#ifndef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
+#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000L
+#endif
+#ifndef SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
+#define SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x0010
+#endif
+
+/** Does the run-time openssl version look like we need
+ * SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION? */
+static int use_unsafe_renegotiation_op = 0;
+/** Does the run-time openssl version look like we need
+ * SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION? */
+static int use_unsafe_renegotiation_flag = 0;
+
 /** Structure holding the TLS state for a single connection. */
 /** Structure holding the TLS state for a single connection. */
 typedef struct tor_tls_context_t {
 typedef struct tor_tls_context_t {
   int refcnt;
   int refcnt;
@@ -309,9 +327,29 @@ static void
 tor_tls_init(void)
 tor_tls_init(void)
 {
 {
   if (!tls_library_is_initialized) {
   if (!tls_library_is_initialized) {
+    long version;
     SSL_library_init();
     SSL_library_init();
     SSL_load_error_strings();
     SSL_load_error_strings();
     crypto_global_init(-1);
     crypto_global_init(-1);
+
+    version = SSLeay();
+    if (version >= 0x009070c0L && version < 0x00908000L) {
+      log_notice(LD_GENERAL, "OpenSSL %s looks like version 0.9.7l or later; "
+                 "I will try SSL3_FLAGS and SSL3_OP to enable renegotation",
+                 SSLeay_version(SSLEAY_VERSION));
+      use_unsafe_renegotiation_flag = 1;
+      use_unsafe_renegotiation_op = 1;
+    } else if (version >= 0x009080c0L) {
+      log_notice(LD_GENERAL, "OpenSSL %s looks like version 0.9.8l or later; "
+                 "I will try SSL3_FLAGS and SSL_OP to enable renegotiation",
+                 SSLeay_version(SSLEAY_VERSION));
+      use_unsafe_renegotiation_flag = 1;
+      use_unsafe_renegotiation_op = 1;
+    } else {
+      log_info(LD_GENERAL, "OpenSSL %s has version %lx",
+               SSLeay_version(SSLEAY_VERSION), version);
+    }
+
     tls_library_is_initialized = 1;
     tls_library_is_initialized = 1;
   }
   }
 }
 }
@@ -568,7 +606,6 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime)
   SSL_CTX_set_options(result->ctx,
   SSL_CTX_set_options(result->ctx,
                       SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
                       SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
 #endif
 #endif
-#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
   /* Yes, we know what we are doing here.  No, we do not treat a renegotiation
   /* Yes, we know what we are doing here.  No, we do not treat a renegotiation
    * as authenticating any earlier-received data.
    * as authenticating any earlier-received data.
    *
    *
@@ -577,9 +614,10 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime)
    * seems) broke anything that used SSL3_FLAGS_* for the purpose.  So we need
    * seems) broke anything that used SSL3_FLAGS_* for the purpose.  So we need
    * to do both.)
    * to do both.)
    */
    */
-  SSL_CTX_set_options(result->ctx,
+  if (use_unsafe_renegotiation_op) {
-                      SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
+    SSL_CTX_set_options(result->ctx,
-#endif
+                        SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
+  }
   /* Don't actually allow compression; it uses ram and time, but the data
   /* Don't actually allow compression; it uses ram and time, but the data
    * we transmit is all encrypted anyway. */
    * we transmit is all encrypted anyway. */
   if (result->ctx->comp_methods)
   if (result->ctx->comp_methods)
@@ -920,19 +958,16 @@ tor_tls_set_renegotiate_callback(tor_tls_t *tls,
 }
 }
 
 
 /** If this version of openssl requires it, turn on renegotiation on
 /** 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
+ * <b>tls</b>.
- * to use belt-and-suspenders here.)
  */
  */
 static void
 static void
 tor_tls_unblock_renegotiation(tor_tls_t *tls)
 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
   /* Yes, we know what we are doing here.  No, we do not treat a renegotiation
    * as authenticating any earlier-received data. */
    * as authenticating any earlier-received data. */
-  tls->ssl->s3->flags |= SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
+  if (use_unsafe_renegotiation_flag) {
-#else
+    tls->ssl->s3->flags |= SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
-  (void)tls;
+  }
-#endif
 }
 }
 
 
 /** If this version of openssl supports it, turn off renegotiation on
 /** If this version of openssl supports it, turn off renegotiation on
@@ -942,11 +977,7 @@ tor_tls_unblock_renegotiation(tor_tls_t *tls)
 void
 void
 tor_tls_block_renegotiation(tor_tls_t *tls)
 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;
   tls->ssl->s3->flags &= ~SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
-#else
-  (void)tls;
-#endif
 }
 }
 
 
 /** Return whether this tls initiated the connect (client) or
 /** Return whether this tls initiated the connect (client) or