In routerlist_assert_ok(), check r2 before taking &(r2->cache_info)
[tor.git] / src / or / ext_orport.c
blob9b550ee90e1b78f42d99a7ad44336d6e44b86372
1 /* Copyright (c) 2012, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /**
5 * \file ext_orport.c
6 * \brief Code implementing the Extended ORPort.
7 */
9 #define EXT_ORPORT_PRIVATE
10 #include "or.h"
11 #include "connection.h"
12 #include "connection_or.h"
13 #include "ext_orport.h"
14 #include "control.h"
15 #include "config.h"
16 #include "util.h"
17 #include "main.h"
19 /** Allocate and return a structure capable of holding an Extended
20 * ORPort message of body length <b>len</b>. */
21 ext_or_cmd_t *
22 ext_or_cmd_new(uint16_t len)
24 size_t size = STRUCT_OFFSET(ext_or_cmd_t, body) + len;
25 ext_or_cmd_t *cmd = tor_malloc(size);
26 cmd->len = len;
27 return cmd;
30 /** Deallocate the Extended ORPort message in <b>cmd</b>. */
31 void
32 ext_or_cmd_free(ext_or_cmd_t *cmd)
34 tor_free(cmd);
37 /** Get an Extended ORPort message from <b>conn</b>, and place it in
38 * <b>out</b>. Return -1 on fail, 0 if we need more data, and 1 if we
39 * successfully extracted an Extended ORPort command from the
40 * buffer. */
41 static int
42 connection_fetch_ext_or_cmd_from_buf(connection_t *conn, ext_or_cmd_t **out)
44 IF_HAS_BUFFEREVENT(conn, {
45 struct evbuffer *input = bufferevent_get_input(conn->bufev);
46 return fetch_ext_or_command_from_evbuffer(input, out);
47 }) ELSE_IF_NO_BUFFEREVENT {
48 return fetch_ext_or_command_from_buf(conn->inbuf, out);
52 /** Write an Extended ORPort message to <b>conn</b>. Use
53 * <b>command</b> as the command type, <b>bodylen</b> as the body
54 * length, and <b>body</b>, if it's present, as the body of the
55 * message. */
56 STATIC int
57 connection_write_ext_or_command(connection_t *conn,
58 uint16_t command,
59 const char *body,
60 size_t bodylen)
62 char header[4];
63 if (bodylen > UINT16_MAX)
64 return -1;
65 set_uint16(header, htons(command));
66 set_uint16(header+2, htons(bodylen));
67 connection_write_to_buf(header, 4, conn);
68 if (bodylen) {
69 tor_assert(body);
70 connection_write_to_buf(body, bodylen, conn);
72 return 0;
75 /** Transition from an Extended ORPort which accepts Extended ORPort
76 * messages, to an Extended ORport which accepts OR traffic. */
77 static void
78 connection_ext_or_transition(or_connection_t *conn)
80 tor_assert(conn->base_.type == CONN_TYPE_EXT_OR);
82 conn->base_.type = CONN_TYPE_OR;
83 TO_CONN(conn)->state = 0; // set the state to a neutral value
84 control_event_or_conn_status(conn, OR_CONN_EVENT_NEW, 0);
85 connection_tls_start_handshake(conn, 1);
88 /** Length of authentication cookie. */
89 #define EXT_OR_PORT_AUTH_COOKIE_LEN 32
90 /** Length of the header of the cookie file. */
91 #define EXT_OR_PORT_AUTH_COOKIE_HEADER_LEN 32
92 /** Static cookie file header. */
93 #define EXT_OR_PORT_AUTH_COOKIE_HEADER "! Extended ORPort Auth Cookie !\x0a"
94 /** Length of safe-cookie protocol hashes. */
95 #define EXT_OR_PORT_AUTH_HASH_LEN DIGEST256_LEN
96 /** Length of safe-cookie protocol nonces. */
97 #define EXT_OR_PORT_AUTH_NONCE_LEN 32
98 /** Safe-cookie protocol constants. */
99 #define EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST \
100 "ExtORPort authentication server-to-client hash"
101 #define EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST \
102 "ExtORPort authentication client-to-server hash"
104 /* Code to indicate cookie authentication */
105 #define EXT_OR_AUTHTYPE_SAFECOOKIE 0x01
107 /** If true, we've set ext_or_auth_cookie to a secret code and stored
108 * it to disk. */
109 STATIC int ext_or_auth_cookie_is_set = 0;
110 /** If ext_or_auth_cookie_is_set, a secret cookie that we've stored to disk
111 * and which we're using to authenticate controllers. (If the controller can
112 * read it off disk, it has permission to connect.) */
113 STATIC uint8_t *ext_or_auth_cookie = NULL;
115 /** Helper: Return a newly allocated string containing a path to the
116 * file where we store our authentication cookie. */
117 char *
118 get_ext_or_auth_cookie_file_name(void)
120 const or_options_t *options = get_options();
121 if (options->ExtORPortCookieAuthFile &&
122 strlen(options->ExtORPortCookieAuthFile)) {
123 return tor_strdup(options->ExtORPortCookieAuthFile);
124 } else {
125 return get_datadir_fname("extended_orport_auth_cookie");
129 /* Initialize the cookie-based authentication system of the
130 * Extended ORPort. If <b>is_enabled</b> is 0, then disable the cookie
131 * authentication system. */
133 init_ext_or_cookie_authentication(int is_enabled)
135 char *fname = NULL;
136 int retval;
138 if (!is_enabled) {
139 ext_or_auth_cookie_is_set = 0;
140 return 0;
143 fname = get_ext_or_auth_cookie_file_name();
144 retval = init_cookie_authentication(fname, EXT_OR_PORT_AUTH_COOKIE_HEADER,
145 EXT_OR_PORT_AUTH_COOKIE_HEADER_LEN,
146 get_options()->ExtORPortCookieAuthFileGroupReadable,
147 &ext_or_auth_cookie,
148 &ext_or_auth_cookie_is_set);
149 tor_free(fname);
150 return retval;
153 /** Read data from <b>conn</b> and see if the client sent us the
154 * authentication type that she prefers to use in this session.
156 * Return -1 if we received corrupted data or if we don't support the
157 * authentication type. Return 0 if we need more data in
158 * <b>conn</b>. Return 1 if the authentication type negotiation was
159 * successful. */
160 static int
161 connection_ext_or_auth_neg_auth_type(connection_t *conn)
163 char authtype[1] = {0};
165 if (connection_get_inbuf_len(conn) < 1)
166 return 0;
168 if (connection_fetch_from_buf(authtype, 1, conn) < 0)
169 return -1;
171 log_debug(LD_GENERAL, "Client wants us to use %d auth type", authtype[0]);
172 if (authtype[0] != EXT_OR_AUTHTYPE_SAFECOOKIE) {
173 /* '1' is the only auth type supported atm */
174 return -1;
177 conn->state = EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE;
178 return 1;
181 /** DOCDOC */
182 STATIC int
183 handle_client_auth_nonce(const char *client_nonce, size_t client_nonce_len,
184 char **client_hash_out,
185 char **reply_out, size_t *reply_len_out)
187 char server_hash[EXT_OR_PORT_AUTH_HASH_LEN] = {0};
188 char server_nonce[EXT_OR_PORT_AUTH_NONCE_LEN] = {0};
189 char *reply;
190 size_t reply_len;
192 if (client_nonce_len != EXT_OR_PORT_AUTH_NONCE_LEN)
193 return -1;
195 /* Get our nonce */
196 if (crypto_rand(server_nonce, EXT_OR_PORT_AUTH_NONCE_LEN) < 0)
197 return -1;
199 { /* set up macs */
200 size_t hmac_s_msg_len = strlen(EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST) +
201 2*EXT_OR_PORT_AUTH_NONCE_LEN;
202 size_t hmac_c_msg_len = strlen(EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST) +
203 2*EXT_OR_PORT_AUTH_NONCE_LEN;
205 char *hmac_s_msg = tor_malloc_zero(hmac_s_msg_len);
206 char *hmac_c_msg = tor_malloc_zero(hmac_c_msg_len);
207 char *correct_client_hash = tor_malloc_zero(EXT_OR_PORT_AUTH_HASH_LEN);
209 memcpy(hmac_s_msg,
210 EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST,
211 strlen(EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST));
212 memcpy(hmac_s_msg + strlen(EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST),
213 client_nonce, EXT_OR_PORT_AUTH_NONCE_LEN);
214 memcpy(hmac_s_msg + strlen(EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST) +
215 EXT_OR_PORT_AUTH_NONCE_LEN,
216 server_nonce, EXT_OR_PORT_AUTH_NONCE_LEN);
218 memcpy(hmac_c_msg,
219 EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST,
220 strlen(EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST));
221 memcpy(hmac_c_msg + strlen(EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST),
222 client_nonce, EXT_OR_PORT_AUTH_NONCE_LEN);
223 memcpy(hmac_c_msg + strlen(EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST) +
224 EXT_OR_PORT_AUTH_NONCE_LEN,
225 server_nonce, EXT_OR_PORT_AUTH_NONCE_LEN);
227 crypto_hmac_sha256(server_hash,
228 (char*)ext_or_auth_cookie,
229 EXT_OR_PORT_AUTH_COOKIE_LEN,
230 hmac_s_msg,
231 hmac_s_msg_len);
233 crypto_hmac_sha256(correct_client_hash,
234 (char*)ext_or_auth_cookie,
235 EXT_OR_PORT_AUTH_COOKIE_LEN,
236 hmac_c_msg,
237 hmac_c_msg_len);
239 /* Store the client hash we generated. We will need to compare it
240 with the hash sent by the client. */
241 *client_hash_out = correct_client_hash;
243 memwipe(hmac_s_msg, 0, hmac_s_msg_len);
244 memwipe(hmac_c_msg, 0, hmac_c_msg_len);
246 tor_free(hmac_s_msg);
247 tor_free(hmac_c_msg);
250 { /* debug logging */ /* XXX disable this codepath if not logging on debug?*/
251 char server_hash_encoded[(2*EXT_OR_PORT_AUTH_HASH_LEN) + 1];
252 char server_nonce_encoded[(2*EXT_OR_PORT_AUTH_NONCE_LEN) + 1];
253 char client_nonce_encoded[(2*EXT_OR_PORT_AUTH_NONCE_LEN) + 1];
255 base16_encode(server_hash_encoded, sizeof(server_hash_encoded),
256 server_hash, sizeof(server_hash));
257 base16_encode(server_nonce_encoded, sizeof(server_nonce_encoded),
258 server_nonce, sizeof(server_nonce));
259 base16_encode(client_nonce_encoded, sizeof(client_nonce_encoded),
260 client_nonce, EXT_OR_PORT_AUTH_NONCE_LEN);
262 log_debug(LD_GENERAL,
263 "server_hash: '%s'\nserver_nonce: '%s'\nclient_nonce: '%s'",
264 server_hash_encoded, server_nonce_encoded, client_nonce_encoded);
266 memwipe(server_hash_encoded, 0, sizeof(server_hash_encoded));
267 memwipe(server_nonce_encoded, 0, sizeof(server_nonce_encoded));
268 memwipe(client_nonce_encoded, 0, sizeof(client_nonce_encoded));
271 { /* write reply: (server_hash, server_nonce) */
273 reply_len = EXT_OR_PORT_AUTH_COOKIE_LEN+EXT_OR_PORT_AUTH_NONCE_LEN;
274 reply = tor_malloc_zero(reply_len);
275 memcpy(reply, server_hash, EXT_OR_PORT_AUTH_HASH_LEN);
276 memcpy(reply + EXT_OR_PORT_AUTH_HASH_LEN, server_nonce,
277 EXT_OR_PORT_AUTH_NONCE_LEN);
280 *reply_out = reply;
281 *reply_len_out = reply_len;
283 return 0;
286 /** Read the client's nonce out of <b>conn</b>, setup the safe-cookie
287 * crypto, and then send our own hash and nonce to the client
289 * Return -1 if there was an error; return 0 if we need more data in
290 * <b>conn</b>, and return 1 if we successfully retrieved the
291 * client's nonce and sent our own. */
292 static int
293 connection_ext_or_auth_handle_client_nonce(connection_t *conn)
295 char client_nonce[EXT_OR_PORT_AUTH_NONCE_LEN];
296 char *reply=NULL;
297 size_t reply_len=0;
299 if (!ext_or_auth_cookie_is_set) { /* this should not happen */
300 log_warn(LD_BUG, "Extended ORPort authentication cookie was not set. "
301 "That's weird since we should have done that on startup. "
302 "This might be a Tor bug, please file a bug report. ");
303 return -1;
306 if (connection_get_inbuf_len(conn) < EXT_OR_PORT_AUTH_NONCE_LEN)
307 return 0;
309 if (connection_fetch_from_buf(client_nonce,
310 EXT_OR_PORT_AUTH_NONCE_LEN, conn) < 0)
311 return -1;
313 /* We extract the ClientNonce from the received data, and use it to
314 calculate ServerHash and ServerNonce according to proposal 217.
316 We also calculate our own ClientHash value and save it in the
317 connection state. We validate it later against the ClientHash
318 sent by the client. */
319 if (handle_client_auth_nonce(client_nonce, sizeof(client_nonce),
320 &TO_OR_CONN(conn)->ext_or_auth_correct_client_hash,
321 &reply, &reply_len) < 0)
322 return -1;
324 connection_write_to_buf(reply, reply_len, conn);
326 memwipe(reply, 0, reply_len);
327 tor_free(reply);
329 log_debug(LD_GENERAL, "Got client nonce, and sent our own nonce and hash.");
331 conn->state = EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_HASH;
332 return 1;
335 #define connection_ext_or_auth_send_result_success(c) \
336 connection_ext_or_auth_send_result(c, 1)
337 #define connection_ext_or_auth_send_result_fail(c) \
338 connection_ext_or_auth_send_result(c, 0)
340 /** Send authentication results to <b>conn</b>. Successful results if
341 * <b>success</b> is set; failure results otherwise. */
342 static void
343 connection_ext_or_auth_send_result(connection_t *conn, int success)
345 if (success)
346 connection_write_to_buf("\x01", 1, conn);
347 else
348 connection_write_to_buf("\x00", 1, conn);
351 /** Receive the client's hash from <b>conn</b>, validate that it's
352 * correct, and then send the authentication results to the client.
354 * Return -1 if there was an error during validation; return 0 if we
355 * need more data in <b>conn</b>, and return 1 if we successfully
356 * validated the client's hash and sent a happy authentication
357 * result. */
358 static int
359 connection_ext_or_auth_handle_client_hash(connection_t *conn)
361 char provided_client_hash[EXT_OR_PORT_AUTH_HASH_LEN] = {0};
363 if (connection_get_inbuf_len(conn) < EXT_OR_PORT_AUTH_HASH_LEN)
364 return 0;
366 if (connection_fetch_from_buf(provided_client_hash,
367 EXT_OR_PORT_AUTH_HASH_LEN, conn) < 0)
368 return -1;
370 if (tor_memneq(TO_OR_CONN(conn)->ext_or_auth_correct_client_hash,
371 provided_client_hash, EXT_OR_PORT_AUTH_HASH_LEN)) {
372 log_warn(LD_GENERAL, "Incorrect client hash. Authentication failed.");
373 connection_ext_or_auth_send_result_fail(conn);
374 return -1;
377 log_debug(LD_GENERAL, "Got client's hash and it was legit.");
379 /* send positive auth result */
380 connection_ext_or_auth_send_result_success(conn);
381 conn->state = EXT_OR_CONN_STATE_OPEN;
382 return 1;
385 /** Handle data from <b>or_conn</b> received on Extended ORPort.
386 * Return -1 on error. 0 on unsufficient data. 1 on correct. */
387 static int
388 connection_ext_or_auth_process_inbuf(or_connection_t *or_conn)
390 connection_t *conn = TO_CONN(or_conn);
392 /* State transitions of the Extended ORPort authentication protocol:
394 EXT_OR_CONN_STATE_AUTH_WAIT_AUTH_TYPE (start state) ->
395 EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE ->
396 EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_HASH ->
397 EXT_OR_CONN_STATE_OPEN
399 During EXT_OR_CONN_STATE_OPEN, data is handled by
400 connection_ext_or_process_inbuf().
403 switch (conn->state) { /* Functionify */
404 case EXT_OR_CONN_STATE_AUTH_WAIT_AUTH_TYPE:
405 return connection_ext_or_auth_neg_auth_type(conn);
407 case EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE:
408 return connection_ext_or_auth_handle_client_nonce(conn);
410 case EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_HASH:
411 return connection_ext_or_auth_handle_client_hash(conn);
413 default:
414 log_warn(LD_BUG, "Encountered unexpected connection state %d while trying "
415 "to process Extended ORPort authentication data.", conn->state);
416 return -1;
420 /** Extended ORPort commands (Transport-to-Bridge) */
421 #define EXT_OR_CMD_TB_DONE 0x0000
422 #define EXT_OR_CMD_TB_USERADDR 0x0001
423 #define EXT_OR_CMD_TB_TRANSPORT 0x0002
425 /** Extended ORPort commands (Bridge-to-Transport) */
426 #define EXT_OR_CMD_BT_OKAY 0x1000
427 #define EXT_OR_CMD_BT_DENY 0x1001
428 #define EXT_OR_CMD_BT_CONTROL 0x1002
430 /** Process a USERADDR command from the Extended
431 * ORPort. <b>payload</b> is a payload of size <b>len</b>.
433 * If the USERADDR command was well formed, change the address of
434 * <b>conn</b> to the address on the USERADDR command.
436 * Return 0 on success and -1 on error. */
437 static int
438 connection_ext_or_handle_cmd_useraddr(connection_t *conn,
439 const char *payload, uint16_t len)
441 /* Copy address string. */
442 tor_addr_t addr;
443 uint16_t port;
444 char *addr_str;
445 char *address_part=NULL;
446 int res;
447 if (memchr(payload, '\0', len)) {
448 log_fn(LOG_PROTOCOL_WARN, LD_NET, "Unexpected NUL in ExtORPort UserAddr");
449 return -1;
452 addr_str = tor_memdup_nulterm(payload, len);
454 res = tor_addr_port_split(LOG_INFO, addr_str, &address_part, &port);
455 tor_free(addr_str);
456 if (res<0)
457 return -1;
459 res = tor_addr_parse(&addr, address_part);
460 tor_free(address_part);
461 if (res<0)
462 return -1;
464 { /* do some logging */
465 char *old_address = tor_dup_addr(&conn->addr);
466 char *new_address = tor_dup_addr(&addr);
468 log_debug(LD_NET, "Received USERADDR."
469 "We rewrite our address from '%s:%u' to '%s:%u'.",
470 safe_str(old_address), conn->port, safe_str(new_address), port);
472 tor_free(old_address);
473 tor_free(new_address);
476 /* record the address */
477 tor_addr_copy(&conn->addr, &addr);
478 conn->port = port;
479 if (conn->address) {
480 tor_free(conn->address);
482 conn->address = tor_dup_addr(&addr);
484 return 0;
487 /** Process a TRANSPORT command from the Extended
488 * ORPort. <b>payload</b> is a payload of size <b>len</b>.
490 * If the TRANSPORT command was well formed, register the name of the
491 * transport on <b>conn</b>.
493 * Return 0 on success and -1 on error. */
494 static int
495 connection_ext_or_handle_cmd_transport(or_connection_t *conn,
496 const char *payload, uint16_t len)
498 char *transport_str;
499 if (memchr(payload, '\0', len)) {
500 log_fn(LOG_PROTOCOL_WARN, LD_NET, "Unexpected NUL in ExtORPort Transport");
501 return -1;
504 transport_str = tor_memdup_nulterm(payload, len);
506 /* Transport names MUST be C-identifiers. */
507 if (!string_is_C_identifier(transport_str)) {
508 tor_free(transport_str);
509 return -1;
512 /* If ext_or_transport is already occupied (because the PT sent two
513 * TRANSPORT commands), deallocate the old name and keep the new
514 * one */
515 if (conn->ext_or_transport)
516 tor_free(conn->ext_or_transport);
518 conn->ext_or_transport = transport_str;
519 return 0;
522 #define EXT_OR_CONN_STATE_IS_AUTHENTICATING(st) \
523 ((st) <= EXT_OR_CONN_STATE_AUTH_MAX)
525 /** Process Extended ORPort messages from <b>or_conn</b>. */
527 connection_ext_or_process_inbuf(or_connection_t *or_conn)
529 connection_t *conn = TO_CONN(or_conn);
530 ext_or_cmd_t *command;
531 int r;
533 /* DOCDOC Document the state machine and transitions in this function */
535 /* If we are still in the authentication stage, process traffic as
536 authentication data: */
537 while (EXT_OR_CONN_STATE_IS_AUTHENTICATING(conn->state)) {
538 log_debug(LD_GENERAL, "Got Extended ORPort authentication data (%u).",
539 (unsigned int) connection_get_inbuf_len(conn));
540 r = connection_ext_or_auth_process_inbuf(or_conn);
541 if (r < 0) {
542 connection_mark_for_close(conn);
543 return -1;
544 } else if (r == 0) {
545 return 0;
547 /* if r > 0, loop and process more data (if any). */
550 while (1) {
551 log_debug(LD_GENERAL, "Got Extended ORPort data.");
552 command = NULL;
553 r = connection_fetch_ext_or_cmd_from_buf(conn, &command);
554 if (r < 0)
555 goto err;
556 else if (r == 0)
557 return 0; /* need to wait for more data */
559 /* Got a command! */
560 tor_assert(command);
562 if (command->cmd == EXT_OR_CMD_TB_DONE) {
563 if (connection_get_inbuf_len(conn)) {
564 /* The inbuf isn't empty; the client is misbehaving. */
565 goto err;
568 log_debug(LD_NET, "Received DONE.");
570 /* If the transport proxy did not use the TRANSPORT command to
571 * specify the transport name, mark this as unknown transport. */
572 if (!or_conn->ext_or_transport) {
573 /* We write this string this way to avoid ??>, which is a C
574 * trigraph. */
575 or_conn->ext_or_transport = tor_strdup("<?" "?>");
578 connection_write_ext_or_command(conn, EXT_OR_CMD_BT_OKAY, NULL, 0);
580 /* can't transition immediately; need to flush first. */
581 conn->state = EXT_OR_CONN_STATE_FLUSHING;
582 connection_stop_reading(conn);
583 } else if (command->cmd == EXT_OR_CMD_TB_USERADDR) {
584 if (connection_ext_or_handle_cmd_useraddr(conn,
585 command->body, command->len) < 0)
586 goto err;
587 } else if (command->cmd == EXT_OR_CMD_TB_TRANSPORT) {
588 if (connection_ext_or_handle_cmd_transport(or_conn,
589 command->body, command->len) < 0)
590 goto err;
591 } else {
592 log_notice(LD_NET,"Got Extended ORPort command we don't regognize (%u).",
593 command->cmd);
596 ext_or_cmd_free(command);
599 return 0;
601 err:
602 ext_or_cmd_free(command);
603 connection_mark_for_close(conn);
604 return -1;
607 /** <b>conn</b> finished flushing Extended ORPort messages to the
608 * network, and is now ready to accept OR traffic. This function
609 * does the transition. */
611 connection_ext_or_finished_flushing(or_connection_t *conn)
613 if (conn->base_.state == EXT_OR_CONN_STATE_FLUSHING) {
614 connection_start_reading(TO_CONN(conn));
615 connection_ext_or_transition(conn);
617 return 0;
620 /** Initiate Extended ORPort authentication, by sending the list of
621 * supported authentication types to the client. */
623 connection_ext_or_start_auth(or_connection_t *or_conn)
625 connection_t *conn = TO_CONN(or_conn);
626 const uint8_t authtypes[] = {
627 /* We only support authtype '1' for now. */
628 EXT_OR_AUTHTYPE_SAFECOOKIE,
629 /* Marks the end of the list. */
633 log_debug(LD_GENERAL,
634 "ExtORPort authentication: Sending supported authentication types");
636 connection_write_to_buf((const char *)authtypes, sizeof(authtypes), conn);
637 conn->state = EXT_OR_CONN_STATE_AUTH_WAIT_AUTH_TYPE;
639 return 0;
642 /** Free any leftover allocated memory of the ext_orport.c subsystem. */
643 void
644 ext_orport_free_all(void)
646 if (ext_or_auth_cookie) /* Free the auth cookie */
647 tor_free(ext_or_auth_cookie);