hs_intropoint.c (29429B)
1 /* Copyright (c) 2016-2021, The Tor Project, Inc. */ 2 /* See LICENSE for licensing information */ 3 4 /** 5 * \file hs_intropoint.c 6 * \brief Implement next generation introductions point functionality 7 **/ 8 9 #define HS_INTROPOINT_PRIVATE 10 11 #include "core/or/or.h" 12 #include "app/config/config.h" 13 #include "core/or/channel.h" 14 #include "core/or/circuitlist.h" 15 #include "core/or/circuituse.h" 16 #include "core/or/relay.h" 17 #include "feature/rend/rendmid.h" 18 #include "feature/relay/relay_metrics.h" 19 #include "feature/stats/rephist.h" 20 #include "lib/crypt_ops/crypto_format.h" 21 #include "lib/time/compat_time.h" 22 23 /* Trunnel */ 24 #include "trunnel/ed25519_cert.h" 25 #include "trunnel/extension.h" 26 #include "trunnel/hs/cell_establish_intro.h" 27 #include "trunnel/hs/cell_introduce1.h" 28 29 #include "feature/hs/hs_circuitmap.h" 30 #include "feature/hs/hs_common.h" 31 #include "feature/hs/hs_config.h" 32 #include "feature/hs/hs_descriptor.h" 33 #include "feature/hs/hs_dos.h" 34 #include "feature/hs/hs_intropoint.h" 35 36 #include "core/or/or_circuit_st.h" 37 38 /** Extract the authentication key from an ESTABLISH_INTRO or INTRODUCE1 using 39 * the given <b>cell_type</b> from <b>cell</b> and place it in 40 * <b>auth_key_out</b>. */ 41 STATIC void 42 get_auth_key_from_cell(ed25519_public_key_t *auth_key_out, 43 unsigned int cell_type, const void *cell) 44 { 45 size_t auth_key_len; 46 const uint8_t *key_array; 47 48 tor_assert(auth_key_out); 49 tor_assert(cell); 50 51 switch (cell_type) { 52 case RELAY_COMMAND_ESTABLISH_INTRO: 53 { 54 const trn_cell_establish_intro_t *c_cell = cell; 55 key_array = trn_cell_establish_intro_getconstarray_auth_key(c_cell); 56 auth_key_len = trn_cell_establish_intro_getlen_auth_key(c_cell); 57 break; 58 } 59 case RELAY_COMMAND_INTRODUCE1: 60 { 61 const trn_cell_introduce1_t *c_cell = cell; 62 key_array = trn_cell_introduce1_getconstarray_auth_key(cell); 63 auth_key_len = trn_cell_introduce1_getlen_auth_key(c_cell); 64 break; 65 } 66 default: 67 /* Getting here is really bad as it means we got a unknown cell type from 68 * this file where every call has an hardcoded value. */ 69 tor_assert_unreached(); /* LCOV_EXCL_LINE */ 70 } 71 tor_assert(key_array); 72 tor_assert(auth_key_len == sizeof(auth_key_out->pubkey)); 73 memcpy(auth_key_out->pubkey, key_array, auth_key_len); 74 } 75 76 /** We received an ESTABLISH_INTRO <b>cell</b>. Verify its signature and MAC, 77 * given <b>circuit_key_material</b>. Return 0 on success else -1 on error. */ 78 STATIC int 79 verify_establish_intro_cell(const trn_cell_establish_intro_t *cell, 80 const uint8_t *circuit_key_material, 81 size_t circuit_key_material_len) 82 { 83 /* We only reach this function if the first byte of the cell is 0x02 which 84 * means that auth_key_type is of ed25519 type, hence this check should 85 * always pass. See hs_intro_received_establish_intro(). */ 86 if (BUG(cell->auth_key_type != TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519)) { 87 return -1; 88 } 89 90 /* Make sure the auth key length is of the right size for this type. For 91 * EXTRA safety, we check both the size of the array and the length which 92 * must be the same. Safety first!*/ 93 if (trn_cell_establish_intro_getlen_auth_key(cell) != ED25519_PUBKEY_LEN || 94 trn_cell_establish_intro_get_auth_key_len(cell) != ED25519_PUBKEY_LEN) { 95 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, 96 "ESTABLISH_INTRO auth key length is invalid"); 97 return -1; 98 } 99 100 const uint8_t *msg = cell->start_cell; 101 102 /* Verify the sig */ 103 { 104 ed25519_signature_t sig_struct; 105 const uint8_t *sig_array = 106 trn_cell_establish_intro_getconstarray_sig(cell); 107 108 /* Make sure the signature length is of the right size. For EXTRA safety, 109 * we check both the size of the array and the length which must be the 110 * same. Safety first!*/ 111 if (trn_cell_establish_intro_getlen_sig(cell) != sizeof(sig_struct.sig) || 112 trn_cell_establish_intro_get_sig_len(cell) != sizeof(sig_struct.sig)) { 113 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, 114 "ESTABLISH_INTRO sig len is invalid"); 115 return -1; 116 } 117 /* We are now sure that sig_len is of the right size. */ 118 memcpy(sig_struct.sig, sig_array, cell->sig_len); 119 120 ed25519_public_key_t auth_key; 121 get_auth_key_from_cell(&auth_key, RELAY_COMMAND_ESTABLISH_INTRO, cell); 122 123 const size_t sig_msg_len = cell->end_sig_fields - msg; 124 int sig_mismatch = ed25519_checksig_prefixed(&sig_struct, 125 msg, sig_msg_len, 126 ESTABLISH_INTRO_SIG_PREFIX, 127 &auth_key); 128 if (sig_mismatch) { 129 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, 130 "ESTABLISH_INTRO signature not as expected"); 131 return -1; 132 } 133 } 134 135 /* Verify the MAC */ 136 { 137 const size_t auth_msg_len = cell->end_mac_fields - msg; 138 uint8_t mac[DIGEST256_LEN]; 139 crypto_mac_sha3_256(mac, sizeof(mac), 140 circuit_key_material, circuit_key_material_len, 141 msg, auth_msg_len); 142 if (tor_memneq(mac, cell->handshake_mac, sizeof(mac))) { 143 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, 144 "ESTABLISH_INTRO handshake_auth not as expected"); 145 return -1; 146 } 147 } 148 149 return 0; 150 } 151 152 /** Send an INTRO_ESTABLISHED cell to <b>circ</b>. */ 153 MOCK_IMPL(int, 154 hs_intro_send_intro_established_cell,(or_circuit_t *circ)) 155 { 156 int ret; 157 uint8_t *encoded_cell = NULL; 158 ssize_t encoded_len, result_len; 159 trn_cell_intro_established_t *cell; 160 trn_extension_t *ext; 161 162 tor_assert(circ); 163 164 /* Build the cell payload. */ 165 cell = trn_cell_intro_established_new(); 166 ext = trn_extension_new(); 167 trn_extension_set_num(ext, 0); 168 trn_cell_intro_established_set_extensions(cell, ext); 169 /* Encode the cell to binary format. */ 170 encoded_len = trn_cell_intro_established_encoded_len(cell); 171 tor_assert(encoded_len > 0); 172 encoded_cell = tor_malloc_zero(encoded_len); 173 result_len = trn_cell_intro_established_encode(encoded_cell, encoded_len, 174 cell); 175 tor_assert(encoded_len == result_len); 176 177 ret = relay_send_command_from_edge(0, TO_CIRCUIT(circ), 178 RELAY_COMMAND_INTRO_ESTABLISHED, 179 (char *) encoded_cell, encoded_len, 180 NULL); 181 /* On failure, the above function will close the circuit. */ 182 trn_cell_intro_established_free(cell); 183 tor_free(encoded_cell); 184 return ret; 185 } 186 187 /** Validate the cell DoS extension parameters. Return true iff they've been 188 * bound check and can be used. Else return false. See proposal 305 for 189 * details and reasons about this validation. */ 190 STATIC bool 191 cell_dos_extension_parameters_are_valid(uint64_t intro2_rate_per_sec, 192 uint64_t intro2_burst_per_sec) 193 { 194 bool ret = false; 195 196 /* Check that received value is not below the minimum. Don't check if minimum 197 is set to 0, since the param is a positive value and gcc will complain. */ 198 #if HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_MIN > 0 199 if (intro2_rate_per_sec < HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_MIN) { 200 log_fn(LOG_PROTOCOL_WARN, LD_REND, 201 "Intro point DoS defenses rate per second is " 202 "too small. Received value: %" PRIu64, intro2_rate_per_sec); 203 goto end; 204 } 205 #endif /* HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_MIN > 0 */ 206 207 /* Check that received value is not above maximum */ 208 if (intro2_rate_per_sec > HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_MAX) { 209 log_fn(LOG_PROTOCOL_WARN, LD_REND, 210 "Intro point DoS defenses rate per second is " 211 "too big. Received value: %" PRIu64, intro2_rate_per_sec); 212 goto end; 213 } 214 215 /* Check that received value is not below the minimum */ 216 #if HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_MIN > 0 217 if (intro2_burst_per_sec < HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_MIN) { 218 log_fn(LOG_PROTOCOL_WARN, LD_REND, 219 "Intro point DoS defenses burst per second is " 220 "too small. Received value: %" PRIu64, intro2_burst_per_sec); 221 goto end; 222 } 223 #endif /* HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_MIN > 0 */ 224 225 /* Check that received value is not above maximum */ 226 if (intro2_burst_per_sec > HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_MAX) { 227 log_fn(LOG_PROTOCOL_WARN, LD_REND, 228 "Intro point DoS defenses burst per second is " 229 "too big. Received value: %" PRIu64, intro2_burst_per_sec); 230 goto end; 231 } 232 233 /* In a rate limiting scenario, burst can never be smaller than the rate. At 234 * best it can be equal. */ 235 if (intro2_burst_per_sec < intro2_rate_per_sec) { 236 log_info(LD_REND, "Intro point DoS defenses burst is smaller than rate. " 237 "Rate: %" PRIu64 " vs Burst: %" PRIu64, 238 intro2_rate_per_sec, intro2_burst_per_sec); 239 goto end; 240 } 241 242 /* Passing validation. */ 243 ret = true; 244 245 end: 246 return ret; 247 } 248 249 /** Parse the cell DoS extension and apply defenses on the given circuit if 250 * validation passes. If the cell extension is malformed or contains unusable 251 * values, the DoS defenses is disabled on the circuit. */ 252 static void 253 handle_establish_intro_cell_dos_extension( 254 const trn_extension_field_t *field, 255 or_circuit_t *circ) 256 { 257 ssize_t ret; 258 uint64_t intro2_rate_per_sec = 0, intro2_burst_per_sec = 0; 259 trn_cell_extension_dos_t *dos = NULL; 260 261 tor_assert(field); 262 tor_assert(circ); 263 264 ret = trn_cell_extension_dos_parse(&dos, 265 trn_extension_field_getconstarray_field(field), 266 trn_extension_field_getlen_field(field)); 267 if (ret < 0) { 268 goto end; 269 } 270 271 for (size_t i = 0; i < trn_cell_extension_dos_get_n_params(dos); i++) { 272 const trn_cell_extension_dos_param_t *param = 273 trn_cell_extension_dos_getconst_params(dos, i); 274 if (BUG(param == NULL)) { 275 goto end; 276 } 277 278 switch (trn_cell_extension_dos_param_get_type(param)) { 279 case TRUNNEL_DOS_PARAM_TYPE_INTRO2_RATE_PER_SEC: 280 intro2_rate_per_sec = trn_cell_extension_dos_param_get_value(param); 281 break; 282 case TRUNNEL_DOS_PARAM_TYPE_INTRO2_BURST_PER_SEC: 283 intro2_burst_per_sec = trn_cell_extension_dos_param_get_value(param); 284 break; 285 default: 286 goto end; 287 } 288 } 289 290 /* At this point, the extension is valid so any values out of it implies 291 * that it was set explicitly and thus flag the circuit that it should not 292 * look at the consensus for that reason for the defenses' values. */ 293 circ->introduce2_dos_defense_explicit = 1; 294 295 /* A value of 0 is valid in the sense that we accept it but we still disable 296 * the defenses so return false. */ 297 if (intro2_rate_per_sec == 0 || intro2_burst_per_sec == 0) { 298 log_info(LD_REND, "Intro point DoS defenses parameter set to 0. " 299 "Disabling INTRO2 DoS defenses on circuit id %u", 300 circ->p_circ_id); 301 circ->introduce2_dos_defense_enabled = 0; 302 goto end; 303 } 304 305 /* If invalid, we disable the defense on the circuit. */ 306 if (!cell_dos_extension_parameters_are_valid(intro2_rate_per_sec, 307 intro2_burst_per_sec)) { 308 circ->introduce2_dos_defense_enabled = 0; 309 log_info(LD_REND, "Disabling INTRO2 DoS defenses on circuit id %u", 310 circ->p_circ_id); 311 goto end; 312 } 313 314 /* We passed validation, enable defenses and apply rate/burst. */ 315 circ->introduce2_dos_defense_enabled = 1; 316 317 /* Initialize the INTRODUCE2 token bucket for the rate limiting. */ 318 token_bucket_ctr_init(&circ->introduce2_bucket, 319 (uint32_t) intro2_rate_per_sec, 320 (uint32_t) intro2_burst_per_sec, 321 (uint32_t) monotime_coarse_absolute_sec()); 322 log_info(LD_REND, "Intro point DoS defenses enabled. Rate is %" PRIu64 323 " and Burst is %" PRIu64, 324 intro2_rate_per_sec, intro2_burst_per_sec); 325 326 end: 327 trn_cell_extension_dos_free(dos); 328 return; 329 } 330 331 /** Parse every cell extension in the given ESTABLISH_INTRO cell. */ 332 static void 333 handle_establish_intro_cell_extensions( 334 const trn_cell_establish_intro_t *parsed_cell, 335 or_circuit_t *circ) 336 { 337 const trn_extension_t *extensions; 338 339 tor_assert(parsed_cell); 340 tor_assert(circ); 341 342 extensions = trn_cell_establish_intro_getconst_extensions(parsed_cell); 343 if (extensions == NULL) { 344 goto end; 345 } 346 347 /* Go over all extensions. */ 348 for (size_t idx = 0; idx < trn_extension_get_num(extensions); idx++) { 349 const trn_extension_field_t *field = 350 trn_extension_getconst_fields(extensions, idx); 351 if (BUG(field == NULL)) { 352 /* The number of extensions should match the number of fields. */ 353 break; 354 } 355 356 switch (trn_extension_field_get_field_type(field)) { 357 case TRUNNEL_CELL_EXTENSION_TYPE_DOS: 358 /* After this, the circuit should be set for DoS defenses. */ 359 handle_establish_intro_cell_dos_extension(field, circ); 360 break; 361 default: 362 /* Unknown extension. Skip over. */ 363 break; 364 } 365 } 366 367 end: 368 return; 369 } 370 371 /** We received an ESTABLISH_INTRO <b>parsed_cell</b> on <b>circ</b>. It's 372 * well-formed and passed our verifications. Perform appropriate actions to 373 * establish an intro point. */ 374 static int 375 handle_verified_establish_intro_cell(or_circuit_t *circ, 376 const trn_cell_establish_intro_t *parsed_cell) 377 { 378 /* Get the auth key of this intro point */ 379 ed25519_public_key_t auth_key; 380 get_auth_key_from_cell(&auth_key, RELAY_COMMAND_ESTABLISH_INTRO, 381 parsed_cell); 382 383 /* Setup INTRODUCE2 defenses on the circuit. Must be done before parsing the 384 * cell extension that can possibly change the defenses' values. */ 385 hs_dos_setup_default_intro2_defenses(circ); 386 387 /* Handle cell extension if any. */ 388 handle_establish_intro_cell_extensions(parsed_cell, circ); 389 390 /* Then notify the hidden service that the intro point is established by 391 sending an INTRO_ESTABLISHED cell */ 392 if (hs_intro_send_intro_established_cell(circ)) { 393 log_warn(LD_PROTOCOL, "Couldn't send INTRO_ESTABLISHED cell."); 394 return -1; 395 } 396 397 /* Associate intro point auth key with this circuit. */ 398 hs_circuitmap_register_intro_circ_v3_relay_side(circ, &auth_key); 399 /* Repurpose this circuit into an intro circuit. */ 400 circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_INTRO_POINT); 401 402 return 0; 403 } 404 405 /** We just received an ESTABLISH_INTRO cell in <b>circ</b> with payload in 406 * <b>request</b>. Handle it by making <b>circ</b> an intro circuit. Return 0 407 * if everything went well, or -1 if there were errors. */ 408 static int 409 handle_establish_intro(or_circuit_t *circ, const uint8_t *request, 410 size_t request_len) 411 { 412 int cell_ok, retval = -1; 413 trn_cell_establish_intro_t *parsed_cell = NULL; 414 415 tor_assert(circ); 416 tor_assert(request); 417 418 log_info(LD_REND, "Received an ESTABLISH_INTRO request on circuit %" PRIu32, 419 circ->p_circ_id); 420 421 /* Check that the circuit is in shape to become an intro point */ 422 if (!hs_intro_circuit_is_suitable_for_establish_intro(circ)) { 423 relay_increment_est_intro_action(EST_INTRO_UNSUITABLE_CIRCUIT); 424 goto err; 425 } 426 427 /* Parse the cell */ 428 ssize_t parsing_result = trn_cell_establish_intro_parse(&parsed_cell, 429 request, request_len); 430 if (parsing_result < 0) { 431 relay_increment_est_intro_action(EST_INTRO_MALFORMED); 432 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, 433 "Rejecting %s ESTABLISH_INTRO cell.", 434 parsing_result == -1 ? "invalid" : "truncated"); 435 goto err; 436 } 437 438 cell_ok = verify_establish_intro_cell(parsed_cell, 439 (uint8_t *) circ->rend_circ_nonce, 440 sizeof(circ->rend_circ_nonce)); 441 if (cell_ok < 0) { 442 relay_increment_est_intro_action(EST_INTRO_MALFORMED); 443 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, 444 "Failed to verify ESTABLISH_INTRO cell."); 445 goto err; 446 } 447 448 /* This cell is legit. Take the appropriate actions. */ 449 cell_ok = handle_verified_establish_intro_cell(circ, parsed_cell); 450 if (cell_ok < 0) { 451 relay_increment_est_intro_action(EST_INTRO_CIRCUIT_DEAD); 452 goto err; 453 } 454 455 relay_increment_est_intro_action(EST_INTRO_SUCCESS); 456 /* We are done! */ 457 retval = 0; 458 goto done; 459 460 err: 461 /* When sending the intro establish ack, on error the circuit can be marked 462 * as closed so avoid a double close. */ 463 if (!TO_CIRCUIT(circ)->marked_for_close) { 464 circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL); 465 } 466 467 done: 468 trn_cell_establish_intro_free(parsed_cell); 469 return retval; 470 } 471 472 /** Return True if circuit is suitable for being an intro circuit. */ 473 static int 474 circuit_is_suitable_intro_point(const or_circuit_t *circ, 475 const char *log_cell_type_str) 476 { 477 tor_assert(circ); 478 tor_assert(log_cell_type_str); 479 480 /* Basic circuit state sanity checks. */ 481 if (circ->base_.purpose != CIRCUIT_PURPOSE_OR) { 482 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, 483 "Rejecting %s on non-OR circuit.", log_cell_type_str); 484 return 0; 485 } 486 487 if (circ->base_.n_chan) { 488 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, 489 "Rejecting %s on non-edge circuit.", log_cell_type_str); 490 return 0; 491 } 492 493 /* Suitable. */ 494 return 1; 495 } 496 497 /** Return True if circuit is suitable for being service-side intro circuit. */ 498 int 499 hs_intro_circuit_is_suitable_for_establish_intro(const or_circuit_t *circ) 500 { 501 return circuit_is_suitable_intro_point(circ, "ESTABLISH_INTRO"); 502 } 503 504 /** We just received an ESTABLISH_INTRO cell in <b>circ</b>. Pass it to the 505 * appropriate handler. */ 506 int 507 hs_intro_received_establish_intro(or_circuit_t *circ, const uint8_t *request, 508 size_t request_len) 509 { 510 tor_assert(circ); 511 tor_assert(request); 512 513 if (request_len == 0) { 514 relay_increment_est_intro_action(EST_INTRO_MALFORMED); 515 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Empty ESTABLISH_INTRO cell."); 516 goto err; 517 } 518 519 /* Using the first byte of the cell, figure out the version of 520 * ESTABLISH_INTRO and pass it to the appropriate cell handler */ 521 const uint8_t first_byte = request[0]; 522 switch (first_byte) { 523 case TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0: 524 case TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1: 525 /* Likely version 2 onion service which is now obsolete. Avoid a 526 * protocol warning considering they still exists on the network. */ 527 relay_increment_est_intro_action(EST_INTRO_MALFORMED); 528 goto err; 529 case TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519: 530 return handle_establish_intro(circ, request, request_len); 531 default: 532 relay_increment_est_intro_action(EST_INTRO_MALFORMED); 533 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, 534 "Unrecognized AUTH_KEY_TYPE %u.", first_byte); 535 goto err; 536 } 537 538 err: 539 circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL); 540 return -1; 541 } 542 543 /** Send an INTRODUCE_ACK cell onto the circuit <b>circ</b> with the status 544 * value in <b>status</b>. Depending on the status, it can be ACK or a NACK. 545 * Return 0 on success else a negative value on error which will close the 546 * circuit. */ 547 static int 548 send_introduce_ack_cell(or_circuit_t *circ, uint16_t status) 549 { 550 int ret = -1; 551 uint8_t *encoded_cell = NULL; 552 ssize_t encoded_len, result_len; 553 trn_cell_introduce_ack_t *cell; 554 trn_extension_t *ext; 555 556 tor_assert(circ); 557 558 /* Setup the INTRODUCE_ACK cell. We have no extensions so the N_EXTENSIONS 559 * field is set to 0 by default with a new object. */ 560 cell = trn_cell_introduce_ack_new(); 561 ret = trn_cell_introduce_ack_set_status(cell, status); 562 /* We have no cell extensions in an INTRODUCE_ACK cell. */ 563 ext = trn_extension_new(); 564 trn_extension_set_num(ext, 0); 565 trn_cell_introduce_ack_set_extensions(cell, ext); 566 /* A wrong status is a very bad code flow error as this value is controlled 567 * by the code in this file and not an external input. This means we use a 568 * code that is not known by the trunnel ABI. */ 569 tor_assert(ret == 0); 570 /* Encode the payload. We should never fail to get the encoded length. */ 571 encoded_len = trn_cell_introduce_ack_encoded_len(cell); 572 tor_assert(encoded_len > 0); 573 encoded_cell = tor_malloc_zero(encoded_len); 574 result_len = trn_cell_introduce_ack_encode(encoded_cell, encoded_len, cell); 575 tor_assert(encoded_len == result_len); 576 577 ret = relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ), 578 RELAY_COMMAND_INTRODUCE_ACK, 579 (char *) encoded_cell, encoded_len, 580 NULL); 581 /* On failure, the above function will close the circuit. */ 582 trn_cell_introduce_ack_free(cell); 583 tor_free(encoded_cell); 584 return ret; 585 } 586 587 /** Validate a parsed INTRODUCE1 <b>cell</b>. Return 0 if valid or else a 588 * negative value for an invalid cell that should be NACKed. */ 589 STATIC int 590 validate_introduce1_parsed_cell(const trn_cell_introduce1_t *cell) 591 { 592 size_t legacy_key_id_len; 593 const uint8_t *legacy_key_id; 594 595 tor_assert(cell); 596 597 /* This code path SHOULD NEVER be reached if the cell is a legacy type so 598 * safety net here. The legacy ID must be zeroes in this case. */ 599 legacy_key_id_len = trn_cell_introduce1_getlen_legacy_key_id(cell); 600 legacy_key_id = trn_cell_introduce1_getconstarray_legacy_key_id(cell); 601 if (BUG(!fast_mem_is_zero((char *) legacy_key_id, legacy_key_id_len))) { 602 goto invalid; 603 } 604 605 /* The auth key of an INTRODUCE1 should be of type ed25519 thus leading to a 606 * known fixed length as well. */ 607 if (trn_cell_introduce1_get_auth_key_type(cell) != 608 TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519) { 609 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, 610 "Rejecting invalid INTRODUCE1 cell auth key type. " 611 "Responding with NACK."); 612 goto invalid; 613 } 614 if (trn_cell_introduce1_get_auth_key_len(cell) != ED25519_PUBKEY_LEN || 615 trn_cell_introduce1_getlen_auth_key(cell) != ED25519_PUBKEY_LEN) { 616 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, 617 "Rejecting invalid INTRODUCE1 cell auth key length. " 618 "Responding with NACK."); 619 goto invalid; 620 } 621 if (trn_cell_introduce1_getlen_encrypted(cell) == 0) { 622 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, 623 "Rejecting invalid INTRODUCE1 cell encrypted length. " 624 "Responding with NACK."); 625 goto invalid; 626 } 627 628 return 0; 629 invalid: 630 return -1; 631 } 632 633 /** We just received a non legacy INTRODUCE1 cell on <b>client_circ</b> with 634 * the payload in <b>request</b> of size <b>request_len</b>. Return 0 if 635 * everything went well, or -1 if an error occurred. This function is in charge 636 * of sending back an INTRODUCE_ACK cell and will close client_circ on error. 637 */ 638 STATIC int 639 handle_introduce1(or_circuit_t *client_circ, const uint8_t *request, 640 size_t request_len) 641 { 642 int ret = -1; 643 or_circuit_t *service_circ; 644 trn_cell_introduce1_t *parsed_cell; 645 uint16_t status = TRUNNEL_HS_INTRO_ACK_STATUS_SUCCESS; 646 647 tor_assert(client_circ); 648 tor_assert(request); 649 650 /* Parse cell. Note that we can only parse the non encrypted section for 651 * which we'll use the authentication key to find the service introduction 652 * circuit and relay the cell on it. */ 653 ssize_t cell_size = trn_cell_introduce1_parse(&parsed_cell, request, 654 request_len); 655 if (cell_size < 0) { 656 relay_increment_intro1_action(INTRO1_MALFORMED); 657 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, 658 "Rejecting %s INTRODUCE1 cell. Responding with NACK.", 659 cell_size == -1 ? "invalid" : "truncated"); 660 /* Inform client that the INTRODUCE1 has a bad format. */ 661 status = TRUNNEL_HS_INTRO_ACK_STATUS_BAD_FORMAT; 662 goto send_ack; 663 } 664 665 /* Once parsed validate the cell format. */ 666 if (validate_introduce1_parsed_cell(parsed_cell) < 0) { 667 relay_increment_intro1_action(INTRO1_MALFORMED); 668 /* Inform client that the INTRODUCE1 has bad format. */ 669 status = TRUNNEL_HS_INTRO_ACK_STATUS_BAD_FORMAT; 670 goto send_ack; 671 } 672 673 /* Find introduction circuit through our circuit map. */ 674 { 675 ed25519_public_key_t auth_key; 676 get_auth_key_from_cell(&auth_key, RELAY_COMMAND_INTRODUCE1, parsed_cell); 677 service_circ = hs_circuitmap_get_intro_circ_v3_relay_side(&auth_key); 678 if (service_circ == NULL) { 679 relay_increment_intro1_action(INTRO1_UNKNOWN_SERVICE); 680 char b64_key[ED25519_BASE64_LEN + 1]; 681 ed25519_public_to_base64(b64_key, &auth_key); 682 log_info(LD_REND, "No intro circuit found for INTRODUCE1 cell " 683 "with auth key %s from circuit %" PRIu32 ". " 684 "Responding with NACK.", 685 safe_str(b64_key), client_circ->p_circ_id); 686 /* Inform the client that we don't know the requested service ID. */ 687 status = TRUNNEL_HS_INTRO_ACK_STATUS_UNKNOWN_ID; 688 goto send_ack; 689 } 690 } 691 692 /* Before sending, lets make sure this cell can be sent on the service 693 * circuit asking the DoS defenses. */ 694 if (!hs_dos_can_send_intro2(service_circ)) { 695 relay_increment_intro1_action(INTRO1_RATE_LIMITED); 696 char *msg; 697 static ratelim_t rlimit = RATELIM_INIT(5 * 60); 698 if ((msg = rate_limit_log(&rlimit, approx_time()))) { 699 log_info(LD_PROTOCOL, "Can't relay INTRODUCE1 v3 cell due to DoS " 700 "limitations. Sending NACK to client."); 701 tor_free(msg); 702 } 703 status = TRUNNEL_HS_INTRO_ACK_STATUS_UNKNOWN_ID; 704 goto send_ack; 705 } 706 707 /* Relay the cell to the service on its intro circuit with an INTRODUCE2 708 * cell which is the same exact payload. */ 709 if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(service_circ), 710 RELAY_COMMAND_INTRODUCE2, 711 (char *) request, request_len, NULL)) { 712 relay_increment_intro1_action(INTRO1_CIRCUIT_DEAD); 713 /* Inform the client that we can't relay the cell. Use the unknown ID 714 * status code since it means that we do not know the service. */ 715 status = TRUNNEL_HS_INTRO_ACK_STATUS_UNKNOWN_ID; 716 goto send_ack; 717 } 718 719 relay_increment_intro1_action(INTRO1_SUCCESS); 720 /* Success! Send an INTRODUCE_ACK success status onto the client circuit. */ 721 status = TRUNNEL_HS_INTRO_ACK_STATUS_SUCCESS; 722 ret = 0; 723 724 send_ack: 725 /* Send INTRODUCE_ACK or INTRODUCE_NACK to client */ 726 if (send_introduce_ack_cell(client_circ, status) < 0) { 727 log_warn(LD_PROTOCOL, "Unable to send an INTRODUCE ACK status %d " 728 "to client.", status); 729 /* Circuit has been closed on failure of transmission. */ 730 goto done; 731 } 732 done: 733 trn_cell_introduce1_free(parsed_cell); 734 return ret; 735 } 736 737 /** Return true iff the circuit <b>circ</b> is suitable for receiving an 738 * INTRODUCE1 cell. */ 739 STATIC int 740 circuit_is_suitable_for_introduce1(const or_circuit_t *circ) 741 { 742 tor_assert(circ); 743 744 /* Is this circuit an intro point circuit? */ 745 if (!circuit_is_suitable_intro_point(circ, "INTRODUCE1")) { 746 return 0; 747 } 748 749 if (circ->already_received_introduce1) { 750 relay_increment_intro1_action(INTRO1_CIRCUIT_REUSED); 751 log_fn(LOG_PROTOCOL_WARN, LD_REND, 752 "Blocking multiple introductions on the same circuit. " 753 "Someone might be trying to attack a hidden service through " 754 "this relay."); 755 return 0; 756 } 757 758 /* Disallow single hop client circuit. */ 759 if (circ->p_chan && channel_is_client(circ->p_chan)) { 760 relay_increment_intro1_action(INTRO1_SINGLE_HOP); 761 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, 762 "Single hop client was rejected while trying to introduce. " 763 "Closing circuit."); 764 return 0; 765 } 766 767 return 1; 768 } 769 770 /** We just received an INTRODUCE1 cell on <b>circ</b>. Figure out which type 771 * it is and pass it to the appropriate handler. Return 0 on success else a 772 * negative value and the circuit is closed. */ 773 int 774 hs_intro_received_introduce1(or_circuit_t *circ, const uint8_t *request, 775 size_t request_len) 776 { 777 tor_assert(circ); 778 tor_assert(request); 779 780 /* A cell that can't hold a DIGEST_LEN is invalid. */ 781 if (request_len < DIGEST_LEN) { 782 relay_increment_intro1_action(INTRO1_MALFORMED); 783 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Invalid INTRODUCE1 cell length."); 784 goto err; 785 } 786 787 /* Make sure we have a circuit that can have an INTRODUCE1 cell on it. */ 788 if (!circuit_is_suitable_for_introduce1(circ)) { 789 /* We do not send a NACK because the circuit is not suitable for any kind 790 * of response or transmission as it's a violation of the protocol. */ 791 goto err; 792 } 793 /* Mark the circuit that we got this cell. None are allowed after this as a 794 * DoS mitigation since one circuit with one client can hammer a service. */ 795 circ->already_received_introduce1 = 1; 796 797 /* Handle the cell. */ 798 return handle_introduce1(circ, request, request_len); 799 800 err: 801 circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL); 802 return -1; 803 } 804 805 /** Clear memory allocated by the given intropoint object ip (but don't free 806 * the object itself). */ 807 void 808 hs_intropoint_clear(hs_intropoint_t *ip) 809 { 810 if (ip == NULL) { 811 return; 812 } 813 tor_cert_free(ip->auth_key_cert); 814 SMARTLIST_FOREACH(ip->link_specifiers, link_specifier_t *, ls, 815 link_specifier_free(ls)); 816 smartlist_free(ip->link_specifiers); 817 memset(ip, 0, sizeof(hs_intropoint_t)); 818 }