|  | @@ -53,6 +53,24 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #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. */
 | 
	
		
			
				|  |  |  typedef struct tor_tls_context_t {
 | 
	
		
			
				|  |  |    int refcnt;
 | 
	
	
		
			
				|  | @@ -333,8 +351,28 @@ static void
 | 
	
		
			
				|  |  |  tor_tls_init(void)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    if (!tls_library_is_initialized) {
 | 
	
		
			
				|  |  | +    long version;
 | 
	
		
			
				|  |  |      SSL_library_init();
 | 
	
		
			
				|  |  |      SSL_load_error_strings();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    version = SSLeay();
 | 
	
		
			
				|  |  | +    if (version >= 0x009070c0L && version < 0x00908000L) {
 | 
	
		
			
				|  |  | +      log_notice(LD_GENERAL, "OpenSSL %s looks like version 0.9.7l or later; "
 | 
	
		
			
				|  |  | +                 "I will use SSL3_FLAGS to enable renegotation",
 | 
	
		
			
				|  |  | +                 SSLeay_version(SSLEAY_VERSION));
 | 
	
		
			
				|  |  | +      use_unsafe_renegotiation_flag = 1;
 | 
	
		
			
				|  |  | +      use_unsafe_renegotiation_op = 1;
 | 
	
		
			
				|  |  | +    } else if (version >= 0x009080d0L) {
 | 
	
		
			
				|  |  | +      log_notice(LD_GENERAL, "OpenSSL %s looks like version 0.9.8m or later; "
 | 
	
		
			
				|  |  | +                 "I will use 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;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -591,7 +629,6 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime)
 | 
	
		
			
				|  |  |    SSL_CTX_set_options(result->ctx,
 | 
	
		
			
				|  |  |                        SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  | -#ifdef SSL_OP_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.
 | 
	
		
			
				|  |  |     *
 | 
	
	
		
			
				|  | @@ -600,9 +637,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
 | 
	
		
			
				|  |  |     * to do both.)
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  | -  SSL_CTX_set_options(result->ctx,
 | 
	
		
			
				|  |  | -                      SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | +  if (use_unsafe_renegotiation_op) {
 | 
	
		
			
				|  |  | +    SSL_CTX_set_options(result->ctx,
 | 
	
		
			
				|  |  | +                        SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |    /* Don't actually allow compression; it uses ram and time, but the data
 | 
	
		
			
				|  |  |     * we transmit is all encrypted anyway. */
 | 
	
		
			
				|  |  |    if (result->ctx->comp_methods)
 | 
	
	
		
			
				|  | @@ -943,19 +981,16 @@ tor_tls_set_renegotiate_callback(tor_tls_t *tls,
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /** 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.)
 | 
	
		
			
				|  |  | + * <b>tls</b>.
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  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 (use_unsafe_renegotiation_flag) {
 | 
	
		
			
				|  |  | +    tls->ssl->s3->flags |= SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /** If this version of openssl supports it, turn off renegotiation on
 | 
	
	
		
			
				|  | @@ -965,11 +1000,7 @@ tor_tls_unblock_renegotiation(tor_tls_t *tls)
 | 
	
		
			
				|  |  |  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
 |