Commit 638fdedc authored by Nick Mathewson's avatar Nick Mathewson 🐚 Committed by Sebastian Hahn
Browse files

Don't send a certificate chain on outgoing TLS connections from non-relays

parent a166f104
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
  o Security fixes:

    - Don't send TLS certificate chains on outgoing OR connections
      from clients and bridges.  Previously, each client or bridge
      would use a single cert chain for all outgoing OR connections
      for up to 24 hours, which allowed any relay connected to by a
      client or bridge to determine which entry guards it is using.
      This is a potential user-tracing bug for *all* users; everyone
      who uses Tor's client or hidden service functionality should
      upgrade.  Fixes CVE-2011-2768.  Bugfix on FIXME; found by
      frosty_un.
+54 −39
Original line number Diff line number Diff line
@@ -186,9 +186,11 @@ static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa,
static void tor_tls_unblock_renegotiation(tor_tls_t *tls);
static int tor_tls_context_init_one(tor_tls_context_t **ppcontext,
                                    crypto_pk_env_t *identity,
                                    unsigned int key_lifetime);
                                    unsigned int key_lifetime,
                                    int is_client);
static tor_tls_context_t *tor_tls_context_new(crypto_pk_env_t *identity,
                                              unsigned int key_lifetime);
                                              unsigned int key_lifetime,
                                              int is_client);

/** Global TLS contexts. We keep them here because nobody else needs
 * to touch them. */
@@ -624,7 +626,7 @@ tor_tls_context_init(int is_public_server,

    rv1 = tor_tls_context_init_one(&server_tls_context,
                                   server_identity,
                                   key_lifetime);
                                   key_lifetime, 0);

    if (rv1 >= 0) {
      new_ctx = server_tls_context;
@@ -640,7 +642,8 @@ tor_tls_context_init(int is_public_server,
    if (server_identity != NULL) {
      rv1 = tor_tls_context_init_one(&server_tls_context,
                                     server_identity,
                                     key_lifetime);
                                     key_lifetime,
                                     0);
    } else {
      tor_tls_context_t *old_ctx = server_tls_context;
      server_tls_context = NULL;
@@ -652,7 +655,8 @@ tor_tls_context_init(int is_public_server,

    rv2 = tor_tls_context_init_one(&client_tls_context,
                                   client_identity,
                                   key_lifetime);
                                   key_lifetime,
                                   1);
  }

  return rv1 < rv2 ? rv1 : rv2;
@@ -669,10 +673,12 @@ tor_tls_context_init(int is_public_server,
static int
tor_tls_context_init_one(tor_tls_context_t **ppcontext,
                         crypto_pk_env_t *identity,
                         unsigned int key_lifetime)
                         unsigned int key_lifetime,
                         int is_client)
{
  tor_tls_context_t *new_ctx = tor_tls_context_new(identity,
                                                   key_lifetime);
                                                   key_lifetime,
                                                   is_client);
  tor_tls_context_t *old_ctx = *ppcontext;

  if (new_ctx != NULL) {
@@ -694,7 +700,8 @@ tor_tls_context_init_one(tor_tls_context_t **ppcontext,
 * certificate.
 */
static tor_tls_context_t *
tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime)
tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime,
                    int is_client)
{
  crypto_pk_env_t *rsa = NULL;
  EVP_PKEY *pkey = NULL;
@@ -711,6 +718,7 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime)
    goto error;
  if (crypto_pk_generate_key(rsa)<0)
    goto error;
  if (!is_client) {
    /* Create certificate signed by identity key. */
    cert = tor_tls_create_certificate(rsa, identity, nickname, nn2,
                                      key_lifetime);
@@ -721,12 +729,15 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime)
      log(LOG_WARN, LD_CRYPTO, "Error creating certificate");
      goto error;
    }
  }

  result = tor_malloc_zero(sizeof(tor_tls_context_t));
  result->refcnt = 1;
  if (!is_client) {
    result->my_cert = X509_dup(cert);
    result->my_id_cert = X509_dup(idcert);
    result->key = crypto_pk_dup_key(rsa);
  }

#ifdef EVERYONE_HAS_AES
  /* Tell OpenSSL to only use TLS1 */
@@ -758,6 +769,7 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime)
#ifdef SSL_MODE_RELEASE_BUFFERS
  SSL_CTX_set_mode(result->ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
  if (! is_client) {
    if (cert && !SSL_CTX_use_certificate(result->ctx,cert))
      goto error;
    X509_free(cert); /* We just added a reference to cert. */
@@ -769,7 +781,9 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime)
      X509_free(idcert); /* The context now owns the reference to idcert */
      idcert = NULL;
    }
  }
  SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF);
  if (!is_client) {
    tor_assert(rsa);
    if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,1)))
      goto error;
@@ -779,6 +793,7 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime)
    pkey = NULL;
    if (!SSL_CTX_check_private_key(result->ctx))
      goto error;
  }
  {
    crypto_dh_env_t *dh = crypto_dh_new(DH_TYPE_TLS);
    SSL_CTX_set_tmp_dh(result->ctx, _crypto_dh_env_get_dh(dh));