LCOV - code coverage report
Current view: top level - feature/relay - ext_orport.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 234 245 95.5 %
Date: 2021-11-24 03:28:48 Functions: 20 20 100.0 %

          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 : }

Generated by: LCOV version 1.14