diff --git a/src/or/circuit.c b/src/or/circuit.c index f47f486a71..c39f8b3171 100644 --- a/src/or/circuit.c +++ b/src/or/circuit.c @@ -1534,8 +1534,8 @@ void assert_cpath_layer_ok(const crypt_path_t *cp) { assert(cp->f_crypto); assert(cp->b_crypto); - assert(cp->addr); - assert(cp->port); +// assert(cp->addr); /* these are zero for rendezvous extra-hops */ +// assert(cp->port); switch(cp->state) { case CPATH_STATE_CLOSED: diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 4dd2c3ea97..d98cde62d2 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -11,6 +11,7 @@ extern char *conn_state_to_string[][_CONN_TYPE_MAX+1]; static int connection_ap_handshake_process_socks(connection_t *conn); static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ); +static int connection_exit_set_rendezvous_addr_port(connection_t *conn); static void connection_edge_consider_sending_sendme(connection_t *conn); static uint32_t client_dns_lookup_entry(const char *address); @@ -144,8 +145,9 @@ int connection_edge_end(connection_t *conn, char reason, crypt_path_t *cpath_lay payload[0] = reason; if(reason == END_STREAM_REASON_EXITPOLICY) { + /* this is safe even for rend circs, because they never fail + * because of exitpolicy */ set_uint32(payload+1, htonl(conn->addr)); -// *(uint32_t *)(payload+1) = htonl(conn->addr); payload_len += 4; } @@ -281,7 +283,8 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, log_fn(LOG_INFO,"Got a relay-level padding cell. Dropping."); return 0; case RELAY_COMMAND_BEGIN: - if(edge_type == EDGE_AP) { + if (edge_type == EDGE_AP && + circ->purpose != CIRCUIT_PURPOSE_S_REND_JOINED) { log_fn(LOG_WARN,"relay begin request unsupported at AP. Dropping."); return 0; } @@ -479,10 +482,16 @@ int connection_edge_finished_flushing(connection_t *conn) { if(connection_wants_to_flush(conn)) /* in case there are any queued relay cells */ connection_start_writing(conn); /* deliver a 'connected' relay cell back through the circuit. */ - *(uint32_t*)connected_payload = htonl(conn->addr); - if(connection_edge_send_command(conn, circuit_get_by_conn(conn), - RELAY_COMMAND_CONNECTED, connected_payload, 4, NULL) < 0) - return 0; /* circuit is closed, don't continue */ + if(*conn->rend_query) { /* rendezvous stream */ + if(connection_edge_send_command(conn, circuit_get_by_conn(conn), + RELAY_COMMAND_CONNECTED, NULL, 0, conn->cpath_layer) < 0) + return 0; /* circuit is closed, don't continue */ + } else { + *(uint32_t*)connected_payload = htonl(conn->addr); + if(connection_edge_send_command(conn, circuit_get_by_conn(conn), + RELAY_COMMAND_CONNECTED, connected_payload, 4, conn->cpath_layer) < 0) + return 0; /* circuit is closed, don't continue */ + } assert(conn->package_window > 0); return connection_edge_process_inbuf(conn); /* in case the server has written anything */ case AP_CONN_STATE_OPEN: @@ -1108,9 +1117,7 @@ static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) { n_stream = connection_new(CONN_TYPE_EXIT); n_stream->stream_id = rh.stream_id; - n_stream->address = tor_strdup(cell->payload + RELAY_HEADER_SIZE); n_stream->port = atoi(colon+1); - n_stream->state = EXIT_CONN_STATE_RESOLVING; /* leave n_stream->s at -1, because it's not yet valid */ n_stream->package_window = STREAMWINDOW_START; n_stream->deliver_window = STREAMWINDOW_START; @@ -1124,6 +1131,22 @@ static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) { n_stream->next_stream = circ->n_streams; circ->n_streams = n_stream; + if(circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED) { + n_stream->address = tor_strdup("(rendezvous)"); + strcpy(n_stream->rend_query, "yes"); /* XXX kludge */ + if(connection_exit_set_rendezvous_addr_port(n_stream) < 0) { + log_fn(LOG_WARN,"Didn't find rendezvous service (port %d)",n_stream->port); + connection_mark_for_close(n_stream,0 /* XXX */); + return 0; + } + n_stream->state = EXIT_CONN_STATE_CONNECTING; + n_stream->cpath_layer = circ->cpath->prev; /* link it */ + connection_exit_connect(n_stream); + return 0; + } + n_stream->address = tor_strdup(cell->payload + RELAY_HEADER_SIZE); + n_stream->state = EXIT_CONN_STATE_RESOLVING; + /* send it off to the gethostbyname farm */ switch(dns_resolve(n_stream)) { case 1: /* resolve worked */ @@ -1145,7 +1168,8 @@ static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) { void connection_exit_connect(connection_t *conn) { unsigned char connected_payload[4]; - if(router_compare_to_my_exit_policy(conn) == ADDR_POLICY_REJECTED) { + if (!*conn->rend_query && + router_compare_to_my_exit_policy(conn) == ADDR_POLICY_REJECTED) { log_fn(LOG_INFO,"%s:%d failed exit policy. Closing.", conn->address, conn->port); connection_mark_for_close(conn, END_STREAM_REASON_EXITPOLICY); return; @@ -1176,9 +1200,29 @@ void connection_exit_connect(connection_t *conn) { connection_watch_events(conn, POLLIN); /* also, deliver a 'connected' cell back through the circuit. */ - *(uint32_t*)connected_payload = htonl(conn->addr); - connection_edge_send_command(conn, circuit_get_by_conn(conn), RELAY_COMMAND_CONNECTED, - connected_payload, 4, NULL); + if(*conn->rend_query) { /* rendezvous stream */ + /* don't send an address back! */ + connection_edge_send_command(conn, circuit_get_by_conn(conn), RELAY_COMMAND_CONNECTED, + NULL, 0, conn->cpath_layer); + } else { /* normal stream */ + *(uint32_t*)connected_payload = htonl(conn->addr); + connection_edge_send_command(conn, circuit_get_by_conn(conn), RELAY_COMMAND_CONNECTED, + connected_payload, 4, conn->cpath_layer); + } +} + +/* This is a beginning rendezvous stream. Look up conn->port, + * and assign the actual conn->addr and conn->port. Return -1 + * if failure, or 0 for success. + */ +static int +connection_exit_set_rendezvous_addr_port(connection_t *conn) { + + /* XXX fill me in */ + + conn->addr = 0x7F000001u; /* 127.0.0.1, host order */ + + return 0; } int connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit) diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 86f9b34faf..ec50465791 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -148,7 +148,7 @@ rend_client_rendcirc_is_open(circuit_t *circ) connection_ap_attach_pending(); } -/* Called when we recieve a RENDEZVOUS_ESTABLISHED cell; changes the state of +/* Called when we receive a RENDEZVOUS_ESTABLISHED cell; changes the state of * the circuit to C_REND_READY. */ int diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index d0bc78d9d6..fd8fb8357b 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -4,7 +4,7 @@ #include "or.h" -/* Free the storage held by held by 'desc'. +/* Free the storage held by 'desc'. */ void rend_service_descriptor_free(rend_service_descriptor_t *desc) { @@ -20,8 +20,8 @@ void rend_service_descriptor_free(rend_service_descriptor_t *desc) tor_free(desc); } -/* Encode a service descriptor for 'desc', and sign it with 'key'. Stores - * the descriptor in *str_out, and sets *len_out to its length. +/* Encode a service descriptor for 'desc', and sign it with 'key'. Store + * the descriptor in *str_out, and set *len_out to its length. */ int rend_encode_service_descriptor(rend_service_descriptor_t *desc, @@ -146,7 +146,7 @@ int rend_get_service_id(crypto_pk_env_t *pk, char *out) typedef struct rend_cache_entry_t { int len; /* Length of desc */ char *desc; /* Service descriptor */ - rend_service_descriptor_t *parsed; /* Parsed vvalue of 'desc' */ + rend_service_descriptor_t *parsed; /* Parsed value of 'desc' */ } rend_cache_entry_t; static strmap_t *rend_cache = NULL;