Commit 790150e5 authored by rl1987's avatar rl1987
Browse files

Allow empty username/password in SOCKS5 username/password auth message

parent 712a622f
Loading
Loading
Loading
Loading

changes/bug29175_035

0 → 100644
+4 −0
Original line number Diff line number Diff line
  o Major bugfixes (networking):
    - Gracefully handle empty username/password fields in SOCKS5
      username/password auth messsage and allow SOCKS5 handshake to
      continue. Fixes bug 29175; bugfix on 0.3.5.1-alpha.
+8 −4
Original line number Diff line number Diff line
@@ -450,17 +450,21 @@ parse_socks5_userpass_auth(const uint8_t *raw_data, socks_request_t *req,
    tor_free(req->username);
    req->username = tor_memdup_nulterm(username, usernamelen);
    req->usernamelen = usernamelen;

    req->got_auth = 1;
  }

  if (passwordlen && password) {
    tor_free(req->password);
    req->password = tor_memdup_nulterm(password, passwordlen);
    req->passwordlen = passwordlen;
  }

  /**
   * Yes, we allow username and/or password to be empty. Yes, that does
   * violate RFC 1929. However, some client software can send a username/
   * password message with these fields being empty and we want to allow them
   * to be used with Tor.
   */
  req->got_auth = 1;
  }

  end:
  socks5_client_userpass_auth_free(trunnel_req);
+39 −0
Original line number Diff line number Diff line
@@ -479,6 +479,44 @@ test_socks_5_authenticate(void *ptr)
  ;
}

/** Perform SOCKS 5 authentication with empty username/password fields.
 * Technically this violates RfC 1929, but some client software will send
 * this kind of message to Tor.
 * */
static void
test_socks_5_authenticate_empty_user_pass(void *ptr)
{
  SOCKS_TEST_INIT();

  /* SOCKS 5 Negotiate username/password authentication */
  ADD_DATA(buf, "\x05\x01\x02");

  tt_assert(!fetch_from_buf_socks(buf, socks,
                                   get_options()->TestSocks,
                                   get_options()->SafeSocks));
  tt_int_op(2,OP_EQ, socks->replylen);
  tt_int_op(5,OP_EQ, socks->reply[0]);
  tt_int_op(SOCKS_USER_PASS,OP_EQ, socks->reply[1]);
  tt_int_op(5,OP_EQ, socks->socks_version);

  tt_int_op(0,OP_EQ, buf_datalen(buf));

  /* SOCKS 5 Send username/password auth message with empty user/pass fields */
  ADD_DATA(buf, "\x01\x00\x00");
  tt_assert(!fetch_from_buf_socks(buf, socks,
                                   get_options()->TestSocks,
                                   get_options()->SafeSocks));
  tt_int_op(5,OP_EQ, socks->socks_version);
  tt_int_op(2,OP_EQ, socks->replylen);
  tt_int_op(1,OP_EQ, socks->reply[0]);
  tt_int_op(0,OP_EQ, socks->reply[1]);

  tt_int_op(0,OP_EQ, socks->usernamelen);
  tt_int_op(0,OP_EQ, socks->passwordlen);

 done:
  ;
}
/** Perform SOCKS 5 authentication and send data all in one go */
static void
test_socks_5_authenticate_with_data(void *ptr)
@@ -1035,6 +1073,7 @@ struct testcase_t socks_tests[] = {
  SOCKSENT(5_auth_unsupported_version),
  SOCKSENT(5_auth_before_negotiation),
  SOCKSENT(5_authenticate),
  SOCKSENT(5_authenticate_empty_user_pass),
  SOCKSENT(5_authenticate_with_data),
  SOCKSENT(5_malformed_commands),
  SOCKSENT(5_bad_arguments),