tor  0.4.0.1-alpha
ext_orport.c
Go to the documentation of this file.
1 /* Copyright (c) 2012-2019, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
3 
19 #define EXT_ORPORT_PRIVATE
20 #include "core/or/or.h"
22 #include "core/or/connection_or.h"
24 #include "app/config/config.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 
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 
45 void
47 {
48  tor_free(cmd);
49 }
50 
55 static int
57 {
58  return fetch_ext_or_command_from_buf(conn->inbuf, out);
59 }
60 
65 STATIC int
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 
86 static void
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 
98 #define EXT_OR_PORT_AUTH_COOKIE_LEN 32
99 
100 #define EXT_OR_PORT_AUTH_COOKIE_HEADER_LEN 32
101 
102 #define EXT_OR_PORT_AUTH_COOKIE_HEADER "! Extended ORPort Auth Cookie !\x0a"
103 
104 #define EXT_OR_PORT_AUTH_HASH_LEN DIGEST256_LEN
105 
106 #define EXT_OR_PORT_AUTH_NONCE_LEN 32
107 
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 
122 STATIC uint8_t *ext_or_auth_cookie = NULL;
123 
126 char *
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
142 init_ext_or_cookie_authentication(int is_enabled)
143 {
144  char *fname = NULL;
145  int retval;
146 
147  if (!is_enabled) {
149  return 0;
150  }
151 
155  get_options()->ExtORPortCookieAuthFileGroupReadable,
158  tor_free(fname);
159  return retval;
160 }
161 
169 static int
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
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) +
210  size_t hmac_c_msg_len = strlen(EXT_OR_PORT_AUTH_CLIENT_TO_SERVER_CONST) +
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,
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) +
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) +
233  server_nonce, EXT_OR_PORT_AUTH_NONCE_LEN);
234 
235  crypto_hmac_sha256(server_hash,
236  (char*)ext_or_auth_cookie,
238  hmac_s_msg,
239  hmac_s_msg_len);
240 
241  crypto_hmac_sha256(correct_client_hash,
242  (char*)ext_or_auth_cookie,
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 
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,
286  }
287 
288  *reply_out = reply;
289  *reply_len_out = reply_len;
290 
291  return 0;
292 }
293 
300 static int
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 
350 static void
352 {
353  if (success)
354  connection_buf_add("\x01", 1, conn);
355  else
356  connection_buf_add("\x00", 1, conn);
357 }
358 
366 static int
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 
395 static int
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:
414 
415  case EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE:
417 
418  case EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_HASH:
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 
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 
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 
445 static int
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  return 0;
498 }
499 
507 static int
509  const char *payload, uint16_t len)
510 {
511  char *transport_str;
512  if (memchr(payload, '\0', len)) {
513  log_fn(LOG_PROTOCOL_WARN, LD_NET, "Unexpected NUL in ExtORPort Transport");
514  return -1;
515  }
516 
517  transport_str = tor_memdup_nulterm(payload, len);
518 
519  /* Transport names MUST be C-identifiers. */
520  if (!string_is_C_identifier(transport_str)) {
521  tor_free(transport_str);
522  return -1;
523  }
524 
525  /* If ext_or_transport is already occupied (because the PT sent two
526  * TRANSPORT commands), deallocate the old name and keep the new
527  * one */
528  if (conn->ext_or_transport)
529  tor_free(conn->ext_or_transport);
530 
531  conn->ext_or_transport = transport_str;
532  return 0;
533 }
534 
535 #define EXT_OR_CONN_STATE_IS_AUTHENTICATING(st) \
536  ((st) <= EXT_OR_CONN_STATE_AUTH_MAX)
537 
539 int
541 {
542  connection_t *conn = TO_CONN(or_conn);
543  ext_or_cmd_t *command;
544  int r;
545 
546  /* DOCDOC Document the state machine and transitions in this function */
547 
548  /* If we are still in the authentication stage, process traffic as
549  authentication data: */
550  while (EXT_OR_CONN_STATE_IS_AUTHENTICATING(conn->state)) {
551  log_debug(LD_GENERAL, "Got Extended ORPort authentication data (%u).",
552  (unsigned int) connection_get_inbuf_len(conn));
554  if (r < 0) {
555  connection_mark_for_close(conn);
556  return -1;
557  } else if (r == 0) {
558  return 0;
559  }
560  /* if r > 0, loop and process more data (if any). */
561  }
562 
563  while (1) {
564  log_debug(LD_GENERAL, "Got Extended ORPort data.");
565  command = NULL;
566  r = connection_fetch_ext_or_cmd_from_buf(conn, &command);
567  if (r < 0)
568  goto err;
569  else if (r == 0)
570  return 0; /* need to wait for more data */
571 
572  /* Got a command! */
573  tor_assert(command);
574 
575  if (command->cmd == EXT_OR_CMD_TB_DONE) {
576  if (connection_get_inbuf_len(conn)) {
577  /* The inbuf isn't empty; the client is misbehaving. */
578  goto err;
579  }
580 
581  log_debug(LD_NET, "Received DONE.");
582 
583  /* If the transport proxy did not use the TRANSPORT command to
584  * specify the transport name, mark this as unknown transport. */
585  if (!or_conn->ext_or_transport) {
586  /* We write this string this way to avoid ??>, which is a C
587  * trigraph. */
588  or_conn->ext_or_transport = tor_strdup("<?" "?>");
589  }
590 
592 
593  /* can't transition immediately; need to flush first. */
594  conn->state = EXT_OR_CONN_STATE_FLUSHING;
595  connection_stop_reading(conn);
596  } else if (command->cmd == EXT_OR_CMD_TB_USERADDR) {
598  command->body, command->len) < 0)
599  goto err;
600  } else if (command->cmd == EXT_OR_CMD_TB_TRANSPORT) {
602  command->body, command->len) < 0)
603  goto err;
604  } else {
605  log_notice(LD_NET,"Got Extended ORPort command we don't regognize (%u).",
606  command->cmd);
607  }
608 
609  ext_or_cmd_free(command);
610  }
611 
612  return 0;
613 
614  err:
615  ext_or_cmd_free(command);
616  connection_mark_for_close(conn);
617  return -1;
618 }
619 
623 int
625 {
626  if (conn->base_.state == EXT_OR_CONN_STATE_FLUSHING) {
627  connection_start_reading(TO_CONN(conn));
629  }
630  return 0;
631 }
632 
635 int
637 {
638  connection_t *conn = TO_CONN(or_conn);
639  const uint8_t authtypes[] = {
640  /* We only support authtype '1' for now. */
641  EXT_OR_AUTHTYPE_SAFECOOKIE,
642  /* Marks the end of the list. */
643  0
644  };
645 
646  log_debug(LD_GENERAL,
647  "ExtORPort authentication: Sending supported authentication types");
648 
649  connection_buf_add((const char *)authtypes, sizeof(authtypes), conn);
650  conn->state = EXT_OR_CONN_STATE_AUTH_WAIT_AUTH_TYPE;
651 
652  return 0;
653 }
654 
656 void
658 {
659  if (ext_or_auth_cookie) /* Free the auth cookie */
661 }
662 
#define EXT_OR_PORT_AUTH_COOKIE_LEN
Definition: ext_orport.c:98
Common functions for using (pseudo-)random number generators.
#define TO_CONN(c)
Definition: or.h:735
tor_addr_t addr
Header file for connection.c.
static void connection_ext_or_transition(or_connection_t *conn)
Definition: ext_orport.c:87
static void set_uint16(void *cp, uint16_t v)
Definition: bytes.h:73
#define LD_GENERAL
Definition: log.h:58
uint8_t state
Definition: connection_st.h:44
#define LOG_INFO
Definition: log.h:41
int connection_ext_or_start_auth(or_connection_t *or_conn)
Definition: ext_orport.c:636
Header file for config.c.
#define CONN_TYPE_OR
Definition: connection.h:24
STATIC uint8_t * ext_or_auth_cookie
Definition: ext_orport.c:122
#define EXT_OR_PORT_AUTH_COOKIE_HEADER_LEN
Definition: ext_orport.c:100
uint16_t port
#define tor_free(p)
Definition: malloc.h:52
static int connection_ext_or_auth_process_inbuf(or_connection_t *or_conn)
Definition: ext_orport.c:396
Header file for mainloop.c.
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition: crypto_util.c:57
void crypto_hmac_sha256(char *hmac_out, const char *key, size_t key_len, const char *msg, size_t msg_len)
int string_is_C_identifier(const char *string)
Definition: util_string.c:417
or_connection_t * TO_OR_CONN(connection_t *c)
void connection_or_event_status(or_connection_t *conn, or_conn_status_event_t tp, int reason)
#define CONN_TYPE_EXT_OR
Definition: connection.h:51
struct buf_t * inbuf
Definition: connection_st.h:93
Common functions for cryptographic routines.
tor_assert(buffer)
#define EXT_OR_PORT_AUTH_HASH_LEN
Definition: ext_orport.c:104
uint16_t len
Definition: proto_ext_or.h:15
static int connection_ext_or_auth_handle_client_hash(connection_t *conn)
Definition: ext_orport.c:367
#define EXT_OR_PORT_AUTH_SERVER_TO_CLIENT_CONST
Definition: ext_orport.c:108
Master header file for Tor-specific functionality.
int connection_ext_or_process_inbuf(or_connection_t *or_conn)
Definition: ext_orport.c:540
int tor_addr_parse(tor_addr_t *addr, const char *src)
Definition: address.c:1185
int connection_buf_get_bytes(char *string, size_t len, connection_t *conn)
Definition: connection.c:3869
unsigned int type
Definition: connection_st.h:45
char body[FLEXIBLE_ARRAY_MEMBER]
Definition: proto_ext_or.h:16
void base16_encode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition: binascii.c:476
static int connection_ext_or_handle_cmd_useraddr(connection_t *conn, const char *payload, uint16_t len)
Definition: ext_orport.c:446
int init_cookie_authentication(const char *fname, const char *header, int cookie_len, int group_readable, uint8_t **cookie_out, int *cookie_is_set_out)
Definition: config.c:8409
void ext_orport_free_all(void)
Definition: ext_orport.c:657
char * tor_addr_to_str_dup(const tor_addr_t *addr)
Definition: address.c:1122
static int connection_ext_or_auth_neg_auth_type(connection_t *conn)
Definition: ext_orport.c:170
#define log_fn(severity, domain, args,...)
Definition: log.h:255
static int connection_ext_or_auth_handle_client_nonce(connection_t *conn)
Definition: ext_orport.c:301
#define EXT_OR_PORT_AUTH_NONCE_LEN
Definition: ext_orport.c:106
Header file for control.c.
ext_or_cmd_t * ext_or_cmd_new(uint16_t len)
Definition: ext_orport.c:36
char * get_ext_or_auth_cookie_file_name(void)
Definition: ext_orport.c:127
Header file for connection_or.c.
#define LD_NET
Definition: log.h:62
#define EXT_OR_CMD_BT_OKAY
Definition: ext_orport.c:434
STATIC int connection_write_ext_or_command(connection_t *conn, uint16_t command, const char *body, size_t bodylen)
Definition: ext_orport.c:66
void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src)
Definition: address.c:892
static int connection_ext_or_handle_cmd_transport(or_connection_t *conn, const char *payload, uint16_t len)
Definition: ext_orport.c:508
#define EXT_OR_PORT_AUTH_COOKIE_HEADER
Definition: ext_orport.c:102
STATIC int ext_or_auth_cookie_is_set
Definition: ext_orport.c:118
void ext_or_cmd_free_(ext_or_cmd_t *cmd)
Definition: ext_orport.c:46
char * ExtORPortCookieAuthFile
#define EXT_OR_CMD_TB_DONE
Definition: ext_orport.c:429
#define LD_BUG
Definition: log.h:82
const char * safe_str(const char *address)
Definition: config.c:1076
static int connection_fetch_ext_or_cmd_from_buf(connection_t *conn, ext_or_cmd_t **out)
Definition: ext_orport.c:56
int connection_ext_or_finished_flushing(or_connection_t *conn)
Definition: ext_orport.c:624
int tor_addr_port_split(int severity, const char *addrport, char **address_out, uint16_t *port_out)
Definition: address.c:1751
static void connection_ext_or_auth_send_result(connection_t *conn, int success)
Definition: ext_orport.c:351