Line data Source code
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 11 : ext_or_cmd_new(uint16_t len)
37 : {
38 11 : size_t size = offsetof(ext_or_cmd_t, body) + len;
39 11 : ext_or_cmd_t *cmd = tor_malloc(size);
40 11 : cmd->len = len;
41 11 : return cmd;
42 : }
43 :
44 : /** Deallocate the Extended ORPort message in <b>cmd</b>. */
45 : void
46 12 : ext_or_cmd_free_(ext_or_cmd_t *cmd)
47 : {
48 12 : tor_free(cmd);
49 12 : }
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 15 : connection_fetch_ext_or_cmd_from_buf(connection_t *conn, ext_or_cmd_t **out)
57 : {
58 15 : 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 5 : connection_write_ext_or_command(connection_t *conn,
67 : uint16_t command,
68 : const char *body,
69 : size_t bodylen)
70 : {
71 5 : char header[4];
72 5 : if (bodylen > UINT16_MAX)
73 : return -1;
74 4 : set_uint16(header, htons(command));
75 4 : set_uint16(header+2, htons(bodylen));
76 4 : connection_buf_add(header, 4, conn);
77 4 : if (bodylen) {
78 2 : tor_assert(body);
79 2 : 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 1 : connection_ext_or_transition(or_connection_t *conn)
88 : {
89 1 : tor_assert(conn->base_.type == CONN_TYPE_EXT_OR);
90 :
91 1 : conn->base_.type = CONN_TYPE_OR;
92 1 : TO_CONN(conn)->state = 0; // set the state to a neutral value
93 1 : connection_or_event_status(conn, OR_CONN_EVENT_NEW, 0);
94 1 : connection_tls_start_handshake(conn, 1);
95 1 : }
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 5 : get_ext_or_auth_cookie_file_name(void)
128 : {
129 5 : const or_options_t *options = get_options();
130 5 : if (options->ExtORPortCookieAuthFile &&
131 : strlen(options->ExtORPortCookieAuthFile)) {
132 4 : return tor_strdup(options->ExtORPortCookieAuthFile);
133 : } else {
134 1 : 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 7 : init_ext_or_cookie_authentication(int is_enabled)
143 : {
144 7 : char *fname = NULL;
145 7 : int retval;
146 :
147 7 : if (!is_enabled) {
148 4 : ext_or_auth_cookie_is_set = 0;
149 4 : return 0;
150 : }
151 :
152 3 : fname = get_ext_or_auth_cookie_file_name();
153 9 : retval = init_cookie_authentication(fname, EXT_OR_PORT_AUTH_COOKIE_HEADER,
154 : EXT_OR_PORT_AUTH_COOKIE_HEADER_LEN,
155 3 : get_options()->ExtORPortCookieAuthFileGroupReadable,
156 : &ext_or_auth_cookie,
157 : &ext_or_auth_cookie_is_set);
158 3 : tor_free(fname);
159 3 : 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 7 : connection_ext_or_auth_neg_auth_type(connection_t *conn)
171 : {
172 7 : char authtype[1] = {0};
173 :
174 7 : if (connection_get_inbuf_len(conn) < 1)
175 : return 0;
176 :
177 6 : if (connection_buf_get_bytes(authtype, 1, conn) < 0)
178 : return -1;
179 :
180 6 : log_debug(LD_GENERAL, "Client wants us to use %d auth type", authtype[0]);
181 6 : if (authtype[0] != EXT_OR_AUTHTYPE_SAFECOOKIE) {
182 : /* '1' is the only auth type supported atm */
183 : return -1;
184 : }
185 :
186 5 : conn->state = EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE;
187 5 : return 1;
188 : }
189 :
190 : /* DOCDOC */
191 : STATIC int
192 10 : 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 10 : char server_hash[EXT_OR_PORT_AUTH_HASH_LEN] = {0};
197 10 : char server_nonce[EXT_OR_PORT_AUTH_NONCE_LEN] = {0};
198 10 : char *reply;
199 10 : size_t reply_len;
200 :
201 10 : if (client_nonce_len != EXT_OR_PORT_AUTH_NONCE_LEN)
202 : return -1;
203 :
204 : /* Get our nonce */
205 8 : crypto_rand(server_nonce, EXT_OR_PORT_AUTH_NONCE_LEN);
206 :
207 : { /* set up macs */
208 8 : size_t hmac_s_msg_len = strlen(EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST) +
209 : 2*EXT_OR_PORT_AUTH_NONCE_LEN;
210 8 : 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 8 : char *hmac_s_msg = tor_malloc_zero(hmac_s_msg_len);
214 8 : char *hmac_c_msg = tor_malloc_zero(hmac_c_msg_len);
215 8 : char *correct_client_hash = tor_malloc_zero(EXT_OR_PORT_AUTH_HASH_LEN);
216 :
217 8 : memcpy(hmac_s_msg,
218 : EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST,
219 : strlen(EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST));
220 8 : memcpy(hmac_s_msg + strlen(EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST),
221 : client_nonce, EXT_OR_PORT_AUTH_NONCE_LEN);
222 8 : 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 8 : memcpy(hmac_c_msg,
227 : EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST,
228 : strlen(EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST));
229 8 : memcpy(hmac_c_msg + strlen(EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST),
230 : client_nonce, EXT_OR_PORT_AUTH_NONCE_LEN);
231 8 : 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 8 : 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 8 : 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 8 : *client_hash_out = correct_client_hash;
250 :
251 8 : memwipe(hmac_s_msg, 0, hmac_s_msg_len);
252 8 : memwipe(hmac_c_msg, 0, hmac_c_msg_len);
253 :
254 8 : tor_free(hmac_s_msg);
255 8 : tor_free(hmac_c_msg);
256 : }
257 :
258 : { /* debug logging */ /* XXX disable this codepath if not logging on debug?*/
259 8 : char server_hash_encoded[(2*EXT_OR_PORT_AUTH_HASH_LEN) + 1];
260 8 : char server_nonce_encoded[(2*EXT_OR_PORT_AUTH_NONCE_LEN) + 1];
261 8 : char client_nonce_encoded[(2*EXT_OR_PORT_AUTH_NONCE_LEN) + 1];
262 :
263 8 : base16_encode(server_hash_encoded, sizeof(server_hash_encoded),
264 : server_hash, sizeof(server_hash));
265 8 : base16_encode(server_nonce_encoded, sizeof(server_nonce_encoded),
266 : server_nonce, sizeof(server_nonce));
267 8 : base16_encode(client_nonce_encoded, sizeof(client_nonce_encoded),
268 : client_nonce, EXT_OR_PORT_AUTH_NONCE_LEN);
269 :
270 8 : 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 8 : memwipe(server_hash_encoded, 0, sizeof(server_hash_encoded));
275 8 : memwipe(server_nonce_encoded, 0, sizeof(server_nonce_encoded));
276 8 : memwipe(client_nonce_encoded, 0, sizeof(client_nonce_encoded));
277 : }
278 :
279 : { /* write reply: (server_hash, server_nonce) */
280 :
281 8 : reply_len = EXT_OR_PORT_AUTH_COOKIE_LEN+EXT_OR_PORT_AUTH_NONCE_LEN;
282 8 : reply = tor_malloc_zero(reply_len);
283 8 : memcpy(reply, server_hash, EXT_OR_PORT_AUTH_HASH_LEN);
284 8 : memcpy(reply + EXT_OR_PORT_AUTH_HASH_LEN, server_nonce,
285 : EXT_OR_PORT_AUTH_NONCE_LEN);
286 : }
287 :
288 8 : *reply_out = reply;
289 8 : *reply_len_out = reply_len;
290 :
291 8 : 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 7 : connection_ext_or_auth_handle_client_nonce(connection_t *conn)
302 : {
303 7 : char client_nonce[EXT_OR_PORT_AUTH_NONCE_LEN];
304 7 : char *reply=NULL;
305 7 : size_t reply_len=0;
306 :
307 7 : if (!ext_or_auth_cookie_is_set) { /* this should not happen */
308 0 : 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 0 : return -1;
312 : }
313 :
314 7 : if (connection_get_inbuf_len(conn) < EXT_OR_PORT_AUTH_NONCE_LEN)
315 : return 0;
316 :
317 5 : 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 5 : if (handle_client_auth_nonce(client_nonce, sizeof(client_nonce),
328 5 : &TO_OR_CONN(conn)->ext_or_auth_correct_client_hash,
329 : &reply, &reply_len) < 0)
330 : return -1;
331 :
332 5 : connection_buf_add(reply, reply_len, conn);
333 :
334 5 : memwipe(reply, 0, reply_len);
335 5 : tor_free(reply);
336 :
337 5 : log_debug(LD_GENERAL, "Got client nonce, and sent our own nonce and hash.");
338 :
339 5 : conn->state = EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_HASH;
340 5 : 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 5 : connection_ext_or_auth_send_result(connection_t *conn, int success)
352 : {
353 5 : if (success)
354 4 : connection_buf_add("\x01", 1, conn);
355 : else
356 1 : connection_buf_add("\x00", 1, conn);
357 5 : }
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 10 : connection_ext_or_auth_handle_client_hash(connection_t *conn)
368 : {
369 10 : char provided_client_hash[EXT_OR_PORT_AUTH_HASH_LEN] = {0};
370 :
371 10 : if (connection_get_inbuf_len(conn) < EXT_OR_PORT_AUTH_HASH_LEN)
372 : return 0;
373 :
374 5 : if (connection_buf_get_bytes(provided_client_hash,
375 : EXT_OR_PORT_AUTH_HASH_LEN, conn) < 0)
376 : return -1;
377 :
378 5 : if (tor_memneq(TO_OR_CONN(conn)->ext_or_auth_correct_client_hash,
379 : provided_client_hash, EXT_OR_PORT_AUTH_HASH_LEN)) {
380 1 : log_warn(LD_GENERAL, "Incorrect client hash. Authentication failed.");
381 1 : connection_ext_or_auth_send_result_fail(conn);
382 1 : return -1;
383 : }
384 :
385 4 : log_debug(LD_GENERAL, "Got client's hash and it was legit.");
386 :
387 : /* send positive auth result */
388 4 : connection_ext_or_auth_send_result_success(conn);
389 4 : conn->state = EXT_OR_CONN_STATE_OPEN;
390 4 : 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 24 : connection_ext_or_auth_process_inbuf(or_connection_t *or_conn)
397 : {
398 24 : 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 24 : switch (conn->state) { /* Functionify */
412 7 : case EXT_OR_CONN_STATE_AUTH_WAIT_AUTH_TYPE:
413 7 : return connection_ext_or_auth_neg_auth_type(conn);
414 :
415 7 : case EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE:
416 7 : return connection_ext_or_auth_handle_client_nonce(conn);
417 :
418 10 : case EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_HASH:
419 10 : return connection_ext_or_auth_handle_client_hash(conn);
420 :
421 0 : default:
422 0 : log_warn(LD_BUG, "Encountered unexpected connection state %d while trying "
423 : "to process Extended ORPort authentication data.", conn->state);
424 0 : 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 2 : connection_ext_or_handle_cmd_useraddr(connection_t *conn,
447 : const char *payload, uint16_t len)
448 : {
449 : /* Copy address string. */
450 2 : tor_addr_t addr;
451 2 : uint16_t port;
452 2 : char *addr_str;
453 2 : char *address_part=NULL;
454 2 : int res;
455 2 : if (memchr(payload, '\0', len)) {
456 1 : log_fn(LOG_PROTOCOL_WARN, LD_NET, "Unexpected NUL in ExtORPort UserAddr");
457 1 : return -1;
458 : }
459 :
460 1 : addr_str = tor_memdup_nulterm(payload, len);
461 :
462 1 : res = tor_addr_port_split(LOG_INFO, addr_str, &address_part, &port);
463 1 : tor_free(addr_str);
464 1 : if (res<0)
465 : return -1;
466 1 : if (port == 0) {
467 0 : 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 1 : res = tor_addr_parse(&addr, address_part);
473 1 : tor_free(address_part);
474 1 : if (res<0)
475 : return -1;
476 :
477 : { /* do some logging */
478 1 : char *old_address = tor_addr_to_str_dup(&conn->addr);
479 1 : char *new_address = tor_addr_to_str_dup(&addr);
480 :
481 1 : 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 1 : tor_free(old_address);
486 1 : tor_free(new_address);
487 : }
488 :
489 : /* record the address */
490 1 : tor_addr_copy(&conn->addr, &addr);
491 1 : conn->port = port;
492 1 : if (conn->address) {
493 0 : tor_free(conn->address);
494 : }
495 1 : 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 1 : conn->always_rate_limit_as_remote = 0;
500 :
501 1 : 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 3 : connection_ext_or_handle_cmd_transport(or_connection_t *conn,
513 : const char *payload, uint16_t len)
514 : {
515 3 : char *transport_str;
516 3 : if (memchr(payload, '\0', len)) {
517 1 : log_fn(LOG_PROTOCOL_WARN, LD_NET, "Unexpected NUL in ExtORPort Transport");
518 1 : return -1;
519 : }
520 :
521 2 : transport_str = tor_memdup_nulterm(payload, len);
522 :
523 : /* Transport names MUST be C-identifiers. */
524 2 : if (!string_is_C_identifier(transport_str)) {
525 1 : tor_free(transport_str);
526 1 : 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 1 : if (conn->ext_or_transport)
533 0 : tor_free(conn->ext_or_transport);
534 :
535 1 : conn->ext_or_transport = transport_str;
536 1 : 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 21 : connection_ext_or_process_inbuf(or_connection_t *or_conn)
545 : {
546 21 : connection_t *conn = TO_CONN(or_conn);
547 21 : ext_or_cmd_t *command;
548 21 : 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 35 : while (EXT_OR_CONN_STATE_IS_AUTHENTICATING(conn->state)) {
555 24 : log_debug(LD_GENERAL, "Got Extended ORPort authentication data (%u).",
556 : (unsigned int) connection_get_inbuf_len(conn));
557 24 : r = connection_ext_or_auth_process_inbuf(or_conn);
558 24 : if (r < 0) {
559 2 : connection_mark_for_close(conn);
560 2 : return -1;
561 22 : } else if (r == 0) {
562 : return 0;
563 : }
564 : /* if r > 0, loop and process more data (if any). */
565 : }
566 :
567 19 : while (1) {
568 15 : log_debug(LD_GENERAL, "Got Extended ORPort data.");
569 15 : command = NULL;
570 15 : r = connection_fetch_ext_or_cmd_from_buf(conn, &command);
571 15 : if (r < 0)
572 0 : goto err;
573 15 : else if (r == 0)
574 : return 0; /* need to wait for more data */
575 :
576 : /* Got a command! */
577 7 : tor_assert(command);
578 :
579 7 : if (command->cmd == EXT_OR_CMD_TB_DONE) {
580 1 : if (connection_get_inbuf_len(conn)) {
581 : /* The inbuf isn't empty; the client is misbehaving. */
582 0 : goto err;
583 : }
584 :
585 1 : 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 1 : if (!or_conn->ext_or_transport) {
590 : /* We write this string this way to avoid ??>, which is a C
591 : * trigraph. */
592 0 : or_conn->ext_or_transport = tor_strdup("<?" "?>");
593 : }
594 :
595 1 : connection_write_ext_or_command(conn, EXT_OR_CMD_BT_OKAY, NULL, 0);
596 :
597 : /* can't transition immediately; need to flush first. */
598 1 : conn->state = EXT_OR_CONN_STATE_FLUSHING;
599 1 : connection_stop_reading(conn);
600 6 : } else if (command->cmd == EXT_OR_CMD_TB_USERADDR) {
601 2 : if (connection_ext_or_handle_cmd_useraddr(conn,
602 2 : command->body, command->len) < 0)
603 1 : goto err;
604 4 : } else if (command->cmd == EXT_OR_CMD_TB_TRANSPORT) {
605 3 : if (connection_ext_or_handle_cmd_transport(or_conn,
606 3 : command->body, command->len) < 0)
607 2 : goto err;
608 : } else {
609 1 : log_notice(LD_NET,"Got Extended ORPort command we don't recognize (%u).",
610 : command->cmd);
611 : }
612 :
613 4 : ext_or_cmd_free(command);
614 : }
615 :
616 : return 0;
617 :
618 3 : err:
619 3 : ext_or_cmd_free(command);
620 3 : connection_mark_for_close(conn);
621 3 : 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 1 : connection_ext_or_finished_flushing(or_connection_t *conn)
629 : {
630 1 : if (conn->base_.state == EXT_OR_CONN_STATE_FLUSHING) {
631 1 : connection_start_reading(TO_CONN(conn));
632 1 : connection_ext_or_transition(conn);
633 : }
634 1 : return 0;
635 : }
636 :
637 : /** Initiate Extended ORPort authentication, by sending the list of
638 : * supported authentication types to the client. */
639 : int
640 6 : connection_ext_or_start_auth(or_connection_t *or_conn)
641 : {
642 6 : connection_t *conn = TO_CONN(or_conn);
643 6 : 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 6 : log_debug(LD_GENERAL,
651 : "ExtORPort authentication: Sending supported authentication types");
652 :
653 6 : connection_buf_add((const char *)authtypes, sizeof(authtypes), conn);
654 6 : conn->state = EXT_OR_CONN_STATE_AUTH_WAIT_AUTH_TYPE;
655 :
656 6 : 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
662 7 : connection_or_set_ext_or_identifier(or_connection_t *conn)
663 : {
664 7 : char random_id[EXT_OR_CONN_ID_LEN];
665 :
666 7 : if (!conn->ext_or_conn_id)
667 7 : conn->ext_or_conn_id = tor_malloc_zero(EXT_OR_CONN_ID_LEN);
668 :
669 7 : memcpy(conn->ext_or_conn_id, random_id, EXT_OR_CONN_ID_LEN);
670 7 : }
671 :
672 : /** Free any leftover allocated memory of the ext_orport.c subsystem. */
673 : void
674 236 : ext_orport_free_all(void)
675 : {
676 236 : if (ext_or_auth_cookie) /* Free the auth cookie */
677 1 : tor_free(ext_or_auth_cookie);
678 236 : }
|