Tor 0.4.9.2-alpha-dev
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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-2021, 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"
25
30
31/** Allocate a new extend_info object based on the various arguments. */
33extend_info_new(const char *nickname,
34 const char *rsa_id_digest,
35 const ed25519_public_key_t *ed_id,
36 const curve25519_public_key_t *ntor_key,
37 const tor_addr_t *addr, uint16_t port,
39 bool for_exit_use)
40{
41 extend_info_t *info = tor_malloc_zero(sizeof(extend_info_t));
42 if (rsa_id_digest)
43 memcpy(info->identity_digest, rsa_id_digest, DIGEST_LEN);
44 if (ed_id && !ed25519_public_key_is_zero(ed_id))
45 memcpy(&info->ed_identity, ed_id, sizeof(ed25519_public_key_t));
46 if (nickname)
47 strlcpy(info->nickname, nickname, sizeof(info->nickname));
48 if (ntor_key)
49 memcpy(&info->curve25519_onion_key, ntor_key,
51 for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
52 tor_addr_make_unspec(&info->orports[i].addr);
53 }
54
55 if (addr) {
56 extend_info_add_orport(info, addr, port);
57 }
58
59 if (pv && for_exit_use) {
62 }
63
64 return info;
65}
66
67/**
68 * Add another address:port pair to a given extend_info_t, if there is
69 * room. Return 0 on success, -1 on failure.
70 **/
71int
73 const tor_addr_t *addr,
74 uint16_t port)
75{
76 for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
77 if (tor_addr_is_unspec(&ei->orports[i].addr)) {
78 tor_addr_copy(&ei->orports[i].addr, addr);
79 ei->orports[i].port = port;
80 return 0;
81 }
82 }
83 return -1;
84}
85
86/** Allocate and return a new extend_info that can be used to build a
87 * circuit to or through the node <b>node</b>. Use the primary address
88 * of the node (i.e. its IPv4 address) unless
89 * <b>for_direct_connect</b> is true, in which case the preferred
90 * address is used instead. May return NULL if there is not enough
91 * info about <b>node</b> to extend to it--for example, if the preferred
92 * routerinfo_t or microdesc_t is missing, or if for_direct_connect is
93 * true and none of the node's addresses is allowed by tor's firewall
94 * and IP version config.
95 **/
97extend_info_from_node(const node_t *node, int for_direct_connect,
98 bool for_exit)
99{
100 extend_info_t *info = NULL;
102 int valid_addr = 0;
103
104 if (!node_has_preferred_descriptor(node, for_direct_connect)) {
105 return NULL;
106 }
107
108 /* Choose a preferred address first, but fall back to an allowed address. */
109 if (for_direct_connect)
110 reachable_addr_choose_from_node(node, FIREWALL_OR_CONNECTION, 0, &ap);
111 else {
112 node_get_prim_orport(node, &ap);
113 }
114 valid_addr = tor_addr_port_is_valid_ap(&ap, 0);
115
116 if (valid_addr)
117 log_debug(LD_CIRC, "using %s for %s",
118 fmt_addrport(&ap.addr, ap.port),
119 node->ri ? node->ri->nickname : node->rs->nickname);
120 else
121 log_warn(LD_CIRC, "Could not choose valid address for %s",
122 node->ri ? node->ri->nickname : node->rs->nickname);
123
124 /* Every node we connect or extend to must support ntor */
126 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
127 "Attempted to create extend_info for a node that does not support "
128 "ntor: %s", node_describe(node));
129 return NULL;
130 }
131
132 const ed25519_public_key_t *ed_pubkey = NULL;
133
134 /* Don't send the ed25519 pubkey unless the target node actually supports
135 * authenticating with it. */
137 log_info(LD_CIRC, "Including Ed25519 ID for %s", node_describe(node));
138 ed_pubkey = node_get_ed25519_id(node);
139 } else if (node_get_ed25519_id(node)) {
140 log_info(LD_CIRC, "Not including the ed25519 ID for %s, since it won't "
141 "be able to authenticate it.",
142 node_describe(node));
143 }
144
145 /* Retrieve the curve25519 pubkey. */
146 const curve25519_public_key_t *curve_pubkey =
148
149 if (valid_addr && node->ri) {
150 info = extend_info_new(node->ri->nickname,
151 node->identity,
152 ed_pubkey,
153 curve_pubkey,
154 &ap.addr,
155 ap.port,
156 &node->ri->pv,
157 for_exit);
158 } else if (valid_addr && node->rs && node->md) {
159 info = extend_info_new(node->rs->nickname,
160 node->identity,
161 ed_pubkey,
162 curve_pubkey,
163 &ap.addr,
164 ap.port,
165 &node->rs->pv,
166 for_exit);
167 }
168
169 return info;
170}
171
172/** Release storage held by an extend_info_t struct. */
173void
175{
176 if (!info)
177 return;
178 tor_free(info);
179}
180
181/** Allocate and return a new extend_info_t with the same contents as
182 * <b>info</b>. */
185{
186 extend_info_t *newinfo;
187 tor_assert(info);
188 newinfo = tor_malloc(sizeof(extend_info_t));
189 memcpy(newinfo, info, sizeof(extend_info_t));
190 return newinfo;
191}
192
193/* Does ei have a valid ntor key? */
194int
195extend_info_supports_ntor(const extend_info_t* ei)
196{
197 tor_assert(ei);
198 /* Valid ntor keys have at least one non-zero byte */
199 return !fast_mem_is_zero(
200 (const char*)ei->curve25519_onion_key.public_key,
202}
203
204/** Return true if we can use the Ntor v3 handshake with `ei` */
205int
207{
208 tor_assert(ei);
209 return extend_info_supports_ntor(ei) &&
211}
212
213/* Does ei have an onion key which it would prefer to use?
214 * Currently, we prefer ntor keys*/
215int
216extend_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. */
223int
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 **/
242bool
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 **/
262const tor_addr_port_t *
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 **/
277const 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.
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 **/
317bool
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}
void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src)
Definition: address.c:933
void tor_addr_make_unspec(tor_addr_t *a)
Definition: address.c:225
int tor_addr_is_multicast(const tor_addr_t *a)
Definition: address.c:1624
const char * fmt_addrport(const tor_addr_t *addr, uint16_t port)
Definition: address.c:1199
static sa_family_t tor_addr_family(const tor_addr_t *a)
Definition: address.h:187
#define tor_addr_eq(a, b)
Definition: address.h:280
static bool tor_addr_is_unspec(const tor_addr_t *a)
Definition: address.h:196
const or_options_t * get_options(void)
Definition: config.c:947
Header file for config.c.
int ed25519_public_key_is_zero(const ed25519_public_key_t *pubkey)
Common functions for using (pseudo-)random number generators.
crypto_fast_rng_t * get_thread_fast_rng(void)
unsigned crypto_fast_rng_get_uint(crypto_fast_rng_t *rng, unsigned limit)
const char * node_describe(const node_t *node)
Definition: describe.c:160
Header file for describe.c.
#define DIGEST_LEN
Definition: digest_sizes.h:20
Extend-info structure.
#define EXTEND_INFO_MAX_ADDRS
void extend_info_free_(extend_info_t *info)
Definition: extendinfo.c:174
extend_info_t * extend_info_dup(extend_info_t *info)
Definition: extendinfo.c:184
extend_info_t * extend_info_from_node(const node_t *node, int for_direct_connect, bool for_exit)
Definition: extendinfo.c:97
const tor_addr_port_t * extend_info_pick_orport(const extend_info_t *ei)
Definition: extendinfo.c:278
int extend_info_add_orport(extend_info_t *ei, const tor_addr_t *addr, uint16_t port)
Definition: extendinfo.c:72
extend_info_t * extend_info_new(const char *nickname, const char *rsa_id_digest, const ed25519_public_key_t *ed_id, const curve25519_public_key_t *ntor_key, const tor_addr_t *addr, uint16_t port, const protover_summary_flags_t *pv, bool for_exit_use)
Definition: extendinfo.c:33
const tor_addr_port_t * extend_info_get_orport(const extend_info_t *ei, int family)
Definition: extendinfo.c:263
int extend_info_supports_ntor_v3(const extend_info_t *ei)
Definition: extendinfo.c:206
bool extend_info_any_orport_addr_is_internal(const extend_info_t *ei)
Definition: extendinfo.c:318
bool extend_info_has_orport(const extend_info_t *ei, const tor_addr_t *addr, uint16_t port)
Definition: extendinfo.c:243
int extend_info_addr_is_allowed(const tor_addr_t *addr)
Definition: extendinfo.c:224
Header for core/or/extendinfo.c.
#define log_fn(severity, domain, args,...)
Definition: log.h:283
#define LD_CIRC
Definition: log.h:82
#define tor_free(p)
Definition: malloc.h:56
Node information structure.
void node_get_prim_orport(const node_t *node, tor_addr_port_t *ap_out)
Definition: nodelist.c:1864
int node_has_preferred_descriptor(const node_t *node, int for_direct_connect)
Definition: nodelist.c:1543
bool node_supports_ed25519_link_authentication(const node_t *node, bool compatible_with_us)
Definition: nodelist.c:1269
const curve25519_public_key_t * node_get_curve25519_onion_key(const node_t *node)
Definition: nodelist.c:2059
const ed25519_public_key_t * node_get_ed25519_id(const node_t *node)
Definition: nodelist.c:1184
int node_has_curve25519_onion_key(const node_t *node)
Definition: nodelist.c:2052
Header file for nodelist.c.
Master header file for Tor-specific functionality.
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:988
Header file for policies.c.
bool router_can_extend_over_ipv6(const or_options_t *options)
Definition: router.c:1630
Header file for router.c.
Router descriptor structure.
int server_mode(const or_options_t *options)
Definition: routermode.c:34
Header file for routermode.c.
Routerstatus (consensus entry) structure.
tor_addr_port_t orports[EXTEND_INFO_MAX_ADDRS]
ed25519_public_key_t ed_identity
char identity_digest[DIGEST_LEN]
char nickname[MAX_HEX_NICKNAME_LEN+1]
bool exit_supports_congestion_control
curve25519_public_key_t curve25519_onion_key
Definition: node_st.h:34
char identity[DIGEST_LEN]
Definition: node_st.h:46
unsigned int supports_congestion_control
Definition: or.h:830
protover_summary_flags_t pv
char * nickname
Definition: routerinfo_st.h:23
protover_summary_flags_t pv
char nickname[MAX_NICKNAME_LEN+1]
#define tor_assert(expr)
Definition: util_bug.h:103
#define IF_BUG_ONCE(cond)
Definition: util_bug.h:254
int fast_mem_is_zero(const char *mem, size_t len)
Definition: util_string.c:76
#define CURVE25519_PUBKEY_LEN
Definition: x25519_sizes.h:20