aboutsummaryrefslogtreecommitdiff
path: root/src/feature/rend/rendcommon.c
blob: 5a9689e7bc814ff46b2d391fe396400f908436bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
 * Copyright (c) 2007-2021, The Tor Project, Inc. */
/* See LICENSE for licensing information */

/**
 * \file rendcommon.c
 * \brief Rendezvous implementation: shared code between
 * introducers, services, clients, and rendezvous points.
 **/

#define RENDCOMMON_PRIVATE

#include "core/or/or.h"

#include "app/config/config.h"

#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"

#include "feature/hs/hs_client.h"
#include "feature/hs/hs_common.h"
#include "feature/hs/hs_intropoint.h"
#include "feature/rend/rendcommon.h"
#include "feature/rend/rendmid.h"

#include "core/or/circuit_st.h"
#include "core/or/cpath_build_state_st.h"
#include "core/or/crypt_path_st.h"
#include "core/or/origin_circuit_st.h"

/** Called when we get a rendezvous-related relay cell on circuit
 * <b>circ</b>.  Dispatch on rendezvous relay command. */
void
rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint,
                        int command, size_t length,
                        const uint8_t *payload)
{
  or_circuit_t *or_circ = NULL;
  origin_circuit_t *origin_circ = NULL;
  int r = -2;
  if (CIRCUIT_IS_ORIGIN(circ)) {
    origin_circ = TO_ORIGIN_CIRCUIT(circ);

    /* Opened onion service circuit receiving cell MUST have an hs_ident as it
     * is the underlying assumption else we can't process the cell. If this is
     * the case, we can't recover so close the circuit. */
    if (BUG(!origin_circ->hs_ident)) {
      circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
      origin_circ = NULL;
    } else if (!layer_hint || layer_hint != origin_circ->cpath->prev) {
      log_fn(LOG_PROTOCOL_WARN, LD_APP,
             "Relay cell (rend purpose %d) from wrong hop on origin circ",
             command);
      origin_circ = NULL;
    }
  } else {
    or_circ = TO_OR_CIRCUIT(circ);
  }

  switch (command) {
    case RELAY_COMMAND_ESTABLISH_INTRO:
      if (or_circ)
        r = hs_intro_received_establish_intro(or_circ, payload, length);
      break;
    case RELAY_COMMAND_ESTABLISH_RENDEZVOUS:
      if (or_circ)
        r = rend_mid_establish_rendezvous(or_circ, payload, length);
      break;
    case RELAY_COMMAND_INTRODUCE1:
      if (or_circ)
        r = hs_intro_received_introduce1(or_circ, payload, length);
      break;
    case RELAY_COMMAND_INTRODUCE2:
      if (origin_circ)
        r = hs_service_receive_introduce2(origin_circ, payload, length);
      break;
    case RELAY_COMMAND_INTRODUCE_ACK:
      if (origin_circ)
        r = hs_client_receive_introduce_ack(origin_circ, payload, length);
      break;
    case RELAY_COMMAND_RENDEZVOUS1:
      if (or_circ)
        r = rend_mid_rendezvous(or_circ, payload, length);
      break;
    case RELAY_COMMAND_RENDEZVOUS2:
      if (origin_circ)
        r = hs_client_receive_rendezvous2(origin_circ, payload, length);
      break;
    case RELAY_COMMAND_INTRO_ESTABLISHED:
      if (origin_circ)
        r = hs_service_receive_intro_established(origin_circ, payload, length);
      break;
    case RELAY_COMMAND_RENDEZVOUS_ESTABLISHED:
      if (origin_circ)
        r = hs_client_receive_rendezvous_acked(origin_circ, payload, length);
      break;
    default:
      tor_fragile_assert();
  }

  if (r == 0 && origin_circ) {
    /* This was a valid cell. Count it as delivered + overhead. */
    circuit_read_valid_data(origin_circ, length);
  }

  if (r == -2)
    log_info(LD_PROTOCOL, "Dropping cell (type %d) for wrong circuit type.",
             command);
}

/* Make sure that tor only builds one-hop circuits when they would not
 * compromise user anonymity.
 *
 * One-hop circuits are permitted in Single Onion modes.
 *
 * Single Onion modes are also allowed to make multi-hop circuits.
 * For example, single onion HSDir circuits are 3-hop to prevent denial of
 * service.
 */
void
assert_circ_anonymity_ok(const origin_circuit_t *circ,
                         const or_options_t *options)
{
  tor_assert(options);
  tor_assert(circ);
  tor_assert(circ->build_state);

  if (circ->build_state->onehop_tunnel) {
    tor_assert(hs_service_allow_non_anonymous_connection(options));
  }
}