ext_orport.c (22101B)
1 /* Copyright (c) 2012-2021, The Tor Project, Inc. */ 2 /* See LICENSE for licensing information */ 3 4 /** 5 * \file ext_orport.c 6 * \brief Code implementing the Extended ORPort. 7 * 8 * The Extended ORPort interface is used by pluggable transports to 9 * communicate additional information to a Tor bridge, including 10 * address information. For more information on this interface, 11 * see pt-spec.txt in torspec.git. 12 * 13 * There is no separate structure for extended ORPort connections; they use 14 * or_connection_t objects, and share most of their implementation with 15 * connection_or.c. Once the handshake is done, an extended ORPort connection 16 * turns into a regular OR connection, using connection_ext_or_transition(). 17 */ 18 19 #define EXT_ORPORT_PRIVATE 20 #include "core/or/or.h" 21 #include "core/mainloop/connection.h" 22 #include "core/or/connection_or.h" 23 #include "feature/control/control_events.h" 24 #include "app/config/config.h" 25 #include "lib/crypt_ops/crypto_rand.h" 26 #include "lib/crypt_ops/crypto_util.h" 27 #include "feature/relay/ext_orport.h" 28 #include "core/mainloop/mainloop.h" 29 #include "core/proto/proto_ext_or.h" 30 31 #include "core/or/or_connection_st.h" 32 33 /** Allocate and return a structure capable of holding an Extended 34 * ORPort message of body length <b>len</b>. */ 35 ext_or_cmd_t * 36 ext_or_cmd_new(uint16_t len) 37 { 38 size_t size = offsetof(ext_or_cmd_t, body) + len; 39 ext_or_cmd_t *cmd = tor_malloc(size); 40 cmd->len = len; 41 return cmd; 42 } 43 44 /** Deallocate the Extended ORPort message in <b>cmd</b>. */ 45 void 46 ext_or_cmd_free_(ext_or_cmd_t *cmd) 47 { 48 tor_free(cmd); 49 } 50 51 /** Get an Extended ORPort message from <b>conn</b>, and place it in 52 * <b>out</b>. Return -1 on fail, 0 if we need more data, and 1 if we 53 * successfully extracted an Extended ORPort command from the 54 * buffer. */ 55 static int 56 connection_fetch_ext_or_cmd_from_buf(connection_t *conn, ext_or_cmd_t **out) 57 { 58 return fetch_ext_or_command_from_buf(conn->inbuf, out); 59 } 60 61 /** Write an Extended ORPort message to <b>conn</b>. Use 62 * <b>command</b> as the command type, <b>bodylen</b> as the body 63 * length, and <b>body</b>, if it's present, as the body of the 64 * message. */ 65 STATIC int 66 connection_write_ext_or_command(connection_t *conn, 67 uint16_t command, 68 const char *body, 69 size_t bodylen) 70 { 71 char header[4]; 72 if (bodylen > UINT16_MAX) 73 return -1; 74 set_uint16(header, htons(command)); 75 set_uint16(header+2, htons(bodylen)); 76 connection_buf_add(header, 4, conn); 77 if (bodylen) { 78 tor_assert(body); 79 connection_buf_add(body, bodylen, conn); 80 } 81 return 0; 82 } 83 84 /** Transition from an Extended ORPort which accepts Extended ORPort 85 * messages, to an Extended ORport which accepts OR traffic. */ 86 static void 87 connection_ext_or_transition(or_connection_t *conn) 88 { 89 tor_assert(conn->base_.type == CONN_TYPE_EXT_OR); 90 91 conn->base_.type = CONN_TYPE_OR; 92 TO_CONN(conn)->state = 0; // set the state to a neutral value 93 connection_or_event_status(conn, OR_CONN_EVENT_NEW, 0); 94 connection_tls_start_handshake(conn, 1); 95 } 96 97 /** Length of authentication cookie. */ 98 #define EXT_OR_PORT_AUTH_COOKIE_LEN 32 99 /** Length of the header of the cookie file. */ 100 #define EXT_OR_PORT_AUTH_COOKIE_HEADER_LEN 32 101 /** Static cookie file header. */ 102 #define EXT_OR_PORT_AUTH_COOKIE_HEADER "! Extended ORPort Auth Cookie !\x0a" 103 /** Length of safe-cookie protocol hashes. */ 104 #define EXT_OR_PORT_AUTH_HASH_LEN DIGEST256_LEN 105 /** Length of safe-cookie protocol nonces. */ 106 #define EXT_OR_PORT_AUTH_NONCE_LEN 32 107 /** Safe-cookie protocol constants. */ 108 #define EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST \ 109 "ExtORPort authentication server-to-client hash" 110 #define EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST \ 111 "ExtORPort authentication client-to-server hash" 112 113 /* Code to indicate cookie authentication */ 114 #define EXT_OR_AUTHTYPE_SAFECOOKIE 0x01 115 116 /** If true, we've set ext_or_auth_cookie to a secret code and stored 117 * it to disk. */ 118 STATIC int ext_or_auth_cookie_is_set = 0; 119 /** If ext_or_auth_cookie_is_set, a secret cookie that we've stored to disk 120 * and which we're using to authenticate controllers. (If the controller can 121 * read it off disk, it has permission to connect.) */ 122 STATIC uint8_t *ext_or_auth_cookie = NULL; 123 124 /** Helper: Return a newly allocated string containing a path to the 125 * file where we store our authentication cookie. */ 126 char * 127 get_ext_or_auth_cookie_file_name(void) 128 { 129 const or_options_t *options = get_options(); 130 if (options->ExtORPortCookieAuthFile && 131 strlen(options->ExtORPortCookieAuthFile)) { 132 return tor_strdup(options->ExtORPortCookieAuthFile); 133 } else { 134 return get_datadir_fname("extended_orport_auth_cookie"); 135 } 136 } 137 138 /* Initialize the cookie-based authentication system of the 139 * Extended ORPort. If <b>is_enabled</b> is 0, then disable the cookie 140 * authentication system. */ 141 int 142 init_ext_or_cookie_authentication(int is_enabled) 143 { 144 char *fname = NULL; 145 int retval; 146 147 if (!is_enabled) { 148 ext_or_auth_cookie_is_set = 0; 149 return 0; 150 } 151 152 fname = get_ext_or_auth_cookie_file_name(); 153 retval = init_cookie_authentication(fname, EXT_OR_PORT_AUTH_COOKIE_HEADER, 154 EXT_OR_PORT_AUTH_COOKIE_HEADER_LEN, 155 get_options()->ExtORPortCookieAuthFileGroupReadable, 156 &ext_or_auth_cookie, 157 &ext_or_auth_cookie_is_set); 158 tor_free(fname); 159 return retval; 160 } 161 162 /** Read data from <b>conn</b> and see if the client sent us the 163 * authentication type that they prefer to use in this session. 164 * 165 * Return -1 if we received corrupted data or if we don't support the 166 * authentication type. Return 0 if we need more data in 167 * <b>conn</b>. Return 1 if the authentication type negotiation was 168 * successful. */ 169 static int 170 connection_ext_or_auth_neg_auth_type(connection_t *conn) 171 { 172 char authtype[1] = {0}; 173 174 if (connection_get_inbuf_len(conn) < 1) 175 return 0; 176 177 if (connection_buf_get_bytes(authtype, 1, conn) < 0) 178 return -1; 179 180 log_debug(LD_GENERAL, "Client wants us to use %d auth type", authtype[0]); 181 if (authtype[0] != EXT_OR_AUTHTYPE_SAFECOOKIE) { 182 /* '1' is the only auth type supported atm */ 183 return -1; 184 } 185 186 conn->state = EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE; 187 return 1; 188 } 189 190 /* DOCDOC */ 191 STATIC int 192 handle_client_auth_nonce(const char *client_nonce, size_t client_nonce_len, 193 char **client_hash_out, 194 char **reply_out, size_t *reply_len_out) 195 { 196 char server_hash[EXT_OR_PORT_AUTH_HASH_LEN] = {0}; 197 char server_nonce[EXT_OR_PORT_AUTH_NONCE_LEN] = {0}; 198 char *reply; 199 size_t reply_len; 200 201 if (client_nonce_len != EXT_OR_PORT_AUTH_NONCE_LEN) 202 return -1; 203 204 /* Get our nonce */ 205 crypto_rand(server_nonce, EXT_OR_PORT_AUTH_NONCE_LEN); 206 207 { /* set up macs */ 208 size_t hmac_s_msg_len = strlen(EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST) + 209 2*EXT_OR_PORT_AUTH_NONCE_LEN; 210 size_t hmac_c_msg_len = strlen(EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST) + 211 2*EXT_OR_PORT_AUTH_NONCE_LEN; 212 213 char *hmac_s_msg = tor_malloc_zero(hmac_s_msg_len); 214 char *hmac_c_msg = tor_malloc_zero(hmac_c_msg_len); 215 char *correct_client_hash = tor_malloc_zero(EXT_OR_PORT_AUTH_HASH_LEN); 216 217 memcpy(hmac_s_msg, 218 EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST, 219 strlen(EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST)); 220 memcpy(hmac_s_msg + strlen(EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST), 221 client_nonce, EXT_OR_PORT_AUTH_NONCE_LEN); 222 memcpy(hmac_s_msg + strlen(EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST) + 223 EXT_OR_PORT_AUTH_NONCE_LEN, 224 server_nonce, EXT_OR_PORT_AUTH_NONCE_LEN); 225 226 memcpy(hmac_c_msg, 227 EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST, 228 strlen(EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST)); 229 memcpy(hmac_c_msg + strlen(EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST), 230 client_nonce, EXT_OR_PORT_AUTH_NONCE_LEN); 231 memcpy(hmac_c_msg + strlen(EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST) + 232 EXT_OR_PORT_AUTH_NONCE_LEN, 233 server_nonce, EXT_OR_PORT_AUTH_NONCE_LEN); 234 235 crypto_hmac_sha256(server_hash, 236 (char*)ext_or_auth_cookie, 237 EXT_OR_PORT_AUTH_COOKIE_LEN, 238 hmac_s_msg, 239 hmac_s_msg_len); 240 241 crypto_hmac_sha256(correct_client_hash, 242 (char*)ext_or_auth_cookie, 243 EXT_OR_PORT_AUTH_COOKIE_LEN, 244 hmac_c_msg, 245 hmac_c_msg_len); 246 247 /* Store the client hash we generated. We will need to compare it 248 with the hash sent by the client. */ 249 *client_hash_out = correct_client_hash; 250 251 memwipe(hmac_s_msg, 0, hmac_s_msg_len); 252 memwipe(hmac_c_msg, 0, hmac_c_msg_len); 253 254 tor_free(hmac_s_msg); 255 tor_free(hmac_c_msg); 256 } 257 258 { /* debug logging */ /* XXX disable this codepath if not logging on debug?*/ 259 char server_hash_encoded[(2*EXT_OR_PORT_AUTH_HASH_LEN) + 1]; 260 char server_nonce_encoded[(2*EXT_OR_PORT_AUTH_NONCE_LEN) + 1]; 261 char client_nonce_encoded[(2*EXT_OR_PORT_AUTH_NONCE_LEN) + 1]; 262 263 base16_encode(server_hash_encoded, sizeof(server_hash_encoded), 264 server_hash, sizeof(server_hash)); 265 base16_encode(server_nonce_encoded, sizeof(server_nonce_encoded), 266 server_nonce, sizeof(server_nonce)); 267 base16_encode(client_nonce_encoded, sizeof(client_nonce_encoded), 268 client_nonce, EXT_OR_PORT_AUTH_NONCE_LEN); 269 270 log_debug(LD_GENERAL, 271 "server_hash: '%s'\nserver_nonce: '%s'\nclient_nonce: '%s'", 272 server_hash_encoded, server_nonce_encoded, client_nonce_encoded); 273 274 memwipe(server_hash_encoded, 0, sizeof(server_hash_encoded)); 275 memwipe(server_nonce_encoded, 0, sizeof(server_nonce_encoded)); 276 memwipe(client_nonce_encoded, 0, sizeof(client_nonce_encoded)); 277 } 278 279 { /* write reply: (server_hash, server_nonce) */ 280 281 reply_len = EXT_OR_PORT_AUTH_COOKIE_LEN+EXT_OR_PORT_AUTH_NONCE_LEN; 282 reply = tor_malloc_zero(reply_len); 283 memcpy(reply, server_hash, EXT_OR_PORT_AUTH_HASH_LEN); 284 memcpy(reply + EXT_OR_PORT_AUTH_HASH_LEN, server_nonce, 285 EXT_OR_PORT_AUTH_NONCE_LEN); 286 } 287 288 *reply_out = reply; 289 *reply_len_out = reply_len; 290 291 return 0; 292 } 293 294 /** Read the client's nonce out of <b>conn</b>, setup the safe-cookie 295 * crypto, and then send our own hash and nonce to the client 296 * 297 * Return -1 if there was an error; return 0 if we need more data in 298 * <b>conn</b>, and return 1 if we successfully retrieved the 299 * client's nonce and sent our own. */ 300 static int 301 connection_ext_or_auth_handle_client_nonce(connection_t *conn) 302 { 303 char client_nonce[EXT_OR_PORT_AUTH_NONCE_LEN]; 304 char *reply=NULL; 305 size_t reply_len=0; 306 307 if (!ext_or_auth_cookie_is_set) { /* this should not happen */ 308 log_warn(LD_BUG, "Extended ORPort authentication cookie was not set. " 309 "That's weird since we should have done that on startup. " 310 "This might be a Tor bug, please file a bug report. "); 311 return -1; 312 } 313 314 if (connection_get_inbuf_len(conn) < EXT_OR_PORT_AUTH_NONCE_LEN) 315 return 0; 316 317 if (connection_buf_get_bytes(client_nonce, 318 EXT_OR_PORT_AUTH_NONCE_LEN, conn) < 0) 319 return -1; 320 321 /* We extract the ClientNonce from the received data, and use it to 322 calculate ServerHash and ServerNonce according to proposal 217. 323 324 We also calculate our own ClientHash value and save it in the 325 connection state. We validate it later against the ClientHash 326 sent by the client. */ 327 if (handle_client_auth_nonce(client_nonce, sizeof(client_nonce), 328 &TO_OR_CONN(conn)->ext_or_auth_correct_client_hash, 329 &reply, &reply_len) < 0) 330 return -1; 331 332 connection_buf_add(reply, reply_len, conn); 333 334 memwipe(reply, 0, reply_len); 335 tor_free(reply); 336 337 log_debug(LD_GENERAL, "Got client nonce, and sent our own nonce and hash."); 338 339 conn->state = EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_HASH; 340 return 1; 341 } 342 343 #define connection_ext_or_auth_send_result_success(c) \ 344 connection_ext_or_auth_send_result(c, 1) 345 #define connection_ext_or_auth_send_result_fail(c) \ 346 connection_ext_or_auth_send_result(c, 0) 347 348 /** Send authentication results to <b>conn</b>. Successful results if 349 * <b>success</b> is set; failure results otherwise. */ 350 static void 351 connection_ext_or_auth_send_result(connection_t *conn, int success) 352 { 353 if (success) 354 connection_buf_add("\x01", 1, conn); 355 else 356 connection_buf_add("\x00", 1, conn); 357 } 358 359 /** Receive the client's hash from <b>conn</b>, validate that it's 360 * correct, and then send the authentication results to the client. 361 * 362 * Return -1 if there was an error during validation; return 0 if we 363 * need more data in <b>conn</b>, and return 1 if we successfully 364 * validated the client's hash and sent a happy authentication 365 * result. */ 366 static int 367 connection_ext_or_auth_handle_client_hash(connection_t *conn) 368 { 369 char provided_client_hash[EXT_OR_PORT_AUTH_HASH_LEN] = {0}; 370 371 if (connection_get_inbuf_len(conn) < EXT_OR_PORT_AUTH_HASH_LEN) 372 return 0; 373 374 if (connection_buf_get_bytes(provided_client_hash, 375 EXT_OR_PORT_AUTH_HASH_LEN, conn) < 0) 376 return -1; 377 378 if (tor_memneq(TO_OR_CONN(conn)->ext_or_auth_correct_client_hash, 379 provided_client_hash, EXT_OR_PORT_AUTH_HASH_LEN)) { 380 log_warn(LD_GENERAL, "Incorrect client hash. Authentication failed."); 381 connection_ext_or_auth_send_result_fail(conn); 382 return -1; 383 } 384 385 log_debug(LD_GENERAL, "Got client's hash and it was legit."); 386 387 /* send positive auth result */ 388 connection_ext_or_auth_send_result_success(conn); 389 conn->state = EXT_OR_CONN_STATE_OPEN; 390 return 1; 391 } 392 393 /** Handle data from <b>or_conn</b> received on Extended ORPort. 394 * Return -1 on error. 0 on insufficient data. 1 on correct. */ 395 static int 396 connection_ext_or_auth_process_inbuf(or_connection_t *or_conn) 397 { 398 connection_t *conn = TO_CONN(or_conn); 399 400 /* State transitions of the Extended ORPort authentication protocol: 401 402 EXT_OR_CONN_STATE_AUTH_WAIT_AUTH_TYPE (start state) -> 403 EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE -> 404 EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_HASH -> 405 EXT_OR_CONN_STATE_OPEN 406 407 During EXT_OR_CONN_STATE_OPEN, data is handled by 408 connection_ext_or_process_inbuf(). 409 */ 410 411 switch (conn->state) { /* Functionify */ 412 case EXT_OR_CONN_STATE_AUTH_WAIT_AUTH_TYPE: 413 return connection_ext_or_auth_neg_auth_type(conn); 414 415 case EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE: 416 return connection_ext_or_auth_handle_client_nonce(conn); 417 418 case EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_HASH: 419 return connection_ext_or_auth_handle_client_hash(conn); 420 421 default: 422 log_warn(LD_BUG, "Encountered unexpected connection state %d while trying " 423 "to process Extended ORPort authentication data.", conn->state); 424 return -1; 425 } 426 } 427 428 /** Extended ORPort commands (Transport-to-Bridge) */ 429 #define EXT_OR_CMD_TB_DONE 0x0000 430 #define EXT_OR_CMD_TB_USERADDR 0x0001 431 #define EXT_OR_CMD_TB_TRANSPORT 0x0002 432 433 /** Extended ORPort commands (Bridge-to-Transport) */ 434 #define EXT_OR_CMD_BT_OKAY 0x1000 435 #define EXT_OR_CMD_BT_DENY 0x1001 436 #define EXT_OR_CMD_BT_CONTROL 0x1002 437 438 /** Process a USERADDR command from the Extended 439 * ORPort. <b>payload</b> is a payload of size <b>len</b>. 440 * 441 * If the USERADDR command was well formed, change the address of 442 * <b>conn</b> to the address on the USERADDR command. 443 * 444 * Return 0 on success and -1 on error. */ 445 static int 446 connection_ext_or_handle_cmd_useraddr(connection_t *conn, 447 const char *payload, uint16_t len) 448 { 449 /* Copy address string. */ 450 tor_addr_t addr; 451 uint16_t port; 452 char *addr_str; 453 char *address_part=NULL; 454 int res; 455 if (memchr(payload, '\0', len)) { 456 log_fn(LOG_PROTOCOL_WARN, LD_NET, "Unexpected NUL in ExtORPort UserAddr"); 457 return -1; 458 } 459 460 addr_str = tor_memdup_nulterm(payload, len); 461 462 res = tor_addr_port_split(LOG_INFO, addr_str, &address_part, &port); 463 tor_free(addr_str); 464 if (res<0) 465 return -1; 466 if (port == 0) { 467 log_warn(LD_GENERAL, "Server transport proxy gave us an empty port " 468 "in ExtORPort UserAddr command."); 469 // return -1; // enable this if nothing breaks after a while. 470 } 471 472 res = tor_addr_parse(&addr, address_part); 473 tor_free(address_part); 474 if (res<0) 475 return -1; 476 477 { /* do some logging */ 478 char *old_address = tor_addr_to_str_dup(&conn->addr); 479 char *new_address = tor_addr_to_str_dup(&addr); 480 481 log_debug(LD_NET, "Received USERADDR." 482 "We rewrite our address from '%s:%u' to '%s:%u'.", 483 safe_str(old_address), conn->port, safe_str(new_address), port); 484 485 tor_free(old_address); 486 tor_free(new_address); 487 } 488 489 /* record the address */ 490 tor_addr_copy(&conn->addr, &addr); 491 conn->port = port; 492 if (conn->address) { 493 tor_free(conn->address); 494 } 495 conn->address = tor_addr_to_str_dup(&addr); 496 497 /* Now that we know the address, we don't have to manually override rate 498 * limiting. */ 499 conn->always_rate_limit_as_remote = 0; 500 501 return 0; 502 } 503 504 /** Process a TRANSPORT command from the Extended 505 * ORPort. <b>payload</b> is a payload of size <b>len</b>. 506 * 507 * If the TRANSPORT command was well formed, register the name of the 508 * transport on <b>conn</b>. 509 * 510 * Return 0 on success and -1 on error. */ 511 static int 512 connection_ext_or_handle_cmd_transport(or_connection_t *conn, 513 const char *payload, uint16_t len) 514 { 515 char *transport_str; 516 if (memchr(payload, '\0', len)) { 517 log_fn(LOG_PROTOCOL_WARN, LD_NET, "Unexpected NUL in ExtORPort Transport"); 518 return -1; 519 } 520 521 transport_str = tor_memdup_nulterm(payload, len); 522 523 /* Transport names MUST be C-identifiers. */ 524 if (!string_is_C_identifier(transport_str)) { 525 tor_free(transport_str); 526 return -1; 527 } 528 529 /* If ext_or_transport is already occupied (because the PT sent two 530 * TRANSPORT commands), deallocate the old name and keep the new 531 * one */ 532 if (conn->ext_or_transport) 533 tor_free(conn->ext_or_transport); 534 535 conn->ext_or_transport = transport_str; 536 return 0; 537 } 538 539 #define EXT_OR_CONN_STATE_IS_AUTHENTICATING(st) \ 540 ((st) <= EXT_OR_CONN_STATE_AUTH_MAX) 541 542 /** Process Extended ORPort messages from <b>or_conn</b>. */ 543 int 544 connection_ext_or_process_inbuf(or_connection_t *or_conn) 545 { 546 connection_t *conn = TO_CONN(or_conn); 547 ext_or_cmd_t *command; 548 int r; 549 550 /* DOCDOC Document the state machine and transitions in this function */ 551 552 /* If we are still in the authentication stage, process traffic as 553 authentication data: */ 554 while (EXT_OR_CONN_STATE_IS_AUTHENTICATING(conn->state)) { 555 log_debug(LD_GENERAL, "Got Extended ORPort authentication data (%u).", 556 (unsigned int) connection_get_inbuf_len(conn)); 557 r = connection_ext_or_auth_process_inbuf(or_conn); 558 if (r < 0) { 559 connection_mark_for_close(conn); 560 return -1; 561 } else if (r == 0) { 562 return 0; 563 } 564 /* if r > 0, loop and process more data (if any). */ 565 } 566 567 while (1) { 568 log_debug(LD_GENERAL, "Got Extended ORPort data."); 569 command = NULL; 570 r = connection_fetch_ext_or_cmd_from_buf(conn, &command); 571 if (r < 0) 572 goto err; 573 else if (r == 0) 574 return 0; /* need to wait for more data */ 575 576 /* Got a command! */ 577 tor_assert(command); 578 579 if (command->cmd == EXT_OR_CMD_TB_DONE) { 580 if (connection_get_inbuf_len(conn)) { 581 /* The inbuf isn't empty; the client is misbehaving. */ 582 goto err; 583 } 584 585 log_debug(LD_NET, "Received DONE."); 586 587 /* If the transport proxy did not use the TRANSPORT command to 588 * specify the transport name, mark this as unknown transport. */ 589 if (!or_conn->ext_or_transport) { 590 /* We write this string this way to avoid ??>, which is a C 591 * trigraph. */ 592 or_conn->ext_or_transport = tor_strdup("<?" "?>"); 593 } 594 595 connection_write_ext_or_command(conn, EXT_OR_CMD_BT_OKAY, NULL, 0); 596 597 /* can't transition immediately; need to flush first. */ 598 conn->state = EXT_OR_CONN_STATE_FLUSHING; 599 connection_stop_reading(conn); 600 } else if (command->cmd == EXT_OR_CMD_TB_USERADDR) { 601 if (connection_ext_or_handle_cmd_useraddr(conn, 602 command->body, command->len) < 0) 603 goto err; 604 } else if (command->cmd == EXT_OR_CMD_TB_TRANSPORT) { 605 if (connection_ext_or_handle_cmd_transport(or_conn, 606 command->body, command->len) < 0) 607 goto err; 608 } else { 609 log_notice(LD_NET,"Got Extended ORPort command we don't recognize (%u).", 610 command->cmd); 611 } 612 613 ext_or_cmd_free(command); 614 } 615 616 return 0; 617 618 err: 619 ext_or_cmd_free(command); 620 connection_mark_for_close(conn); 621 return -1; 622 } 623 624 /** <b>conn</b> finished flushing Extended ORPort messages to the 625 * network, and is now ready to accept OR traffic. This function 626 * does the transition. */ 627 int 628 connection_ext_or_finished_flushing(or_connection_t *conn) 629 { 630 if (conn->base_.state == EXT_OR_CONN_STATE_FLUSHING) { 631 connection_start_reading(TO_CONN(conn)); 632 connection_ext_or_transition(conn); 633 } 634 return 0; 635 } 636 637 /** Initiate Extended ORPort authentication, by sending the list of 638 * supported authentication types to the client. */ 639 int 640 connection_ext_or_start_auth(or_connection_t *or_conn) 641 { 642 connection_t *conn = TO_CONN(or_conn); 643 const uint8_t authtypes[] = { 644 /* We only support authtype '1' for now. */ 645 EXT_OR_AUTHTYPE_SAFECOOKIE, 646 /* Marks the end of the list. */ 647 0 648 }; 649 650 log_debug(LD_GENERAL, 651 "ExtORPort authentication: Sending supported authentication types"); 652 653 connection_buf_add((const char *)authtypes, sizeof(authtypes), conn); 654 conn->state = EXT_OR_CONN_STATE_AUTH_WAIT_AUTH_TYPE; 655 656 return 0; 657 } 658 659 /** Free any leftover allocated memory of the ext_orport.c subsystem. */ 660 void 661 ext_orport_free_all(void) 662 { 663 if (ext_or_auth_cookie) /* Free the auth cookie */ 664 tor_free(ext_or_auth_cookie); 665 }