diff --git a/src/DHTConnectionSocksProxyImpl.cc b/src/DHTConnectionSocksProxyImpl.cc index 45202c19..f7dd7e7c 100644 --- a/src/DHTConnectionSocksProxyImpl.cc +++ b/src/DHTConnectionSocksProxyImpl.cc @@ -61,28 +61,9 @@ bool DHTConnectionSocksProxyImpl::startProxy(const std::string& host, socket_->establish(host, port); // Authentication negotiation - bool noAuth = user.empty() || passwd.empty(); - if (noAuth) { - int authMethod = socket_->negotiateAuth( - std::vector{SOCKS_AUTH_NO_AUTH}); - if (authMethod < 0) { - return false; - } - } - else { - int authMethod = socket_->negotiateAuth(std::vector{ - SOCKS_AUTH_NO_AUTH, SOCKS_AUTH_USERPASS}); - if (authMethod < 0) { - return false; - } - - // Username/Password authentication - if (authMethod == SOCKS_AUTH_USERPASS) { - int status = socket_->authByUserpass(user, passwd); - if (status != 0) { - return false; - } - } + bool res = socket_->authByUserpassOrNone(user, passwd); + if (!res) { + return false; } // UDP associate diff --git a/src/SocksProxySocket.cc b/src/SocksProxySocket.cc index ebb18b7e..5f4d6270 100644 --- a/src/SocksProxySocket.cc +++ b/src/SocksProxySocket.cc @@ -93,8 +93,8 @@ int SocksProxySocket::negotiateAuth(std::vector expected) return authMethod; } -char SocksProxySocket::authByUserpass(const std::string& user, - const std::string& passwd) +int SocksProxySocket::authByUserpass(const std::string& user, + const std::string& passwd) { std::stringstream req; req << C_AUTH_USERPASS_VER; @@ -111,6 +111,33 @@ char SocksProxySocket::authByUserpass(const std::string& user, return res[1]; } +bool SocksProxySocket::authByUserpassOrNone(const std::string& user, + const std::string& passwd) +{ + bool noAuth = user.empty() || passwd.empty(); + if (noAuth) { + int authMethod = + negotiateAuth(std::vector{SOCKS_AUTH_NO_AUTH}); + if (authMethod < 0) { + return false; + } + } + else { + int authMethod = negotiateAuth(std::vector{ + SOCKS_AUTH_NO_AUTH, SOCKS_AUTH_USERPASS}); + if (authMethod < 0) { + return false; + } + if (authMethod == SOCKS_AUTH_USERPASS) { + int status = authByUserpass(user, passwd); + if (status != 0) { + return false; + } + } + } + return true; +} + void SocksProxySocket::sendCmd(SocksProxyCmd cmd, const std::string& dstAddr, uint16_t dstPort, bool allowEmpty) { diff --git a/src/SocksProxySocket.h b/src/SocksProxySocket.h index f0979b45..0b603950 100644 --- a/src/SocksProxySocket.h +++ b/src/SocksProxySocket.h @@ -93,7 +93,12 @@ public: // Username/Password authentication. // user and pass should not be empty. // Returns status replied from proxy server. 0 is OK. - char authByUserpass(const std::string& user, const std::string& passwd); + int authByUserpass(const std::string& user, const std::string& passwd); + + // Helper to negotiate and auth by username/password authentication, or skip + // it if not required. + // Leave either user or pass empty to force no authentication. + bool authByUserpassOrNone(const std::string& user, const std::string& passwd); // Create an UDP association to start UDP proxy. // Leave listen host and port empty / 0 to indicate no receiving from proxy.