Line data Source code
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 describe.c
9 : * \brief Format short descriptions of relays.
10 : */
11 :
12 : #define DESCRIBE_PRIVATE
13 :
14 : #include "core/or/or.h"
15 : #include "core/or/extendinfo.h"
16 : #include "feature/nodelist/describe.h"
17 : #include "feature/nodelist/nodelist.h"
18 : #include "feature/nodelist/routerinfo.h"
19 : #include "lib/crypt_ops/crypto_ed25519.h"
20 : #include "lib/crypt_ops/crypto_format.h"
21 :
22 : #include "core/or/extend_info_st.h"
23 : #include "feature/nodelist/node_st.h"
24 : #include "feature/nodelist/routerinfo_st.h"
25 : #include "feature/nodelist/routerstatus_st.h"
26 : #include "feature/nodelist/microdesc_st.h"
27 :
28 : /** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to
29 : * hold a human-readable description of a node with identity digest
30 : * <b>id_digest</b>, nickname <b>nickname</b>, and addresses <b>addr32h</b> and
31 : * <b>addr</b>.
32 : *
33 : * The <b>nickname</b>, <b>ipv6_addr</b> and <b>ipv4_addr</b> fields are
34 : * optional and may be set to NULL or the null address.
35 : *
36 : * Return a pointer to the front of <b>buf</b>.
37 : * If buf is NULL, return a string constant describing the error.
38 : */
39 : STATIC const char *
40 8068 : format_node_description(char *buf,
41 : const char *rsa_id_digest,
42 : const ed25519_public_key_t *ed25519_id,
43 : const char *nickname,
44 : const tor_addr_t *ipv4_addr,
45 : const tor_addr_t *ipv6_addr)
46 : {
47 8068 : size_t rv = 0;
48 8068 : bool has_ipv6 = ipv6_addr && !tor_addr_is_null(ipv6_addr);
49 8068 : bool valid_ipv4 = false;
50 :
51 8068 : if (!buf)
52 : return "<NULL BUFFER>";
53 :
54 8067 : memset(buf, 0, NODE_DESC_BUF_LEN);
55 :
56 8067 : if (!rsa_id_digest) {
57 : /* strlcpy() returns the length of the source string it attempted to copy,
58 : * ignoring any required truncation due to the buffer length. */
59 1 : rv = strlcpy(buf, "<NULL ID DIGEST>", NODE_DESC_BUF_LEN);
60 1 : tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
61 1 : return buf;
62 : }
63 :
64 : /* strlcat() returns the length of the concatenated string it attempted to
65 : * create, ignoring any required truncation due to the buffer length. */
66 8066 : rv = strlcat(buf, "$", NODE_DESC_BUF_LEN);
67 8066 : tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
68 :
69 : {
70 8066 : char hex_digest[HEX_DIGEST_LEN+1];
71 8066 : memset(hex_digest, 0, sizeof(hex_digest));
72 :
73 8066 : base16_encode(hex_digest, sizeof(hex_digest),
74 : rsa_id_digest, DIGEST_LEN);
75 8066 : rv = strlcat(buf, hex_digest, NODE_DESC_BUF_LEN);
76 8066 : tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
77 : }
78 :
79 8066 : if (nickname) {
80 8054 : rv = strlcat(buf, "~", NODE_DESC_BUF_LEN);
81 8054 : tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
82 8054 : rv = strlcat(buf, nickname, NODE_DESC_BUF_LEN);
83 8054 : tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
84 : }
85 8066 : if (ed25519_id) {
86 33 : char ed_base64[ED25519_BASE64_LEN+1];
87 33 : ed25519_public_to_base64(ed_base64, ed25519_id);
88 33 : rv = strlcat(buf, " [", NODE_DESC_BUF_LEN);
89 33 : tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
90 33 : rv = strlcat(buf, ed_base64, NODE_DESC_BUF_LEN);
91 33 : tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
92 33 : rv = strlcat(buf, "]", NODE_DESC_BUF_LEN);
93 33 : tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
94 : }
95 8066 : if (ipv4_addr || has_ipv6) {
96 8063 : rv = strlcat(buf, " at ", NODE_DESC_BUF_LEN);
97 8063 : tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
98 : }
99 8066 : if (ipv4_addr) {
100 8061 : const char *str_rv = NULL;
101 8061 : char addr_str[TOR_ADDR_BUF_LEN];
102 8061 : memset(addr_str, 0, sizeof(addr_str));
103 :
104 8061 : str_rv = tor_addr_to_str(addr_str, ipv4_addr, sizeof(addr_str), 0);
105 8061 : if (str_rv) {
106 8029 : rv = strlcat(buf, addr_str, NODE_DESC_BUF_LEN);
107 8029 : tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
108 : valid_ipv4 = true;
109 : }
110 : }
111 : /* Both addresses are valid */
112 8066 : if (valid_ipv4 && has_ipv6) {
113 25 : rv = strlcat(buf, " and ", NODE_DESC_BUF_LEN);
114 25 : tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
115 : }
116 8066 : if (has_ipv6) {
117 31 : const char *str_rv = NULL;
118 31 : char addr_str[TOR_ADDR_BUF_LEN];
119 31 : memset(addr_str, 0, sizeof(addr_str));
120 :
121 31 : str_rv = tor_addr_to_str(addr_str, ipv6_addr, sizeof(addr_str), 1);
122 31 : if (str_rv) {
123 31 : rv = strlcat(buf, addr_str, NODE_DESC_BUF_LEN);
124 31 : tor_assert_nonfatal(rv < NODE_DESC_BUF_LEN);
125 : }
126 : }
127 :
128 : return buf;
129 : }
130 :
131 : /** Return a human-readable description of the routerinfo_t <b>ri</b>.
132 : *
133 : * This function is not thread-safe. Each call to this function invalidates
134 : * previous values returned by this function.
135 : */
136 : const char *
137 38 : router_describe(const routerinfo_t *ri)
138 : {
139 38 : static char buf[NODE_DESC_BUF_LEN];
140 :
141 38 : if (!ri)
142 : return "<null>";
143 :
144 37 : const ed25519_public_key_t *ed25519_id = routerinfo_get_ed25519_id(ri);
145 :
146 37 : return format_node_description(buf,
147 37 : ri->cache_info.identity_digest,
148 : ed25519_id,
149 37 : ri->nickname,
150 : &ri->ipv4_addr,
151 : &ri->ipv6_addr);
152 : }
153 :
154 : /** Return a human-readable description of the node_t <b>node</b>.
155 : *
156 : * This function is not thread-safe. Each call to this function invalidates
157 : * previous values returned by this function.
158 : */
159 : const char *
160 7998 : node_describe(const node_t *node)
161 : {
162 7998 : static char buf[NODE_DESC_BUF_LEN];
163 7998 : const char *nickname = NULL;
164 7998 : const tor_addr_t *ipv6_addr = NULL, *ipv4_addr = NULL;
165 :
166 7998 : if (!node)
167 : return "<null>";
168 :
169 7997 : if (node->rs) {
170 7988 : nickname = node->rs->nickname;
171 7988 : ipv4_addr = &node->rs->ipv4_addr;
172 7988 : ipv6_addr = &node->rs->ipv6_addr;
173 : /* Support consensus versions less than 28, when IPv6 addresses were in
174 : * microdescs. This code can be removed when 0.2.9 is no longer supported,
175 : * and the MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC macro is removed. */
176 7988 : if (node->md && tor_addr_is_null(ipv6_addr)) {
177 7963 : ipv6_addr = &node->md->ipv6_addr;
178 : }
179 9 : } else if (node->ri) {
180 8 : nickname = node->ri->nickname;
181 8 : ipv4_addr = &node->ri->ipv4_addr;
182 8 : ipv6_addr = &node->ri->ipv6_addr;
183 : } else {
184 : return "<null rs and ri>";
185 : }
186 :
187 7996 : const ed25519_public_key_t *ed25519_id = node_get_ed25519_id(node);
188 :
189 7996 : return format_node_description(buf,
190 7996 : node->identity,
191 : ed25519_id,
192 : nickname,
193 : ipv4_addr,
194 : ipv6_addr);
195 : }
196 :
197 : /** Return a human-readable description of the routerstatus_t <b>rs</b>.
198 : *
199 : * This function is not thread-safe. Each call to this function invalidates
200 : * previous values returned by this function.
201 : */
202 : const char *
203 4 : routerstatus_describe(const routerstatus_t *rs)
204 : {
205 4 : static char buf[NODE_DESC_BUF_LEN];
206 :
207 4 : if (!rs)
208 : return "<null>";
209 :
210 3 : return format_node_description(buf,
211 3 : rs->identity_digest,
212 : NULL,
213 3 : rs->nickname,
214 : &rs->ipv4_addr,
215 : &rs->ipv6_addr);
216 : }
217 :
218 : /** Return a human-readable description of the extend_info_t <b>ei</b>.
219 : *
220 : * This function is not thread-safe. Each call to this function invalidates
221 : * previous values returned by this function.
222 : */
223 : const char *
224 24 : extend_info_describe(const extend_info_t *ei)
225 : {
226 24 : static char buf[NODE_DESC_BUF_LEN];
227 :
228 24 : if (!ei)
229 : return "<null>";
230 :
231 23 : const tor_addr_port_t *ap4 = extend_info_get_orport(ei, AF_INET);
232 23 : const tor_addr_port_t *ap6 = extend_info_get_orport(ei, AF_INET6);
233 23 : const tor_addr_t *addr4 = ap4 ? &ap4->addr : NULL;
234 23 : const tor_addr_t *addr6 = ap6 ? &ap6->addr : NULL;
235 :
236 23 : const ed25519_public_key_t *ed25519_id = &ei->ed_identity;
237 23 : if (ed25519_public_key_is_zero(ed25519_id))
238 23 : ed25519_id = NULL;
239 :
240 23 : return format_node_description(buf,
241 23 : ei->identity_digest,
242 : ed25519_id,
243 23 : ei->nickname,
244 : addr4,
245 : addr6);
246 : }
247 :
248 : /** Set <b>buf</b> (which must have MAX_VERBOSE_NICKNAME_LEN+1 bytes) to the
249 : * verbose representation of the identity of <b>router</b>. The format is:
250 : * A dollar sign.
251 : * The upper-case hexadecimal encoding of the SHA1 hash of router's identity.
252 : * A "=" if the router is named (no longer implemented); a "~" if it is not.
253 : * The router's nickname.
254 : **/
255 : void
256 4 : router_get_verbose_nickname(char *buf, const routerinfo_t *router)
257 : {
258 4 : size_t rv = 0;
259 :
260 4 : if (!buf)
261 : return;
262 :
263 2 : memset(buf, 0, MAX_VERBOSE_NICKNAME_LEN+1);
264 :
265 2 : if (!router) {
266 : /* strlcpy() returns the length of the source string it attempted to copy,
267 : * ignoring any required truncation due to the buffer length. */
268 1 : rv = strlcpy(buf, "<null>", MAX_VERBOSE_NICKNAME_LEN+1);
269 1 : tor_assert_nonfatal(rv < MAX_VERBOSE_NICKNAME_LEN+1);
270 1 : return;
271 : }
272 :
273 : /* strlcat() returns the length of the concatenated string it attempted to
274 : * create, ignoring any required truncation due to the buffer length. */
275 1 : rv = strlcat(buf, "$", MAX_VERBOSE_NICKNAME_LEN+1);
276 1 : tor_assert_nonfatal(rv < MAX_VERBOSE_NICKNAME_LEN+1);
277 :
278 : {
279 1 : char hex_digest[HEX_DIGEST_LEN+1];
280 1 : memset(hex_digest, 0, sizeof(hex_digest));
281 :
282 1 : base16_encode(hex_digest, sizeof(hex_digest),
283 1 : router->cache_info.identity_digest, DIGEST_LEN);
284 1 : rv = strlcat(buf, hex_digest, MAX_VERBOSE_NICKNAME_LEN+1);
285 1 : tor_assert_nonfatal(rv < MAX_VERBOSE_NICKNAME_LEN+1);
286 : }
287 :
288 1 : rv = strlcat(buf, "~", MAX_VERBOSE_NICKNAME_LEN+1);
289 1 : tor_assert_nonfatal(rv < MAX_VERBOSE_NICKNAME_LEN+1);
290 :
291 1 : rv = strlcat(buf, router->nickname, MAX_VERBOSE_NICKNAME_LEN+1);
292 1 : tor_assert_nonfatal(rv < MAX_VERBOSE_NICKNAME_LEN+1);
293 : }
|