Files
SingularityViewer/indra/llmessage/llsocks5.cpp
Aleric Inglewood 474acdbff9 Add support for libcwd.
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"
2011-05-08 17:08:48 +02:00

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;
}