[or-cvs] [tor/master] Merge remote branch 'origin/maint-0.2.2'

nickm at torproject.org nickm at torproject.org
Mon Jan 24 22:52:51 UTC 2011


commit aaa5737a2e6141bdff13f03051500d2f0ce84861
Merge: c496229 5ed73e3
Author: Nick Mathewson <nickm at torproject.org>
Date:   Mon Jan 24 17:51:52 2011 -0500

    Merge remote branch 'origin/maint-0.2.2'

 changes/dhparam        |    3 +++
 src/common/crypto.c    |   34 ++++++++++++++++++++++++++++------
 src/common/crypto.h    |    5 ++++-
 src/common/tortls.c    |    2 +-
 src/or/onion.c         |    4 ++--
 src/or/rendclient.c    |    2 +-
 src/or/rendservice.c   |    2 +-
 src/test/test_crypto.c |    4 ++--
 8 files changed, 42 insertions(+), 14 deletions(-)

diff --combined src/common/crypto.c
index 1c0b21f,5264fd8..1108ba2
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@@ -927,7 -927,7 +927,7 @@@ crypto_pk_public_checksig_digest(crypto
      log_warn(LD_BUG, "couldn't compute digest");
      return -1;
    }
 -  buflen = crypto_pk_keysize(env)+1;
 +  buflen = crypto_pk_keysize(env);
    buf = tor_malloc(buflen);
    r = crypto_pk_public_checksig(env,buf,buflen,sig,siglen);
    if (r != DIGEST_LEN) {
@@@ -1112,8 -1112,8 +1112,8 @@@ crypto_pk_private_hybrid_decrypt(crypto
                                       warnOnFailure);
    }
  
 -  buf = tor_malloc(pkeylen+1);
 -  outlen = crypto_pk_private_decrypt(env,buf,pkeylen+1,from,pkeylen,padding,
 +  buf = tor_malloc(pkeylen);
 +  outlen = crypto_pk_private_decrypt(env,buf,pkeylen,from,pkeylen,padding,
                                       warnOnFailure);
    if (outlen<0) {
      log_fn(warnOnFailure?LOG_WARN:LOG_DEBUG, LD_CRYPTO,
@@@ -1685,8 -1685,10 +1685,10 @@@ crypto_hmac_sha1(char *hmac_out
  
  /* DH */
  
- /** Shared P parameter for our DH key exchanged. */
+ /** Shared P parameter for our circuit-crypto DH key exchanges. */
  static BIGNUM *dh_param_p = NULL;
+ /** Shared P parameter for our TLS DH key exchanges. */
+ static BIGNUM *dh_param_p_tls = NULL;
  /** Shared G parameter for our DH key exchanges. */
  static BIGNUM *dh_param_g = NULL;
  
@@@ -1695,14 -1697,16 +1697,16 @@@
  static void
  init_dh_param(void)
  {
-   BIGNUM *p, *g;
+   BIGNUM *p, *p2, *g;
    int r;
-   if (dh_param_p && dh_param_g)
+   if (dh_param_p && dh_param_g && dh_param_p_tls)
      return;
  
    p = BN_new();
+   p2 = BN_new();
    g = BN_new();
    tor_assert(p);
+   tor_assert(p2);
    tor_assert(g);
  
    /* This is from rfc2409, section 6.2.  It's a safe prime, and
@@@ -1716,10 -1720,20 +1720,20 @@@
                  "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
                  "49286651ECE65381FFFFFFFFFFFFFFFF");
    tor_assert(r);
+   /* This is the 1024-bit safe prime that Apache uses for its DH stuff; see
+    * modules/ssl/ssl_engine_dh.c */
+   r = BN_hex2bn(&p2,
+                   "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98"
+                 "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A"
+                 "467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7"
+                 "DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68"
+                 "B0E7393E0F24218EB3");
+   tor_assert(r);
  
    r = BN_set_word(g, 2);
    tor_assert(r);
    dh_param_p = p;
+   dh_param_p_tls = p2;
    dh_param_g = g;
  }
  
@@@ -1728,18 -1742,26 +1742,26 @@@
  /** Allocate and return a new DH object for a key exchange.
   */
  crypto_dh_env_t *
- crypto_dh_new(void)
+ crypto_dh_new(int dh_type)
  {
    crypto_dh_env_t *res = tor_malloc_zero(sizeof(crypto_dh_env_t));
  
+   tor_assert(dh_type == DH_TYPE_CIRCUIT || dh_type == DH_TYPE_TLS ||
+              dh_type == DH_TYPE_REND);
+ 
    if (!dh_param_p)
      init_dh_param();
  
    if (!(res->dh = DH_new()))
      goto err;
  
-   if (!(res->dh->p = BN_dup(dh_param_p)))
-     goto err;
+   if (dh_type == DH_TYPE_TLS) {
+     if (!(res->dh->p = BN_dup(dh_param_p_tls)))
+       goto err;
+   } else {
+     if (!(res->dh->p = BN_dup(dh_param_p)))
+       goto err;
+   }
  
    if (!(res->dh->g = BN_dup(dh_param_g)))
      goto err;
@@@ -2667,3 -2689,4 +2689,3 @@@ setup_openssl_threading(void
    return 0;
  }
  #endif
 -
diff --combined src/common/crypto.h
index ee27831,7134956..f114dd6
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@@ -195,7 -195,10 +195,10 @@@ void crypto_hmac_sha1(char *hmac_out
                        const char *msg, size_t msg_len);
  
  /* Key negotiation */
- crypto_dh_env_t *crypto_dh_new(void);
+ #define DH_TYPE_CIRCUIT 1
+ #define DH_TYPE_REND 2
+ #define DH_TYPE_TLS 3
+ crypto_dh_env_t *crypto_dh_new(int dh_type);
  int crypto_dh_get_bytes(crypto_dh_env_t *dh);
  int crypto_dh_generate_public(crypto_dh_env_t *dh);
  int crypto_dh_get_public(crypto_dh_env_t *dh, char *pubkey_out,
@@@ -240,8 -243,7 +243,8 @@@ void secret_to_key(char *key_out, size_
                     size_t secret_len, const char *s2k_specifier);
  
  #ifdef CRYPTO_PRIVATE
 -/* Prototypes for private functions only used by tortls.c and crypto.c */
 +/* Prototypes for private functions only used by tortls.c, crypto.c, and the
 + * unit tests. */
  struct rsa_st;
  struct evp_pkey_st;
  struct dh_st;
diff --combined src/common/tortls.c
index aa5dd1b,8ad0f2f..6d38b55
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@@ -44,14 -44,7 +44,14 @@@
  #error "We require OpenSSL >= 0.9.7"
  #endif
  
 +#ifdef USE_BUFFEREVENTS
 +#include <event2/bufferevent_ssl.h>
 +#include <event2/buffer.h>
 +#include "compat_libevent.h"
 +#endif
 +
  #define CRYPTO_PRIVATE /* to import prototypes from crypto.h */
 +#define TORTLS_PRIVATE
  
  #include "crypto.h"
  #include "tortls.h"
@@@ -116,7 -109,6 +116,7 @@@ struct tor_tls_t 
    enum {
      TOR_TLS_ST_HANDSHAKE, TOR_TLS_ST_OPEN, TOR_TLS_ST_GOTCLOSE,
      TOR_TLS_ST_SENTCLOSE, TOR_TLS_ST_CLOSED, TOR_TLS_ST_RENEGOTIATE,
 +    TOR_TLS_ST_BUFFEREVENT
    } state : 3; /**< The current SSL state, depending on which operations have
                  * completed successfully. */
    unsigned int isServer:1; /**< True iff this is a server-side connection */
@@@ -125,10 -117,8 +125,10 @@@
                                    * of the connection protocol (client sends
                                    * different cipher list, server sends only
                                    * one certificate). */
 - /** True iff we should call negotiated_callback when we're done reading. */
 +  /** True iff we should call negotiated_callback when we're done reading. */
    unsigned int got_renegotiate:1;
 +  /** Incremented every time we start the server side of a handshake. */
 +  uint8_t server_handshake_count;
    size_t wantwrite_n; /**< 0 normally, >0 if we returned wantwrite last
                         * time. */
    /** Last values retrieved from BIO_number_read()/write(); see
@@@ -199,7 -189,7 +199,7 @@@ static X509* tor_tls_create_certificate
                                          const char *cname,
                                          const char *cname_sign,
                                          unsigned int lifetime);
 -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);
@@@ -210,7 -200,6 +210,7 @@@ static tor_tls_context_t *tor_tls_conte
   * to touch them. */
  static tor_tls_context_t *server_tls_context = NULL;
  static tor_tls_context_t *client_tls_context = NULL;
 +
  /** True iff tor_tls_init() has been called. */
  static int tls_library_is_initialized = 0;
  
@@@ -234,46 -223,36 +234,46 @@@ ssl_state_to_string(int ssl_state
    return buf;
  }
  
 +void
 +tor_tls_log_one_error(tor_tls_t *tls, unsigned long err,
 +                  int severity, int domain, const char *doing)
 +{
 +  const char *state = NULL, *addr;
 +  const char *msg, *lib, *func;
 +  int st;
 +
 +  st = (tls && tls->ssl) ? tls->ssl->state : -1;
 +  state = (st>=0)?ssl_state_to_string(st):"---";
 +
 +  addr = tls ? tls->address : NULL;
 +
 +  msg = (const char*)ERR_reason_error_string(err);
 +  lib = (const char*)ERR_lib_error_string(err);
 +  func = (const char*)ERR_func_error_string(err);
 +  if (!msg) msg = "(null)";
 +  if (!lib) lib = "(null)";
 +  if (!func) func = "(null)";
 +  if (doing) {
 +    log(severity, domain, "TLS error while %s%s%s: %s (in %s:%s:%s)",
 +        doing, addr?" with ":"", addr?addr:"",
 +        msg, lib, func, state);
 +  } else {
 +    log(severity, domain, "TLS error%s%s: %s (in %s:%s:%s)",
 +        addr?" with ":"", addr?addr:"",
 +        msg, lib, func, state);
 +  }
 +}
 +
  /** Log all pending tls errors at level <b>severity</b>.  Use
   * <b>doing</b> to describe our current activities.
   */
  static void
  tls_log_errors(tor_tls_t *tls, int severity, int domain, const char *doing)
  {
 -  const char *state = NULL;
 -  int st;
    unsigned long err;
 -  const char *msg, *lib, *func, *addr;
 -  addr = tls ? tls->address : NULL;
 -  st = (tls && tls->ssl) ? tls->ssl->state : -1;
 +
    while ((err = ERR_get_error()) != 0) {
 -    msg = (const char*)ERR_reason_error_string(err);
 -    lib = (const char*)ERR_lib_error_string(err);
 -    func = (const char*)ERR_func_error_string(err);
 -    if (!state)
 -      state = (st>=0)?ssl_state_to_string(st):"---";
 -    if (!msg) msg = "(null)";
 -    if (!lib) lib = "(null)";
 -    if (!func) func = "(null)";
 -    if (doing) {
 -      log(severity, domain, "TLS error while %s%s%s: %s (in %s:%s:%s)",
 -          doing, addr?" with ":"", addr?addr:"",
 -          msg, lib, func, state);
 -    } else {
 -      log(severity, domain, "TLS error%s%s: %s (in %s:%s:%s)",
 -          addr?" with ":"", addr?addr:"",
 -          msg, lib, func, state);
 -    }
 +    tor_tls_log_one_error(tls, err, severity, domain, doing);
    }
  }
  
@@@ -828,7 -807,7 +828,7 @@@ tor_tls_context_new(crypto_pk_env_t *id
    if (!SSL_CTX_check_private_key(result->ctx))
      goto error;
    {
-     crypto_dh_env_t *dh = crypto_dh_new();
+     crypto_dh_env_t *dh = crypto_dh_new(DH_TYPE_TLS);
      SSL_CTX_set_tmp_dh(result->ctx, _crypto_dh_env_get_dh(dh));
      crypto_dh_free(dh);
    }
@@@ -933,8 -912,6 +933,8 @@@ tor_tls_server_info_callback(const SSL 
      /* Check whether we're watching for renegotiates.  If so, this is one! */
      if (tls->negotiated_callback)
        tls->got_renegotiate = 1;
 +    if (tls->server_handshake_count < 127) /*avoid any overflow possibility*/
 +      ++tls->server_handshake_count;
    } else {
      log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!");
    }
@@@ -953,10 -930,6 +953,10 @@@
  
      if (tls) {
        tls->wasV2Handshake = 1;
 +#ifdef USE_BUFFEREVENTS
 +      if (use_unsafe_renegotiation_flag)
 +        tls->ssl->s3->flags |= SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
 +#endif
      } else {
        log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!");
      }
@@@ -1143,7 -1116,7 +1143,7 @@@ tor_tls_set_renegotiate_callback(tor_tl
  /** If this version of openssl requires it, turn on renegotiation on
   * <b>tls</b>.
   */
 -static void
 +void
  tor_tls_unblock_renegotiation(tor_tls_t *tls)
  {
    /* Yes, we know what we are doing here.  No, we do not treat a renegotiation
@@@ -1167,19 -1140,6 +1167,19 @@@ tor_tls_block_renegotiation(tor_tls_t *
    tls->ssl->s3->flags &= ~SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
  }
  
 +void
 +tor_tls_assert_renegotiation_unblocked(tor_tls_t *tls)
 +{
 +  if (use_unsafe_renegotiation_flag) {
 +    tor_assert(0 != (tls->ssl->s3->flags &
 +                     SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION));
 +  }
 +  if (use_unsafe_renegotiation_op) {
 +    long options = SSL_get_options(tls->ssl);
 +    tor_assert(0 != (options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION));
 +  }
 +}
 +
  /** Return whether this tls initiated the connect (client) or
   * received it (server). */
  int
@@@ -1324,86 -1284,56 +1324,86 @@@ tor_tls_handshake(tor_tls_t *tls
    }
    if (r == TOR_TLS_DONE) {
      tls->state = TOR_TLS_ST_OPEN;
 -    if (tls->isServer) {
 -      SSL_set_info_callback(tls->ssl, NULL);
 -      SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, always_accept_verify_cb);
 -      /* There doesn't seem to be a clear OpenSSL API to clear mode flags. */
 -      tls->ssl->mode &= ~SSL_MODE_NO_AUTO_CHAIN;
 +    return tor_tls_finish_handshake(tls);
 +  }
 +  return r;
 +}
 +
 +/** Perform the final part of the intial TLS handshake on <b>tls</b>.  This
 + * should be called for the first handshake only: it determines whether the v1
 + * or the v2 handshake was used, and adjusts things for the renegotiation
 + * handshake as appropriate.
 + *
 + * tor_tls_handshake() calls this on its own; you only need to call this if
 + * bufferevent is doing the handshake for you.
 + */
 +int
 +tor_tls_finish_handshake(tor_tls_t *tls)
 +{
 +  int r = TOR_TLS_DONE;
 +  if (tls->isServer) {
 +    SSL_set_info_callback(tls->ssl, NULL);
 +    SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, always_accept_verify_cb);
 +    /* There doesn't seem to be a clear OpenSSL API to clear mode flags. */
 +    tls->ssl->mode &= ~SSL_MODE_NO_AUTO_CHAIN;
  #ifdef V2_HANDSHAKE_SERVER
 -      if (tor_tls_client_is_using_v2_ciphers(tls->ssl, ADDR(tls))) {
 -        /* This check is redundant, but back when we did it in the callback,
 -         * we might have not been able to look up the tor_tls_t if the code
 -         * was buggy.  Fixing that. */
 -        if (!tls->wasV2Handshake) {
 -          log_warn(LD_BUG, "For some reason, wasV2Handshake didn't"
 -                   " get set. Fixing that.");
 -        }
 -        tls->wasV2Handshake = 1;
 -        log_debug(LD_HANDSHAKE,
 -                  "Completed V2 TLS handshake with client; waiting "
 -                  "for renegotiation.");
 -      } else {
 -        tls->wasV2Handshake = 0;
 +    if (tor_tls_client_is_using_v2_ciphers(tls->ssl, ADDR(tls))) {
 +      /* This check is redundant, but back when we did it in the callback,
 +       * we might have not been able to look up the tor_tls_t if the code
 +       * was buggy.  Fixing that. */
 +      if (!tls->wasV2Handshake) {
 +        log_warn(LD_BUG, "For some reason, wasV2Handshake didn't"
 +                 " get set. Fixing that.");
        }
 -#endif
 +      tls->wasV2Handshake = 1;
 +      log_debug(LD_HANDSHAKE, "Completed V2 TLS handshake with client; waiting"
 +                " for renegotiation.");
      } else {
 +      tls->wasV2Handshake = 0;
 +    }
 +#endif
 +  } else {
  #ifdef V2_HANDSHAKE_CLIENT
 -      /* If we got no ID cert, we're a v2 handshake. */
 -      X509 *cert = SSL_get_peer_certificate(tls->ssl);
 -      STACK_OF(X509) *chain = SSL_get_peer_cert_chain(tls->ssl);
 -      int n_certs = sk_X509_num(chain);
 -      if (n_certs > 1 || (n_certs == 1 && cert != sk_X509_value(chain, 0))) {
 -        log_debug(LD_HANDSHAKE, "Server sent back multiple certificates; it "
 -                  "looks like a v1 handshake on %p", tls);
 -        tls->wasV2Handshake = 0;
 -      } else {
 -        log_debug(LD_HANDSHAKE,
 -                  "Server sent back a single certificate; looks like "
 -                  "a v2 handshake on %p.", tls);
 -        tls->wasV2Handshake = 1;
 -      }
 -      if (cert)
 -        X509_free(cert);
 +    /* If we got no ID cert, we're a v2 handshake. */
 +    X509 *cert = SSL_get_peer_certificate(tls->ssl);
 +    STACK_OF(X509) *chain = SSL_get_peer_cert_chain(tls->ssl);
 +    int n_certs = sk_X509_num(chain);
 +    if (n_certs > 1 || (n_certs == 1 && cert != sk_X509_value(chain, 0))) {
 +      log_debug(LD_HANDSHAKE, "Server sent back multiple certificates; it "
 +                "looks like a v1 handshake on %p", tls);
 +      tls->wasV2Handshake = 0;
 +    } else {
 +      log_debug(LD_HANDSHAKE,
 +                "Server sent back a single certificate; looks like "
 +                "a v2 handshake on %p.", tls);
 +      tls->wasV2Handshake = 1;
 +    }
 +    if (cert)
 +      X509_free(cert);
  #endif
 -      if (SSL_set_cipher_list(tls->ssl, SERVER_CIPHER_LIST) == 0) {
 -        tls_log_errors(NULL, LOG_WARN, LD_HANDSHAKE, "re-setting ciphers");
 -        r = TOR_TLS_ERROR_MISC;
 -      }
 +    if (SSL_set_cipher_list(tls->ssl, SERVER_CIPHER_LIST) == 0) {
 +      tls_log_errors(NULL, LOG_WARN, LD_HANDSHAKE, "re-setting ciphers");
 +      r = TOR_TLS_ERROR_MISC;
      }
    }
    return r;
  }
  
 +#ifdef USE_BUFFEREVENTS
 +/** Put <b>tls</b>, which must be a client connection, into renegotiation
 + * mode. */
 +int
 +tor_tls_start_renegotiating(tor_tls_t *tls)
 +{
 +  int r = SSL_renegotiate(tls->ssl);
 +  if (r <= 0) {
 +    return tor_tls_get_error(tls, r, 0, "renegotiating", LOG_WARN,
 +                             LD_HANDSHAKE);
 +  }
 +  return 0;
 +}
 +#endif
 +
  /** Client only: Renegotiate a TLS session.  When finished, returns
   * TOR_TLS_DONE.  On failure, returns TOR_TLS_ERROR, TOR_TLS_WANTREAD, or
   * TOR_TLS_WANTWRITE.
@@@ -1620,8 -1550,6 +1620,8 @@@ tor_tls_verify(int severity, tor_tls_t 
      log_fn(severity,LD_PROTOCOL,"No distinct identity certificate found");
      goto done;
    }
 +  tls_log_errors(tls, severity, LD_HANDSHAKE, "before verifying certificate");
 +
    if (!(id_pkey = X509_get_pubkey(id_cert)) ||
        X509_verify(cert, id_pkey) <= 0) {
      log_fn(severity,LD_PROTOCOL,"X509_verify on cert and pkey returned <= 0");
@@@ -1771,22 -1699,6 +1771,22 @@@ tor_tls_used_v1_handshake(tor_tls_t *tl
    return 1;
  }
  
 +/** Return the number of server handshakes that we've noticed doing on
 + * <b>tls</b>. */
 +int
 +tor_tls_get_num_server_handshakes(tor_tls_t *tls)
 +{
 +  return tls->server_handshake_count;
 +}
 +
 +/** Return true iff the server TLS connection <b>tls</b> got the renegotiation
 + * request it was waiting for. */
 +int
 +tor_tls_server_got_renegotiate(tor_tls_t *tls)
 +{
 +  return tls->got_renegotiate;
 +}
 +
  /** Examine the amount of memory used and available for buffers in <b>tls</b>.
   * Set *<b>rbuf_capacity</b> to the amount of storage allocated for the read
   * buffer and *<b>rbuf_bytes</b> to the amount actually used.
@@@ -1809,71 -1721,3 +1809,71 @@@ tor_tls_get_buffer_sizes(tor_tls_t *tls
    *wbuf_bytes = tls->ssl->s3->wbuf.left;
  }
  
 +#ifdef USE_BUFFEREVENTS
 +/** Construct and return an TLS-encrypting bufferevent to send data over
 + * <b>socket</b>, which must match the socket of the underlying bufferevent
 + * <b>bufev_in</b>.  The TLS object <b>tls</b> is used for encryption.
 + *
 + * This function will either create a filtering bufferevent that wraps around
 + * <b>bufev_in</b>, or it will free bufev_in and return a new bufferevent that
 + * uses the <b>tls</b> to talk to the network directly.  Do not use
 + * <b>bufev_in</b> after calling this function.
 + *
 + * The connection will start out doing a server handshake if <b>receiving</b>
 + * is strue, and a client handshake otherwise.
 + *
 + * Returns NULL on failure.
 + */
 +struct bufferevent *
 +tor_tls_init_bufferevent(tor_tls_t *tls, struct bufferevent *bufev_in,
 +                         evutil_socket_t socket, int receiving,
 +                         int filter)
 +{
 +  struct bufferevent *out;
 +  const enum bufferevent_ssl_state state = receiving ?
 +    BUFFEREVENT_SSL_ACCEPTING : BUFFEREVENT_SSL_CONNECTING;
 +
 +  if (filter) {
 +    /* Grab an extra reference to the SSL, since BEV_OPT_CLOSE_ON_FREE
 +       means that the SSL will get freed too.
 +
 +       This increment makes our SSL usage not-threadsafe, BTW.  We should
 +       see if we're allowed to use CRYPTO_add from outside openssl. */
 +    tls->ssl->references += 1;
 +    out = bufferevent_openssl_filter_new(tor_libevent_get_base(),
 +                                         bufev_in,
 +                                         tls->ssl,
 +                                         state,
 +                                         BEV_OPT_DEFER_CALLBACKS|
 +                                         BEV_OPT_CLOSE_ON_FREE);
 +  } else {
 +    if (bufev_in) {
 +      evutil_socket_t s = bufferevent_getfd(bufev_in);
 +      tor_assert(s == -1 || s == socket);
 +      tor_assert(evbuffer_get_length(bufferevent_get_input(bufev_in)) == 0);
 +      tor_assert(evbuffer_get_length(bufferevent_get_output(bufev_in)) == 0);
 +      tor_assert(BIO_number_read(SSL_get_rbio(tls->ssl)) == 0);
 +      tor_assert(BIO_number_written(SSL_get_rbio(tls->ssl)) == 0);
 +      bufferevent_free(bufev_in);
 +    }
 +
 +    /* Current versions (as of 2.0.x) of Libevent need to defer
 +     * bufferevent_openssl callbacks, or else our callback functions will
 +     * get called reentrantly, which is bad for us.
 +     */
 +    out = bufferevent_openssl_socket_new(tor_libevent_get_base(),
 +                                         socket,
 +                                         tls->ssl,
 +                                         state,
 +                                         BEV_OPT_DEFER_CALLBACKS);
 +  }
 +  tls->state = TOR_TLS_ST_BUFFEREVENT;
 +
 +  /* Unblock _after_ creating the bufferevent, since accept/connect tend to
 +   * clear flags. */
 +  tor_tls_unblock_renegotiation(tls);
 +
 +  return out;
 +}
 +#endif
 +
diff --combined src/or/rendclient.c
index 255c16b,ba5987c..7b71850
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@@ -16,7 -16,6 +16,7 @@@
  #include "connection_edge.h"
  #include "directory.h"
  #include "main.h"
 +#include "nodelist.h"
  #include "relay.h"
  #include "rendclient.h"
  #include "rendcommon.h"
@@@ -122,7 -121,7 +122,7 @@@ rend_client_send_introduction(origin_ci
      cpath = rendcirc->build_state->pending_final_cpath =
        tor_malloc_zero(sizeof(crypt_path_t));
      cpath->magic = CRYPT_PATH_MAGIC;
-     if (!(cpath->dh_handshake_state = crypto_dh_new())) {
+     if (!(cpath->dh_handshake_state = crypto_dh_new(DH_TYPE_REND))) {
        log_warn(LD_BUG, "Internal error: couldn't allocate DH.");
        goto err;
      }
@@@ -416,7 -415,7 +416,7 @@@ directory_get_from_hs_dir(const char *d
    SMARTLIST_FOREACH(responsible_dirs, routerstatus_t *, dir, {
      if (lookup_last_hid_serv_request(dir, desc_id_base32, 0, 0) +
              REND_HID_SERV_DIR_REQUERY_PERIOD >= now ||
 -        !router_get_by_digest(dir->identity_digest))
 +        !router_get_by_id_digest(dir->identity_digest))
        SMARTLIST_DEL_CURRENT(responsible_dirs, dir);
    });
  
@@@ -743,6 -742,7 +743,6 @@@ rend_client_get_random_intro(const rend
    int i;
    rend_cache_entry_t *entry;
    rend_intro_point_t *intro;
 -  routerinfo_t *router;
  
    if (rend_cache_lookup_entry(rend_query->onion_address, -1, &entry) < 1) {
      log_warn(LD_REND,
@@@ -759,12 -759,11 +759,12 @@@
    intro = smartlist_get(entry->parsed->intro_nodes, i);
    /* Do we need to look up the router or is the extend info complete? */
    if (!intro->extend_info->onion_key) {
 +    const node_t *node;
      if (tor_digest_is_zero(intro->extend_info->identity_digest))
 -      router = router_get_by_hexdigest(intro->extend_info->nickname);
 +      node = node_get_by_hex_id(intro->extend_info->nickname);
      else
 -      router = router_get_by_digest(intro->extend_info->identity_digest);
 -    if (!router) {
 +      node = node_get_by_id(intro->extend_info->identity_digest);
 +    if (!node) {
        log_info(LD_REND, "Unknown router with nickname '%s'; trying another.",
                 intro->extend_info->nickname);
        rend_intro_point_free(intro);
@@@ -772,7 -771,7 +772,7 @@@
        goto again;
      }
      extend_info_free(intro->extend_info);
 -    intro->extend_info = extend_info_from_router(router);
 +    intro->extend_info = extend_info_from_node(node);
    }
    return extend_info_dup(intro->extend_info);
  }
diff --combined src/or/rendservice.c
index c920ecf,4503982..5d65f47
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@@ -14,7 -14,6 +14,7 @@@
  #include "config.h"
  #include "directory.h"
  #include "networkstatus.h"
 +#include "nodelist.h"
  #include "rendclient.h"
  #include "rendcommon.h"
  #include "rendservice.h"
@@@ -1003,7 -1002,7 +1003,7 @@@ rend_service_introduce(origin_circuit_
    } else {
      char *rp_nickname;
      size_t nickname_field_len;
 -    routerinfo_t *router;
 +    const node_t *node;
      int version;
      if (*buf == 1) {
        rp_nickname = buf+1;
@@@ -1030,8 -1029,8 +1030,8 @@@
      len -= nickname_field_len;
      len -= rp_nickname - buf; /* also remove header space used by version, if
                                 * any */
 -    router = router_get_by_nickname(rp_nickname, 0);
 -    if (!router) {
 +    node = node_get_by_nickname(rp_nickname, 0);
 +    if (!node) {
        log_info(LD_REND, "Couldn't find router %s named in introduce2 cell.",
                 escaped_safe_str_client(rp_nickname));
        /* XXXX Add a no-such-router reason? */
@@@ -1039,7 -1038,7 +1039,7 @@@
        goto err;
      }
  
 -    extend_info = extend_info_from_router(router);
 +    extend_info = extend_info_from_node(node);
    }
  
    if (len != REND_COOKIE_LEN+DH_KEY_LEN) {
@@@ -1101,7 -1100,7 +1101,7 @@@
    }
  
    /* Try DH handshake... */
-   dh = crypto_dh_new();
+   dh = crypto_dh_new(DH_TYPE_REND);
    if (!dh || crypto_dh_generate_public(dh)<0) {
      log_warn(LD_BUG,"Internal error: couldn't build DH state "
               "or generate public key.");
@@@ -1583,7 -1582,7 +1583,7 @@@ directory_post_to_hs_dir(rend_service_d
                                  hs_dir->identity_digest))
          /* Don't upload descriptor if we succeeded in doing so last time. */
          continue;
 -      if (!router_get_by_digest(hs_dir->identity_digest)) {
 +      if (!router_get_by_id_digest(hs_dir->identity_digest)) {
          log_info(LD_REND, "Not sending publish request for v2 descriptor to "
                            "hidden service directory '%s'; we don't have its "
                            "router descriptor. Queuing for later upload.",
@@@ -1760,19 -1759,19 +1760,19 @@@ voi
  rend_services_introduce(void)
  {
    int i,j,r;
 -  routerinfo_t *router;
 +  const node_t *node;
    rend_service_t *service;
    rend_intro_point_t *intro;
    int changed, prev_intro_nodes;
 -  smartlist_t *intro_routers;
 +  smartlist_t *intro_nodes;
    time_t now;
    or_options_t *options = get_options();
  
 -  intro_routers = smartlist_create();
 +  intro_nodes = smartlist_create();
    now = time(NULL);
  
    for (i=0; i < smartlist_len(rend_service_list); ++i) {
 -    smartlist_clear(intro_routers);
 +    smartlist_clear(intro_nodes);
      service = smartlist_get(rend_service_list, i);
  
      tor_assert(service);
@@@ -1792,8 -1791,8 +1792,8 @@@
         service. */
      for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
        intro = smartlist_get(service->intro_nodes, j);
 -      router = router_get_by_digest(intro->extend_info->identity_digest);
 -      if (!router || !find_intro_circuit(intro, service->pk_digest)) {
 +      node = node_get_by_id(intro->extend_info->identity_digest);
 +      if (!node || !find_intro_circuit(intro, service->pk_digest)) {
          log_info(LD_REND,"Giving up on %s as intro point for %s.",
                   intro->extend_info->nickname, service->service_id);
          if (service->desc) {
@@@ -1812,8 -1811,8 +1812,8 @@@
          smartlist_del(service->intro_nodes,j--);
          changed = 1;
        }
 -      if (router)
 -        smartlist_add(intro_routers, router);
 +      if (node)
 +        smartlist_add(intro_nodes, (void*)node);
      }
  
      /* We have enough intro points, and the intro points we thought we had were
@@@ -1842,26 -1841,26 +1842,26 @@@
  #define NUM_INTRO_POINTS_INIT (NUM_INTRO_POINTS + 2)
      for (j=prev_intro_nodes; j < (prev_intro_nodes == 0 ?
               NUM_INTRO_POINTS_INIT : NUM_INTRO_POINTS); ++j) {
 -      router_crn_flags_t flags = CRN_NEED_UPTIME;
 +      router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC;
        if (get_options()->_AllowInvalid & ALLOW_INVALID_INTRODUCTION)
          flags |= CRN_ALLOW_INVALID;
 -      router = router_choose_random_node(intro_routers,
 -                                         options->ExcludeNodes, flags);
 -      if (!router) {
 +      node = router_choose_random_node(intro_nodes,
 +                                       options->ExcludeNodes, flags);
 +      if (!node) {
          log_warn(LD_REND,
                   "Could only establish %d introduction points for %s.",
                   smartlist_len(service->intro_nodes), service->service_id);
          break;
        }
        changed = 1;
 -      smartlist_add(intro_routers, router);
 +      smartlist_add(intro_nodes, (void*)node);
        intro = tor_malloc_zero(sizeof(rend_intro_point_t));
 -      intro->extend_info = extend_info_from_router(router);
 +      intro->extend_info = extend_info_from_node(node);
        intro->intro_key = crypto_new_pk_env();
        tor_assert(!crypto_pk_generate_key(intro->intro_key));
        smartlist_add(service->intro_nodes, intro);
        log_info(LD_REND, "Picked router %s as an intro point for %s.",
 -               router->nickname, service->service_id);
 +               node_get_nickname(node), service->service_id);
      }
  
      /* If there's no need to launch new circuits, stop here. */
@@@ -1878,7 -1877,7 +1878,7 @@@
        }
      }
    }
 -  smartlist_free(intro_routers);
 +  smartlist_free(intro_nodes);
  }
  
  /** Regenerate and upload rendezvous service descriptors for all



More information about the tor-commits mailing list