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 *
ext_or_cmd_new(uint16_t len)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
ext_or_cmd_free_(ext_or_cmd_t * cmd)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
connection_fetch_ext_or_cmd_from_buf(connection_t * conn,ext_or_cmd_t ** out)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
connection_write_ext_or_command(connection_t * conn,uint16_t command,const char * body,size_t bodylen)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
connection_ext_or_transition(or_connection_t * conn)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 *
get_ext_or_auth_cookie_file_name(void)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
init_ext_or_cookie_authentication(int is_enabled)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
connection_ext_or_auth_neg_auth_type(connection_t * conn)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
handle_client_auth_nonce(const char * client_nonce,size_t client_nonce_len,char ** client_hash_out,char ** reply_out,size_t * reply_len_out)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
connection_ext_or_auth_handle_client_nonce(connection_t * conn)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
connection_ext_or_auth_send_result(connection_t * conn,int success)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
connection_ext_or_auth_handle_client_hash(connection_t * conn)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
connection_ext_or_auth_process_inbuf(or_connection_t * or_conn)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
connection_ext_or_handle_cmd_useraddr(connection_t * conn,const char * payload,uint16_t len)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
connection_ext_or_handle_cmd_transport(or_connection_t * conn,const char * payload,uint16_t len)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
connection_ext_or_process_inbuf(or_connection_t * or_conn)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
connection_ext_or_finished_flushing(or_connection_t * conn)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
connection_ext_or_start_auth(or_connection_t * or_conn)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 /** Creates an Extended ORPort identifier for <b>conn</b> and deposits
660 * it into the global list of identifiers. */
661 void
connection_or_set_ext_or_identifier(or_connection_t * conn)662 connection_or_set_ext_or_identifier(or_connection_t *conn)
663 {
664 char random_id[EXT_OR_CONN_ID_LEN];
665
666 if (!conn->ext_or_conn_id)
667 conn->ext_or_conn_id = tor_malloc_zero(EXT_OR_CONN_ID_LEN);
668
669 memcpy(conn->ext_or_conn_id, random_id, EXT_OR_CONN_ID_LEN);
670 }
671
672 /** Free any leftover allocated memory of the ext_orport.c subsystem. */
673 void
ext_orport_free_all(void)674 ext_orport_free_all(void)
675 {
676 if (ext_or_auth_cookie) /* Free the auth cookie */
677 tor_free(ext_or_auth_cookie);
678 }
679