minor updates on upcoming changelog
[tor.git] / src / or / ext_orport.c
blob28377a3f36cce1ccf429dfe08efc690c2a4aa3e1
1 /* Copyright (c) 2012-2017, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /**
5 * \file ext_orport.c
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
20 #include "or.h"
21 #include "connection.h"
22 #include "connection_or.h"
23 #include "ext_orport.h"
24 #include "control.h"
25 #include "config.h"
26 #include "main.h"
27 #include "proto_ext_or.h"
28 #include "util.h"
30 /** Allocate and return a structure capable of holding an Extended
31 * ORPort message of body length <b>len</b>. */
32 ext_or_cmd_t *
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);
37 cmd->len = len;
38 return cmd;
41 /** Deallocate the Extended ORPort message in <b>cmd</b>. */
42 void
43 ext_or_cmd_free(ext_or_cmd_t *cmd)
45 tor_free(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
51 * buffer. */
52 static int
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
61 * message. */
62 STATIC int
63 connection_write_ext_or_command(connection_t *conn,
64 uint16_t command,
65 const char *body,
66 size_t bodylen)
68 char header[4];
69 if (bodylen > UINT16_MAX)
70 return -1;
71 set_uint16(header, htons(command));
72 set_uint16(header+2, htons(bodylen));
73 connection_buf_add(header, 4, conn);
74 if (bodylen) {
75 tor_assert(body);
76 connection_buf_add(body, bodylen, conn);
78 return 0;
81 /** Transition from an Extended ORPort which accepts Extended ORPort
82 * messages, to an Extended ORport which accepts OR traffic. */
83 static void
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
114 * it to disk. */
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. */
123 char *
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);
130 } else {
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)
141 char *fname = NULL;
142 int retval;
144 if (!is_enabled) {
145 ext_or_auth_cookie_is_set = 0;
146 return 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,
153 &ext_or_auth_cookie,
154 &ext_or_auth_cookie_is_set);
155 tor_free(fname);
156 return retval;
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
165 * successful. */
166 static int
167 connection_ext_or_auth_neg_auth_type(connection_t *conn)
169 char authtype[1] = {0};
171 if (connection_get_inbuf_len(conn) < 1)
172 return 0;
174 if (connection_buf_get_bytes(authtype, 1, conn) < 0)
175 return -1;
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 */
180 return -1;
183 conn->state = EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE;
184 return 1;
187 /* DOCDOC */
188 STATIC int
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};
195 char *reply;
196 size_t reply_len;
198 if (client_nonce_len != EXT_OR_PORT_AUTH_NONCE_LEN)
199 return -1;
201 /* Get our nonce */
202 crypto_rand(server_nonce, EXT_OR_PORT_AUTH_NONCE_LEN);
204 { /* set up macs */
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);
214 memcpy(hmac_s_msg,
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);
223 memcpy(hmac_c_msg,
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,
235 hmac_s_msg,
236 hmac_s_msg_len);
238 crypto_hmac_sha256(correct_client_hash,
239 (char*)ext_or_auth_cookie,
240 EXT_OR_PORT_AUTH_COOKIE_LEN,
241 hmac_c_msg,
242 hmac_c_msg_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);
285 *reply_out = reply;
286 *reply_len_out = reply_len;
288 return 0;
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. */
297 static int
298 connection_ext_or_auth_handle_client_nonce(connection_t *conn)
300 char client_nonce[EXT_OR_PORT_AUTH_NONCE_LEN];
301 char *reply=NULL;
302 size_t reply_len=0;
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. ");
308 return -1;
311 if (connection_get_inbuf_len(conn) < EXT_OR_PORT_AUTH_NONCE_LEN)
312 return 0;
314 if (connection_buf_get_bytes(client_nonce,
315 EXT_OR_PORT_AUTH_NONCE_LEN, conn) < 0)
316 return -1;
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)
327 return -1;
329 connection_buf_add(reply, reply_len, conn);
331 memwipe(reply, 0, reply_len);
332 tor_free(reply);
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;
337 return 1;
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. */
347 static void
348 connection_ext_or_auth_send_result(connection_t *conn, int success)
350 if (success)
351 connection_buf_add("\x01", 1, conn);
352 else
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
362 * result. */
363 static int
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)
369 return 0;
371 if (connection_buf_get_bytes(provided_client_hash,
372 EXT_OR_PORT_AUTH_HASH_LEN, conn) < 0)
373 return -1;
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);
379 return -1;
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;
387 return 1;
390 /** Handle data from <b>or_conn</b> received on Extended ORPort.
391 * Return -1 on error. 0 on unsufficient data. 1 on correct. */
392 static int
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);
418 default:
419 log_warn(LD_BUG, "Encountered unexpected connection state %d while trying "
420 "to process Extended ORPort authentication data.", conn->state);
421 return -1;
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. */
442 static int
443 connection_ext_or_handle_cmd_useraddr(connection_t *conn,
444 const char *payload, uint16_t len)
446 /* Copy address string. */
447 tor_addr_t addr;
448 uint16_t port;
449 char *addr_str;
450 char *address_part=NULL;
451 int res;
452 if (memchr(payload, '\0', len)) {
453 log_fn(LOG_PROTOCOL_WARN, LD_NET, "Unexpected NUL in ExtORPort UserAddr");
454 return -1;
457 addr_str = tor_memdup_nulterm(payload, len);
459 res = tor_addr_port_split(LOG_INFO, addr_str, &address_part, &port);
460 tor_free(addr_str);
461 if (res<0)
462 return -1;
463 if (port == 0) {
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);
471 if (res<0)
472 return -1;
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);
488 conn->port = port;
489 if (conn->address) {
490 tor_free(conn->address);
492 conn->address = tor_addr_to_str_dup(&addr);
494 return 0;
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. */
504 static int
505 connection_ext_or_handle_cmd_transport(or_connection_t *conn,
506 const char *payload, uint16_t len)
508 char *transport_str;
509 if (memchr(payload, '\0', len)) {
510 log_fn(LOG_PROTOCOL_WARN, LD_NET, "Unexpected NUL in ExtORPort Transport");
511 return -1;
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);
519 return -1;
522 /* If ext_or_transport is already occupied (because the PT sent two
523 * TRANSPORT commands), deallocate the old name and keep the new
524 * one */
525 if (conn->ext_or_transport)
526 tor_free(conn->ext_or_transport);
528 conn->ext_or_transport = transport_str;
529 return 0;
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;
541 int r;
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);
551 if (r < 0) {
552 connection_mark_for_close(conn);
553 return -1;
554 } else if (r == 0) {
555 return 0;
557 /* if r > 0, loop and process more data (if any). */
560 while (1) {
561 log_debug(LD_GENERAL, "Got Extended ORPort data.");
562 command = NULL;
563 r = connection_fetch_ext_or_cmd_from_buf(conn, &command);
564 if (r < 0)
565 goto err;
566 else if (r == 0)
567 return 0; /* need to wait for more data */
569 /* Got a command! */
570 tor_assert(command);
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. */
575 goto err;
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
584 * trigraph. */
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)
596 goto err;
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)
600 goto err;
601 } else {
602 log_notice(LD_NET,"Got Extended ORPort command we don't regognize (%u).",
603 command->cmd);
606 ext_or_cmd_free(command);
609 return 0;
611 err:
612 ext_or_cmd_free(command);
613 connection_mark_for_close(conn);
614 return -1;
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);
627 return 0;
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;
649 return 0;
652 /** Free any leftover allocated memory of the ext_orport.c subsystem. */
653 void
654 ext_orport_free_all(void)
656 if (ext_or_auth_cookie) /* Free the auth cookie */
657 tor_free(ext_or_auth_cookie);