diff options
author | Roger Dingledine <arma@torproject.org> | 2004-04-05 07:41:31 +0000 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2004-04-05 07:41:31 +0000 |
commit | 5b6099e8a2197a04e8c2e0fe8586471711bbd3f1 (patch) | |
tree | 2b2a3c18cd25e25463b942cb0e7e4ef252ccf4ff /src | |
parent | d70063578d331769bbed3d61fd94c484e67e46bc (diff) | |
download | tor-5b6099e8a2197a04e8c2e0fe8586471711bbd3f1.tar tor-5b6099e8a2197a04e8c2e0fe8586471711bbd3f1.tar.gz |
more alice-side infrastructure
handle rendezvous acks,
do rend begin cells right,
send an introduction cell (sort of)
receive a rendezvous2 cell (sort of)
svn:r1475
Diffstat (limited to 'src')
-rw-r--r-- | src/or/connection_edge.c | 73 | ||||
-rw-r--r-- | src/or/or.h | 4 | ||||
-rw-r--r-- | src/or/rendclient.c | 100 | ||||
-rw-r--r-- | src/or/rendcommon.c | 3 | ||||
-rw-r--r-- | src/or/rendmid.c | 6 |
5 files changed, 145 insertions, 41 deletions
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index d726549db..0c293b265 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -9,7 +9,6 @@ extern or_options_t options; /* command-line and config-file options */ 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 @@ circuit_get_open_circ_or_launch(connection_t *conn, 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 @@ int connection_ap_handshake_attach_circuit(connection_t *conn) { 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 @@ int connection_ap_handshake_attach_circuit(connection_t *conn) { 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 @@ int connection_ap_handshake_attach_circuit(connection_t *conn) { 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 @@ again: } /* 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 @@ static void connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t 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 diff --git a/src/or/or.h b/src/or/or.h index 6f7b79eba..d74115636 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -850,6 +850,7 @@ int connection_edge_finished_flushing(connection_t *conn); 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 rep_hist_dump_stats(time_t now, int severity); 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 @@ char *rend_get_random_intro(char *query); 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 ***************************/ diff --git a/src/or/rendclient.c b/src/or/rendclient.c index daca03b5d..d726cb5cb 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -15,6 +15,9 @@ rend_client_introcirc_is_open(circuit_t *circ) 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 @@ rend_client_send_establish_rendezvous(circuit_t *circ) 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 @@ rend_client_send_establish_rendezvous(circuit_t *circ) 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 @@ rend_client_rendcirc_is_open(circuit_t *circ) /* 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 @@ rend_client_rendezvous_acked(circuit_t *circ, const char *request, int request_l 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. */ diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index 0bb2fe295..4fb333af9 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -281,8 +281,7 @@ void rend_process_relay_cell(circuit_t *circ, int command, int length, 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); diff --git a/src/or/rendmid.c b/src/or/rendmid.c index fa24aed7e..fd3ee54b0 100644 --- a/src/or/rendmid.c +++ b/src/or/rendmid.c @@ -111,14 +111,14 @@ rend_mid_introduce(circuit_t *circ, const char *request, int request_len) 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 @@ rend_mid_introduce(circuit_t *circ, const char *request, int request_len) 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; } |