This patch has no influence if you don't have libcwd installed. Note that libcwd (http://libcwd.sourceforge.net/) is only available for linux. A default compile of libcwd does memory allocation tracking, which is too slow for everyday usage of the viewer (usable, but notably slower) and we don't need that. Configure your libcwd as follows: ./configure --prefix=/sl/usr --disable-alloc --enable-optimize Or whatever prefix you prefer (add --enable-maintainer-mode if you're compiling it from the SVN repository), add --disable-nonthreading to compile twice as fast. If you have it installed you can activate it's use by setting a few environment variables: CXXFLAGS="$(pkg-config --cflags libcwd_r)" LDFLAGS="$(pkg-config --libs libcwd_r) -lpthread" and then reconfiguring the viewer. The -lpthread is needed when using ld.gold, however, if you leave it out you might get an LDFLAGS that ends on trailing whitespaces, which doesn't work for some reason. Also, if you installed it in a non-standard place (/sl/usr above) then you need this to run the viewer (and tests): export LD_LIBRARY_PATH="/sl/usr/lib"
210 lines
6.5 KiB
C++
210 lines
6.5 KiB
C++
/**
|
|
* @file llsocks5.cpp
|
|
* @brief Socks 5 implementation
|
|
*
|
|
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
|
*
|
|
* Copyright (c) 2000-2009, Linden Research, Inc.
|
|
*
|
|
* Second Life Viewer Source Code
|
|
* The source code in this file ("Source Code") is provided by Linden Lab
|
|
* to you under the terms of the GNU General Public License, version 2.0
|
|
* ("GPL"), unless you have obtained a separate licensing agreement
|
|
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
|
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
|
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
|
*
|
|
* There are special exceptions to the terms and conditions of the GPL as
|
|
* it is applied to this Source Code. View the full text of the exception
|
|
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
|
* online at
|
|
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
|
*
|
|
* By copying, modifying or distributing this software, you acknowledge
|
|
* that you have read and understood your obligations described above,
|
|
* and agree to abide by those obligations.
|
|
*
|
|
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
|
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
|
* COMPLETENESS OR PERFORMANCE.
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#include "linden_common.h"
|
|
#include "net.h"
|
|
#include "llhost.h"
|
|
#include "message.h"
|
|
#include "llsocks5.h"
|
|
#include <string>
|
|
|
|
// Static class variable instances
|
|
|
|
// We want this to be static to avoid excessive indirection on every
|
|
// incomming packet just to do a simple bool test. The getter for this
|
|
// member is also static
|
|
bool LLSocks::sUdpProxyEnabled;
|
|
bool LLSocks::sHttpProxyEnabled;
|
|
|
|
LLSocks::LLSocks()
|
|
{
|
|
sUdpProxyEnabled = false;
|
|
sHttpProxyEnabled = false;
|
|
mNeedUpdate = false;
|
|
}
|
|
|
|
// Perform a Socks5 authentication and UDP assioacation to the proxy
|
|
// specified by proxy, and assiocate UDP port message_port
|
|
int LLSocks::proxyHandshake(LLHost proxy, U32 message_port)
|
|
{
|
|
int result;
|
|
|
|
/* Socks 5 Auth request */
|
|
socks_auth_request_t socks_auth_request;
|
|
socks_auth_response_t socks_auth_response;
|
|
|
|
socks_auth_request.version = SOCKS_VERSION; // Socks version 5
|
|
socks_auth_request.num_methods = 1; // Sending 1 method
|
|
socks_auth_request.methods = mAuthMethodSelected; // send only the selected metho
|
|
|
|
result = tcp_handshake(hProxyControlChannel, (char*)&socks_auth_request, sizeof(socks_auth_request_t), (char*)&socks_auth_response, sizeof(socks_auth_response_t));
|
|
if (result != 0)
|
|
{
|
|
llwarns << "Socks authentication request failed, error on TCP control channel : " << result << llendl;
|
|
stopProxy();
|
|
return SOCKS_CONNECT_ERROR;
|
|
}
|
|
|
|
if (socks_auth_response.method == AUTH_NOT_ACCEPTABLE)
|
|
{
|
|
llwarns << "Socks5 server refused all our authentication methods" << llendl;
|
|
stopProxy();
|
|
return SOCKS_NOT_ACCEPTABLE;
|
|
}
|
|
|
|
// SOCKS5 USERNAME/PASSWORD authentication
|
|
if (socks_auth_response.method == METHOD_PASSWORD)
|
|
{
|
|
// The server has requested a username/password combination
|
|
U32 request_size = mSocksUsername.size() + mSocksPassword.size() + 3;
|
|
char * password_auth = (char *)malloc(request_size);
|
|
password_auth[0] = 0x01;
|
|
password_auth[1] = mSocksUsername.size();
|
|
memcpy(&password_auth[2],mSocksUsername.c_str(), mSocksUsername.size());
|
|
password_auth[mSocksUsername.size()+2] = mSocksPassword.size();
|
|
memcpy(&password_auth[mSocksUsername.size()+3], mSocksPassword.c_str(), mSocksPassword.size());
|
|
|
|
authmethod_password_reply_t password_reply;
|
|
|
|
result = tcp_handshake(hProxyControlChannel, password_auth, request_size, (char*)&password_reply, sizeof(authmethod_password_reply_t));
|
|
free (password_auth);
|
|
|
|
if (result != 0)
|
|
{
|
|
llwarns << "Socks authentication failed, error on TCP control channel : " << result << llendl;
|
|
stopProxy();
|
|
return SOCKS_CONNECT_ERROR;
|
|
}
|
|
|
|
if (password_reply.status != AUTH_SUCCESS)
|
|
{
|
|
llwarns << "Socks authentication failed" << llendl;
|
|
stopProxy();
|
|
return SOCKS_AUTH_FAIL;
|
|
}
|
|
}
|
|
|
|
/* SOCKS5 connect request */
|
|
|
|
socks_command_request_t connect_request;
|
|
socks_command_response_t connect_reply;
|
|
|
|
connect_request.version = SOCKS_VERSION; //Socks V5
|
|
connect_request.command = COMMAND_UDP_ASSOCIATE; // Associate UDP
|
|
connect_request.flag = FIELD_RESERVED;
|
|
connect_request.atype = ADDRESS_IPV4;
|
|
connect_request.address = 0; // 0.0.0.0 We are not fussy about address
|
|
// UDP is promiscious receive for our protocol
|
|
connect_request.port = 0; // Port must be 0 if you ever want to connect via NAT and your router does port rewrite for you
|
|
|
|
result = tcp_handshake(hProxyControlChannel, (char*)&connect_request, sizeof(socks_command_request_t), (char*)&connect_reply, sizeof(socks_command_response_t));
|
|
if (result != 0)
|
|
{
|
|
llwarns << "Socks connect request failed, error on TCP control channel : " << result << llendl;
|
|
stopProxy();
|
|
return SOCKS_CONNECT_ERROR;
|
|
}
|
|
|
|
if (connect_reply.reply != REPLY_REQUEST_GRANTED)
|
|
{
|
|
//Something went wrong
|
|
llwarns << "Connection to SOCKS5 server failed, UDP forward request not granted" << llendl;
|
|
stopProxy();
|
|
return SOCKS_UDP_FWD_NOT_GRANTED;
|
|
}
|
|
|
|
mUDPProxy.setPort(ntohs(connect_reply.port)); // reply port is in network byte order
|
|
mUDPProxy.setAddress(proxy.getAddress());
|
|
// All good now we have been given the UDP port to send requests that need forwarding.
|
|
llinfos << "Socks 5 UDP proxy connected on " << mUDPProxy << llendl;
|
|
return SOCKS_OK;
|
|
}
|
|
|
|
int LLSocks::startProxy(LLHost proxy, U32 message_port)
|
|
{
|
|
int status;
|
|
|
|
mTCPProxy = proxy;
|
|
mNeedUpdate = false;
|
|
|
|
stopProxy();
|
|
hProxyControlChannel = tcp_open_channel(proxy);
|
|
if (hProxyControlChannel == -1)
|
|
{
|
|
return SOCKS_HOST_CONNECT_FAILED;
|
|
}
|
|
|
|
status = proxyHandshake(proxy, message_port);
|
|
if (status == SOCKS_OK)
|
|
{
|
|
sUdpProxyEnabled=true;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
int LLSocks::startProxy(std::string host, U32 port)
|
|
{
|
|
mTCPProxy.setHostByName(host);
|
|
mTCPProxy.setPort(port);
|
|
return startProxy(mTCPProxy, (U32)gMessageSystem->mPort);
|
|
}
|
|
|
|
void LLSocks::stopProxy()
|
|
{
|
|
sUdpProxyEnabled = false;
|
|
|
|
if (hProxyControlChannel)
|
|
{
|
|
tcp_close_channel(hProxyControlChannel);
|
|
}
|
|
}
|
|
|
|
void LLSocks::setAuthNone()
|
|
{
|
|
mAuthMethodSelected = METHOD_NOAUTH;
|
|
}
|
|
|
|
|
|
void LLSocks::setAuthPassword(std::string username, std::string password)
|
|
{
|
|
mAuthMethodSelected = METHOD_PASSWORD;
|
|
mSocksUsername = username;
|
|
mSocksPassword = password;
|
|
}
|
|
|
|
void LLSocks::EnableHttpProxy(LLHost httpHost, LLHttpProxyType type)
|
|
{
|
|
sHttpProxyEnabled = true;
|
|
mHTTPProxy = httpHost;
|
|
mProxyType = type;
|
|
}
|