tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

proto_socks.c (36837B)


      1 /* Copyright (c) 2001 Matej Pfajfar.
      2 * Copyright (c) 2001-2004, Roger Dingledine.
      3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      5 /* See LICENSE for licensing information */
      6 
      7 /**
      8 * @file proto_socks.c
      9 * @brief Implementations for SOCKS4 and SOCKS5 protocols.
     10 **/
     11 
     12 #include "core/or/or.h"
     13 #include "feature/client/addressmap.h"
     14 #include "lib/buf/buffers.h"
     15 #include "core/mainloop/connection.h"
     16 #include "feature/control/control_events.h"
     17 #include "app/config/config.h"
     18 #include "lib/crypt_ops/crypto_util.h"
     19 #include "feature/relay/ext_orport.h"
     20 #include "core/proto/proto_socks.h"
     21 #include "core/or/reasons.h"
     22 
     23 #include "core/or/socks_request_st.h"
     24 
     25 #include "trunnel/socks5.h"
     26 
     27 #define SOCKS_VER_5 0x05 /* First octet of non-auth SOCKS5 messages */
     28 #define SOCKS_VER_4 0x04 /*                SOCKS4 messages */
     29 #define SOCKS_AUTH  0x01 /*                SOCKS5 auth messages */
     30 
     31 typedef enum {
     32  SOCKS_RESULT_INVALID       = -1, /* Message invalid. */
     33  SOCKS_RESULT_TRUNCATED     =  0, /* Message incomplete/truncated. */
     34  SOCKS_RESULT_DONE          =  1, /* OK, we're done. */
     35  SOCKS_RESULT_MORE_EXPECTED =  2, /* OK, more messages expected. */
     36 } socks_result_t;
     37 
     38 static void socks_request_set_socks5_error(socks_request_t *req,
     39                              socks5_reply_status_t reason);
     40 
     41 static socks_result_t parse_socks(const char *data,
     42                                  size_t datalen,
     43                                  socks_request_t *req,
     44                                  int log_sockstype,
     45                                  int safe_socks,
     46                                  size_t *drain_out);
     47 static int parse_socks_client(const uint8_t *data, size_t datalen,
     48                              int state, char **reason,
     49                              ssize_t *drain_out);
     50 /**
     51 * Wait this many seconds before warning the user about using SOCKS unsafely
     52 * again. */
     53 #define SOCKS_WARN_INTERVAL 5
     54 
     55 /** Warn that the user application has made an unsafe socks request using
     56 * protocol <b>socks_protocol</b> on port <b>port</b>.  Don't warn more than
     57 * once per SOCKS_WARN_INTERVAL, unless <b>safe_socks</b> is set. */
     58 static void
     59 log_unsafe_socks_warning(int socks_protocol, const char *address,
     60                         uint16_t port, int safe_socks)
     61 {
     62  static ratelim_t socks_ratelim = RATELIM_INIT(SOCKS_WARN_INTERVAL);
     63 
     64  if (safe_socks) {
     65    log_fn_ratelim(&socks_ratelim, LOG_WARN, LD_APP,
     66             "Your application (using socks%d to port %d) is giving "
     67             "Tor only an IP address. Applications that do DNS resolves "
     68             "themselves may leak information. Consider using Socks4A "
     69             "(e.g. via privoxy or socat) instead. For more information, "
     70             "please see https://2019.www.torproject.org/docs/faq.html.en"
     71             "#WarningsAboutSOCKSandDNSInformationLeaks.%s",
     72             socks_protocol,
     73             (int)port,
     74             safe_socks ? " Rejecting." : "");
     75  }
     76  control_event_client_status(LOG_WARN,
     77                              "DANGEROUS_SOCKS PROTOCOL=SOCKS%d ADDRESS=%s:%d",
     78                              socks_protocol, address, (int)port);
     79 }
     80 
     81 /** Do not attempt to parse socks messages longer than this.  This value is
     82 * actually significantly higher than the longest possible socks message. */
     83 #define MAX_SOCKS_MESSAGE_LEN 512
     84 
     85 /** Return a new socks_request_t. */
     86 socks_request_t *
     87 socks_request_new(void)
     88 {
     89  return tor_malloc_zero(sizeof(socks_request_t));
     90 }
     91 
     92 /** Free all storage held in the socks_request_t <b>req</b>. */
     93 void
     94 socks_request_free_(socks_request_t *req)
     95 {
     96  if (!req)
     97    return;
     98  if (req->username) {
     99    memwipe(req->username, 0x10, req->usernamelen);
    100    tor_free(req->username);
    101  }
    102  if (req->password) {
    103    memwipe(req->password, 0x04, req->passwordlen);
    104    tor_free(req->password);
    105  }
    106  memwipe(req, 0xCC, sizeof(socks_request_t));
    107  tor_free(req);
    108 }
    109 
    110 /**
    111 * Parse a single SOCKS4 request from buffer <b>raw_data</b> of length
    112 * <b>datalen</b> and update relevant fields of <b>req</b>. If SOCKS4a
    113 * request is detected, set <b>*is_socks4a</b> to true. Set <b>*drain_out</b>
    114 * to number of bytes we parsed so far.
    115 *
    116 * Return SOCKS_RESULT_DONE if parsing succeeded, SOCKS_RESULT_INVALID if
    117 * parsing failed because of invalid input or SOCKS_RESULT_TRUNCATED if it
    118 * failed due to incomplete (truncated) input.
    119 */
    120 static socks_result_t
    121 parse_socks4_request(const uint8_t *raw_data, socks_request_t *req,
    122                     size_t datalen, int *is_socks4a, size_t *drain_out)
    123 {
    124  // http://ss5.sourceforge.net/socks4.protocol.txt
    125  // http://ss5.sourceforge.net/socks4A.protocol.txt
    126  socks_result_t res = SOCKS_RESULT_DONE;
    127  tor_addr_t destaddr;
    128 
    129  tor_assert(is_socks4a);
    130  tor_assert(drain_out);
    131 
    132  *is_socks4a = 0;
    133  *drain_out = 0;
    134 
    135  req->socks_version = SOCKS_VER_4;
    136 
    137  socks4_client_request_t *trunnel_req;
    138 
    139  ssize_t parsed =
    140  socks4_client_request_parse(&trunnel_req, raw_data, datalen);
    141 
    142  if (parsed == -1) {
    143    log_warn(LD_APP, "socks4: parsing failed - invalid request.");
    144    res = SOCKS_RESULT_INVALID;
    145    goto end;
    146  } else if (parsed == -2) {
    147    res = SOCKS_RESULT_TRUNCATED;
    148    if (datalen >= MAX_SOCKS_MESSAGE_LEN) {
    149      log_warn(LD_APP, "socks4: parsing failed - invalid request.");
    150      res = SOCKS_RESULT_INVALID;
    151    }
    152    goto end;
    153  }
    154 
    155  tor_assert(parsed >= 0);
    156  *drain_out = (size_t)parsed;
    157 
    158  uint8_t command = socks4_client_request_get_command(trunnel_req);
    159  req->command = command;
    160 
    161  req->port = socks4_client_request_get_port(trunnel_req);
    162  uint32_t dest_ip = socks4_client_request_get_addr(trunnel_req);
    163 
    164  if ((!req->port && req->command != SOCKS_COMMAND_RESOLVE) ||
    165      dest_ip == 0) {
    166    log_warn(LD_APP, "socks4: Port or DestIP is zero. Rejecting.");
    167    res = SOCKS_RESULT_INVALID;
    168    goto end;
    169  }
    170 
    171  *is_socks4a = (dest_ip >> 8) == 0;
    172 
    173  const char *username = socks4_client_request_get_username(trunnel_req);
    174  const size_t usernamelen = username ? strlen(username) : 0;
    175  if (username && usernamelen) {
    176    if (usernamelen > MAX_SOCKS_MESSAGE_LEN) {
    177      log_warn(LD_APP, "Socks4 user name too long; rejecting.");
    178      res = SOCKS_RESULT_INVALID;
    179      goto end;
    180    }
    181 
    182    tor_free(req->username);
    183    req->got_auth = 1;
    184    req->username = tor_strdup(username);
    185    req->usernamelen = usernamelen;
    186  }
    187 
    188  if (*is_socks4a) {
    189    const char *trunnel_hostname =
    190      socks4_client_request_get_socks4a_addr_hostname(trunnel_req);
    191    if (BUG(!trunnel_hostname)) {
    192      res = SOCKS_RESULT_INVALID;
    193      goto end;
    194    }
    195    size_t hostname_len = strlen(trunnel_hostname);
    196    if (hostname_len < sizeof(req->address)) {
    197      strlcpy(req->address, trunnel_hostname, sizeof(req->address));
    198    } else {
    199      log_warn(LD_APP, "socks4: Destaddr too long. Rejecting.");
    200      res = SOCKS_RESULT_INVALID;
    201      goto end;
    202    }
    203  } else {
    204    tor_addr_from_ipv4h(&destaddr, dest_ip);
    205 
    206    if (!tor_addr_to_str(req->address, &destaddr,
    207                         MAX_SOCKS_ADDR_LEN, 0)) {
    208      res = SOCKS_RESULT_INVALID;
    209      goto end;
    210    }
    211  }
    212 
    213  end:
    214  socks4_client_request_free(trunnel_req);
    215 
    216  return res;
    217 }
    218 
    219 /**
    220 * Validate SOCKS4/4a related fields in <b>req</b>. Expect SOCKS4a
    221 * if <b>is_socks4a</b> is true. If <b>log_sockstype</b> is true,
    222 * log a notice about possible DNS leaks on local system. If
    223 * <b>safe_socks</b> is true, reject insecure usage of SOCKS
    224 * protocol.
    225 *
    226 * Return SOCKS_RESULT_DONE if validation passed or
    227 * SOCKS_RESULT_INVALID if it failed.
    228 */
    229 static socks_result_t
    230 process_socks4_request(const socks_request_t *req, int is_socks4a,
    231                       int log_sockstype, int safe_socks)
    232 {
    233  if (!is_socks4a && !addressmap_have_mapping(req->address, 0)) {
    234    log_unsafe_socks_warning(4, req->address, req->port, safe_socks);
    235 
    236    if (safe_socks)
    237      return SOCKS_RESULT_INVALID;
    238  }
    239 
    240  if (req->command != SOCKS_COMMAND_CONNECT &&
    241      req->command != SOCKS_COMMAND_RESOLVE) {
    242    /* not a connect or resolve? we don't support it. (No resolve_ptr with
    243     * socks4.) */
    244    log_warn(LD_APP, "socks4: command %d not recognized. Rejecting.",
    245             req->command);
    246    return SOCKS_RESULT_INVALID;
    247  }
    248 
    249  if (is_socks4a) {
    250    if (log_sockstype)
    251      log_notice(LD_APP,
    252                 "Your application (using socks4a to port %d) instructed "
    253                 "Tor to take care of the DNS resolution itself if "
    254                 "necessary. This is good.", req->port);
    255  }
    256 
    257  if (!string_is_valid_dest(req->address)) {
    258    log_warn(LD_PROTOCOL,
    259             "Your application (using socks4 to port %d) gave Tor "
    260             "a malformed hostname: %s. Rejecting the connection.",
    261             req->port, escaped_safe_str_client(req->address));
    262     return SOCKS_RESULT_INVALID;
    263  }
    264 
    265  return SOCKS_RESULT_DONE;
    266 }
    267 
    268 /** Parse a single SOCKS5 version identifier/method selection message
    269 * from buffer <b>raw_data</b> (of length <b>datalen</b>). Update
    270 * relevant fields of <b>req</b> (if any). Set <b>*have_user_pass</b> to
    271 * true if username/password method is found. Set <b>*have_no_auth</b>
    272 * if no-auth method is found. Set <b>*drain_out</b> to number of bytes
    273 * we parsed so far.
    274 *
    275 * Return SOCKS_RESULT_DONE if parsing succeeded, SOCKS_RESULT_INVALID if
    276 * parsing failed because of invalid input or SOCKS_RESULT_TRUNCATED if it
    277 * failed due to incomplete (truncated) input.
    278 */
    279 static socks_result_t
    280 parse_socks5_methods_request(const uint8_t *raw_data, socks_request_t *req,
    281                             size_t datalen, int *have_user_pass,
    282                             int *have_no_auth, size_t *drain_out)
    283 {
    284  socks_result_t res = SOCKS_RESULT_DONE;
    285  socks5_client_version_t *trunnel_req;
    286 
    287  ssize_t parsed = socks5_client_version_parse(&trunnel_req, raw_data,
    288                                               datalen);
    289 
    290  (void)req;
    291 
    292  tor_assert(have_no_auth);
    293  tor_assert(have_user_pass);
    294  tor_assert(drain_out);
    295 
    296  *drain_out = 0;
    297 
    298  if (parsed == -1) {
    299    log_warn(LD_APP, "socks5: parsing failed - invalid version "
    300                     "id/method selection message.");
    301    res = SOCKS_RESULT_INVALID;
    302    goto end;
    303  } else if (parsed == -2) {
    304    res = SOCKS_RESULT_TRUNCATED;
    305    if (datalen > MAX_SOCKS_MESSAGE_LEN) {
    306      log_warn(LD_APP, "socks5: parsing failed - invalid version "
    307                       "id/method selection message.");
    308      res = SOCKS_RESULT_INVALID;
    309    }
    310    goto end;
    311  }
    312 
    313  tor_assert(parsed >= 0);
    314  *drain_out = (size_t)parsed;
    315 
    316  size_t n_methods = (size_t)socks5_client_version_get_n_methods(trunnel_req);
    317  if (n_methods == 0) {
    318    res = SOCKS_RESULT_INVALID;
    319    goto end;
    320  }
    321 
    322  *have_no_auth = 0;
    323  *have_user_pass = 0;
    324 
    325  for (size_t i = 0; i < n_methods; i++) {
    326    uint8_t method = socks5_client_version_get_methods(trunnel_req,
    327                                                       i);
    328 
    329    if (method == SOCKS_USER_PASS) {
    330      *have_user_pass = 1;
    331    } else if (method == SOCKS_NO_AUTH) {
    332      *have_no_auth = 1;
    333    }
    334  }
    335 
    336  end:
    337  socks5_client_version_free(trunnel_req);
    338 
    339  return res;
    340 }
    341 
    342 /**
    343 * Validate and respond to version identifier/method selection message
    344 * we parsed in parse_socks5_methods_request (corresponding to <b>req</b>
    345 * and having user/pass method if <b>have_user_pass</b> is true, no-auth
    346 * method if <b>have_no_auth</b> is true). Set <b>req->reply</b> to
    347 * an appropriate response (in SOCKS5 wire format).
    348 *
    349 * On success, return SOCKS_RESULT_DONE. On failure, return
    350 * SOCKS_RESULT_INVALID.
    351 */
    352 static socks_result_t
    353 process_socks5_methods_request(socks_request_t *req, int have_user_pass,
    354                               int have_no_auth)
    355 {
    356  socks_result_t res = SOCKS_RESULT_DONE;
    357  socks5_server_method_t *trunnel_resp = socks5_server_method_new();
    358  tor_assert(trunnel_resp);
    359 
    360  socks5_server_method_set_version(trunnel_resp, SOCKS_VER_5);
    361 
    362  if (have_user_pass && !(have_no_auth && req->socks_prefer_no_auth)) {
    363    req->auth_type = SOCKS_USER_PASS;
    364    socks5_server_method_set_method(trunnel_resp, SOCKS_USER_PASS);
    365 
    366    req->socks_version = SOCKS_VER_5;
    367    // FIXME: come up with better way to remember
    368    // that we negotiated auth
    369 
    370    log_debug(LD_APP,"socks5: accepted method 2 (username/password)");
    371  } else if (have_no_auth) {
    372    req->auth_type = SOCKS_NO_AUTH;
    373    socks5_server_method_set_method(trunnel_resp, SOCKS_NO_AUTH);
    374 
    375    req->socks_version = SOCKS_VER_5;
    376 
    377    log_debug(LD_APP,"socks5: accepted method 0 (no authentication)");
    378  } else {
    379    log_warn(LD_APP,
    380             "socks5: offered methods don't include 'no auth' or "
    381             "username/password. Rejecting.");
    382    socks5_server_method_set_method(trunnel_resp, 0xFF); // reject all
    383    res = SOCKS_RESULT_INVALID;
    384  }
    385 
    386  const char *errmsg = socks5_server_method_check(trunnel_resp);
    387  if (errmsg) {
    388    log_warn(LD_APP, "socks5: method selection validation failed: %s",
    389             errmsg);
    390    res = SOCKS_RESULT_INVALID;
    391  } else {
    392    ssize_t encoded =
    393    socks5_server_method_encode(req->reply, sizeof(req->reply),
    394                                trunnel_resp);
    395 
    396    if (encoded < 0) {
    397      log_warn(LD_APP, "socks5: method selection encoding failed");
    398      res = SOCKS_RESULT_INVALID;
    399    } else {
    400      req->replylen = (size_t)encoded;
    401    }
    402  }
    403 
    404  socks5_server_method_free(trunnel_resp);
    405  return res;
    406 }
    407 
    408 /**
    409 * Parse SOCKS5/RFC1929 username/password request from buffer
    410 * <b>raw_data</b> of length <b>datalen</b> and update relevant
    411 * fields of <b>req</b>. Set <b>*drain_out</b> to number of bytes
    412 * we parsed so far.
    413 *
    414 * Return SOCKS_RESULT_DONE if parsing succeeded, SOCKS_RESULT_INVALID if
    415 * parsing failed because of invalid input or SOCKS_RESULT_TRUNCATED if it
    416 * failed due to incomplete (truncated) input.
    417 */
    418 static socks_result_t
    419 parse_socks5_userpass_auth(const uint8_t *raw_data, socks_request_t *req,
    420                           size_t datalen, size_t *drain_out)
    421 {
    422  socks_result_t res = SOCKS_RESULT_DONE;
    423  socks5_client_userpass_auth_t *trunnel_req = NULL;
    424  ssize_t parsed = socks5_client_userpass_auth_parse(&trunnel_req, raw_data,
    425                                                     datalen);
    426  tor_assert(drain_out);
    427  *drain_out = 0;
    428 
    429  if (parsed == -1) {
    430    log_warn(LD_APP, "socks5: parsing failed - invalid user/pass "
    431                     "authentication message.");
    432    res = SOCKS_RESULT_INVALID;
    433    goto end;
    434  } else if (parsed == -2) {
    435    res = SOCKS_RESULT_TRUNCATED;
    436    goto end;
    437  }
    438 
    439  tor_assert(parsed >= 0);
    440  *drain_out = (size_t)parsed;
    441 
    442  uint8_t usernamelen =
    443   socks5_client_userpass_auth_get_username_len(trunnel_req);
    444  uint8_t passwordlen =
    445   socks5_client_userpass_auth_get_passwd_len(trunnel_req);
    446  const char *username =
    447   socks5_client_userpass_auth_getconstarray_username(trunnel_req);
    448  const char *password =
    449   socks5_client_userpass_auth_getconstarray_passwd(trunnel_req);
    450 
    451  /* Detect invalid SOCKS5 extended-parameter requests. */
    452  if (usernamelen >= 8 &&
    453      tor_memeq(username, "<torS0X>", 8)) {
    454    /* This is indeed an extended-parameter request. */
    455    if (usernamelen != 9 ||
    456        tor_memneq(username, "<torS0X>0", 9)) {
    457      /* This request is an unrecognized version, or it includes an Arti RPC
    458       * object ID (which we do not recognize). */
    459      res = SOCKS_RESULT_INVALID;
    460      goto end;
    461    }
    462  }
    463 
    464  if (usernamelen && username) {
    465    tor_free(req->username);
    466    req->username = tor_memdup_nulterm(username, usernamelen);
    467    req->usernamelen = usernamelen;
    468  }
    469 
    470  if (passwordlen && password) {
    471    tor_free(req->password);
    472    req->password = tor_memdup_nulterm(password, passwordlen);
    473    req->passwordlen = passwordlen;
    474  }
    475 
    476  /**
    477   * Yes, we allow username and/or password to be empty. Yes, that does
    478   * violate RFC 1929. However, some client software can send a username/
    479   * password message with these fields being empty and we want to allow them
    480   * to be used with Tor.
    481   */
    482  req->got_auth = 1;
    483 
    484  end:
    485  socks5_client_userpass_auth_free(trunnel_req);
    486  return res;
    487 }
    488 
    489 /**
    490 * Validate and respond to SOCKS5 username/password request we
    491 * parsed in parse_socks5_userpass_auth (corresponding to <b>req</b>.
    492 * Set <b>req->reply</b> to appropriate response. Return
    493 * SOCKS_RESULT_DONE on success or SOCKS_RESULT_INVALID on failure.
    494 */
    495 static socks_result_t
    496 process_socks5_userpass_auth(socks_request_t *req)
    497 {
    498  socks_result_t res = SOCKS_RESULT_DONE;
    499  socks5_server_userpass_auth_t *trunnel_resp =
    500    socks5_server_userpass_auth_new();
    501  tor_assert(trunnel_resp);
    502 
    503  if (req->socks_version != SOCKS_VER_5) {
    504    res = SOCKS_RESULT_INVALID;
    505    goto end;
    506  }
    507 
    508  if (req->auth_type != SOCKS_USER_PASS &&
    509      req->auth_type != SOCKS_NO_AUTH) {
    510    res = SOCKS_RESULT_INVALID;
    511    goto end;
    512  }
    513 
    514  socks5_server_userpass_auth_set_version(trunnel_resp, SOCKS_AUTH);
    515  socks5_server_userpass_auth_set_status(trunnel_resp, 0); // auth OK
    516 
    517  const char *errmsg = socks5_server_userpass_auth_check(trunnel_resp);
    518  if (errmsg) {
    519    log_warn(LD_APP, "socks5: server userpass auth validation failed: %s",
    520             errmsg);
    521    res = SOCKS_RESULT_INVALID;
    522    goto end;
    523  }
    524 
    525  ssize_t encoded = socks5_server_userpass_auth_encode(req->reply,
    526                                                       sizeof(req->reply),
    527                                                       trunnel_resp);
    528 
    529  if (encoded < 0) {
    530    log_warn(LD_APP, "socks5: server userpass auth encoding failed");
    531    res = SOCKS_RESULT_INVALID;
    532    goto end;
    533  }
    534 
    535  req->replylen = (size_t)encoded;
    536 
    537  end:
    538  socks5_server_userpass_auth_free(trunnel_resp);
    539  return res;
    540 }
    541 
    542 /**
    543 * Parse a single SOCKS5 client request (RFC 1928 section 4) from buffer
    544 * <b>raw_data</b> of length <b>datalen</b> and update relevant field of
    545 * <b>req</b>. Set <b>*drain_out</b> to number of bytes we parsed so far.
    546 *
    547 * Return SOCKS_RESULT_DONE if parsing succeeded, SOCKS_RESULT_INVALID if
    548 * parsing failed because of invalid input or SOCKS_RESULT_TRUNCATED if it
    549 * failed due to incomplete (truncated) input.
    550 */
    551 static socks_result_t
    552 parse_socks5_client_request(const uint8_t *raw_data, socks_request_t *req,
    553                            size_t datalen, size_t *drain_out)
    554 {
    555  socks_result_t res = SOCKS_RESULT_DONE;
    556  tor_addr_t destaddr;
    557  socks5_client_request_t *trunnel_req = NULL;
    558  ssize_t parsed =
    559   socks5_client_request_parse(&trunnel_req, raw_data, datalen);
    560  if (parsed == -1) {
    561    log_warn(LD_APP, "socks5: parsing failed - invalid client request");
    562    res = SOCKS_RESULT_INVALID;
    563    socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
    564    goto end;
    565  } else if (parsed == -2) {
    566    res = SOCKS_RESULT_TRUNCATED;
    567    goto end;
    568  }
    569 
    570  tor_assert(parsed >= 0);
    571  *drain_out = (size_t)parsed;
    572 
    573  if (socks5_client_request_get_version(trunnel_req) != 5) {
    574    res = SOCKS_RESULT_INVALID;
    575    socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
    576    goto end;
    577  }
    578 
    579  req->command = socks5_client_request_get_command(trunnel_req);
    580 
    581  req->port = socks5_client_request_get_dest_port(trunnel_req);
    582 
    583  uint8_t atype = socks5_client_request_get_atype(trunnel_req);
    584  req->socks5_atyp = atype;
    585 
    586  switch (atype) {
    587    case 1: {
    588      uint32_t ipv4 = socks5_client_request_get_dest_addr_ipv4(trunnel_req);
    589      tor_addr_from_ipv4h(&destaddr, ipv4);
    590 
    591      tor_addr_to_str(req->address, &destaddr, sizeof(req->address), 1);
    592    } break;
    593    case 3: {
    594      const struct domainname_st *dns_name =
    595        socks5_client_request_getconst_dest_addr_domainname(trunnel_req);
    596 
    597      const char *hostname = domainname_getconstarray_name(dns_name);
    598 
    599      strlcpy(req->address, hostname, sizeof(req->address));
    600    } break;
    601    case 4: {
    602      const uint8_t *ipv6 =
    603          socks5_client_request_getarray_dest_addr_ipv6(trunnel_req);
    604      tor_addr_from_ipv6_bytes(&destaddr, ipv6);
    605 
    606      tor_addr_to_str(req->address, &destaddr, sizeof(req->address), 1);
    607    } break;
    608    default: {
    609      socks_request_set_socks5_error(req, SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED);
    610      res = -1;
    611    } break;
    612  }
    613 
    614  end:
    615  socks5_client_request_free(trunnel_req);
    616  return res;
    617 }
    618 
    619 /**
    620 * Validate and respond to SOCKS5 request we parsed in
    621 * parse_socks5_client_request (corresponding to <b>req</b>.
    622 * Write appropriate response to <b>req->reply</b> (in
    623 * SOCKS5 wire format). If <b>log_sockstype</b> is true, log a
    624 * notice about possible DNS leaks on local system. If
    625 * <b>safe_socks</b> is true, disallow insecure usage of SOCKS
    626 * protocol. Return SOCKS_RESULT_DONE on success or
    627 * SOCKS_RESULT_INVALID on failure.
    628 */
    629 static socks_result_t
    630 process_socks5_client_request(socks_request_t *req,
    631                              int log_sockstype,
    632                              int safe_socks)
    633 {
    634  socks_result_t res = SOCKS_RESULT_DONE;
    635  tor_addr_t tmpaddr;
    636 
    637  if (req->command != SOCKS_COMMAND_CONNECT &&
    638      req->command != SOCKS_COMMAND_RESOLVE &&
    639      req->command != SOCKS_COMMAND_RESOLVE_PTR) {
    640    socks_request_set_socks5_error(req,SOCKS5_COMMAND_NOT_SUPPORTED);
    641    res = SOCKS_RESULT_INVALID;
    642    goto end;
    643  }
    644 
    645  if (req->command == SOCKS_COMMAND_RESOLVE_PTR &&
    646      tor_addr_parse(&tmpaddr, req->address) < 0) {
    647    socks_request_set_socks5_error(req, SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED);
    648    log_warn(LD_APP, "socks5 received RESOLVE_PTR command with "
    649                     "a malformed address. Rejecting.");
    650 
    651    res = SOCKS_RESULT_INVALID;
    652    goto end;
    653  }
    654 
    655  if (!string_is_valid_dest(req->address)) {
    656    socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
    657 
    658    log_warn(LD_PROTOCOL,
    659             "Your application (using socks5 to port %d) gave Tor "
    660             "a malformed hostname: %s. Rejecting the connection.",
    661             req->port, escaped_safe_str_client(req->address));
    662 
    663    res = SOCKS_RESULT_INVALID;
    664    goto end;
    665  }
    666 
    667  if (req->socks5_atyp == 1 || req->socks5_atyp == 4) {
    668    if (req->command != SOCKS_COMMAND_RESOLVE_PTR &&
    669        !addressmap_have_mapping(req->address,0)) {
    670      log_unsafe_socks_warning(5, req->address, req->port, safe_socks);
    671      if (safe_socks) {
    672        socks_request_set_socks5_error(req, SOCKS5_NOT_ALLOWED);
    673        res = SOCKS_RESULT_INVALID;
    674        goto end;
    675      }
    676    }
    677  }
    678 
    679  if (log_sockstype)
    680    log_notice(LD_APP,
    681              "Your application (using socks5 to port %d) instructed "
    682              "Tor to take care of the DNS resolution itself if "
    683              "necessary. This is good.", req->port);
    684 
    685  end:
    686  return res;
    687 }
    688 
    689 /**
    690 * Handle (parse, validate, process, respond) a single SOCKS
    691 * message in buffer <b>raw_data</b> of length <b>datalen</b>.
    692 * Update relevant fields of <b>req</b>. If <b>log_sockstype</b>
    693 * is true, log a warning about possible DNS leaks on local
    694 * system. If <b>safe_socks</b> is true, disallow insecure
    695 * usage of SOCKS protocol. Set <b>*drain_out</b> to number
    696 * of bytes in <b>raw_data</b> that we processed so far and
    697 * that can be safely drained from buffer.
    698 *
    699 * Return:
    700 *  - SOCKS_RESULT_DONE if succeeded and not expecting further
    701 *    messages from client.
    702 *  - SOCKS_RESULT_INVALID if any of the steps failed due to
    703 *    request being invalid or unexpected given current state.
    704 *  - SOCKS_RESULT_TRUNCATED if we do not found an expected
    705 *    SOCKS message in its entirety (more stuff has to arrive
    706 *    from client).
    707 *  - SOCKS_RESULT_MORE_EXPECTED if we handled current message
    708 *    successfully, but we expect more messages from the
    709 *    client.
    710 */
    711 static socks_result_t
    712 handle_socks_message(const uint8_t *raw_data, size_t datalen,
    713                     socks_request_t *req, int log_sockstype,
    714                     int safe_socks, size_t *drain_out)
    715 {
    716  socks_result_t res = SOCKS_RESULT_DONE;
    717 
    718  uint8_t socks_version = raw_data[0];
    719 
    720  if (socks_version == SOCKS_AUTH)
    721    socks_version = SOCKS_VER_5; // SOCKS5 username/pass subnegotiation
    722 
    723  if (socks_version == SOCKS_VER_4) {
    724    if (datalen < SOCKS4_NETWORK_LEN) {
    725      res = 0;
    726      goto end;
    727    }
    728 
    729    int is_socks4a = 0;
    730    res = parse_socks4_request((const uint8_t *)raw_data, req, datalen,
    731                               &is_socks4a, drain_out);
    732 
    733    if (res != SOCKS_RESULT_DONE) {
    734      goto end;
    735    }
    736 
    737    res = process_socks4_request(req, is_socks4a,log_sockstype,
    738                                 safe_socks);
    739 
    740    if (res != SOCKS_RESULT_DONE) {
    741      goto end;
    742    }
    743 
    744    goto end;
    745  } else if (socks_version == SOCKS_VER_5) {
    746    if (datalen < 2) { /* version and another byte */
    747      res = 0;
    748      goto end;
    749    }
    750    /* RFC1929 SOCKS5 username/password subnegotiation. */
    751    if (!req->got_auth && (raw_data[0] == 1 ||
    752        req->auth_type == SOCKS_USER_PASS)) {
    753      res = parse_socks5_userpass_auth(raw_data, req, datalen,
    754                                       drain_out);
    755 
    756      if (res != SOCKS_RESULT_DONE) {
    757        goto end;
    758      }
    759 
    760      res = process_socks5_userpass_auth(req);
    761      if (res != SOCKS_RESULT_DONE) {
    762        goto end;
    763      }
    764 
    765      res = SOCKS_RESULT_MORE_EXPECTED;
    766      goto end;
    767    } else if (req->socks_version != SOCKS_VER_5) {
    768      int have_user_pass=0, have_no_auth=0;
    769      res = parse_socks5_methods_request(raw_data, req, datalen,
    770                                         &have_user_pass,
    771                                         &have_no_auth,
    772                                         drain_out);
    773 
    774      if (res != SOCKS_RESULT_DONE) {
    775        goto end;
    776      }
    777 
    778      res = process_socks5_methods_request(req, have_user_pass,
    779                                           have_no_auth);
    780 
    781      if (res != SOCKS_RESULT_DONE) {
    782        goto end;
    783      }
    784 
    785      res = SOCKS_RESULT_MORE_EXPECTED;
    786      goto end;
    787    } else {
    788      res = parse_socks5_client_request(raw_data, req,
    789                                        datalen, drain_out);
    790      if (BUG(res == SOCKS_RESULT_INVALID && req->replylen == 0)) {
    791        socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
    792      }
    793      if (res != SOCKS_RESULT_DONE) {
    794        goto end;
    795      }
    796 
    797      res = process_socks5_client_request(req, log_sockstype,
    798                                          safe_socks);
    799 
    800      if (res != SOCKS_RESULT_DONE) {
    801        goto end;
    802      }
    803    }
    804  } else {
    805    *drain_out = datalen;
    806    res = SOCKS_RESULT_INVALID;
    807  }
    808 
    809  end:
    810  return res;
    811 }
    812 
    813 /** There is a (possibly incomplete) socks handshake on <b>buf</b>, of one
    814 * of the forms
    815 *  - socks4: "socksheader username\\0"
    816 *  - socks4a: "socksheader username\\0 destaddr\\0"
    817 *  - socks5 phase one: "version #methods methods"
    818 *  - socks5 phase two: "version command 0 addresstype..."
    819 * If it's a complete and valid handshake, and destaddr fits in
    820 *   MAX_SOCKS_ADDR_LEN bytes, then pull the handshake off the buf,
    821 *   assign to <b>req</b>, and return 1.
    822 *
    823 * If it's invalid or too big, return -1.
    824 *
    825 * Else it's not all there yet, leave buf alone and return 0.
    826 *
    827 * If you want to specify the socks reply, write it into <b>req->reply</b>
    828 *   and set <b>req->replylen</b>, else leave <b>req->replylen</b> alone.
    829 *
    830 * If <b>log_sockstype</b> is non-zero, then do a notice-level log of whether
    831 * the connection is possibly leaking DNS requests locally or not.
    832 *
    833 * If <b>safe_socks</b> is true, then reject unsafe socks protocols.
    834 *
    835 * If returning 0 or -1, <b>req->address</b> and <b>req->port</b> are
    836 * undefined.
    837 */
    838 int
    839 fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
    840                     int log_sockstype, int safe_socks)
    841 {
    842  int res = 0;
    843  size_t datalen = buf_datalen(buf);
    844  size_t n_drain;
    845  const char *head = NULL;
    846  socks_result_t socks_res;
    847  size_t n_pullup;
    848 
    849  if (buf_datalen(buf) < 2) { /* version and another byte */
    850    res = 0;
    851    goto end;
    852  }
    853 
    854  do {
    855    n_drain = 0;
    856    n_pullup = MIN(MAX_SOCKS_MESSAGE_LEN, buf_datalen(buf));
    857    buf_pullup(buf, n_pullup, &head, &datalen);
    858    tor_assert(head && datalen >= 2);
    859 
    860    socks_res = parse_socks(head, datalen, req, log_sockstype,
    861                            safe_socks, &n_drain);
    862 
    863    if (socks_res == SOCKS_RESULT_INVALID)
    864      buf_clear(buf);
    865    else if (socks_res != SOCKS_RESULT_TRUNCATED && n_drain > 0)
    866      buf_drain(buf, n_drain);
    867 
    868    switch (socks_res) {
    869      case SOCKS_RESULT_INVALID:
    870        res = -1;
    871        break;
    872      case SOCKS_RESULT_DONE:
    873        res = 1;
    874        break;
    875      case SOCKS_RESULT_TRUNCATED:
    876        if (datalen == n_pullup)
    877          return 0;
    878        FALLTHROUGH;
    879      case SOCKS_RESULT_MORE_EXPECTED:
    880        res = 0;
    881        break;
    882    }
    883  } while (res == 0 && head && buf_datalen(buf) >= 2);
    884 
    885  end:
    886  return res;
    887 }
    888 
    889 /** Create a SOCKS5 reply message with <b>reason</b> in its REP field and
    890 * have Tor send it as error response to <b>req</b>.
    891 */
    892 static void
    893 socks_request_set_socks5_error(socks_request_t *req,
    894                  socks5_reply_status_t reason)
    895 {
    896  socks5_server_reply_t *trunnel_resp = socks5_server_reply_new();
    897  tor_assert(trunnel_resp);
    898 
    899  socks5_server_reply_set_version(trunnel_resp, SOCKS_VER_5);
    900  socks5_server_reply_set_reply(trunnel_resp, reason);
    901  socks5_server_reply_set_atype(trunnel_resp, 0x01);
    902 
    903  const char *errmsg = socks5_server_reply_check(trunnel_resp);
    904  if (errmsg) {
    905    log_warn(LD_APP, "socks5: reply validation failed: %s",
    906             errmsg);
    907    goto end;
    908  }
    909 
    910  ssize_t encoded = socks5_server_reply_encode(req->reply,
    911                                               sizeof(req->reply),
    912                                               trunnel_resp);
    913  if (encoded < 0) {
    914    log_warn(LD_APP, "socks5: reply encoding failed: %d",
    915             (int)encoded);
    916  } else {
    917    req->replylen = (size_t)encoded;
    918  }
    919 
    920  end:
    921  socks5_server_reply_free(trunnel_resp);
    922 }
    923 
    924 static const char SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG[] =
    925  "HTTP/1.0 501 Tor is not an HTTP Proxy\r\n"
    926  "Content-Type: text/html; charset=iso-8859-1\r\n\r\n"
    927  "<html>\n"
    928  "<head>\n"
    929  "<title>This is a SOCKS Proxy, Not An HTTP Proxy</title>\n"
    930  "</head>\n"
    931  "<body>\n"
    932  "<h1>This is a SOCKS proxy, not an HTTP proxy.</h1>\n"
    933  "<p>\n"
    934  "It appears you have configured your web browser to use this Tor port as\n"
    935  "an HTTP proxy.\n"
    936  "</p>\n"
    937  "<p>\n"
    938  "This is not correct: This port is configured as a SOCKS proxy, not\n"
    939  "an HTTP proxy. If you need an HTTP proxy tunnel, use the HTTPTunnelPort\n"
    940  "configuration option in place of, or in addition to, SOCKSPort.\n"
    941  "Please configure your client accordingly.\n"
    942  "</p>\n"
    943  "<p>\n"
    944  "See <a href=\"https://www.torproject.org/documentation.html\">"
    945  "https://www.torproject.org/documentation.html</a> for more "
    946  "information.\n"
    947  "</p>\n"
    948  "</body>\n"
    949  "</html>\n";
    950 
    951 /** Implementation helper to implement fetch_from_*_socks.  Instead of looking
    952 * at a buffer's contents, we look at the <b>datalen</b> bytes of data in
    953 * <b>data</b>. Instead of removing data from the buffer, we set
    954 * <b>drain_out</b> to the amount of data that should be removed (or -1 if the
    955 * buffer should be cleared).  Instead of pulling more data into the first
    956 * chunk of the buffer, we set *<b>want_length_out</b> to the number of bytes
    957 * we'd like to see in the input buffer, if they're available. */
    958 static socks_result_t
    959 parse_socks(const char *data, size_t datalen, socks_request_t *req,
    960            int log_sockstype, int safe_socks, size_t *drain_out)
    961 {
    962  uint8_t first_octet;
    963 
    964  if (datalen < 2) {
    965    /* We always need at least 2 bytes. */
    966    return SOCKS_RESULT_TRUNCATED;
    967  }
    968 
    969  first_octet = get_uint8(data);
    970 
    971  if (first_octet == SOCKS_VER_5 || first_octet == SOCKS_VER_4 ||
    972      first_octet == SOCKS_AUTH) { // XXX: RFC 1929
    973    return handle_socks_message((const uint8_t *)data, datalen, req,
    974                                log_sockstype, safe_socks, drain_out);
    975  }
    976 
    977  switch (first_octet) { /* which version of socks? */
    978    case 'G': /* get */
    979    case 'H': /* head */
    980    case 'P': /* put/post */
    981    case 'C': /* connect */
    982      strlcpy((char*)req->reply, SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG,
    983              MAX_SOCKS_REPLY_LEN);
    984      req->replylen = strlen((char*)req->reply)+1;
    985      FALLTHROUGH;
    986    default: /* version is not socks4 or socks5 */
    987      log_warn(LD_APP,
    988               "Socks version %d not recognized. (This port is not an "
    989               "HTTP proxy; did you want to use HTTPTunnelPort?)",
    990               *(data));
    991      {
    992        /* Tell the controller the first 8 bytes. */
    993        char *tmp = tor_strndup(data, datalen < 8 ? datalen : 8);
    994        control_event_client_status(LOG_WARN,
    995                                    "SOCKS_UNKNOWN_PROTOCOL DATA=\"%s\"",
    996                                    escaped(tmp));
    997        tor_free(tmp);
    998      }
    999      return SOCKS_RESULT_INVALID;
   1000  }
   1001 
   1002  tor_assert_unreached();
   1003  return SOCKS_RESULT_INVALID;
   1004 }
   1005 
   1006 /** Inspect a reply from SOCKS server stored in <b>buf</b> according
   1007 * to <b>state</b>, removing the protocol data upon success. Return 0 on
   1008 * incomplete response, 1 on success and -1 on error, in which case
   1009 * <b>reason</b> is set to a descriptive message (free() when finished
   1010 * with it).
   1011 *
   1012 * As a special case, 2 is returned when user/pass is required
   1013 * during SOCKS5 handshake and user/pass is configured.
   1014 */
   1015 int
   1016 fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
   1017 {
   1018  ssize_t drain = 0;
   1019  int r;
   1020  const char *head = NULL;
   1021  size_t datalen = 0;
   1022 
   1023  if (buf_datalen(buf) < 2)
   1024    return 0;
   1025 
   1026  buf_pullup(buf, MAX_SOCKS_MESSAGE_LEN, &head, &datalen);
   1027  tor_assert(head && datalen >= 2);
   1028 
   1029  r = parse_socks_client((uint8_t*)head, datalen,
   1030                         state, reason, &drain);
   1031  if (drain > 0)
   1032    buf_drain(buf, drain);
   1033  else if (drain < 0)
   1034    buf_clear(buf);
   1035 
   1036  return r;
   1037 }
   1038 
   1039 /** Implementation logic for fetch_from_*_socks_client. */
   1040 static int
   1041 parse_socks_client(const uint8_t *data, size_t datalen,
   1042                   int state, char **reason,
   1043                   ssize_t *drain_out)
   1044 {
   1045  unsigned int addrlen;
   1046  *drain_out = 0;
   1047  if (datalen < 2)
   1048    return 0;
   1049 
   1050  switch (state) {
   1051    case PROXY_SOCKS4_WANT_CONNECT_OK:
   1052      /* Wait for the complete response */
   1053      if (datalen < 8)
   1054        return 0;
   1055 
   1056      if (data[1] != 0x5a) {
   1057        *reason = tor_strdup(socks4_response_code_to_string(data[1]));
   1058        return -1;
   1059      }
   1060 
   1061      /* Success */
   1062      *drain_out = 8;
   1063      return 1;
   1064 
   1065    case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE:
   1066      /* we don't have any credentials */
   1067      if (data[1] != 0x00) {
   1068        *reason = tor_strdup("server doesn't support any of our "
   1069                             "available authentication methods");
   1070        return -1;
   1071      }
   1072 
   1073      log_info(LD_NET, "SOCKS 5 client: continuing without authentication");
   1074      *drain_out = -1;
   1075      return 1;
   1076 
   1077    case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929:
   1078      /* we have a username and password. return 1 if we can proceed without
   1079       * providing authentication, or 2 otherwise. */
   1080      switch (data[1]) {
   1081        case 0x00:
   1082          log_info(LD_NET, "SOCKS 5 client: we have auth details but server "
   1083                            "doesn't require authentication.");
   1084          *drain_out = -1;
   1085          return 1;
   1086        case 0x02:
   1087          log_info(LD_NET, "SOCKS 5 client: need authentication.");
   1088          *drain_out = -1;
   1089          return 2;
   1090        default:
   1091          /* This wasn't supposed to be exhaustive; there are other
   1092           * authentication methods too. */
   1093          ;
   1094      }
   1095 
   1096      *reason = tor_strdup("server doesn't support any of our available "
   1097                           "authentication methods");
   1098      return -1;
   1099 
   1100    case PROXY_SOCKS5_WANT_AUTH_RFC1929_OK:
   1101      /* handle server reply to rfc1929 authentication */
   1102      if (data[1] != 0x00) {
   1103        *reason = tor_strdup("authentication failed");
   1104        return -1;
   1105      }
   1106 
   1107      log_info(LD_NET, "SOCKS 5 client: authentication successful.");
   1108      *drain_out = -1;
   1109      return 1;
   1110 
   1111    case PROXY_SOCKS5_WANT_CONNECT_OK:
   1112      /* response is variable length. BND.ADDR, etc, isn't needed
   1113       * (don't bother with buf_pullup()), but make sure to eat all
   1114       * the data used */
   1115 
   1116      /* wait for address type field to arrive */
   1117      if (datalen < 4)
   1118        return 0;
   1119 
   1120      switch (data[3]) {
   1121        case 0x01: /* ip4 */
   1122          addrlen = 4;
   1123          break;
   1124        case 0x04: /* ip6 */
   1125          addrlen = 16;
   1126          break;
   1127        case 0x03: /* fqdn (can this happen here?) */
   1128          if (datalen < 5)
   1129            return 0;
   1130          addrlen = 1 + data[4];
   1131          break;
   1132        default:
   1133          *reason = tor_strdup("invalid response to connect request");
   1134          return -1;
   1135      }
   1136 
   1137      /* wait for address and port */
   1138      if (datalen < 6 + addrlen)
   1139        return 0;
   1140 
   1141      if (data[1] != 0x00) {
   1142        *reason = tor_strdup(socks5_response_code_to_string(data[1]));
   1143        return -1;
   1144      }
   1145 
   1146      *drain_out = 6 + addrlen;
   1147      return 1;
   1148  }
   1149 
   1150  /* LCOV_EXCL_START */
   1151  /* shouldn't get here if the input state is one we know about... */
   1152  tor_assert(0);
   1153 
   1154  return -1;
   1155  /* LCOV_EXCL_STOP */
   1156 }