[or-cvs] more alice-side infrastructure

Roger Dingledine arma at seul.org
Mon Apr 5 07:41:33 UTC 2004


Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/home2/arma/work/onion/cvs/src/or

Modified Files:
	connection_edge.c or.h rendclient.c rendcommon.c rendmid.c 
Log Message:
more alice-side infrastructure

handle rendezvous acks,
do rend begin cells right,
send an introduction cell (sort of)
receive a rendezvous2 cell (sort of)


Index: connection_edge.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_edge.c,v
retrieving revision 1.136
retrieving revision 1.137
diff -u -d -r1.136 -r1.137
--- connection_edge.c	5 Apr 2004 00:47:47 -0000	1.136
+++ connection_edge.c	5 Apr 2004 07:41:30 -0000	1.137
@@ -9,7 +9,6 @@
 extern char *conn_state_to_string[][_CONN_TYPE_MAX+1];
 
 static int connection_ap_handshake_process_socks(connection_t *conn);
-static void connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ);
 
 static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
 static void connection_edge_consider_sending_sendme(connection_t *conn);
@@ -804,6 +803,18 @@
   return 0;
 }
 
+void link_apconn_to_circ(connection_t *apconn, circuit_t *circ) {
+  /* add it into the linked list of streams on this circuit */
+  log_fn(LOG_DEBUG,"attaching new conn to circ. n_circ_id %d.", circ->n_circ_id);
+  apconn->next_stream = circ->p_streams;
+  /* assert_connection_ok(conn, time(NULL)); */
+  circ->p_streams = apconn;
+
+  assert(circ->cpath && circ->cpath->prev);
+  assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
+  apconn->cpath_layer = circ->cpath->prev;
+}
+
 /* Try to find a safe live circuit for CONN_TYPE_AP connection conn. If
  * we don't find one: if conn cannot be handled by any known nodes,
  * warn and return -1 (conn needs to die);
@@ -835,16 +846,7 @@
     if(!circ->timestamp_dirty)
       circ->timestamp_dirty = time(NULL);
 
-    /* add it into the linked list of streams on this circuit */
-    log_fn(LOG_DEBUG,"attaching new conn to circ. n_circ_id %d.", circ->n_circ_id);
-    conn->next_stream = circ->p_streams;
-    /* assert_connection_ok(conn, time(NULL)); */
-    circ->p_streams = conn;
-
-    assert(circ->cpath && circ->cpath->prev);
-    assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
-    conn->cpath_layer = circ->cpath->prev;
-
+    link_apconn_to_circ(conn, circ);
     connection_ap_handshake_send_begin(conn, circ);
 
     return 1;
@@ -859,16 +861,20 @@
 
     if(retval > 0) {
       /* one is already established, attach */
-
-      log_fn(LOG_WARN,"XXX rend joined circ already here. should reuse.");
-      return -1;
+      log_fn(LOG_INFO,"rend joined circ already here. reusing.");
+      link_apconn_to_circ(conn, rendcirc);
+      if(connection_ap_handshake_send_begin(conn, rendcirc) < 0)
+        return 0; /* already marked, let them fade away */
+      return 1;
     }
 
     if(rendcirc &&
        rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY &&
        rendcirc->build_state->pending_final_cpath) {
-      log_fn(LOG_WARN,"XXX pending-join circ already here. should reuse.");
-      return -1;
+      log_fn(LOG_INFO,"pending-join circ already here. reusing.");
+      link_apconn_to_circ(conn, rendcirc);
+      /* don't send the begin, because we're still waiting for contact from bob */
+      return 1;
     }
 
     /* it's on its way. find an intro circ. */
@@ -880,8 +886,13 @@
       if(rendcirc &&
          rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY) {
         /* then we know !pending_final_cpath, from above */
-        log_fn(LOG_WARN,"XXX intro and rend are both ready. do the magic.");
-        return -1;
+        log_fn(LOG_INFO,"intro and rend circs are both ready. introducing.");
+        if(rend_client_send_introduction(introcirc, rendcirc) < 0) {
+          return -1;
+        }
+        /* now attach conn to rendcirc */
+        link_apconn_to_circ(conn, rendcirc);
+        return 1;
       }
     }
     log_fn(LOG_INFO,"Intro and rend circs are not both ready. Stalling conn.");
@@ -913,7 +924,7 @@
 }
 
 /* deliver the destaddr:destport in a relay cell */
-static void connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ)
+int connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ)
 {
   char payload[CELL_PAYLOAD_SIZE];
   int payload_len;
@@ -928,29 +939,35 @@
   if (ap_conn->stream_id==0) {
     /* Don't send end: there is no 'other side' yet */
     connection_mark_for_close(ap_conn, 0);
-    return;
+    circuit_mark_for_close(circ);
+    return -1;
   }
 
-  in.s_addr = htonl(client_dns_lookup_entry(ap_conn->socks_request->address));
-  string_addr = in.s_addr ? inet_ntoa(in) : NULL;
+  if(circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) {
+    in.s_addr = htonl(client_dns_lookup_entry(ap_conn->socks_request->address));
+    string_addr = in.s_addr ? inet_ntoa(in) : NULL;
 
-  snprintf(payload,RELAY_PAYLOAD_SIZE,
-           "%s:%d",
-           string_addr ? string_addr : ap_conn->socks_request->address,
-           ap_conn->socks_request->port);
+    snprintf(payload,RELAY_PAYLOAD_SIZE,
+             "%s:%d",
+             string_addr ? string_addr : ap_conn->socks_request->address,
+             ap_conn->socks_request->port);
+  } else {
+    snprintf(payload,RELAY_PAYLOAD_SIZE,
+             ":%d", ap_conn->socks_request->port);
+  }
   payload_len = strlen(payload)+1;
 
   log_fn(LOG_DEBUG,"Sending relay cell to begin stream %d.",ap_conn->stream_id);
 
   if(connection_edge_send_command(ap_conn, circ, RELAY_COMMAND_BEGIN,
                                payload, payload_len, ap_conn->cpath_layer) < 0)
-    return; /* circuit is closed, don't continue */
+    return -1; /* circuit is closed, don't continue */
 
   ap_conn->package_window = STREAMWINDOW_START;
   ap_conn->deliver_window = STREAMWINDOW_START;
   ap_conn->state = AP_CONN_STATE_CONNECT_WAIT;
   log_fn(LOG_INFO,"Address/port sent, ap socket %d, n_circ_id %d",ap_conn->s,circ->n_circ_id);
-  return;
+  return 0;
 }
 
 /* make an ap connection_t, do a socketpair and attach one side

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.296
retrieving revision 1.297
diff -u -d -r1.296 -r1.297
--- or.h	5 Apr 2004 00:47:47 -0000	1.296
+++ or.h	5 Apr 2004 07:41:31 -0000	1.297
@@ -850,6 +850,7 @@
 int connection_edge_package_raw_inbuf(connection_t *conn);
 
 int connection_ap_handshake_attach_circuit(connection_t *conn);
+int connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ);
 
 int connection_ap_make_bridge(char *address, uint16_t port);
 
@@ -1041,7 +1042,7 @@
 void rend_client_introcirc_is_open(circuit_t *circ);
 void rend_client_rendcirc_is_open(circuit_t *circ);
 int rend_client_rendezvous_acked(circuit_t *circ, const char *request, int request_len);
-void rend_client_rendezvous(connection_t *apconn, circuit_t *circ);
+int rend_client_receive_rendezvous(circuit_t *circ, const char *request, int request_len);
 void rend_client_desc_fetched(char *query, int success);
 
 int rend_cmp_service_ids(char *one, char *two);
@@ -1049,6 +1050,7 @@
 int rend_parse_rendezvous_address(char *address);
 
 int rend_client_send_establish_rendezvous(circuit_t *circ);
+int rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc);
 
 /********************************* rendcommon.c ***************************/
 

Index: rendclient.c
===================================================================
RCS file: /home/or/cvsroot/src/or/rendclient.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- rendclient.c	5 Apr 2004 00:47:48 -0000	1.8
+++ rendclient.c	5 Apr 2004 07:41:31 -0000	1.9
@@ -15,6 +15,9 @@
   connection_ap_attach_pending();
 }
 
+/* send the establish-rendezvous cell. if it fails, mark
+ * the circ for close and return -1. else return 0.
+ */
 int
 rend_client_send_establish_rendezvous(circuit_t *circ)
 {
@@ -23,12 +26,14 @@
 
   if (crypto_rand(REND_COOKIE_LEN, circ->rend_cookie)<0) {
     log_fn(LOG_WARN, "Couldn't get random cookie");
+    circuit_mark_for_close(circ);
     return -1;
   }
   if (connection_edge_send_command(NULL,circ,
                                    RELAY_COMMAND_ESTABLISH_RENDEZVOUS,
                                    circ->rend_cookie, REND_COOKIE_LEN,
                                    circ->cpath->prev)<0) {
+    /* circ is already marked for close */
     log_fn(LOG_WARN, "Couldn't send ESTABLISH_RENDEZVOUS cell");
     return -1;
   }
@@ -36,6 +41,72 @@
   return 0;
 }
 
+#define LEN_REND_INTRODUCE1 204
+
+int
+rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc) {
+  const char *descp;
+  int desc_len;
+  char payload[LEN_REND_INTRODUCE1];
+  char tmp[LEN_REND_INTRODUCE1-20-16];
+  rend_service_descriptor_t *parsed=NULL;
+
+  assert(introcirc->purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
+  assert(rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY);
+  assert(!rend_cmp_service_ids(introcirc->rend_query, rendcirc->rend_query));
+
+  if(rend_cache_lookup(introcirc->rend_query, &descp, &desc_len) < 1) {
+    log_fn(LOG_WARN,"query '%s' didn't have valid rend desc in cache. Failing.",
+           introcirc->rend_query);
+    goto err;
+  }
+
+  parsed = rend_parse_service_descriptor(descp,desc_len);
+  if (!parsed) {
+    log_fn(LOG_WARN,"Couldn't parse service descriptor");
+    goto err;
+  }
+
+  /* first 20 bytes of payload are the hash of bob's pk */
+  if (crypto_pk_get_digest(parsed->pk, payload)<0) {
+    log_fn(LOG_WARN, "Couldn't hash public key.");
+    goto err;
+  }
+
+  /* write the remaining items into tmp */
+  strncpy(tmp, rendcirc->build_state->chosen_exit, 20); /* nul pads */
+  memcpy(tmp+20, rendcirc->rend_cookie, 20);
+  memset(tmp+40, 0, 128); /* XXX g^x is all zero's for now */
+
+  /* XXX copy the appropriate stuff into rendcirc's pending_final_cpath */
+
+  if(crypto_pk_public_hybrid_encrypt(parsed->pk, tmp,
+                                     20+20+128, payload+20,
+                                     PK_PKCS1_OAEP_PADDING) < 0) {
+    log_fn(LOG_WARN,"hybrid pk encrypt failed.");
+    goto err;
+  }
+
+  rend_service_descriptor_free(parsed);
+
+  if (connection_edge_send_command(NULL, introcirc,
+                                   RELAY_COMMAND_INTRODUCE1,
+                                   payload, LEN_REND_INTRODUCE1,
+                                   introcirc->cpath->prev)<0) {
+    /* introcirc is already marked for close. leave rendcirc alone. */
+    log_fn(LOG_WARN, "Couldn't send INTRODUCE1 cell");
+    return -1;
+  }
+
+  return 0;
+err:
+  if(parsed)
+    rend_service_descriptor_free(parsed);
+  circuit_mark_for_close(introcirc);
+  circuit_mark_for_close(rendcirc);
+  return -1;
+}
+
 /* send the rendezvous cell */
 void
 rend_client_rendcirc_is_open(circuit_t *circ)
@@ -47,7 +118,6 @@
 
   /* generate a rendezvous cookie, store it in circ */
   if (rend_client_send_establish_rendezvous(circ) < 0) {
-    circuit_mark_for_close(circ);
     return;
   }
 
@@ -63,22 +133,38 @@
     circuit_mark_for_close(circ);
     return -1;
   }
+  log_fn(LOG_INFO,"Got rendezvous ack. This circuit is now ready for rendezvous.");
   circ->purpose = CIRCUIT_PURPOSE_C_REND_READY;
   return 0;
 }
 
 /* bob sent us a rendezvous cell, join the circs. */
-void
-rend_client_rendezvous(connection_t *apconn, circuit_t *circ)
+int
+rend_client_receive_rendezvous(circuit_t *circ, const char *request, int request_len)
 {
+  connection_t *apconn;
 
+  if(circ->purpose != CIRCUIT_PURPOSE_C_REND_READY ||
+     !circ->build_state->pending_final_cpath) {
+    log_fn(LOG_WARN,"Got rendezvous2 cell from Bob, but not expecting it. Closing.");
+    circuit_mark_for_close(circ);
+    return -1;
+  }
 
-}
-
-
+  /* XXX
+   * take 'request' and 'circ->build_state->pending_final_cpath'
+   * and do the right thing to circ
+   */
 
+  circ->purpose = CIRCUIT_PURPOSE_C_REND_JOINED;
+  for(apconn = circ->p_streams; apconn; apconn = apconn->next_stream) {
+    if(connection_ap_handshake_send_begin(apconn, circ) < 0)
+      return -1;
+  }
+  return 0;
+}
 
-/* Find all the apconns in purpose AP_PURPOSE_RENDDESC_WAIT that
+/* Find all the apconns in state AP_CONN_STATE_RENDDESC_WAIT that
  * are waiting on query. If success==1, move them to the next state.
  * If success==0, fail them.
  */

Index: rendcommon.c
===================================================================
RCS file: /home/or/cvsroot/src/or/rendcommon.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- rendcommon.c	5 Apr 2004 00:47:48 -0000	1.17
+++ rendcommon.c	5 Apr 2004 07:41:31 -0000	1.18
@@ -281,8 +281,7 @@
       r = rend_mid_rendezvous(circ,payload,length);
       break;
     case RELAY_COMMAND_RENDEZVOUS2:
-      /* r = rend_client_rendezvous(circ,payload,length); */
-      log_fn(LOG_NOTICE, "Ignoring a rendezvous2 cell");
+      r = rend_client_receive_rendezvous(circ,payload,length);
       break;
     case RELAY_COMMAND_INTRO_ESTABLISHED:
       r = rend_service_intro_established(circ,payload,length);

Index: rendmid.c
===================================================================
RCS file: /home/or/cvsroot/src/or/rendmid.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- rendmid.c	3 Apr 2004 04:55:22 -0000	1.8
+++ rendmid.c	5 Apr 2004 07:41:31 -0000	1.9
@@ -111,14 +111,14 @@
   char hexid[9];
 
   if (circ->purpose != CIRCUIT_PURPOSE_OR || circ->n_conn) {
-    log_fn(LOG_WARN, "Rejecting INTRODUCE2 on non-OR or non-edge circuit %d",
+    log_fn(LOG_WARN, "Rejecting INTRODUCE1 on non-OR or non-edge circuit %d",
            circ->p_circ_id);
     goto err;
   }
 
   if (request_len < 276) {
     log_fn(LOG_WARN,
-           "Impossibly short INTRODUCE2 cell on circuit %d; dropping.",
+           "Impossibly short INTRODUCE1 cell on circuit %d; dropping.",
            circ->p_circ_id);
     goto err;
   }
@@ -130,7 +130,7 @@
                              NULL, request, CIRCUIT_PURPOSE_INTRO_POINT);
   if (!intro_circ) {
     log_fn(LOG_WARN,
-           "No intro circ found for INTRODUCE2 cell (%s) from circuit %d; dropping",
+           "No intro circ found for INTRODUCE1 cell (%s) from circuit %d; dropping",
            hexid, circ->p_circ_id);
     goto err;
   }



More information about the tor-commits mailing list