1 /* Copyright (c) 2012-2017, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
6 * \brief Code implementing the Extended ORPort.
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.
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().
19 #define EXT_ORPORT_PRIVATE
21 #include "connection.h"
22 #include "connection_or.h"
23 #include "ext_orport.h"
27 #include "proto_ext_or.h"
30 /** Allocate and return a structure capable of holding an Extended
31 * ORPort message of body length <b>len</b>. */
33 ext_or_cmd_new(uint16_t len
)
35 size_t size
= offsetof(ext_or_cmd_t
, body
) + len
;
36 ext_or_cmd_t
*cmd
= tor_malloc(size
);
41 /** Deallocate the Extended ORPort message in <b>cmd</b>. */
43 ext_or_cmd_free(ext_or_cmd_t
*cmd
)
48 /** Get an Extended ORPort message from <b>conn</b>, and place it in
49 * <b>out</b>. Return -1 on fail, 0 if we need more data, and 1 if we
50 * successfully extracted an Extended ORPort command from the
53 connection_fetch_ext_or_cmd_from_buf(connection_t
*conn
, ext_or_cmd_t
**out
)
55 return fetch_ext_or_command_from_buf(conn
->inbuf
, out
);
58 /** Write an Extended ORPort message to <b>conn</b>. Use
59 * <b>command</b> as the command type, <b>bodylen</b> as the body
60 * length, and <b>body</b>, if it's present, as the body of the
63 connection_write_ext_or_command(connection_t
*conn
,
69 if (bodylen
> UINT16_MAX
)
71 set_uint16(header
, htons(command
));
72 set_uint16(header
+2, htons(bodylen
));
73 connection_buf_add(header
, 4, conn
);
76 connection_buf_add(body
, bodylen
, conn
);
81 /** Transition from an Extended ORPort which accepts Extended ORPort
82 * messages, to an Extended ORport which accepts OR traffic. */
84 connection_ext_or_transition(or_connection_t
*conn
)
86 tor_assert(conn
->base_
.type
== CONN_TYPE_EXT_OR
);
88 conn
->base_
.type
= CONN_TYPE_OR
;
89 TO_CONN(conn
)->state
= 0; // set the state to a neutral value
90 control_event_or_conn_status(conn
, OR_CONN_EVENT_NEW
, 0);
91 connection_tls_start_handshake(conn
, 1);
94 /** Length of authentication cookie. */
95 #define EXT_OR_PORT_AUTH_COOKIE_LEN 32
96 /** Length of the header of the cookie file. */
97 #define EXT_OR_PORT_AUTH_COOKIE_HEADER_LEN 32
98 /** Static cookie file header. */
99 #define EXT_OR_PORT_AUTH_COOKIE_HEADER "! Extended ORPort Auth Cookie !\x0a"
100 /** Length of safe-cookie protocol hashes. */
101 #define EXT_OR_PORT_AUTH_HASH_LEN DIGEST256_LEN
102 /** Length of safe-cookie protocol nonces. */
103 #define EXT_OR_PORT_AUTH_NONCE_LEN 32
104 /** Safe-cookie protocol constants. */
105 #define EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST \
106 "ExtORPort authentication server-to-client hash"
107 #define EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST \
108 "ExtORPort authentication client-to-server hash"
110 /* Code to indicate cookie authentication */
111 #define EXT_OR_AUTHTYPE_SAFECOOKIE 0x01
113 /** If true, we've set ext_or_auth_cookie to a secret code and stored
115 STATIC
int ext_or_auth_cookie_is_set
= 0;
116 /** If ext_or_auth_cookie_is_set, a secret cookie that we've stored to disk
117 * and which we're using to authenticate controllers. (If the controller can
118 * read it off disk, it has permission to connect.) */
119 STATIC
uint8_t *ext_or_auth_cookie
= NULL
;
121 /** Helper: Return a newly allocated string containing a path to the
122 * file where we store our authentication cookie. */
124 get_ext_or_auth_cookie_file_name(void)
126 const or_options_t
*options
= get_options();
127 if (options
->ExtORPortCookieAuthFile
&&
128 strlen(options
->ExtORPortCookieAuthFile
)) {
129 return tor_strdup(options
->ExtORPortCookieAuthFile
);
131 return get_datadir_fname("extended_orport_auth_cookie");
135 /* Initialize the cookie-based authentication system of the
136 * Extended ORPort. If <b>is_enabled</b> is 0, then disable the cookie
137 * authentication system. */
139 init_ext_or_cookie_authentication(int is_enabled
)
145 ext_or_auth_cookie_is_set
= 0;
149 fname
= get_ext_or_auth_cookie_file_name();
150 retval
= init_cookie_authentication(fname
, EXT_OR_PORT_AUTH_COOKIE_HEADER
,
151 EXT_OR_PORT_AUTH_COOKIE_HEADER_LEN
,
152 get_options()->ExtORPortCookieAuthFileGroupReadable
,
154 &ext_or_auth_cookie_is_set
);
159 /** Read data from <b>conn</b> and see if the client sent us the
160 * authentication type that they prefer to use in this session.
162 * Return -1 if we received corrupted data or if we don't support the
163 * authentication type. Return 0 if we need more data in
164 * <b>conn</b>. Return 1 if the authentication type negotiation was
167 connection_ext_or_auth_neg_auth_type(connection_t
*conn
)
169 char authtype
[1] = {0};
171 if (connection_get_inbuf_len(conn
) < 1)
174 if (connection_buf_get_bytes(authtype
, 1, conn
) < 0)
177 log_debug(LD_GENERAL
, "Client wants us to use %d auth type", authtype
[0]);
178 if (authtype
[0] != EXT_OR_AUTHTYPE_SAFECOOKIE
) {
179 /* '1' is the only auth type supported atm */
183 conn
->state
= EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE
;
189 handle_client_auth_nonce(const char *client_nonce
, size_t client_nonce_len
,
190 char **client_hash_out
,
191 char **reply_out
, size_t *reply_len_out
)
193 char server_hash
[EXT_OR_PORT_AUTH_HASH_LEN
] = {0};
194 char server_nonce
[EXT_OR_PORT_AUTH_NONCE_LEN
] = {0};
198 if (client_nonce_len
!= EXT_OR_PORT_AUTH_NONCE_LEN
)
202 crypto_rand(server_nonce
, EXT_OR_PORT_AUTH_NONCE_LEN
);
205 size_t hmac_s_msg_len
= strlen(EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST
) +
206 2*EXT_OR_PORT_AUTH_NONCE_LEN
;
207 size_t hmac_c_msg_len
= strlen(EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST
) +
208 2*EXT_OR_PORT_AUTH_NONCE_LEN
;
210 char *hmac_s_msg
= tor_malloc_zero(hmac_s_msg_len
);
211 char *hmac_c_msg
= tor_malloc_zero(hmac_c_msg_len
);
212 char *correct_client_hash
= tor_malloc_zero(EXT_OR_PORT_AUTH_HASH_LEN
);
215 EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST
,
216 strlen(EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST
));
217 memcpy(hmac_s_msg
+ strlen(EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST
),
218 client_nonce
, EXT_OR_PORT_AUTH_NONCE_LEN
);
219 memcpy(hmac_s_msg
+ strlen(EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST
) +
220 EXT_OR_PORT_AUTH_NONCE_LEN
,
221 server_nonce
, EXT_OR_PORT_AUTH_NONCE_LEN
);
224 EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST
,
225 strlen(EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST
));
226 memcpy(hmac_c_msg
+ strlen(EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST
),
227 client_nonce
, EXT_OR_PORT_AUTH_NONCE_LEN
);
228 memcpy(hmac_c_msg
+ strlen(EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST
) +
229 EXT_OR_PORT_AUTH_NONCE_LEN
,
230 server_nonce
, EXT_OR_PORT_AUTH_NONCE_LEN
);
232 crypto_hmac_sha256(server_hash
,
233 (char*)ext_or_auth_cookie
,
234 EXT_OR_PORT_AUTH_COOKIE_LEN
,
238 crypto_hmac_sha256(correct_client_hash
,
239 (char*)ext_or_auth_cookie
,
240 EXT_OR_PORT_AUTH_COOKIE_LEN
,
244 /* Store the client hash we generated. We will need to compare it
245 with the hash sent by the client. */
246 *client_hash_out
= correct_client_hash
;
248 memwipe(hmac_s_msg
, 0, hmac_s_msg_len
);
249 memwipe(hmac_c_msg
, 0, hmac_c_msg_len
);
251 tor_free(hmac_s_msg
);
252 tor_free(hmac_c_msg
);
255 { /* debug logging */ /* XXX disable this codepath if not logging on debug?*/
256 char server_hash_encoded
[(2*EXT_OR_PORT_AUTH_HASH_LEN
) + 1];
257 char server_nonce_encoded
[(2*EXT_OR_PORT_AUTH_NONCE_LEN
) + 1];
258 char client_nonce_encoded
[(2*EXT_OR_PORT_AUTH_NONCE_LEN
) + 1];
260 base16_encode(server_hash_encoded
, sizeof(server_hash_encoded
),
261 server_hash
, sizeof(server_hash
));
262 base16_encode(server_nonce_encoded
, sizeof(server_nonce_encoded
),
263 server_nonce
, sizeof(server_nonce
));
264 base16_encode(client_nonce_encoded
, sizeof(client_nonce_encoded
),
265 client_nonce
, EXT_OR_PORT_AUTH_NONCE_LEN
);
267 log_debug(LD_GENERAL
,
268 "server_hash: '%s'\nserver_nonce: '%s'\nclient_nonce: '%s'",
269 server_hash_encoded
, server_nonce_encoded
, client_nonce_encoded
);
271 memwipe(server_hash_encoded
, 0, sizeof(server_hash_encoded
));
272 memwipe(server_nonce_encoded
, 0, sizeof(server_nonce_encoded
));
273 memwipe(client_nonce_encoded
, 0, sizeof(client_nonce_encoded
));
276 { /* write reply: (server_hash, server_nonce) */
278 reply_len
= EXT_OR_PORT_AUTH_COOKIE_LEN
+EXT_OR_PORT_AUTH_NONCE_LEN
;
279 reply
= tor_malloc_zero(reply_len
);
280 memcpy(reply
, server_hash
, EXT_OR_PORT_AUTH_HASH_LEN
);
281 memcpy(reply
+ EXT_OR_PORT_AUTH_HASH_LEN
, server_nonce
,
282 EXT_OR_PORT_AUTH_NONCE_LEN
);
286 *reply_len_out
= reply_len
;
291 /** Read the client's nonce out of <b>conn</b>, setup the safe-cookie
292 * crypto, and then send our own hash and nonce to the client
294 * Return -1 if there was an error; return 0 if we need more data in
295 * <b>conn</b>, and return 1 if we successfully retrieved the
296 * client's nonce and sent our own. */
298 connection_ext_or_auth_handle_client_nonce(connection_t
*conn
)
300 char client_nonce
[EXT_OR_PORT_AUTH_NONCE_LEN
];
304 if (!ext_or_auth_cookie_is_set
) { /* this should not happen */
305 log_warn(LD_BUG
, "Extended ORPort authentication cookie was not set. "
306 "That's weird since we should have done that on startup. "
307 "This might be a Tor bug, please file a bug report. ");
311 if (connection_get_inbuf_len(conn
) < EXT_OR_PORT_AUTH_NONCE_LEN
)
314 if (connection_buf_get_bytes(client_nonce
,
315 EXT_OR_PORT_AUTH_NONCE_LEN
, conn
) < 0)
318 /* We extract the ClientNonce from the received data, and use it to
319 calculate ServerHash and ServerNonce according to proposal 217.
321 We also calculate our own ClientHash value and save it in the
322 connection state. We validate it later against the ClientHash
323 sent by the client. */
324 if (handle_client_auth_nonce(client_nonce
, sizeof(client_nonce
),
325 &TO_OR_CONN(conn
)->ext_or_auth_correct_client_hash
,
326 &reply
, &reply_len
) < 0)
329 connection_buf_add(reply
, reply_len
, conn
);
331 memwipe(reply
, 0, reply_len
);
334 log_debug(LD_GENERAL
, "Got client nonce, and sent our own nonce and hash.");
336 conn
->state
= EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_HASH
;
340 #define connection_ext_or_auth_send_result_success(c) \
341 connection_ext_or_auth_send_result(c, 1)
342 #define connection_ext_or_auth_send_result_fail(c) \
343 connection_ext_or_auth_send_result(c, 0)
345 /** Send authentication results to <b>conn</b>. Successful results if
346 * <b>success</b> is set; failure results otherwise. */
348 connection_ext_or_auth_send_result(connection_t
*conn
, int success
)
351 connection_buf_add("\x01", 1, conn
);
353 connection_buf_add("\x00", 1, conn
);
356 /** Receive the client's hash from <b>conn</b>, validate that it's
357 * correct, and then send the authentication results to the client.
359 * Return -1 if there was an error during validation; return 0 if we
360 * need more data in <b>conn</b>, and return 1 if we successfully
361 * validated the client's hash and sent a happy authentication
364 connection_ext_or_auth_handle_client_hash(connection_t
*conn
)
366 char provided_client_hash
[EXT_OR_PORT_AUTH_HASH_LEN
] = {0};
368 if (connection_get_inbuf_len(conn
) < EXT_OR_PORT_AUTH_HASH_LEN
)
371 if (connection_buf_get_bytes(provided_client_hash
,
372 EXT_OR_PORT_AUTH_HASH_LEN
, conn
) < 0)
375 if (tor_memneq(TO_OR_CONN(conn
)->ext_or_auth_correct_client_hash
,
376 provided_client_hash
, EXT_OR_PORT_AUTH_HASH_LEN
)) {
377 log_warn(LD_GENERAL
, "Incorrect client hash. Authentication failed.");
378 connection_ext_or_auth_send_result_fail(conn
);
382 log_debug(LD_GENERAL
, "Got client's hash and it was legit.");
384 /* send positive auth result */
385 connection_ext_or_auth_send_result_success(conn
);
386 conn
->state
= EXT_OR_CONN_STATE_OPEN
;
390 /** Handle data from <b>or_conn</b> received on Extended ORPort.
391 * Return -1 on error. 0 on unsufficient data. 1 on correct. */
393 connection_ext_or_auth_process_inbuf(or_connection_t
*or_conn
)
395 connection_t
*conn
= TO_CONN(or_conn
);
397 /* State transitions of the Extended ORPort authentication protocol:
399 EXT_OR_CONN_STATE_AUTH_WAIT_AUTH_TYPE (start state) ->
400 EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE ->
401 EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_HASH ->
402 EXT_OR_CONN_STATE_OPEN
404 During EXT_OR_CONN_STATE_OPEN, data is handled by
405 connection_ext_or_process_inbuf().
408 switch (conn
->state
) { /* Functionify */
409 case EXT_OR_CONN_STATE_AUTH_WAIT_AUTH_TYPE
:
410 return connection_ext_or_auth_neg_auth_type(conn
);
412 case EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE
:
413 return connection_ext_or_auth_handle_client_nonce(conn
);
415 case EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_HASH
:
416 return connection_ext_or_auth_handle_client_hash(conn
);
419 log_warn(LD_BUG
, "Encountered unexpected connection state %d while trying "
420 "to process Extended ORPort authentication data.", conn
->state
);
425 /** Extended ORPort commands (Transport-to-Bridge) */
426 #define EXT_OR_CMD_TB_DONE 0x0000
427 #define EXT_OR_CMD_TB_USERADDR 0x0001
428 #define EXT_OR_CMD_TB_TRANSPORT 0x0002
430 /** Extended ORPort commands (Bridge-to-Transport) */
431 #define EXT_OR_CMD_BT_OKAY 0x1000
432 #define EXT_OR_CMD_BT_DENY 0x1001
433 #define EXT_OR_CMD_BT_CONTROL 0x1002
435 /** Process a USERADDR command from the Extended
436 * ORPort. <b>payload</b> is a payload of size <b>len</b>.
438 * If the USERADDR command was well formed, change the address of
439 * <b>conn</b> to the address on the USERADDR command.
441 * Return 0 on success and -1 on error. */
443 connection_ext_or_handle_cmd_useraddr(connection_t
*conn
,
444 const char *payload
, uint16_t len
)
446 /* Copy address string. */
450 char *address_part
=NULL
;
452 if (memchr(payload
, '\0', len
)) {
453 log_fn(LOG_PROTOCOL_WARN
, LD_NET
, "Unexpected NUL in ExtORPort UserAddr");
457 addr_str
= tor_memdup_nulterm(payload
, len
);
459 res
= tor_addr_port_split(LOG_INFO
, addr_str
, &address_part
, &port
);
464 log_warn(LD_GENERAL
, "Server transport proxy gave us an empty port "
465 "in ExtORPort UserAddr command.");
466 // return -1; // enable this if nothing breaks after a while.
469 res
= tor_addr_parse(&addr
, address_part
);
470 tor_free(address_part
);
474 { /* do some logging */
475 char *old_address
= tor_addr_to_str_dup(&conn
->addr
);
476 char *new_address
= tor_addr_to_str_dup(&addr
);
478 log_debug(LD_NET
, "Received USERADDR."
479 "We rewrite our address from '%s:%u' to '%s:%u'.",
480 safe_str(old_address
), conn
->port
, safe_str(new_address
), port
);
482 tor_free(old_address
);
483 tor_free(new_address
);
486 /* record the address */
487 tor_addr_copy(&conn
->addr
, &addr
);
490 tor_free(conn
->address
);
492 conn
->address
= tor_addr_to_str_dup(&addr
);
497 /** Process a TRANSPORT command from the Extended
498 * ORPort. <b>payload</b> is a payload of size <b>len</b>.
500 * If the TRANSPORT command was well formed, register the name of the
501 * transport on <b>conn</b>.
503 * Return 0 on success and -1 on error. */
505 connection_ext_or_handle_cmd_transport(or_connection_t
*conn
,
506 const char *payload
, uint16_t len
)
509 if (memchr(payload
, '\0', len
)) {
510 log_fn(LOG_PROTOCOL_WARN
, LD_NET
, "Unexpected NUL in ExtORPort Transport");
514 transport_str
= tor_memdup_nulterm(payload
, len
);
516 /* Transport names MUST be C-identifiers. */
517 if (!string_is_C_identifier(transport_str
)) {
518 tor_free(transport_str
);
522 /* If ext_or_transport is already occupied (because the PT sent two
523 * TRANSPORT commands), deallocate the old name and keep the new
525 if (conn
->ext_or_transport
)
526 tor_free(conn
->ext_or_transport
);
528 conn
->ext_or_transport
= transport_str
;
532 #define EXT_OR_CONN_STATE_IS_AUTHENTICATING(st) \
533 ((st) <= EXT_OR_CONN_STATE_AUTH_MAX)
535 /** Process Extended ORPort messages from <b>or_conn</b>. */
537 connection_ext_or_process_inbuf(or_connection_t
*or_conn
)
539 connection_t
*conn
= TO_CONN(or_conn
);
540 ext_or_cmd_t
*command
;
543 /* DOCDOC Document the state machine and transitions in this function */
545 /* If we are still in the authentication stage, process traffic as
546 authentication data: */
547 while (EXT_OR_CONN_STATE_IS_AUTHENTICATING(conn
->state
)) {
548 log_debug(LD_GENERAL
, "Got Extended ORPort authentication data (%u).",
549 (unsigned int) connection_get_inbuf_len(conn
));
550 r
= connection_ext_or_auth_process_inbuf(or_conn
);
552 connection_mark_for_close(conn
);
557 /* if r > 0, loop and process more data (if any). */
561 log_debug(LD_GENERAL
, "Got Extended ORPort data.");
563 r
= connection_fetch_ext_or_cmd_from_buf(conn
, &command
);
567 return 0; /* need to wait for more data */
572 if (command
->cmd
== EXT_OR_CMD_TB_DONE
) {
573 if (connection_get_inbuf_len(conn
)) {
574 /* The inbuf isn't empty; the client is misbehaving. */
578 log_debug(LD_NET
, "Received DONE.");
580 /* If the transport proxy did not use the TRANSPORT command to
581 * specify the transport name, mark this as unknown transport. */
582 if (!or_conn
->ext_or_transport
) {
583 /* We write this string this way to avoid ??>, which is a C
585 or_conn
->ext_or_transport
= tor_strdup("<?" "?>");
588 connection_write_ext_or_command(conn
, EXT_OR_CMD_BT_OKAY
, NULL
, 0);
590 /* can't transition immediately; need to flush first. */
591 conn
->state
= EXT_OR_CONN_STATE_FLUSHING
;
592 connection_stop_reading(conn
);
593 } else if (command
->cmd
== EXT_OR_CMD_TB_USERADDR
) {
594 if (connection_ext_or_handle_cmd_useraddr(conn
,
595 command
->body
, command
->len
) < 0)
597 } else if (command
->cmd
== EXT_OR_CMD_TB_TRANSPORT
) {
598 if (connection_ext_or_handle_cmd_transport(or_conn
,
599 command
->body
, command
->len
) < 0)
602 log_notice(LD_NET
,"Got Extended ORPort command we don't regognize (%u).",
606 ext_or_cmd_free(command
);
612 ext_or_cmd_free(command
);
613 connection_mark_for_close(conn
);
617 /** <b>conn</b> finished flushing Extended ORPort messages to the
618 * network, and is now ready to accept OR traffic. This function
619 * does the transition. */
621 connection_ext_or_finished_flushing(or_connection_t
*conn
)
623 if (conn
->base_
.state
== EXT_OR_CONN_STATE_FLUSHING
) {
624 connection_start_reading(TO_CONN(conn
));
625 connection_ext_or_transition(conn
);
630 /** Initiate Extended ORPort authentication, by sending the list of
631 * supported authentication types to the client. */
633 connection_ext_or_start_auth(or_connection_t
*or_conn
)
635 connection_t
*conn
= TO_CONN(or_conn
);
636 const uint8_t authtypes
[] = {
637 /* We only support authtype '1' for now. */
638 EXT_OR_AUTHTYPE_SAFECOOKIE
,
639 /* Marks the end of the list. */
643 log_debug(LD_GENERAL
,
644 "ExtORPort authentication: Sending supported authentication types");
646 connection_buf_add((const char *)authtypes
, sizeof(authtypes
), conn
);
647 conn
->state
= EXT_OR_CONN_STATE_AUTH_WAIT_AUTH_TYPE
;
652 /** Free any leftover allocated memory of the ext_orport.c subsystem. */
654 ext_orport_free_all(void)
656 if (ext_or_auth_cookie
) /* Free the auth cookie */
657 tor_free(ext_or_auth_cookie
);