[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r12495: When we complete an OR handshake, set up all the internal fi (in tor/trunk: . doc src/common src/or)



Author: nickm
Date: 2007-11-14 15:01:12 -0500 (Wed, 14 Nov 2007)
New Revision: 12495

Modified:
   tor/trunk/
   tor/trunk/doc/TODO
   tor/trunk/src/common/tortls.c
   tor/trunk/src/common/tortls.h
   tor/trunk/src/or/command.c
   tor/trunk/src/or/connection_or.c
   tor/trunk/src/or/or.h
Log:
 r16669@catbus:  nickm | 2007-11-14 14:50:03 -0500
 When we complete an OR handshake, set up all the internal fields and mark the connection as open.



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/trunk [r16669] on 8246c3cf-6607-4228-993b-4d95d33730f1

Modified: tor/trunk/doc/TODO
===================================================================
--- tor/trunk/doc/TODO	2007-11-14 18:52:37 UTC (rev 12494)
+++ tor/trunk/doc/TODO	2007-11-14 20:01:12 UTC (rev 12495)
@@ -50,11 +50,10 @@
         o Generate CERT cells
         o Keep copies of X509 certs around, not necessarily associated with
           connection.
-      . LINK_AUTH cells
+      o LINK_AUTH cells
         o Code to generate
           o Remember certificate digests from TLS
         o Code to parse and check
-        - Unit tests
       - Revised handshake: TLS
         - Server checks for new cipher types, and if it finds them, sends
           only one cert and does not ask for client certs.
@@ -65,9 +64,9 @@
         o If in 'handshaking' state (since v2+ conn is in use), accept
           VERSIONS and NETINFO and CERT and LINK_AUTH.
         o After we send NETINFO, send CERT and LINK_AUTH if needed.
-        - Once we get a good LINK_AUTH, the connection is OPEN.
+        o Once we get a good LINK_AUTH, the connection is OPEN.
         - Ban most cell types on a non-OPEN connection.
-        - Close connections on handshake failure.
+        o Close connections on handshake failure.
       o Make code work right wrt TLS context rotation.
       - NETINFO fallout
         - Don't extend a circuit over a noncanonical connection with

Modified: tor/trunk/src/common/tortls.c
===================================================================
--- tor/trunk/src/common/tortls.c	2007-11-14 18:52:37 UTC (rev 12494)
+++ tor/trunk/src/common/tortls.c	2007-11-14 20:01:12 UTC (rev 12495)
@@ -933,6 +933,7 @@
                         const char *id_cert_str, size_t id_cert_len,
                         crypto_pk_env_t **cert_key_out,
                         char *conn_cert_digest_out,
+                        crypto_pk_env_t **id_key_out,
                         char *id_digest_out)
 {
   X509 *cert = NULL, *id_cert = NULL;
@@ -942,6 +943,7 @@
 
   tor_assert(cert_key_out);
   tor_assert(conn_cert_digest_out);
+  tor_assert(id_key_out);
   tor_assert(id_digest_out);
 
   *cert_key_out = NULL;
@@ -996,13 +998,9 @@
     goto done;
   }
 
-  {
-    crypto_pk_env_t *i = _crypto_new_pk_env_evp_pkey(id_pkey);
-    if (!i)
-      goto done;
-    crypto_pk_get_digest(i, id_digest_out);
-    crypto_free_pk_env(i);
-  }
+  if (!(*id_key_out = _crypto_new_pk_env_evp_pkey(id_pkey)))
+    goto done;
+  crypto_pk_get_digest(*id_key_out, id_digest_out);
   if (!(cert_pkey = X509_get_pubkey(cert)))
     goto done;
   if (!(*cert_key_out = _crypto_new_pk_env_evp_pkey(cert_pkey)))

Modified: tor/trunk/src/common/tortls.h
===================================================================
--- tor/trunk/src/common/tortls.h	2007-11-14 18:52:37 UTC (rev 12494)
+++ tor/trunk/src/common/tortls.h	2007-11-14 20:01:12 UTC (rev 12495)
@@ -67,6 +67,7 @@
                             const char *id_cert_str, size_t id_cert_len,
                             crypto_pk_env_t **cert_key_out,
                             char *conn_cert_digest_out,
+                            crypto_pk_env_t **id_key_out,
                             char *id_digest_out);
 int tor_tls_check_lifetime(tor_tls_t *tls, int tolerance);
 int tor_tls_read(tor_tls_t *tls, char *cp, size_t len);

Modified: tor/trunk/src/or/command.c
===================================================================
--- tor/trunk/src/or/command.c	2007-11-14 18:52:37 UTC (rev 12494)
+++ tor/trunk/src/or/command.c	2007-11-14 20:01:12 UTC (rev 12495)
@@ -475,18 +475,20 @@
   }
   if (!highest_supported_version) {
     log_fn(LOG_PROTOCOL_WARN, LD_OR,
-           "Couldn't find a version in common; defaulting to v1.");
-    /*XXXX020 just break the connection! */
-    conn->link_proto = 1;
+           "Couldn't find a version in common between my version list and the "
+           "list in the VERSIONS cell; closing connection.");
+    connection_mark_for_close(TO_CONN(conn));
     return;
   }
   conn->link_proto = highest_supported_version;
   conn->handshake_state->received_versions = 1;
 
   if (highest_supported_version >= 2) {
-    /*XXXX020 check return values. */
-    connection_or_send_netinfo(conn);
-    connection_or_send_cert(conn);
+    if (connection_or_send_netinfo(conn) < 0 ||
+        connection_or_send_cert(conn) < 0) {
+      connection_mark_for_close(TO_CONN(conn));
+      return;
+    }
     if (conn->handshake_state->started_here)
       connection_or_send_link_auth(conn);
   } else {
@@ -536,8 +538,8 @@
   cp = cell->payload + 6 + my_addr_len;
   if (cp >= end) {
     log_fn(LOG_PROTOCOL_WARN, LD_OR,
-           "Address too long in netinfo cell; dropping.");
-    /*XXXX020 reject and break OR conn! */
+           "Addresses too long in netinfo cell; closing connection.");
+    connection_mark_for_close(TO_CONN(conn));
     return;
   } else if (my_addr_type == RESOLVED_TYPE_IPV4 && my_addr_len == 4) {
     conn->handshake_state->my_apparent_addr = ntohl(get_uint32(my_addr_ptr));
@@ -549,8 +551,12 @@
      * "canonical." */
     uint8_t other_addr_type = (uint8_t) *cp++;
     uint8_t other_addr_len = (uint8_t) *cp++;
-    if (cp + other_addr_len >= end)
-      break; /*XXXX020 protocol warn. */
+    if (cp + other_addr_len >= end) {
+      log_fn(LOG_PROTOCOL_WARN, LD_OR,
+             "Address too long in netinfo cell; closing connection.");
+      connection_mark_for_close(TO_CONN(conn));
+      return;
+    }
     if (other_addr_type == RESOLVED_TYPE_IPV4 && other_addr_len == 4) {
       uint32_t addr = ntohl(get_uint32(cp));
       if (addr == conn->real_addr) {
@@ -568,12 +574,12 @@
 /*XXXX020 move to connection_or.c */
 /** DOCDOC Called when we're done authenticating; act on stuff we
  * learned in netinfo. */
-void
+int
 connection_or_act_on_netinfo(or_connection_t *conn)
 {
   long delta;
   if (!conn->handshake_state)
-    return;
+    return -1;
 
   tor_assert(conn->handshake_state->authenticated != 0);
 
@@ -601,6 +607,8 @@
   if (conn->handshake_state->apparently_canonical) {
     conn->is_canonical = 1;
   }
+
+  return 0;
 }
 
 /*DOCDOC*/
@@ -611,16 +619,25 @@
   uint16_t conn_cert_len = 0, id_cert_len = 0;
   const char *conn_cert = NULL, *id_cert = NULL;
   const char *cp, *end;
-  int authenticated = 0;
+  int done = 0;
 
-  /*XXXX020 log messages*/
-  if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING)
-    goto err;
+  if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING) {
+    log_fn(LOG_PROTOCOL_WARN, LD_OR, "Got CERT cell when not handshaking. "
+           "Ignoring.");
+    return;
+  }
   tor_assert(conn->handshake_state);
   if (!conn->handshake_state->received_versions ||
-      !conn->handshake_state->received_netinfo ||
-      conn->handshake_state->received_certs)
+      !conn->handshake_state->received_netinfo) {
+    log_fn(LOG_PROTOCOL_WARN, LD_OR, "Got CERT cell before VERSIONS and "
+           "NETINFO. Closing the connection.");
     goto err;
+  }
+  if (conn->handshake_state->received_certs) {
+    log_fn(LOG_PROTOCOL_WARN, LD_OR, "Got duplicate CERT cell. "
+           "Closing the connection.");
+    goto err;
+  }
 
   cp = cell->payload;
   end = cell->payload + cell->payload_len;
@@ -651,6 +668,7 @@
   /* Now we have 0, 1, or 2 certs. */
   if (n_certs == 0) {
     /* The other side is unauthenticated. */
+    done = 1;
   } else {
     int r;
     r = tor_tls_verify_certs_v2(LOG_PROTOCOL_WARN, conn->tls,
@@ -660,23 +678,27 @@
                                 (conn->handshake_state->started_here ?
                                  conn->handshake_state->server_cert_digest :
                                  conn->handshake_state->client_cert_digest),
+                                &conn->handshake_state->identity_key,
                                 conn->handshake_state->cert_id_digest);
     if (r < 0)
       goto err;
-    if (r == 1)
-      authenticated = 1;
+    if (r == 1) {
+      done = 1;
+      conn->handshake_state->authenticated = 1;
+    }
   }
 
   conn->handshake_state->received_certs = 1;
-  if (authenticated) {
-    /* XXXX020 make the connection open. */
+  if (done) {
+    if (connection_or_finish_or_handshake(conn) < 0)
+      goto err;
   }
   if (! conn->handshake_state->signing_key)
     goto err;
 
   return;
  err:
-  /*XXXX020 close the connection */;
+  connection_mark_for_close(TO_CONN(conn));
 }
 
 #define LINK_AUTH_STRING "Tor initiator certificate verification"
@@ -746,11 +768,12 @@
     goto err;
   }
 
-  /* Okay, we're authenticated. */
   s->authenticated = 1;
 
-  /* XXXX020 act on being authenticated: Open the connection. */
+  if (connection_or_finish_or_handshake(conn)<0)
+    goto err;
 
+  tor_free(checked);
   return;
  err:
   tor_free(checked);

Modified: tor/trunk/src/or/connection_or.c
===================================================================
--- tor/trunk/src/or/connection_or.c	2007-11-14 18:52:37 UTC (rev 12494)
+++ tor/trunk/src/or/connection_or.c	2007-11-14 20:01:12 UTC (rev 12495)
@@ -614,6 +614,8 @@
   tor_assert(conn->_base.type == CONN_TYPE_OR);
   if (!conn->tls)
     return 1; /* it's still in proxy states or something */
+  if (conn->handshake_state)
+    return conn->handshake_state->started_here;
   return !tor_tls_is_server(conn->tls);
 }
 
@@ -651,8 +653,15 @@
     started_here ? conn->_base.address : safe_str(conn->_base.address);
   const char *conn_type = started_here ? "outgoing" : "incoming";
   int has_cert = 0, has_identity = 0;
+  int v1 = (conn->link_proto == 1);
 
   check_no_tls_errors();
+  if (v1) {
+    has_cert = tor_tls_peer_has_cert(conn->tls);
+  } else {
+    tor_assert(conn->handshake_state);
+    has_cert = !tor_digest_is_zero(conn->handshake_state->cert_id_digest);
+  }
   has_cert = tor_tls_peer_has_cert(conn->tls);
   if (started_here && !has_cert) {
     log_info(LD_PROTOCOL,"Tried connecting to router at %s:%d, but it didn't "
@@ -665,28 +674,34 @@
   }
   check_no_tls_errors();
 
-  if (has_cert) {
-    int v = tor_tls_verify_v1(started_here?severity:LOG_INFO,
-                              conn->tls, &identity_rcvd);
-    if (started_here && v<0) {
-      log_fn(severity,LD_OR,"Tried connecting to router at %s:%d: It"
-             " has a cert but it's invalid. Closing.",
-             safe_address, conn->_base.port);
-      return -1;
-    } else if (v<0) {
-      log_info(LD_PROTOCOL,"Incoming connection gave us an invalid cert "
-               "chain; ignoring.");
-    } else {
-      log_debug(LD_OR,"The certificate seems to be valid on %s connection "
-                "with %s:%d", conn_type, safe_address, conn->_base.port);
+  if (v1) {
+    if (has_cert) {
+      int v = tor_tls_verify_v1(started_here?severity:LOG_INFO,
+                                conn->tls, &identity_rcvd);
+      if (started_here && v<0) {
+        log_fn(severity,LD_OR,"Tried connecting to router at %s:%d: It"
+               " has a cert but it's invalid. Closing.",
+               safe_address, conn->_base.port);
+        return -1;
+      } else if (v<0) {
+        log_info(LD_PROTOCOL,"Incoming connection gave us an invalid cert "
+                 "chain; ignoring.");
+      } else {
+        log_debug(LD_OR,"The certificate seems to be valid on %s connection "
+                  "with %s:%d", conn_type, safe_address, conn->_base.port);
+      }
+      check_no_tls_errors();
     }
-    check_no_tls_errors();
+  } else {
+    if (conn->handshake_state->authenticated &&
+        conn->handshake_state->identity_key) {
+      identity_rcvd = crypto_pk_dup_key(conn->handshake_state->identity_key);
+    }
   }
 
   if (identity_rcvd) {
     has_identity=1;
     crypto_pk_get_digest(identity_rcvd, digest_rcvd_out);
-
     if (crypto_pk_cmp_keys(get_identity_key(), identity_rcvd)<0) {
       conn->circ_id_type = CIRC_ID_TYPE_LOWER;
     } else {
@@ -744,6 +759,29 @@
   return 0;
 }
 
+/** DOCDOC */
+int
+connection_or_finish_or_handshake(or_connection_t *conn)
+{
+  char id_digest[DIGEST_LEN];
+  tor_assert(conn);
+  tor_assert(conn->handshake_state);
+  tor_assert(conn->link_proto >= 2);
+  tor_assert(conn->handshake_state->received_versions != 0);
+  tor_assert(conn->handshake_state->received_netinfo != 0);
+  tor_assert(conn->handshake_state->received_certs != 0);
+
+  if (connection_or_check_valid_tls_handshake(conn,
+                                  conn->handshake_state->started_here,
+                                              id_digest) < 0)
+    return -1;
+  connection_or_init_conn_from_address(conn, conn->_base.addr,
+                                       conn->_base.port, id_digest, 0);
+  if (connection_or_act_on_netinfo(conn)<0)
+    return -1;
+  return connection_or_set_state_open(conn);
+}
+
 /** The tls handshake is finished.
  *
  * Make sure we are happy with the person we just handshaked with.
@@ -815,6 +853,8 @@
   tor_assert(state);
   if (state->signing_key)
     crypto_free_pk_env(state->signing_key);
+  if (state->identity_key)
+    crypto_free_pk_env(state->identity_key);
   memset(state, 0xBE, sizeof(or_handshake_state_t));
   tor_free(state);
 }
@@ -836,6 +876,10 @@
     }
     router_set_status(conn->identity_digest, 1);
   }
+  if (conn->handshake_state) {
+    or_handshake_state_free(conn->handshake_state);
+    conn->handshake_state = NULL;
+  }
   connection_watch_events(TO_CONN(conn), EV_READ);
   circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */
 
@@ -1120,8 +1164,6 @@
 
   connection_or_write_cell_to_buf(&cell, conn);
 
-  /* XXXX020 at this point, as a client, we can consider ourself
-   * authenticated. */
   return 0;
 }
 

Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h	2007-11-14 18:52:37 UTC (rev 12494)
+++ tor/trunk/src/or/or.h	2007-11-14 20:01:12 UTC (rev 12495)
@@ -894,6 +894,7 @@
   /* from certs */
   char cert_id_digest[DIGEST_LEN];
   crypto_pk_env_t *signing_key;
+  crypto_pk_env_t *identity_key;
 } or_handshake_state_t;
 
 /** Subtype of connection_t for an "OR connection" -- that is, one that speaks
@@ -2561,7 +2562,7 @@
 
 void command_process_cell(cell_t *cell, or_connection_t *conn);
 void command_process_var_cell(var_cell_t *cell, or_connection_t *conn);
-void connection_or_act_on_netinfo(or_connection_t *conn);
+int connection_or_act_on_netinfo(or_connection_t *conn);
 
 extern uint64_t stats_n_padding_cells_processed;
 extern uint64_t stats_n_create_cells_processed;
@@ -2781,6 +2782,7 @@
 int connection_or_flushed_some(or_connection_t *conn);
 int connection_or_finished_flushing(or_connection_t *conn);
 int connection_or_finished_connecting(or_connection_t *conn);
+int connection_or_finish_or_handshake(or_connection_t *conn);
 
 or_connection_t *connection_or_connect(uint32_t addr, uint16_t port,
                                     const char *id_digest);