summaryrefslogtreecommitdiff
path: root/src/or/connection_edge.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/connection_edge.c')
-rw-r--r--src/or/connection_edge.c87
1 files changed, 59 insertions, 28 deletions
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 8e447131fd..41e5f88ab8 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -76,6 +76,7 @@
#include "dirserv.h"
#include "hibernate.h"
#include "hs_common.h"
+#include "hs_circuit.h"
#include "main.h"
#include "nodelist.h"
#include "policies.h"
@@ -3066,58 +3067,88 @@ begin_cell_parse(const cell_t *cell, begin_cell_t *bcell,
return 0;
}
-/** For the given <b>circ</b> and the edge connection <b>n_stream</b>, setup
- * the the connection, attach it to the circ and connect it. Return 0 on
- * success or END_CIRC_AT_ORIGIN if we can't find the requested hidden
- * service port where the caller should close the circuit. */
+/** For the given <b>circ</b> and the edge connection <b>conn</b>, setup the
+ * connection, attach it to the circ and connect it. Return 0 on success
+ * or END_CIRC_AT_ORIGIN if we can't find the requested hidden service port
+ * where the caller should close the circuit. */
static int
-handle_hs_exit_conn(circuit_t *circ, edge_connection_t *n_stream)
+handle_hs_exit_conn(circuit_t *circ, edge_connection_t *conn)
{
- origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
- log_info(LD_REND,"begin is for rendezvous. configuring stream.");
- n_stream->base_.address = tor_strdup("(rendezvous)");
- n_stream->base_.state = EXIT_CONN_STATE_CONNECTING;
- n_stream->rend_data = rend_data_dup(origin_circ->rend_data);
- tor_assert(connection_edge_is_rendezvous_stream(n_stream));
+ int ret;
+ origin_circuit_t *origin_circ;
+
assert_circuit_ok(circ);
+ tor_assert(circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
+ tor_assert(conn);
- const int r = rend_service_set_connection_addr_port(n_stream, origin_circ);
- if (r < 0) {
- log_info(LD_REND,"Didn't find rendezvous service (port %d)",
- n_stream->base_.port);
+ log_debug(LD_REND, "Connecting the hidden service rendezvous circuit "
+ "to the service destination.");
+
+ origin_circ = TO_ORIGIN_CIRCUIT(circ);
+ conn->base_.address = tor_strdup("(rendezvous)");
+ conn->base_.state = EXIT_CONN_STATE_CONNECTING;
+
+ /* The circuit either has an hs identifier for v3+ or a rend_data for legacy
+ * service. */
+ if (origin_circ->rend_data) {
+ conn->rend_data = rend_data_dup(origin_circ->rend_data);
+ tor_assert(connection_edge_is_rendezvous_stream(conn));
+ ret = rend_service_set_connection_addr_port(conn, origin_circ);
+ } else if (origin_circ->hs_ident) {
+ /* Setup the identifier to be the one for the circuit service. */
+ conn->hs_ident =
+ hs_ident_edge_conn_new(&origin_circ->hs_ident->identity_pk);
+ ret = hs_service_set_conn_addr_port(origin_circ, conn);
+ } else {
+ /* We should never get here if the circuit's purpose is rendezvous. */
+ tor_assert(0);
+ }
+ if (ret < 0) {
+ log_info(LD_REND, "Didn't find rendezvous service (addr%s, port %d)",
+ fmt_addr(&TO_CONN(conn)->addr), TO_CONN(conn)->port);
/* Send back reason DONE because we want to make hidden service port
* scanning harder thus instead of returning that the exit policy
* didn't match, which makes it obvious that the port is closed,
* return DONE and kill the circuit. That way, a user (malicious or
* not) needs one circuit per bad port unless it matches the policy of
* the hidden service. */
- relay_send_end_cell_from_edge(n_stream->stream_id, circ,
+ relay_send_end_cell_from_edge(conn->stream_id, circ,
END_STREAM_REASON_DONE,
origin_circ->cpath->prev);
- connection_free(TO_CONN(n_stream));
+ connection_free(TO_CONN(conn));
/* Drop the circuit here since it might be someone deliberately
* scanning the hidden service ports. Note that this mitigates port
* scanning by adding more work on the attacker side to successfully
* scan but does not fully solve it. */
- if (r < -1)
+ if (ret < -1) {
return END_CIRC_AT_ORIGIN;
- else
+ } else {
return 0;
+ }
}
- assert_circuit_ok(circ);
- log_debug(LD_REND,"Finished assigning addr/port");
- n_stream->cpath_layer = origin_circ->cpath->prev; /* link it */
- /* add it into the linked list of p_streams on this circuit */
- n_stream->next_stream = origin_circ->p_streams;
- n_stream->on_circuit = circ;
- origin_circ->p_streams = n_stream;
+ /* Link the circuit and the connection crypt path. */
+ conn->cpath_layer = origin_circ->cpath->prev;
+
+ /* Add it into the linked list of p_streams on this circuit */
+ conn->next_stream = origin_circ->p_streams;
+ origin_circ->p_streams = conn;
+ conn->on_circuit = circ;
assert_circuit_ok(circ);
- origin_circ->rend_data->nr_streams++;
+ if (origin_circ->rend_data) {
+ origin_circ->rend_data->nr_streams++;
+ } else if (origin_circ->hs_ident) {
+ origin_circ->hs_ident->num_rdv_streams++;
+ } else {
+ /* The previous if/else at the start of the function guarantee that we'll
+ * never end up in a else situation unless it's freed in between. */
+ tor_assert(0);
+ }
- connection_exit_connect(n_stream);
+ /* Connect tor to the hidden service destination. */
+ connection_exit_connect(conn);
/* For path bias: This circuit was used successfully */
pathbias_mark_use_success(origin_circ);