Tor  0.4.6.0-alpha-dev
extendinfo.c
Go to the documentation of this file.
1 /* Copyright (c) 2001 Matej Pfajfar.
2  * Copyright (c) 2001-2004, Roger Dingledine.
3  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4  * Copyright (c) 2007-2020, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
6 
7 /**
8  * @file extendinfo.c
9  * @brief Functions for creating and using extend_info_t objects.
10  *
11  * An extend_info_t is the information we hold about a relay in order to
12  * extend a circuit to it.
13  **/
14 
15 #include "core/or/or.h"
16 #include "core/or/extendinfo.h"
17 
18 #include "app/config/config.h"
19 #include "core/or/policies.h"
22 #include "feature/relay/router.h"
25 
26 #include "core/or/extend_info_st.h"
30 
31 /** Allocate a new extend_info object based on the various arguments. */
33 extend_info_new(const char *nickname,
34  const char *rsa_id_digest,
35  const ed25519_public_key_t *ed_id,
36  crypto_pk_t *onion_key,
37  const curve25519_public_key_t *ntor_key,
38  const tor_addr_t *addr, uint16_t port)
39 {
40  extend_info_t *info = tor_malloc_zero(sizeof(extend_info_t));
41  if (rsa_id_digest)
42  memcpy(info->identity_digest, rsa_id_digest, DIGEST_LEN);
43  if (ed_id && !ed25519_public_key_is_zero(ed_id))
44  memcpy(&info->ed_identity, ed_id, sizeof(ed25519_public_key_t));
45  if (nickname)
46  strlcpy(info->nickname, nickname, sizeof(info->nickname));
47  if (onion_key)
48  info->onion_key = crypto_pk_dup_key(onion_key);
49  if (ntor_key)
50  memcpy(&info->curve25519_onion_key, ntor_key,
51  sizeof(curve25519_public_key_t));
52  for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
53  tor_addr_make_unspec(&info->orports[i].addr);
54  }
55 
56  if (addr) {
57  extend_info_add_orport(info, addr, port);
58  }
59  return info;
60 }
61 
62 /**
63  * Add another address:port pair to a given extend_info_t, if there is
64  * room. Return 0 on success, -1 on failure.
65  **/
66 int
68  const tor_addr_t *addr,
69  uint16_t port)
70 {
71  for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
72  if (tor_addr_is_unspec(&ei->orports[i].addr)) {
73  tor_addr_copy(&ei->orports[i].addr, addr);
74  ei->orports[i].port = port;
75  return 0;
76  }
77  }
78  return -1;
79 }
80 
81 /** Allocate and return a new extend_info that can be used to build a
82  * circuit to or through the node <b>node</b>. Use the primary address
83  * of the node (i.e. its IPv4 address) unless
84  * <b>for_direct_connect</b> is true, in which case the preferred
85  * address is used instead. May return NULL if there is not enough
86  * info about <b>node</b> to extend to it--for example, if the preferred
87  * routerinfo_t or microdesc_t is missing, or if for_direct_connect is
88  * true and none of the node's addresses is allowed by tor's firewall
89  * and IP version config.
90  **/
92 extend_info_from_node(const node_t *node, int for_direct_connect)
93 {
94  crypto_pk_t *rsa_pubkey = NULL;
95  extend_info_t *info = NULL;
96  tor_addr_port_t ap;
97  int valid_addr = 0;
98 
99  if (!node_has_preferred_descriptor(node, for_direct_connect)) {
100  return NULL;
101  }
102 
103  /* Choose a preferred address first, but fall back to an allowed address. */
104  if (for_direct_connect)
105  reachable_addr_choose_from_node(node, FIREWALL_OR_CONNECTION, 0, &ap);
106  else {
107  node_get_prim_orport(node, &ap);
108  }
109  valid_addr = tor_addr_port_is_valid_ap(&ap, 0);
110 
111  if (valid_addr)
112  log_debug(LD_CIRC, "using %s for %s",
113  fmt_addrport(&ap.addr, ap.port),
114  node->ri ? node->ri->nickname : node->rs->nickname);
115  else
116  log_warn(LD_CIRC, "Could not choose valid address for %s",
117  node->ri ? node->ri->nickname : node->rs->nickname);
118 
119  /* Every node we connect or extend to must support ntor */
120  if (!node_has_curve25519_onion_key(node)) {
121  log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
122  "Attempted to create extend_info for a node that does not support "
123  "ntor: %s", node_describe(node));
124  return NULL;
125  }
126 
127  const ed25519_public_key_t *ed_pubkey = NULL;
128 
129  /* Don't send the ed25519 pubkey unless the target node actually supports
130  * authenticating with it. */
132  log_info(LD_CIRC, "Including Ed25519 ID for %s", node_describe(node));
133  ed_pubkey = node_get_ed25519_id(node);
134  } else if (node_get_ed25519_id(node)) {
135  log_info(LD_CIRC, "Not including the ed25519 ID for %s, since it won't "
136  "be able to authenticate it.",
137  node_describe(node));
138  }
139 
140  /* Retrieve the curve25519 pubkey. */
141  const curve25519_public_key_t *curve_pubkey =
143  rsa_pubkey = node_get_rsa_onion_key(node);
144 
145  if (valid_addr && node->ri) {
146  info = extend_info_new(node->ri->nickname,
147  node->identity,
148  ed_pubkey,
149  rsa_pubkey,
150  curve_pubkey,
151  &ap.addr,
152  ap.port);
153  } else if (valid_addr && node->rs && node->md) {
154  info = extend_info_new(node->rs->nickname,
155  node->identity,
156  ed_pubkey,
157  rsa_pubkey,
158  curve_pubkey,
159  &ap.addr,
160  ap.port);
161  }
162 
163  crypto_pk_free(rsa_pubkey);
164  return info;
165 }
166 
167 /** Release storage held by an extend_info_t struct. */
168 void
170 {
171  if (!info)
172  return;
173  crypto_pk_free(info->onion_key);
174  tor_free(info);
175 }
176 
177 /** Allocate and return a new extend_info_t with the same contents as
178  * <b>info</b>. */
181 {
182  extend_info_t *newinfo;
183  tor_assert(info);
184  newinfo = tor_malloc(sizeof(extend_info_t));
185  memcpy(newinfo, info, sizeof(extend_info_t));
186  if (info->onion_key)
187  newinfo->onion_key = crypto_pk_dup_key(info->onion_key);
188  else
189  newinfo->onion_key = NULL;
190  return newinfo;
191 }
192 
193 /* Does ei have a valid TAP key? */
194 int
195 extend_info_supports_tap(const extend_info_t* ei)
196 {
197  tor_assert(ei);
198  /* Valid TAP keys are not NULL */
199  return ei->onion_key != NULL;
200 }
201 
202 /* Does ei have a valid ntor key? */
203 int
204 extend_info_supports_ntor(const extend_info_t* ei)
205 {
206  tor_assert(ei);
207  /* Valid ntor keys have at least one non-zero byte */
208  return !fast_mem_is_zero(
209  (const char*)ei->curve25519_onion_key.public_key,
211 }
212 
213 /* Does ei have an onion key which it would prefer to use?
214  * Currently, we prefer ntor keys*/
215 int
216 extend_info_has_preferred_onion_key(const extend_info_t* ei)
217 {
218  tor_assert(ei);
219  return extend_info_supports_ntor(ei);
220 }
221 
222 /** Return true iff the given address can be used to extend to. */
223 int
225 {
226  tor_assert(addr);
227 
228  /* Check if we have a private address and if we can extend to it. */
229  if ((tor_addr_is_internal(addr, 0) || tor_addr_is_multicast(addr)) &&
230  !get_options()->ExtendAllowPrivateAddresses) {
231  goto disallow;
232  }
233  /* Allowed! */
234  return 1;
235  disallow:
236  return 0;
237 }
238 
239 /**
240  * Return true if @a addr : @a port is a listed ORPort in @a ei.
241  **/
242 bool
244  const tor_addr_t *addr, uint16_t port)
245 {
246  IF_BUG_ONCE(ei == NULL) {
247  return false;
248  }
249 
250  for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
251  const tor_addr_port_t *ei_ap = &ei->orports[i];
252  if (tor_addr_eq(&ei_ap->addr, addr) && ei_ap->port == port)
253  return true;
254  }
255  return false;
256 }
257 
258 /**
259  * If the extend_info @a ei has an orport of the chosen family, then return
260  * that orport. Otherwise, return NULL.
261  **/
262 const tor_addr_port_t *
263 extend_info_get_orport(const extend_info_t *ei, int family)
264 {
265  for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
266  if (tor_addr_is_unspec(&ei->orports[i].addr))
267  continue;
268  if (tor_addr_family(&ei->orports[i].addr) == family)
269  return &ei->orports[i];
270  }
271  return NULL;
272 }
273 
274 /**
275  * Chose an addr_port_t within @a ei to connect to.
276  **/
277 const tor_addr_port_t *
279 {
280  IF_BUG_ONCE(!ei) {
281  return NULL;
282  }
283  const or_options_t *options = get_options();
284  if (!server_mode(options)) {
285  // If we aren't a server, just pick the first address we built into
286  // this extendinfo.
287  return &ei->orports[0];
288  }
289 
290  const bool ipv6_ok = router_can_extend_over_ipv6(options);
291 
292  // Use 'usable' to collect the usable orports, then pick one.
293  const tor_addr_port_t *usable[EXTEND_INFO_MAX_ADDRS];
294  int n_usable = 0;
295  for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
296  const tor_addr_port_t *a = &ei->orports[i];
297  const int family = tor_addr_family(&a->addr);
298  if (family == AF_INET || (ipv6_ok && family == AF_INET6)) {
299  usable[n_usable++] = a;
300  }
301  }
302 
303  if (n_usable == 0) {
304  // Need to bail out early, since nothing will work.
305  return NULL;
306  }
307 
309  const int idx = crypto_fast_rng_get_uint(rng, n_usable);
310 
311  return usable[idx];
312 }
313 
314 /**
315  * Return true if any orport address in @a ei is an internal address.
316  **/
317 bool
319 {
320  IF_BUG_ONCE(ei == NULL) {
321  return false;
322  }
323 
324  for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
325  if (! tor_addr_is_unspec(&ei->orports[i].addr) &&
326  tor_addr_is_internal(&ei->orports[i].addr, 0))
327  return true;
328  }
329  return false;
330 }
log_fn
#define log_fn(severity, domain, args,...)
Definition: log.h:283
routermode.h
Header file for routermode.c.
tor_free
#define tor_free(p)
Definition: malloc.h:52
CURVE25519_PUBKEY_LEN
#define CURVE25519_PUBKEY_LEN
Definition: x25519_sizes.h:20
tor_addr_family
static sa_family_t tor_addr_family(const tor_addr_t *a)
Definition: address.h:187
get_thread_fast_rng
crypto_fast_rng_t * get_thread_fast_rng(void)
Definition: crypto_rand_fast.c:377
tor_addr_t
Definition: address.h:69
extend_info_t::onion_key
crypto_pk_t * onion_key
Definition: extend_info_st.h:38
extend_info_add_orport
int extend_info_add_orport(extend_info_t *ei, const tor_addr_t *addr, uint16_t port)
Definition: extendinfo.c:67
tor_assert
#define tor_assert(expr)
Definition: util_bug.h:102
router.h
Header file for router.c.
fast_mem_is_zero
int fast_mem_is_zero(const char *mem, size_t len)
Definition: util_string.c:74
crypto_pk_dup_key
crypto_pk_t * crypto_pk_dup_key(crypto_pk_t *orig)
Definition: crypto_rsa_nss.c:351
describe.h
Header file for describe.c.
ed25519_public_key_is_zero
int ed25519_public_key_is_zero(const ed25519_public_key_t *pubkey)
Definition: crypto_ed25519.c:227
routerstatus_t::nickname
char nickname[MAX_NICKNAME_LEN+1]
Definition: routerstatus_st.h:25
tor_addr_make_unspec
void tor_addr_make_unspec(tor_addr_t *a)
Definition: address.c:225
LD_CIRC
#define LD_CIRC
Definition: log.h:82
extend_info_new
extend_info_t * extend_info_new(const char *nickname, const char *rsa_id_digest, const ed25519_public_key_t *ed_id, crypto_pk_t *onion_key, const curve25519_public_key_t *ntor_key, const tor_addr_t *addr, uint16_t port)
Definition: extendinfo.c:33
DIGEST_LEN
#define DIGEST_LEN
Definition: digest_sizes.h:20
extend_info_has_orport
bool extend_info_has_orport(const extend_info_t *ei, const tor_addr_t *addr, uint16_t port)
Definition: extendinfo.c:243
tor_addr_port_t
Definition: address.h:81
tor_addr_is_unspec
static bool tor_addr_is_unspec(const tor_addr_t *a)
Definition: address.h:196
node_t
Definition: node_st.h:34
extend_info_from_node
extend_info_t * extend_info_from_node(const node_t *node, int for_direct_connect)
Definition: extendinfo.c:92
ed25519_public_key_t
Definition: crypto_ed25519.h:23
extend_info_t::orports
tor_addr_port_t orports[EXTEND_INFO_MAX_ADDRS]
Definition: extend_info_st.h:36
crypto_fast_rng_t
Definition: crypto_rand_fast.c:95
EXTEND_INFO_MAX_ADDRS
#define EXTEND_INFO_MAX_ADDRS
Definition: extend_info_st.h:21
extend_info_t::ed_identity
ed25519_public_key_t ed_identity
Definition: extend_info_st.h:33
tor_addr_is_multicast
int tor_addr_is_multicast(const tor_addr_t *a)
Definition: address.c:1624
nodelist.h
Header file for nodelist.c.
extend_info_addr_is_allowed
int extend_info_addr_is_allowed(const tor_addr_t *addr)
Definition: extendinfo.c:224
node_has_curve25519_onion_key
int node_has_curve25519_onion_key(const node_t *node)
Definition: nodelist.c:1928
routerinfo_st.h
Router descriptor structure.
extendinfo.h
Header for core/or/extendinfo.c.
extend_info_t::curve25519_onion_key
curve25519_public_key_t curve25519_onion_key
Definition: extend_info_st.h:40
crypto_rand.h
Common functions for using (pseudo-)random number generators.
get_options
const or_options_t * get_options(void)
Definition: config.c:932
fmt_addrport
const char * fmt_addrport(const tor_addr_t *addr, uint16_t port)
Definition: address.c:1199
extend_info_st.h
Extend-info structure.
routerstatus_st.h
Routerstatus (consensus entry) structure.
node_describe
const char * node_describe(const node_t *node)
Definition: describe.c:160
reachable_addr_choose_from_node
void reachable_addr_choose_from_node(const node_t *node, firewall_connection_t fw_connection, int pref_only, tor_addr_port_t *ap)
Definition: policies.c:985
curve25519_public_key_t
Definition: crypto_curve25519.h:24
IF_BUG_ONCE
#define IF_BUG_ONCE(cond)
Definition: util_bug.h:246
extend_info_t::identity_digest
char identity_digest[DIGEST_LEN]
Definition: extend_info_st.h:31
node_supports_ed25519_link_authentication
bool node_supports_ed25519_link_authentication(const node_t *node, bool compatible_with_us)
Definition: nodelist.c:1154
server_mode
int server_mode(const or_options_t *options)
Definition: routermode.c:34
node_get_ed25519_id
const ed25519_public_key_t * node_get_ed25519_id(const node_t *node)
Definition: nodelist.c:1069
crypto_pk_t
Definition: crypto_rsa_nss.c:37
node_get_prim_orport
void node_get_prim_orport(const node_t *node, tor_addr_port_t *ap_out)
Definition: nodelist.c:1740
node_st.h
Node information structure.
extend_info_any_orport_addr_is_internal
bool extend_info_any_orport_addr_is_internal(const extend_info_t *ei)
Definition: extendinfo.c:318
policies.h
Header file for policies.c.
extend_info_dup
extend_info_t * extend_info_dup(extend_info_t *info)
Definition: extendinfo.c:180
extend_info_free_
void extend_info_free_(extend_info_t *info)
Definition: extendinfo.c:169
config.h
Header file for config.c.
extend_info_t::nickname
char nickname[MAX_HEX_NICKNAME_LEN+1]
Definition: extend_info_st.h:28
node_get_curve25519_onion_key
const curve25519_public_key_t * node_get_curve25519_onion_key(const node_t *node)
Definition: nodelist.c:1935
extend_info_get_orport
const tor_addr_port_t * extend_info_get_orport(const extend_info_t *ei, int family)
Definition: extendinfo.c:263
or_options_t
Definition: or_options_st.h:64
crypto_fast_rng_get_uint
unsigned crypto_fast_rng_get_uint(crypto_fast_rng_t *rng, unsigned limit)
Definition: crypto_rand_numeric.c:139
routerinfo_t::nickname
char * nickname
Definition: routerinfo_st.h:22
extend_info_pick_orport
const tor_addr_port_t * extend_info_pick_orport(const extend_info_t *ei)
Definition: extendinfo.c:278
node_has_preferred_descriptor
int node_has_preferred_descriptor(const node_t *node, int for_direct_connect)
Definition: nodelist.c:1419
tor_addr_eq
#define tor_addr_eq(a, b)
Definition: address.h:280
tor_addr_copy
void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src)
Definition: address.c:933
extend_info_t
Definition: extend_info_st.h:27
router_can_extend_over_ipv6
bool router_can_extend_over_ipv6(const or_options_t *options)
Definition: router.c:1556
node_t::identity
char identity[DIGEST_LEN]
Definition: node_st.h:46
or.h
Master header file for Tor-specific functionality.