Tor 0.4.9.0-alpha-dev
onion.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 onion.c
9 * \brief Functions to queue create cells,
10 * and parse and create the CREATE cell and its allies.
11 *
12 * This module has a few functions, all related to the CREATE/CREATED
13 * handshake that we use on links in order to create a circuit, and the
14 * related EXTEND/EXTENDED handshake that we use over circuits in order to
15 * extend them an additional hop.
16 *
17 * Clients invoke these functions when creating or extending a circuit,
18 * from circuitbuild.c.
19 *
20 * Relays invoke these functions when they receive a CREATE or EXTEND
21 * cell in command.c or relay.c, in order to queue the pending request.
22 * They also invoke them from cpuworker.c, which handles dispatching
23 * onionskin requests to different worker threads.
24 *
25 * <br>
26 *
27 * This module also handles:
28 * <ul>
29 * <li> Queueing incoming onionskins on the relay side before passing
30 * them to worker threads.
31 * <li>Expiring onionskins on the relay side if they have waited for
32 * too long.
33 * <li>Packaging private keys on the server side in order to pass
34 * them to worker threads.
35 * <li>Encoding and decoding CREATE, CREATED, CREATE2, and CREATED2 cells.
36 * <li>Encoding and decodign EXTEND, EXTENDED, EXTEND2, and EXTENDED2
37 * relay cells.
38 * </ul>
39 **/
40
41#include "core/or/or.h"
42
43#include "app/config/config.h"
48#include "core/or/onion.h"
50
51#include "core/or/cell_st.h"
52
53// trunnel
54#include "trunnel/ed25519_cert.h"
55
56/** Helper: return 0 if <b>cell</b> appears valid, -1 otherwise. If
57 * <b>unknown_ok</b> is true, allow cells with handshake types we don't
58 * recognize. */
59static int
60check_create_cell(const create_cell_t *cell, int unknown_ok)
61{
62 switch (cell->cell_type) {
63 case CELL_CREATE:
64 if (cell->handshake_type != ONION_HANDSHAKE_TYPE_TAP &&
65 cell->handshake_type != ONION_HANDSHAKE_TYPE_NTOR)
66 return -1;
67 break;
68 case CELL_CREATE_FAST:
69 if (cell->handshake_type != ONION_HANDSHAKE_TYPE_FAST)
70 return -1;
71 break;
72 case CELL_CREATE2:
73 break;
74 default:
75 return -1;
76 }
77
78 switch (cell->handshake_type) {
79 case ONION_HANDSHAKE_TYPE_TAP:
80 if (cell->handshake_len != TAP_ONIONSKIN_CHALLENGE_LEN)
81 return -1;
82 break;
83 case ONION_HANDSHAKE_TYPE_FAST:
84 if (cell->handshake_len != CREATE_FAST_LEN)
85 return -1;
86 break;
87 case ONION_HANDSHAKE_TYPE_NTOR:
89 return -1;
90 break;
91 case ONION_HANDSHAKE_TYPE_NTOR_V3:
92 /* ntor v3 has variable length fields that are checked
93 * elsewhere. Fall through to always valid here. */
94 break;
95 default:
96 if (! unknown_ok)
97 return -1;
98 }
99
100 return 0;
101}
102
103/** Write the various parameters into the create cell. Separate from
104 * create_cell_parse() to make unit testing easier.
105 */
106void
107create_cell_init(create_cell_t *cell_out, uint8_t cell_type,
108 uint16_t handshake_type, uint16_t handshake_len,
109 const uint8_t *onionskin)
110{
111 memset(cell_out, 0, sizeof(*cell_out));
112
113 cell_out->cell_type = cell_type;
114 cell_out->handshake_type = handshake_type;
115 cell_out->handshake_len = handshake_len;
116 memcpy(cell_out->onionskin, onionskin, handshake_len);
117}
118
119/** Helper: parse the CREATE2 payload at <b>p</b>, which could be up to
120 * <b>p_len</b> bytes long, and use it to fill the fields of
121 * <b>cell_out</b>. Return 0 on success and -1 on failure.
122 *
123 * Note that part of the body of an EXTEND2 cell is a CREATE2 payload, so
124 * this function is also used for parsing those.
125 */
126static int
127parse_create2_payload(create_cell_t *cell_out, const uint8_t *p, size_t p_len)
128{
129 uint16_t handshake_type, handshake_len;
130
131 if (p_len < 4)
132 return -1;
133
134 handshake_type = ntohs(get_uint16(p));
135 handshake_len = ntohs(get_uint16(p+2));
136
137 if (handshake_len > CELL_PAYLOAD_SIZE - 4 || handshake_len > p_len - 4)
138 return -1;
139 if (handshake_type == ONION_HANDSHAKE_TYPE_FAST)
140 return -1;
141
142 create_cell_init(cell_out, CELL_CREATE2, handshake_type, handshake_len,
143 p+4);
144 return 0;
145}
146
147/** Magic string which, in a CREATE or EXTEND cell, indicates that a seeming
148 * TAP payload is really an ntor payload. We'd do away with this if every
149 * relay supported EXTEND2, but we want to be able to extend from A to B with
150 * ntor even when A doesn't understand EXTEND2 and so can't generate a
151 * CREATE2 cell.
152 **/
153#define NTOR_CREATE_MAGIC "ntorNTORntorNTOR"
154
155/** Parse a CREATE, CREATE_FAST, or CREATE2 cell from <b>cell_in</b> into
156 * <b>cell_out</b>. Return 0 on success, -1 on failure. (We reject some
157 * syntactically valid CREATE2 cells that we can't generate or react to.) */
158int
159create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in)
160{
161 switch (cell_in->command) {
162 case CELL_CREATE:
163 if (tor_memeq(cell_in->payload, NTOR_CREATE_MAGIC, 16)) {
164 create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR,
165 NTOR_ONIONSKIN_LEN, cell_in->payload+16);
166 } else {
167 create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP,
168 TAP_ONIONSKIN_CHALLENGE_LEN, cell_in->payload);
169 }
170 break;
171 case CELL_CREATE_FAST:
172 create_cell_init(cell_out, CELL_CREATE_FAST, ONION_HANDSHAKE_TYPE_FAST,
173 CREATE_FAST_LEN, cell_in->payload);
174 break;
175 case CELL_CREATE2:
176 if (parse_create2_payload(cell_out, cell_in->payload,
178 return -1;
179 break;
180 default:
181 return -1;
182 }
183
184 return check_create_cell(cell_out, 0);
185}
186
187/** Helper: return 0 if <b>cell</b> appears valid, -1 otherwise. */
188static int
190{
191 switch (cell->cell_type) {
192 case CELL_CREATED:
193 if (cell->handshake_len != TAP_ONIONSKIN_REPLY_LEN &&
195 return -1;
196 break;
197 case CELL_CREATED_FAST:
198 if (cell->handshake_len != CREATED_FAST_LEN)
199 return -1;
200 break;
201 case CELL_CREATED2:
202 if (cell->handshake_len > RELAY_PAYLOAD_SIZE-2)
203 return -1;
204 break;
205 }
206
207 return 0;
208}
209
210/** Parse a CREATED, CREATED_FAST, or CREATED2 cell from <b>cell_in</b> into
211 * <b>cell_out</b>. Return 0 on success, -1 on failure. */
212int
213created_cell_parse(created_cell_t *cell_out, const cell_t *cell_in)
214{
215 memset(cell_out, 0, sizeof(*cell_out));
216
217 switch (cell_in->command) {
218 case CELL_CREATED:
219 cell_out->cell_type = CELL_CREATED;
220 cell_out->handshake_len = TAP_ONIONSKIN_REPLY_LEN;
221 memcpy(cell_out->reply, cell_in->payload, TAP_ONIONSKIN_REPLY_LEN);
222 break;
223 case CELL_CREATED_FAST:
224 cell_out->cell_type = CELL_CREATED_FAST;
225 cell_out->handshake_len = CREATED_FAST_LEN;
226 memcpy(cell_out->reply, cell_in->payload, CREATED_FAST_LEN);
227 break;
228 case CELL_CREATED2:
229 {
230 const uint8_t *p = cell_in->payload;
231 cell_out->cell_type = CELL_CREATED2;
232 cell_out->handshake_len = ntohs(get_uint16(p));
233 if (cell_out->handshake_len > CELL_PAYLOAD_SIZE - 2)
234 return -1;
235 memcpy(cell_out->reply, p+2, cell_out->handshake_len);
236 break;
237 }
238 }
239
240 return check_created_cell(cell_out);
241}
242
243/** Helper: return 0 if <b>cell</b> appears valid, -1 otherwise. */
244static int
246{
247 const bool is_extend2 = (cell->cell_type == RELAY_COMMAND_EXTEND2);
248
249 if (tor_digest_is_zero((const char*)cell->node_id))
250 return -1;
251 if (!tor_addr_port_is_valid_ap(&cell->orport_ipv4, 0)) {
252 /* EXTEND cells must have an IPv4 address. */
253 if (!is_extend2) {
254 return -1;
255 }
256 /* EXTEND2 cells must have at least one IP address.
257 * It can be IPv4 or IPv6. */
258 if (!tor_addr_port_is_valid_ap(&cell->orport_ipv6, 0)) {
259 return -1;
260 }
261 }
262 if (cell->create_cell.cell_type == CELL_CREATE) {
263 if (cell->cell_type != RELAY_COMMAND_EXTEND)
264 return -1;
265 } else if (cell->create_cell.cell_type == CELL_CREATE2) {
266 if (cell->cell_type != RELAY_COMMAND_EXTEND2 &&
267 cell->cell_type != RELAY_COMMAND_EXTEND)
268 return -1;
269 } else {
270 /* In particular, no CREATE_FAST cells are allowed */
271 return -1;
272 }
273 if (cell->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_FAST)
274 return -1;
275
276 return check_create_cell(&cell->create_cell, 1);
277}
278
279static int
280extend_cell_from_extend1_cell_body(extend_cell_t *cell_out,
281 const extend1_cell_body_t *cell)
282{
283 tor_assert(cell_out);
284 tor_assert(cell);
285 memset(cell_out, 0, sizeof(*cell_out));
286 tor_addr_make_unspec(&cell_out->orport_ipv4.addr);
287 tor_addr_make_unspec(&cell_out->orport_ipv6.addr);
288
289 cell_out->cell_type = RELAY_COMMAND_EXTEND;
290 tor_addr_from_ipv4h(&cell_out->orport_ipv4.addr, cell->ipv4addr);
291 cell_out->orport_ipv4.port = cell->port;
292 if (tor_memeq(cell->onionskin, NTOR_CREATE_MAGIC, 16)) {
293 cell_out->create_cell.cell_type = CELL_CREATE2;
294 cell_out->create_cell.handshake_type = ONION_HANDSHAKE_TYPE_NTOR;
296 memcpy(cell_out->create_cell.onionskin, cell->onionskin + 16,
298 } else {
299 cell_out->create_cell.cell_type = CELL_CREATE;
300 cell_out->create_cell.handshake_type = ONION_HANDSHAKE_TYPE_TAP;
301 cell_out->create_cell.handshake_len = TAP_ONIONSKIN_CHALLENGE_LEN;
302 memcpy(cell_out->create_cell.onionskin, cell->onionskin,
303 TAP_ONIONSKIN_CHALLENGE_LEN);
304 }
305 memcpy(cell_out->node_id, cell->identity, DIGEST_LEN);
306 return 0;
307}
308
309static int
310create_cell_from_create2_cell_body(create_cell_t *cell_out,
311 const create2_cell_body_t *cell)
312{
313 tor_assert(cell_out);
314 tor_assert(cell);
315 memset(cell_out, 0, sizeof(create_cell_t));
316 if (BUG(cell->handshake_len > sizeof(cell_out->onionskin))) {
317 /* This should be impossible because there just isn't enough room in the
318 * input cell to make the handshake_len this large and provide a
319 * handshake_data to match. */
320 return -1;
321 }
322
323 cell_out->cell_type = CELL_CREATE2;
324 cell_out->handshake_type = cell->handshake_type;
325 cell_out->handshake_len = cell->handshake_len;
326 memcpy(cell_out->onionskin,
327 create2_cell_body_getconstarray_handshake_data(cell),
328 cell->handshake_len);
329 return 0;
330}
331
332static int
333extend_cell_from_extend2_cell_body(extend_cell_t *cell_out,
334 const extend2_cell_body_t *cell)
335{
336 tor_assert(cell_out);
337 tor_assert(cell);
338 int found_ipv4 = 0, found_ipv6 = 0, found_rsa_id = 0, found_ed_id = 0;
339 memset(cell_out, 0, sizeof(*cell_out));
340 tor_addr_make_unspec(&cell_out->orport_ipv4.addr);
341 tor_addr_make_unspec(&cell_out->orport_ipv6.addr);
342 cell_out->cell_type = RELAY_COMMAND_EXTEND2;
343
344 unsigned i;
345 for (i = 0; i < cell->n_spec; ++i) {
346 const link_specifier_t *ls = extend2_cell_body_getconst_ls(cell, i);
347 switch (ls->ls_type) {
348 case LS_IPV4:
349 if (found_ipv4)
350 continue;
351 found_ipv4 = 1;
352 tor_addr_from_ipv4h(&cell_out->orport_ipv4.addr, ls->un_ipv4_addr);
353 cell_out->orport_ipv4.port = ls->un_ipv4_port;
354 break;
355 case LS_IPV6:
356 if (found_ipv6)
357 continue;
358 found_ipv6 = 1;
360 ls->un_ipv6_addr);
361 cell_out->orport_ipv6.port = ls->un_ipv6_port;
362 break;
363 case LS_LEGACY_ID:
364 if (found_rsa_id)
365 return -1;
366 found_rsa_id = 1;
367 memcpy(cell_out->node_id, ls->un_legacy_id, 20);
368 break;
369 case LS_ED25519_ID:
370 if (found_ed_id)
371 return -1;
372 found_ed_id = 1;
373 memcpy(cell_out->ed_pubkey.pubkey, ls->un_ed25519_id, 32);
374 break;
375 default:
376 /* Ignore this, whatever it is. */
377 break;
378 }
379 }
380
381 /* EXTEND2 cells must have an RSA ID */
382 if (!found_rsa_id)
383 return -1;
384
385 /* EXTEND2 cells must have at least one IP address */
386 if (!found_ipv4 && !found_ipv6)
387 return -1;
388
389 return create_cell_from_create2_cell_body(&cell_out->create_cell,
390 cell->create2);
391}
392
393/** Parse an EXTEND or EXTEND2 cell (according to <b>command</b>) from the
394 * <b>payload_length</b> bytes of <b>payload</b> into <b>cell_out</b>. Return
395 * 0 on success, -1 on failure. */
396MOCK_IMPL(int,
398 const uint8_t command,
399 const uint8_t *payload,
400 size_t payload_length))
401{
402
403 tor_assert(cell_out);
404 tor_assert(payload);
405
406 if (payload_length > RELAY_PAYLOAD_SIZE)
407 return -1;
408
409 switch (command) {
410 case RELAY_COMMAND_EXTEND:
411 {
412 extend1_cell_body_t *cell = NULL;
413 if (extend1_cell_body_parse(&cell, payload, payload_length)<0 ||
414 cell == NULL) {
415 if (cell)
416 extend1_cell_body_free(cell);
417 return -1;
418 }
419 int r = extend_cell_from_extend1_cell_body(cell_out, cell);
420 extend1_cell_body_free(cell);
421 if (r < 0)
422 return r;
423 }
424 break;
425 case RELAY_COMMAND_EXTEND2:
426 {
427 extend2_cell_body_t *cell = NULL;
428 if (extend2_cell_body_parse(&cell, payload, payload_length) < 0 ||
429 cell == NULL) {
430 if (cell)
431 extend2_cell_body_free(cell);
432 return -1;
433 }
434 int r = extend_cell_from_extend2_cell_body(cell_out, cell);
435 extend2_cell_body_free(cell);
436 if (r < 0)
437 return r;
438 }
439 break;
440 default:
441 return -1;
442 }
443
444 return check_extend_cell(cell_out);
445}
446
447/** Helper: return 0 if <b>cell</b> appears valid, -1 otherwise. */
448static int
450{
451 tor_assert(cell);
452 if (cell->created_cell.cell_type == CELL_CREATED) {
453 if (cell->cell_type != RELAY_COMMAND_EXTENDED)
454 return -1;
455 } else if (cell->created_cell.cell_type == CELL_CREATED2) {
456 if (cell->cell_type != RELAY_COMMAND_EXTENDED2)
457 return -1;
458 } else {
459 return -1;
460 }
461
462 return check_created_cell(&cell->created_cell);
463}
464
465/** Parse an EXTENDED or EXTENDED2 cell (according to <b>command</b>) from the
466 * <b>payload_length</b> bytes of <b>payload</b> into <b>cell_out</b>. Return
467 * 0 on success, -1 on failure. */
468int
470 const uint8_t command, const uint8_t *payload,
471 size_t payload_len)
472{
473 tor_assert(cell_out);
474 tor_assert(payload);
475
476 memset(cell_out, 0, sizeof(*cell_out));
477 if (payload_len > RELAY_PAYLOAD_SIZE)
478 return -1;
479
480 switch (command) {
481 case RELAY_COMMAND_EXTENDED:
482 if (payload_len != TAP_ONIONSKIN_REPLY_LEN)
483 return -1;
484 cell_out->cell_type = RELAY_COMMAND_EXTENDED;
485 cell_out->created_cell.cell_type = CELL_CREATED;
486 cell_out->created_cell.handshake_len = TAP_ONIONSKIN_REPLY_LEN;
487 memcpy(cell_out->created_cell.reply, payload, TAP_ONIONSKIN_REPLY_LEN);
488 break;
489 case RELAY_COMMAND_EXTENDED2:
490 {
491 cell_out->cell_type = RELAY_COMMAND_EXTENDED2;
492 cell_out->created_cell.cell_type = CELL_CREATED2;
493 cell_out->created_cell.handshake_len = ntohs(get_uint16(payload));
494 if (cell_out->created_cell.handshake_len > RELAY_PAYLOAD_SIZE - 2 ||
495 cell_out->created_cell.handshake_len > payload_len - 2)
496 return -1;
497 memcpy(cell_out->created_cell.reply, payload+2,
498 cell_out->created_cell.handshake_len);
499 }
500 break;
501 default:
502 return -1;
503 }
504
505 return check_extended_cell(cell_out);
506}
507
508/** Fill <b>cell_out</b> with a correctly formatted version of the
509 * CREATE{,_FAST,2} cell in <b>cell_in</b>. Return 0 on success, -1 on
510 * failure. This is a cell we didn't originate if <b>relayed</b> is true. */
511static int
513 int relayed)
514{
515 uint8_t *p;
516 size_t space;
517 if (check_create_cell(cell_in, relayed) < 0)
518 return -1;
519
520 memset(cell_out->payload, 0, sizeof(cell_out->payload));
521 cell_out->command = cell_in->cell_type;
522
523 p = cell_out->payload;
524 space = sizeof(cell_out->payload);
525
526 switch (cell_in->cell_type) {
527 case CELL_CREATE:
528 if (BUG(cell_in->handshake_type == ONION_HANDSHAKE_TYPE_NTOR_V3)) {
529 log_warn(LD_BUG, "Create cells cannot contain ntorv3.");
530 return -1;
531 }
532
533 if (cell_in->handshake_type == ONION_HANDSHAKE_TYPE_NTOR) {
534 memcpy(p, NTOR_CREATE_MAGIC, 16);
535 p += 16;
536 space -= 16;
537 }
538 FALLTHROUGH;
539 case CELL_CREATE_FAST:
540 tor_assert(cell_in->handshake_len <= space);
541 memcpy(p, cell_in->onionskin, cell_in->handshake_len);
542 break;
543 case CELL_CREATE2:
544 tor_assert(cell_in->handshake_len <= sizeof(cell_out->payload)-4);
545 set_uint16(cell_out->payload, htons(cell_in->handshake_type));
546 set_uint16(cell_out->payload+2, htons(cell_in->handshake_len));
547 memcpy(cell_out->payload + 4, cell_in->onionskin, cell_in->handshake_len);
548 break;
549 default:
550 return -1;
551 }
552
553 return 0;
554}
555
556int
557create_cell_format(cell_t *cell_out, const create_cell_t *cell_in)
558{
559 return create_cell_format_impl(cell_out, cell_in, 0);
560}
561
562int
563create_cell_format_relayed(cell_t *cell_out, const create_cell_t *cell_in)
564{
565 return create_cell_format_impl(cell_out, cell_in, 1);
566}
567
568/** Fill <b>cell_out</b> with a correctly formatted version of the
569 * CREATED{,_FAST,2} cell in <b>cell_in</b>. Return 0 on success, -1 on
570 * failure. */
571int
572created_cell_format(cell_t *cell_out, const created_cell_t *cell_in)
573{
574 if (check_created_cell(cell_in) < 0)
575 return -1;
576
577 memset(cell_out->payload, 0, sizeof(cell_out->payload));
578 cell_out->command = cell_in->cell_type;
579
580 switch (cell_in->cell_type) {
581 case CELL_CREATED:
582 case CELL_CREATED_FAST:
583 tor_assert(cell_in->handshake_len <= sizeof(cell_out->payload));
584 memcpy(cell_out->payload, cell_in->reply, cell_in->handshake_len);
585 break;
586 case CELL_CREATED2:
587 tor_assert(cell_in->handshake_len <= sizeof(cell_out->payload)-2);
588 set_uint16(cell_out->payload, htons(cell_in->handshake_len));
589 memcpy(cell_out->payload + 2, cell_in->reply, cell_in->handshake_len);
590 break;
591 default:
592 return -1;
593 }
594 return 0;
595}
596
597/** Return true iff we are configured (by torrc or by the networkstatus
598 * parameters) to use Ed25519 identities in our Extend2 cells. */
599static int
601 const or_options_t *options)
602{
603 if (options->ExtendByEd25519ID != -1)
604 return options->ExtendByEd25519ID; /* The user has an opinion. */
605
606 return (int) networkstatus_get_param(ns, "ExtendByEd25519ID",
607 0 /* default */,
608 0 /* min */,
609 1 /*max*/);
610}
611
612/** Format the EXTEND{,2} cell in <b>cell_in</b>, storing its relay payload in
613 * <b>payload_out</b>, the number of bytes used in *<b>len_out</b>, and the
614 * relay command in *<b>command_out</b>. The <b>payload_out</b> must have
615 * RELAY_PAYLOAD_SIZE bytes available. Return 0 on success, -1 on failure. */
616int
617extend_cell_format(uint8_t *command_out, uint16_t *len_out,
618 uint8_t *payload_out, const extend_cell_t *cell_in)
619{
620 uint8_t *p;
621 if (check_extend_cell(cell_in) < 0)
622 return -1;
623
624 p = payload_out;
625
626 memset(p, 0, RELAY_PAYLOAD_SIZE);
627
628 switch (cell_in->cell_type) {
629 case RELAY_COMMAND_EXTEND:
630 {
631 if (BUG(cell_in->create_cell.handshake_type ==
632 ONION_HANDSHAKE_TYPE_NTOR_V3)) {
633 log_warn(LD_BUG, "Extend cells cannot contain ntorv3!");
634 return -1;
635 }
636 *command_out = RELAY_COMMAND_EXTEND;
637 *len_out = 6 + TAP_ONIONSKIN_CHALLENGE_LEN + DIGEST_LEN;
638 set_uint32(p, tor_addr_to_ipv4n(&cell_in->orport_ipv4.addr));
639 set_uint16(p+4, htons(cell_in->orport_ipv4.port));
640 if (cell_in->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_NTOR) {
641 memcpy(p+6, NTOR_CREATE_MAGIC, 16);
642 memcpy(p+22, cell_in->create_cell.onionskin, NTOR_ONIONSKIN_LEN);
643 } else {
644 memcpy(p+6, cell_in->create_cell.onionskin,
645 TAP_ONIONSKIN_CHALLENGE_LEN);
646 }
647 memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, cell_in->node_id, DIGEST_LEN);
648 }
649 break;
650 case RELAY_COMMAND_EXTEND2:
651 {
652 uint8_t n_specifiers = 1;
653 *command_out = RELAY_COMMAND_EXTEND2;
654 extend2_cell_body_t *cell = extend2_cell_body_new();
655 link_specifier_t *ls;
656 if (tor_addr_port_is_valid_ap(&cell_in->orport_ipv4, 0)) {
657 /* Maybe IPv4 specifier first. */
658 ++n_specifiers;
659 ls = link_specifier_new();
660 extend2_cell_body_add_ls(cell, ls);
661 ls->ls_type = LS_IPV4;
662 ls->ls_len = 6;
663 ls->un_ipv4_addr = tor_addr_to_ipv4h(&cell_in->orport_ipv4.addr);
664 ls->un_ipv4_port = cell_in->orport_ipv4.port;
665 }
666 {
667 /* Then RSA id */
668 ls = link_specifier_new();
669 extend2_cell_body_add_ls(cell, ls);
670 ls->ls_type = LS_LEGACY_ID;
671 ls->ls_len = DIGEST_LEN;
672 memcpy(ls->un_legacy_id, cell_in->node_id, DIGEST_LEN);
673 }
676 /* Then, maybe, the ed25519 id! */
677 ++n_specifiers;
678 ls = link_specifier_new();
679 extend2_cell_body_add_ls(cell, ls);
680 ls->ls_type = LS_ED25519_ID;
681 ls->ls_len = 32;
682 memcpy(ls->un_ed25519_id, cell_in->ed_pubkey.pubkey, 32);
683 }
684 if (tor_addr_port_is_valid_ap(&cell_in->orport_ipv6, 0)) {
685 /* Then maybe IPv6 specifier. */
686 ++n_specifiers;
687 ls = link_specifier_new();
688 extend2_cell_body_add_ls(cell, ls);
689 ls->ls_type = LS_IPV6;
690 ls->ls_len = 18;
691 tor_addr_copy_ipv6_bytes(ls->un_ipv6_addr,
692 &cell_in->orport_ipv6.addr);
693 ls->un_ipv6_port = cell_in->orport_ipv6.port;
694 }
695 cell->n_spec = n_specifiers;
696
697 /* Now, the handshake */
698 cell->create2 = create2_cell_body_new();
699 cell->create2->handshake_type = cell_in->create_cell.handshake_type;
700 cell->create2->handshake_len = cell_in->create_cell.handshake_len;
701 create2_cell_body_setlen_handshake_data(cell->create2,
702 cell_in->create_cell.handshake_len);
703 memcpy(create2_cell_body_getarray_handshake_data(cell->create2),
704 cell_in->create_cell.onionskin,
705 cell_in->create_cell.handshake_len);
706
707 ssize_t len_encoded = extend2_cell_body_encode(
708 payload_out, RELAY_PAYLOAD_SIZE,
709 cell);
710 extend2_cell_body_free(cell);
711 if (len_encoded < 0 || len_encoded > UINT16_MAX)
712 return -1;
713 *len_out = (uint16_t) len_encoded;
714 }
715 break;
716 default:
717 return -1;
718 }
719
720 return 0;
721}
722
723/** Format the EXTENDED{,2} cell in <b>cell_in</b>, storing its relay payload
724 * in <b>payload_out</b>, the number of bytes used in *<b>len_out</b>, and the
725 * relay command in *<b>command_out</b>. The <b>payload_out</b> must have
726 * RELAY_PAYLOAD_SIZE bytes available. Return 0 on success, -1 on failure. */
727int
728extended_cell_format(uint8_t *command_out, uint16_t *len_out,
729 uint8_t *payload_out, const extended_cell_t *cell_in)
730{
731 uint8_t *p;
732 if (check_extended_cell(cell_in) < 0)
733 return -1;
734
735 p = payload_out;
736 memset(p, 0, RELAY_PAYLOAD_SIZE);
737
738 switch (cell_in->cell_type) {
739 case RELAY_COMMAND_EXTENDED:
740 {
741 *command_out = RELAY_COMMAND_EXTENDED;
742 *len_out = TAP_ONIONSKIN_REPLY_LEN;
743 memcpy(payload_out, cell_in->created_cell.reply,
744 TAP_ONIONSKIN_REPLY_LEN);
745 }
746 break;
747 case RELAY_COMMAND_EXTENDED2:
748 {
749 *command_out = RELAY_COMMAND_EXTENDED2;
750 *len_out = 2 + cell_in->created_cell.handshake_len;
751 set_uint16(payload_out, htons(cell_in->created_cell.handshake_len));
753 return -1;
754 memcpy(payload_out+2, cell_in->created_cell.reply,
755 cell_in->created_cell.handshake_len);
756 }
757 break;
758 default:
759 return -1;
760 }
761
762 return 0;
763}
void tor_addr_make_unspec(tor_addr_t *a)
Definition: address.c:225
void tor_addr_copy_ipv6_bytes(uint8_t *dest, const tor_addr_t *src)
Definition: address.c:920
void tor_addr_from_ipv6_bytes(tor_addr_t *dest, const uint8_t *ipv6_bytes)
Definition: address.c:900
static uint32_t tor_addr_to_ipv4n(const tor_addr_t *a)
Definition: address.h:152
static uint32_t tor_addr_to_ipv4h(const tor_addr_t *a)
Definition: address.h:160
#define tor_addr_from_ipv4h(dest, v4addr)
Definition: address.h:327
static void set_uint16(void *cp, uint16_t v)
Definition: bytes.h:78
static uint16_t get_uint16(const void *cp)
Definition: bytes.h:42
static void set_uint32(void *cp, uint32_t v)
Definition: bytes.h:87
Fixed-size cell structure.
const or_options_t * get_options(void)
Definition: config.c:944
tor_cmdline_mode_t command
Definition: config.c:2468
Header file for config.c.
int ed25519_public_key_is_zero(const ed25519_public_key_t *pubkey)
int tor_memeq(const void *a, const void *b, size_t sz)
Definition: di_ops.c:107
#define DIGEST_LEN
Definition: digest_sizes.h:20
#define LD_BUG
Definition: log.h:86
int32_t networkstatus_get_param(const networkstatus_t *ns, const char *param_name, int32_t default_val, int32_t min_val, int32_t max_val)
Header file for networkstatus.c.
static int check_created_cell(const created_cell_t *cell)
Definition: onion.c:189
static int should_include_ed25519_id_extend_cells(const networkstatus_t *ns, const or_options_t *options)
Definition: onion.c:600
static int parse_create2_payload(create_cell_t *cell_out, const uint8_t *p, size_t p_len)
Definition: onion.c:127
#define NTOR_CREATE_MAGIC
Definition: onion.c:153
static int check_create_cell(const create_cell_t *cell, int unknown_ok)
Definition: onion.c:60
static int create_cell_format_impl(cell_t *cell_out, const create_cell_t *cell_in, int relayed)
Definition: onion.c:512
int created_cell_parse(created_cell_t *cell_out, const cell_t *cell_in)
Definition: onion.c:213
void create_cell_init(create_cell_t *cell_out, uint8_t cell_type, uint16_t handshake_type, uint16_t handshake_len, const uint8_t *onionskin)
Definition: onion.c:107
static int check_extend_cell(const extend_cell_t *cell)
Definition: onion.c:245
int create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in)
Definition: onion.c:159
int extend_cell_parse(extend_cell_t *cell_out, const uint8_t command, const uint8_t *payload, size_t payload_length)
Definition: onion.c:400
int created_cell_format(cell_t *cell_out, const created_cell_t *cell_in)
Definition: onion.c:572
int extended_cell_format(uint8_t *command_out, uint16_t *len_out, uint8_t *payload_out, const extended_cell_t *cell_in)
Definition: onion.c:728
int extended_cell_parse(extended_cell_t *cell_out, const uint8_t command, const uint8_t *payload, size_t payload_len)
Definition: onion.c:469
int extend_cell_format(uint8_t *command_out, uint16_t *len_out, uint8_t *payload_out, const extend_cell_t *cell_in)
Definition: onion.c:617
static int check_extended_cell(const extended_cell_t *cell)
Definition: onion.c:449
Header file for onion.c.
Header file for onion_crypto.c.
Header file for onion_fast.c.
Header for onion_ntor.c.
#define NTOR_REPLY_LEN
Definition: onion_ntor.h:25
#define NTOR_ONIONSKIN_LEN
Definition: onion_ntor.h:23
Header file for onion_tap.c.
Master header file for Tor-specific functionality.
#define CELL_PAYLOAD_SIZE
Definition: or.h:465
#define RELAY_PAYLOAD_SIZE
Definition: or.h:494
Definition: cell_st.h:17
uint8_t payload[CELL_PAYLOAD_SIZE]
Definition: cell_st.h:21
uint8_t command
Definition: cell_st.h:19
uint16_t handshake_len
Definition: onion.h:30
uint16_t handshake_type
Definition: onion.h:28
uint8_t onionskin[CELL_PAYLOAD_SIZE - 4]
Definition: onion.h:32
uint8_t cell_type
Definition: onion.h:26
uint16_t handshake_len
Definition: onion.h:40
uint8_t reply[CELL_PAYLOAD_SIZE - 2]
Definition: onion.h:42
uint8_t cell_type
Definition: onion.h:38
tor_addr_port_t orport_ipv4
Definition: onion.h:50
create_cell_t create_cell
Definition: onion.h:60
struct ed25519_public_key_t ed_pubkey
Definition: onion.h:56
uint8_t node_id[DIGEST_LEN]
Definition: onion.h:54
tor_addr_port_t orport_ipv6
Definition: onion.h:52
uint8_t cell_type
Definition: onion.h:48
created_cell_t created_cell
Definition: onion.h:68
uint8_t cell_type
Definition: onion.h:66
#define MOCK_IMPL(rv, funcname, arglist)
Definition: testsupport.h:133
#define tor_assert(expr)
Definition: util_bug.h:103
int tor_digest_is_zero(const char *digest)
Definition: util_string.c:98