summaryrefslogtreecommitdiff
path: root/src/or/hs_service.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/hs_service.c')
-rw-r--r--src/or/hs_service.c99
1 files changed, 93 insertions, 6 deletions
diff --git a/src/or/hs_service.c b/src/or/hs_service.c
index 4cd808133c..5edfdd5b31 100644
--- a/src/or/hs_service.c
+++ b/src/or/hs_service.c
@@ -1725,14 +1725,8 @@ service_intro_circ_has_opened(origin_circuit_t *circ)
goto err;
}
- /* From the service object, get the intro point object of that circuit. The
- * following will query both descriptors intro points list. */
ip = service_intro_point_find(service, &circ->hs_ident->intro_auth_pk);
if (ip == NULL) {
- log_warn(LD_REND, "Unknown authentication key on the introduction "
- "circuit %u for service %s",
- TO_CIRCUIT(circ)->n_circ_id,
- safe_str_client(service->onion_address));
/* Closing this circuit because we don't recognize the key. */
close_reason = END_CIRC_REASON_NOSUCHSERVICE;
goto err;
@@ -1764,10 +1758,103 @@ service_rendezvous_circ_has_opened(origin_circuit_t *circ)
/* XXX: Implement rendezvous support. */
}
+/* Handle an INTRO_ESTABLISHED cell arriving on the given introduction
+ * circuit. Return 0 on success else a negative value. */
+static int
+service_handle_intro_established(origin_circuit_t *circ,
+ const uint8_t *payload,
+ size_t payload_len)
+{
+ hs_service_t *service = NULL;
+ hs_service_intro_point_t *ip = NULL;
+
+ tor_assert(circ);
+ tor_assert(payload);
+ tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
+
+ /* Get service object from the circuit identifier. */
+ service = find_service(hs_service_map, &circ->hs_ident->identity_pk);
+ if (service == NULL) {
+ log_warn(LD_REND, "Unknown service identity key %s on the introduction "
+ "circuit %u. Can't find onion service.",
+ safe_str_client(ed25519_fmt(&circ->hs_ident->identity_pk)),
+ TO_CIRCUIT(circ)->n_circ_id);
+ goto err;
+ }
+
+ /* From the service object, get the intro point object of that circuit. The
+ * following will query both descriptors intro points list. */
+ ip = service_intro_point_find(service, &circ->hs_ident->intro_auth_pk);
+ if (ip == NULL) {
+ /* We don't recognize the key. */
+ log_warn(LD_REND, "Introduction circuit established without an intro "
+ "point object on circuit %u for service %s",
+ TO_CIRCUIT(circ)->n_circ_id,
+ safe_str_client(service->onion_address));
+ goto err;
+ }
+
+ /* Try to parse the payload into a cell making sure we do actually have a
+ * valid cell. On success, the ip object is updated. */
+ if (hs_circ_handle_intro_established(service, ip, circ, payload,
+ payload_len) < 0) {
+ goto err;
+ }
+
+ /* Flag that we have an established circuit for this intro point. This value
+ * is what indicates the upload scheduled event if we are ready to build the
+ * intro point into the descriptor and upload. */
+ ip->circuit_established = 1;
+
+ log_info(LD_REND, "Successfully received an INTRO_ESTABLISHED cell "
+ "on circuit %u for service %s",
+ TO_CIRCUIT(circ)->n_circ_id,
+ safe_str_client(service->onion_address));
+ return 0;
+
+ err:
+ return -1;
+}
+
/* ========== */
/* Public API */
/* ========== */
+/* Called when we get an INTRO_ESTABLISHED cell. Mark the circuit as an
+ * established introduction point. Return 0 on success else a negative value
+ * and the circuit is closed. */
+int
+hs_service_receive_intro_established(origin_circuit_t *circ,
+ const uint8_t *payload,
+ size_t payload_len)
+{
+ int ret = -1;
+
+ tor_assert(circ);
+ tor_assert(payload);
+
+ if (TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
+ log_warn(LD_PROTOCOL, "Received an INTRO_ESTABLISHED cell on a "
+ "non introduction circuit of purpose %d",
+ TO_CIRCUIT(circ)->purpose);
+ goto err;
+ }
+
+ /* Handle both version. v2 uses rend_data and v3 uses the hs circuit
+ * identifier hs_ident. Can't be both. */
+ ret = (circ->hs_ident) ? service_handle_intro_established(circ, payload,
+ payload_len) :
+ rend_service_intro_established(circ, payload,
+ payload_len);
+ if (ret < 0) {
+ goto err;
+ }
+ return 0;
+ err:
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
+ return -1;
+}
+
/* Called when any kind of hidden service circuit is done building thus
* opened. This is the entry point from the circuit subsystem. */
void