From 967627e58a3730d143aa0b15693a54bb93f0d0e8 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 12 Feb 2024 21:55:30 -0500 Subject: [PATCH] read correct reply length and handle reply codes --- libi2pd/Socks5.h | 106 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 81 insertions(+), 25 deletions(-) diff --git a/libi2pd/Socks5.h b/libi2pd/Socks5.h index 84a23997..d611bff3 100644 --- a/libi2pd/Socks5.h +++ b/libi2pd/Socks5.h @@ -29,7 +29,87 @@ namespace transport const size_t SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE = 10; const size_t SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE = 22; + const uint8_t SOCKS5_REPLY_SUCCESS = 0x00; + const uint8_t SOCKS5_REPLY_SERVER_FAILURE = 0x01; + const uint8_t SOCKS5_REPLY_CONNECTION_NOT_ALLOWED = 0x02; + const uint8_t SOCKS5_REPLY_NETWORK_UNREACHABLE = 0x03; + const uint8_t SOCKS5_REPLY_HOST_UNREACHABLE = 0x04; + const uint8_t SOCKS5_REPLY_CONNECTION_REFUSED = 0x05; + const uint8_t SOCKS5_REPLY_TTL_EXPIRED = 0x06; + const uint8_t SOCKS5_REPLY_COMMAND_NOT_SUPPORTED = 0x07; + const uint8_t SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED = 0x08; + // SOCKS5 handshake + template + void Socks5ReadReply (Socket& s, Handler handler) + { + auto readbuff = std::make_shared >(258); // max possible + boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), 5), boost::asio::transfer_all(), // read 4 bytes of header + first byte of address + [readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) + { + if (!ec) + { + if ((*readbuff)[1] == SOCKS5_REPLY_SUCCESS) + { + size_t len = 0; + switch ((*readbuff)[3]) // ATYP + { + case SOCKS5_ATYP_IPV4: len = 3; break; // address length 4 bytes + case SOCKS5_ATYP_IPV6: len = 15; break; // address length 16 bytes + case SOCKS5_ATYP_NAME: len += (*readbuff)[4]; break; // first byte of address is length + default: ; + } + if (len) + { + len += 2; // port + boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), len), boost::asio::transfer_all(), + [readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) + { + if (!ec) + handler (boost::system::error_code ()); // success + else + handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted)); + }); + } + else + handler (boost::asio::error::make_error_code (boost::asio::error::fault)); // unknown address type + } + else + switch ((*readbuff)[1]) // REP + { + case SOCKS5_REPLY_SERVER_FAILURE: + handler (boost::asio::error::make_error_code (boost::asio::error::access_denied )); + break; + case SOCKS5_REPLY_CONNECTION_NOT_ALLOWED: + handler (boost::asio::error::make_error_code (boost::asio::error::no_permission)); + break; + case SOCKS5_REPLY_HOST_UNREACHABLE: + handler (boost::asio::error::make_error_code (boost::asio::error::host_unreachable)); + break; + case SOCKS5_REPLY_NETWORK_UNREACHABLE: + handler (boost::asio::error::make_error_code (boost::asio::error::network_unreachable)); + break; + case SOCKS5_REPLY_CONNECTION_REFUSED: + handler (boost::asio::error::make_error_code (boost::asio::error::connection_refused)); + break; + case SOCKS5_REPLY_TTL_EXPIRED: + handler (boost::asio::error::make_error_code (boost::asio::error::timed_out)); + break; + case SOCKS5_REPLY_COMMAND_NOT_SUPPORTED: + handler (boost::asio::error::make_error_code (boost::asio::error::operation_not_supported)); + break; + case SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED: + handler (boost::asio::error::make_error_code (boost::asio::error::no_protocol_option)); + break; + default: + handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted)); + } + } + else + handler (ec); + }); + } + template void Socks5Connect (Socket& s, Handler handler, std::shared_ptr > buff, uint16_t port) { @@ -44,31 +124,7 @@ namespace transport { (void) transferred; if (!ec) - { - auto readbuff = std::make_shared >(262); // max possible - boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), 7), boost::asio::transfer_all(), // read min reply size - [readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) - { - if (!ec) - { - if (!(*readbuff)[1]) // succeeded - { - boost::system::error_code ec; - size_t moreBytes = s.available(ec); - if (!ec && moreBytes) // read remaining portion of reply - boost::asio::read (s, boost::asio::buffer(readbuff->data (), moreBytes), boost::asio::transfer_all (), ec); - if (!ec) - handler (boost::system::error_code ()); - else - handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted)); - } - else - handler (boost::asio::error::make_error_code (boost::asio::error::connection_refused)); - } - else - handler (ec); - }); - } + Socks5ReadReply (s, handler); else handler (ec); });