Added ip spoofing protectection.
This commit is contained in:
@@ -55,6 +55,7 @@ set(llmessage_SOURCE_FILES
|
|||||||
llmessagethrottle.cpp
|
llmessagethrottle.cpp
|
||||||
llmime.cpp
|
llmime.cpp
|
||||||
llnamevalue.cpp
|
llnamevalue.cpp
|
||||||
|
llnetcanary.cpp
|
||||||
llnullcipher.cpp
|
llnullcipher.cpp
|
||||||
llpacketack.cpp
|
llpacketack.cpp
|
||||||
llpacketbuffer.cpp
|
llpacketbuffer.cpp
|
||||||
@@ -147,6 +148,7 @@ set(llmessage_HEADER_FILES
|
|||||||
llmime.h
|
llmime.h
|
||||||
llmsgvariabletype.h
|
llmsgvariabletype.h
|
||||||
llnamevalue.h
|
llnamevalue.h
|
||||||
|
llnetcanary.h
|
||||||
llnullcipher.h
|
llnullcipher.h
|
||||||
llpacketack.h
|
llpacketack.h
|
||||||
llpacketbuffer.h
|
llpacketbuffer.h
|
||||||
|
|||||||
140
indra/llmessage/llnetcanary.cpp
Normal file
140
indra/llmessage/llnetcanary.cpp
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
// <edit>
|
||||||
|
#include "llnetcanary.h"
|
||||||
|
#include "llerror.h"
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#include <winsock2.h>
|
||||||
|
static WSADATA trapWSAData;
|
||||||
|
#else
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
extern int errno; //error number
|
||||||
|
#define SOCKADDR_IN struct sockaddr_in
|
||||||
|
#define SOCKADDR struct sockaddr
|
||||||
|
#define SOCKET int
|
||||||
|
#define INVALID_SOCKET -1
|
||||||
|
#define SOCKET_ERROR -1
|
||||||
|
#define SD_BOTH 2
|
||||||
|
#define closesocket close
|
||||||
|
#endif
|
||||||
|
SOCKADDR_IN trapLclAddr;
|
||||||
|
LLNetCanary::LLNetCanary(int requested_port)
|
||||||
|
{
|
||||||
|
mGood = TRUE;
|
||||||
|
int nRet;
|
||||||
|
int hSocket;
|
||||||
|
int snd_size = 400000;
|
||||||
|
int rec_size = 400000;
|
||||||
|
int buff_size = 4;
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
if(WSAStartup(0x0202, &trapWSAData))
|
||||||
|
{
|
||||||
|
S32 err = WSAGetLastError();
|
||||||
|
WSACleanup();
|
||||||
|
llwarns << "WSAStartup() failure: " << err << llendl;
|
||||||
|
mGood = FALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// Get a datagram socket
|
||||||
|
hSocket = (int)socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (hSocket == INVALID_SOCKET)
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
S32 err = WSAGetLastError();
|
||||||
|
WSACleanup();
|
||||||
|
#else
|
||||||
|
S32 err = errno;
|
||||||
|
#endif
|
||||||
|
mGood = FALSE;
|
||||||
|
llwarns << "socket() failure: " << err << llendl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name the socket (assign the local port number to receive on)
|
||||||
|
trapLclAddr.sin_family = AF_INET;
|
||||||
|
trapLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
trapLclAddr.sin_port = htons(requested_port);
|
||||||
|
//llinfos << "bind() port: " << requested_port << llendl;
|
||||||
|
nRet = bind(hSocket, (struct sockaddr*) &trapLclAddr, sizeof(trapLclAddr));
|
||||||
|
if (nRet == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
S32 err = WSAGetLastError();
|
||||||
|
WSACleanup();
|
||||||
|
#else
|
||||||
|
S32 err = errno;
|
||||||
|
#endif
|
||||||
|
mGood = FALSE;
|
||||||
|
llwarns << "bind() failed: " << err << llendl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find out what address we got
|
||||||
|
SOCKADDR_IN socket_address;
|
||||||
|
S32 socket_address_size = sizeof(socket_address);
|
||||||
|
getsockname(hSocket, (SOCKADDR*) &socket_address, (socklen_t *)&socket_address_size);
|
||||||
|
mPort = ntohs(socket_address.sin_port);
|
||||||
|
//llinfos << "got port " << mPort << llendl;
|
||||||
|
|
||||||
|
// Set socket to be non-blocking
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
unsigned long argp = 1;
|
||||||
|
nRet = ioctlsocket (hSocket, FIONBIO, &argp);
|
||||||
|
#else
|
||||||
|
nRet = fcntl(hSocket, F_SETFL, O_NONBLOCK);
|
||||||
|
#endif
|
||||||
|
if (nRet == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
S32 err = WSAGetLastError();
|
||||||
|
WSACleanup();
|
||||||
|
#else
|
||||||
|
S32 err = errno;
|
||||||
|
#endif
|
||||||
|
mGood = FALSE;
|
||||||
|
llwarns << "Failed to set socket non-blocking, Err: " << err << llendl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set a large receive buffer
|
||||||
|
nRet = setsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, buff_size);
|
||||||
|
if (nRet)
|
||||||
|
{
|
||||||
|
llinfos << "Can't set receive buffer size!" << llendl;
|
||||||
|
}
|
||||||
|
// set a large send buffer
|
||||||
|
nRet = setsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, buff_size);
|
||||||
|
if (nRet)
|
||||||
|
{
|
||||||
|
llinfos << "Can't set send buffer size!" << llendl;
|
||||||
|
}
|
||||||
|
//getsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, &buff_size);
|
||||||
|
//getsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, &buff_size);
|
||||||
|
//LL_DEBUGS("AppInit") << "startNet - receive buffer size : " << rec_size << LL_ENDL;
|
||||||
|
//LL_DEBUGS("AppInit") << "startNet - send buffer size : " << snd_size << LL_ENDL;
|
||||||
|
|
||||||
|
mSocket = hSocket;
|
||||||
|
}
|
||||||
|
LLNetCanary::~LLNetCanary()
|
||||||
|
{
|
||||||
|
if(mGood)
|
||||||
|
{
|
||||||
|
if(mSocket)
|
||||||
|
{
|
||||||
|
shutdown(mSocket, SD_BOTH);
|
||||||
|
closesocket(mSocket);
|
||||||
|
}
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// </edit>
|
||||||
25
indra/llmessage/llnetcanary.h
Normal file
25
indra/llmessage/llnetcanary.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// <edit>
|
||||||
|
#ifndef LL_LLNETCANARY_H
|
||||||
|
#define LL_LLNETCANARY_H
|
||||||
|
#include "stdtypes.h"
|
||||||
|
#include <string>
|
||||||
|
class LLNetCanary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LLNetCanary(int requested_port);
|
||||||
|
~LLNetCanary();
|
||||||
|
BOOL mGood;
|
||||||
|
S32 mSocket;
|
||||||
|
U16 mPort;
|
||||||
|
U8 mBuffer[8192];
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
F64 time; // LLTimer::getElapsedSeconds();
|
||||||
|
//U8 message[4];
|
||||||
|
U32 message;
|
||||||
|
U32 points;
|
||||||
|
std::string name;
|
||||||
|
} entry;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
// </edit>
|
||||||
@@ -550,6 +550,76 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count, bool faked_message, U8 fak
|
|||||||
S32 receive_size = 0;
|
S32 receive_size = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
// <edit>
|
||||||
|
// Expire old canary entries
|
||||||
|
F64 now = LLTimer::getElapsedSeconds();
|
||||||
|
std::map<U32, LLNetCanary::entry>::iterator canary_entry_iter;
|
||||||
|
std::map<U32, LLNetCanary::entry>::iterator canary_entry_end = mCanaryEntries.end();
|
||||||
|
for( canary_entry_iter = mCanaryEntries.begin();
|
||||||
|
canary_entry_iter != mCanaryEntries.end(); )
|
||||||
|
{
|
||||||
|
if( ((*canary_entry_iter).second.time + 30.0f) < now)
|
||||||
|
{
|
||||||
|
llinfos << "Expiring ban on " << (*canary_entry_iter).second.name << " message, " << (*canary_entry_iter).second.points << " points" << llendl;
|
||||||
|
mCanaryEntries.erase(canary_entry_iter++);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
canary_entry_iter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!faked_message && mSpoofProtectionLevel > 1)
|
||||||
|
{
|
||||||
|
// Canaries receive
|
||||||
|
std::vector<LLNetCanary*>::iterator canary_iter = mCanaries.begin();
|
||||||
|
std::vector<LLNetCanary*>::iterator canary_end = mCanaries.end();
|
||||||
|
for( ; canary_iter != canary_end; ++canary_iter)
|
||||||
|
{
|
||||||
|
U8* canary_buffer = (*canary_iter)->mBuffer;
|
||||||
|
S32 len = receive_packet((*canary_iter)->mSocket, (char*)canary_buffer);
|
||||||
|
if(len)
|
||||||
|
{
|
||||||
|
//llinfos << "canary received " << len << " bytes on port " << (*canary_iter)->mPort << llendl;
|
||||||
|
zeroCodeExpand(&canary_buffer, &len);
|
||||||
|
if(len < 7) continue; // too short to be an slmsg
|
||||||
|
LLNetCanary::entry entry;
|
||||||
|
entry.message = 0;
|
||||||
|
if(canary_buffer[6] != 0xFF) // High XX
|
||||||
|
entry.message = canary_buffer[6];
|
||||||
|
else if((len >= 8) && (canary_buffer[7] != 0xFF)) // Medium FFXX
|
||||||
|
entry.message = (255 << 8) | canary_buffer[7];
|
||||||
|
else if((len >= 10) && (canary_buffer[7] == 0xFF)) // Low FFFFXXXX
|
||||||
|
{
|
||||||
|
U16 message_id_U16 = 0;
|
||||||
|
memcpy(&message_id_U16, &canary_buffer[8], 2);
|
||||||
|
message_id_U16 = ntohs(message_id_U16);
|
||||||
|
entry.message = 0xFFFF0000 | message_id_U16;
|
||||||
|
}
|
||||||
|
else continue; // not an slmsg
|
||||||
|
|
||||||
|
if(mCanaryEntries.find(entry.message) == mCanaryEntries.end())
|
||||||
|
{
|
||||||
|
// brand new entry
|
||||||
|
LLMessageTemplate* temp = get_ptr_in_map(mMessageNumbers, entry.message);
|
||||||
|
entry.name = temp ? temp->mName : "Invalid";
|
||||||
|
entry.points = 1;
|
||||||
|
entry.time = now;
|
||||||
|
mCanaryEntries[entry.message] = entry;
|
||||||
|
if(mSpoofProtectionLevel == 2)
|
||||||
|
llinfos << "Temporarily banning a " << entry.name << " message" << llendl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// strike two, three...
|
||||||
|
mCanaryEntries[entry.message].points++;
|
||||||
|
mCanaryEntries[entry.message].time = now;
|
||||||
|
if((mSpoofProtectionLevel > 2) && (mCanaryEntries[entry.message].points == 2))
|
||||||
|
llinfos << "Temporarily banning a " << mCanaryEntries[entry.message].name << " message" << llendl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// </edit>
|
||||||
clearReceiveState();
|
clearReceiveState();
|
||||||
|
|
||||||
BOOL recv_reliable = FALSE;
|
BOOL recv_reliable = FALSE;
|
||||||
@@ -625,6 +695,61 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count, bool faked_message, U8 fak
|
|||||||
// process the message as normal
|
// process the message as normal
|
||||||
mIncomingCompressedSize = zeroCodeExpand(&buffer, &receive_size);
|
mIncomingCompressedSize = zeroCodeExpand(&buffer, &receive_size);
|
||||||
mCurrentRecvPacketID = ntohl(*((U32*)(&buffer[1])));
|
mCurrentRecvPacketID = ntohl(*((U32*)(&buffer[1])));
|
||||||
|
// <edit>
|
||||||
|
BOOL spoofed_packet = FALSE;
|
||||||
|
if(mSpoofProtectionLevel > 0)
|
||||||
|
{
|
||||||
|
S32 len = receive_size;
|
||||||
|
U32 message = 0;
|
||||||
|
if(buffer[6] != 0xFF) // High XX
|
||||||
|
message = buffer[6];
|
||||||
|
else if((len >= 8) && (buffer[7] != 0xFF)) // Medium FFXX
|
||||||
|
message = (255 << 8) | buffer[7];
|
||||||
|
else if((len >= 10) && (buffer[7] == 0xFF)) // Low FFFFXXXX
|
||||||
|
{
|
||||||
|
U16 message_id_U16 = 0;
|
||||||
|
memcpy(&message_id_U16, &buffer[8], 2);
|
||||||
|
message_id_U16 = ntohs(message_id_U16);
|
||||||
|
message = 0xFFFF0000 | message_id_U16;
|
||||||
|
}
|
||||||
|
if(!mCurrentRecvPacketID)
|
||||||
|
{
|
||||||
|
LL_WARNS("Messaging") << "CODE DONKEY_A" << llendl;
|
||||||
|
if(mSpoofDroppedCallback)
|
||||||
|
{
|
||||||
|
LLNetCanary::entry entry;
|
||||||
|
LLMessageTemplate* temp = get_ptr_in_map(mMessageNumbers, message);
|
||||||
|
entry.name = temp ? temp->mName : "Invalid";
|
||||||
|
entry.message = message;
|
||||||
|
entry.time = now;
|
||||||
|
entry.points = 1;
|
||||||
|
mSpoofDroppedCallback(entry);
|
||||||
|
}
|
||||||
|
spoofed_packet = TRUE;
|
||||||
|
valid_packet = FALSE;
|
||||||
|
}
|
||||||
|
else if((mSpoofProtectionLevel > 1) && (receive_size >= 7))
|
||||||
|
{
|
||||||
|
if(mCanaryEntries.find(message) != mCanaryEntries.end())
|
||||||
|
{
|
||||||
|
if(
|
||||||
|
(mSpoofProtectionLevel == 2) ||
|
||||||
|
(mCanaryEntries[message].points > 1)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LL_WARNS("Messaging") << "Dropped probably spoofed " << mCanaryEntries[message].name << " packet, " << mCanaryEntries[message].points << " points" << llendl;
|
||||||
|
if(mSpoofDroppedCallback)
|
||||||
|
{
|
||||||
|
mSpoofDroppedCallback(mCanaryEntries[message]);
|
||||||
|
}
|
||||||
|
spoofed_packet = TRUE;
|
||||||
|
valid_packet = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // mSpoofProtectionLevel
|
||||||
|
// </edit>
|
||||||
host = getSender();
|
host = getSender();
|
||||||
|
|
||||||
const bool resetPacketId = true;
|
const bool resetPacketId = true;
|
||||||
@@ -707,6 +832,9 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count, bool faked_message, U8 fak
|
|||||||
// But we don't want to acknowledge UseCircuitCode until the circuit is
|
// But we don't want to acknowledge UseCircuitCode until the circuit is
|
||||||
// available, which is why the acknowledgement test is done above. JC
|
// available, which is why the acknowledgement test is done above. JC
|
||||||
bool trusted = cdp && cdp->getTrusted();
|
bool trusted = cdp && cdp->getTrusted();
|
||||||
|
// <edit>
|
||||||
|
if(!spoofed_packet)
|
||||||
|
// </edit>
|
||||||
valid_packet = mTemplateMessageReader->validateMessage(
|
valid_packet = mTemplateMessageReader->validateMessage(
|
||||||
buffer,
|
buffer,
|
||||||
receive_size,
|
receive_size,
|
||||||
@@ -1862,7 +1990,11 @@ void open_circuit(LLMessageSystem *msgsystem, void** /*user_data*/)
|
|||||||
msgsystem->getIPPortFast(_PREHASH_CircuitInfo, _PREHASH_Port, port);
|
msgsystem->getIPPortFast(_PREHASH_CircuitInfo, _PREHASH_Port, port);
|
||||||
|
|
||||||
// By default, OpenCircuit's are untrusted
|
// By default, OpenCircuit's are untrusted
|
||||||
msgsystem->enableCircuit(LLHost(ip, port), FALSE);
|
// <edit>
|
||||||
|
//#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||||
|
llwarns << "OpenCircuit " << LLHost(ip, port) << llendl;
|
||||||
|
//#endif
|
||||||
|
// </edit>msgsystem->enableCircuit(LLHost(ip, port), FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_circuit(LLMessageSystem *msgsystem, void** /*user_data*/)
|
void close_circuit(LLMessageSystem *msgsystem, void** /*user_data*/)
|
||||||
@@ -2718,6 +2850,9 @@ void end_messaging_system(bool print_summary)
|
|||||||
LLTransferTargetVFile::updateQueue(true); // shutdown LLTransferTargetVFile
|
LLTransferTargetVFile::updateQueue(true); // shutdown LLTransferTargetVFile
|
||||||
if (gMessageSystem)
|
if (gMessageSystem)
|
||||||
{
|
{
|
||||||
|
// <edit>
|
||||||
|
gMessageSystem->stopSpoofProtection();
|
||||||
|
// </edit>
|
||||||
gMessageSystem->stopLogging();
|
gMessageSystem->stopLogging();
|
||||||
|
|
||||||
if (print_summary)
|
if (print_summary)
|
||||||
@@ -4080,4 +4215,155 @@ const LLHost& LLMessageSystem::getSender() const
|
|||||||
|
|
||||||
LLHTTPRegistration<LLHTTPNodeAdapter<LLTrustedMessageService> >
|
LLHTTPRegistration<LLHTTPNodeAdapter<LLTrustedMessageService> >
|
||||||
gHTTPRegistrationTrustedMessageWildcard("/trusted-message/<message-name>");
|
gHTTPRegistrationTrustedMessageWildcard("/trusted-message/<message-name>");
|
||||||
|
// <edit>
|
||||||
|
void LLMessageSystem::startSpoofProtection(U32 level)
|
||||||
|
{
|
||||||
|
if(!mPort)
|
||||||
|
{
|
||||||
|
llwarns << "listen port is 0!!!" << llendl;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSpoofProtectionLevel = level;
|
||||||
|
mCanaries.clear();
|
||||||
|
mCanaryEntries.clear();
|
||||||
|
// Make canaries
|
||||||
|
std::string canary_info("");
|
||||||
|
|
||||||
|
if(mSpoofProtectionLevel > 2) // 3 or greater
|
||||||
|
{
|
||||||
|
// FULL CANARY POWER
|
||||||
|
int rPort = 768 + ll_rand(32);
|
||||||
|
if(mPort < rPort) rPort = mPort - 16;
|
||||||
|
if(rPort < 1) rPort = 1;
|
||||||
|
while(rPort < 65536)
|
||||||
|
{
|
||||||
|
if(rPort != mPort)
|
||||||
|
{
|
||||||
|
LLNetCanary* canary = new LLNetCanary(rPort);
|
||||||
|
if(canary->mGood)
|
||||||
|
{
|
||||||
|
mCanaries.push_back(canary);
|
||||||
|
canary_info.append(llformat(" %d", canary->mPort));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
delete canary;
|
||||||
|
}
|
||||||
|
int dist = llabs(mPort - rPort);
|
||||||
|
if(dist > 4096)
|
||||||
|
rPort += ll_rand(2048) + 2048;
|
||||||
|
else if(dist > 2048)
|
||||||
|
rPort += ll_rand(1024) + 1024;
|
||||||
|
else if(dist > 1024)
|
||||||
|
rPort += ll_rand(512) + 512;
|
||||||
|
else if(dist > 512)
|
||||||
|
rPort += ll_rand(256) + 256;
|
||||||
|
else if(dist > 128)
|
||||||
|
rPort += ll_rand(64) + 64;
|
||||||
|
else if(dist > 16)
|
||||||
|
rPort += ll_rand(8) + 8;
|
||||||
|
else
|
||||||
|
rPort += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(mSpoofProtectionLevel == 2)
|
||||||
|
{
|
||||||
|
// Minimal canaries
|
||||||
|
for(int o = -32; o <= 32; o += 8)
|
||||||
|
{
|
||||||
|
int rPort = mPort + o;
|
||||||
|
if(rPort != mPort)
|
||||||
|
{
|
||||||
|
LLNetCanary* canary = new LLNetCanary(rPort);
|
||||||
|
if(canary->mGood)
|
||||||
|
{
|
||||||
|
mCanaries.push_back(canary);
|
||||||
|
canary_info.append(llformat(" %d", canary->mPort));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
delete canary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mCanaries.size())
|
||||||
|
{
|
||||||
|
llinfos << "level " << mSpoofProtectionLevel << ", " << mCanaries.size() << " canaries: " << canary_info << llendl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
llinfos << "level " << mSpoofProtectionLevel << ", no canaries" << llendl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLMessageSystem::stopSpoofProtection()
|
||||||
|
{
|
||||||
|
llinfos << "cleaning up" << llendl;
|
||||||
|
// Shut down canaries
|
||||||
|
std::vector<LLNetCanary*>::iterator canary_iter = mCanaries.begin();
|
||||||
|
std::vector<LLNetCanary*>::iterator canary_end = mCanaries.end();
|
||||||
|
for( ; canary_iter != canary_end; ++canary_iter)
|
||||||
|
{
|
||||||
|
LLNetCanary* canary = (*canary_iter);
|
||||||
|
delete canary;
|
||||||
|
}
|
||||||
|
mCanaries.clear();
|
||||||
|
// Empty canary entries
|
||||||
|
mCanaryEntries.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLMessageSystem::setSpoofDroppedCallback(void (*callback)(LLNetCanary::entry))
|
||||||
|
{
|
||||||
|
mSpoofDroppedCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copypasta from LLTemplateMessageReader
|
||||||
|
BOOL LLMessageSystem::decodeTemplate( const U8* buffer, S32 buffer_size, LLMessageTemplate** msg_template )
|
||||||
|
{
|
||||||
|
const U8* header = buffer + LL_PACKET_ID_SIZE;
|
||||||
|
if (buffer_size <= 0) return FALSE;
|
||||||
|
U32 num = 0;
|
||||||
|
if (header[0] != 255)
|
||||||
|
{
|
||||||
|
// high frequency message
|
||||||
|
num = header[0];
|
||||||
|
}
|
||||||
|
else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 1)) && (header[1] != 255))
|
||||||
|
{
|
||||||
|
// medium frequency message
|
||||||
|
num = (255 << 8) | header[1];
|
||||||
|
}
|
||||||
|
else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 3)) && (header[1] == 255))
|
||||||
|
{
|
||||||
|
// low frequency message
|
||||||
|
U16 message_id_U16 = 0;
|
||||||
|
// I think this check busts the message system.
|
||||||
|
// it appears that if there is a NULL in the message #, it won't copy it....
|
||||||
|
// what was the goal?
|
||||||
|
//if(header[2])
|
||||||
|
memcpy(&message_id_U16, &header[2], 2);
|
||||||
|
|
||||||
|
// dependant on endian-ness:
|
||||||
|
// U32 temp = (255 << 24) | (255 << 16) | header[2];
|
||||||
|
|
||||||
|
// independant of endian-ness:
|
||||||
|
message_id_U16 = ntohs(message_id_U16);
|
||||||
|
num = 0xFFFF0000 | message_id_U16;
|
||||||
|
}
|
||||||
|
else // bogus packet received (too short)
|
||||||
|
{
|
||||||
|
return(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
LLMessageTemplate* temp = get_ptr_in_map(mMessageNumbers,num);
|
||||||
|
if (temp)
|
||||||
|
{
|
||||||
|
*msg_template = temp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(TRUE);
|
||||||
|
}
|
||||||
|
// </edit
|
||||||
|
|||||||
@@ -67,6 +67,9 @@
|
|||||||
|
|
||||||
#include "llstoredmessage.h"
|
#include "llstoredmessage.h"
|
||||||
#include "llsocks5.h"
|
#include "llsocks5.h"
|
||||||
|
// <edit>
|
||||||
|
#include "llnetcanary.h"
|
||||||
|
// </edit>
|
||||||
|
|
||||||
const U32 MESSAGE_MAX_STRINGS_LENGTH = 64;
|
const U32 MESSAGE_MAX_STRINGS_LENGTH = 64;
|
||||||
const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192;
|
const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192;
|
||||||
@@ -215,6 +218,12 @@ class LLMessageSystem : public LLMessageSenderInterface
|
|||||||
private:
|
private:
|
||||||
U8 mSendBuffer[MAX_BUFFER_SIZE];
|
U8 mSendBuffer[MAX_BUFFER_SIZE];
|
||||||
S32 mSendSize;
|
S32 mSendSize;
|
||||||
|
// <edit>
|
||||||
|
U32 mSpoofProtectionLevel;
|
||||||
|
std::vector<LLNetCanary*> mCanaries;
|
||||||
|
std::map<U32, LLNetCanary::entry> mCanaryEntries;
|
||||||
|
void (*mSpoofDroppedCallback)(LLNetCanary::entry);
|
||||||
|
// </edit>
|
||||||
|
|
||||||
bool mBlockUntrustedInterface;
|
bool mBlockUntrustedInterface;
|
||||||
LLHost mUntrustedInterface;
|
LLHost mUntrustedInterface;
|
||||||
@@ -236,7 +245,6 @@ class LLMessageSystem : public LLMessageSenderInterface
|
|||||||
// </edit>
|
// </edit>
|
||||||
message_template_name_map_t mMessageTemplates;
|
message_template_name_map_t mMessageTemplates;
|
||||||
message_template_number_map_t mMessageNumbers;
|
message_template_number_map_t mMessageNumbers;
|
||||||
|
|
||||||
// <edit>
|
// <edit>
|
||||||
//public:
|
//public:
|
||||||
// </edit>
|
// </edit>
|
||||||
@@ -614,6 +622,11 @@ public:
|
|||||||
// Change this message to be UDP black listed.
|
// Change this message to be UDP black listed.
|
||||||
void banUdpMessage(const std::string& name);
|
void banUdpMessage(const std::string& name);
|
||||||
|
|
||||||
|
// <edit>
|
||||||
|
void startSpoofProtection(U32 level);
|
||||||
|
void stopSpoofProtection();
|
||||||
|
void setSpoofDroppedCallback(void (*callback)(LLNetCanary::entry));
|
||||||
|
// </edit>
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// A list of the circuits that need to be sent DenyTrustedCircuit messages.
|
// A list of the circuits that need to be sent DenyTrustedCircuit messages.
|
||||||
@@ -756,7 +769,13 @@ private:
|
|||||||
LLUUID mSessionID;
|
LLUUID mSessionID;
|
||||||
|
|
||||||
void addTemplate(LLMessageTemplate *templatep);
|
void addTemplate(LLMessageTemplate *templatep);
|
||||||
|
// <edit>
|
||||||
|
public:
|
||||||
|
// </edit>
|
||||||
BOOL decodeTemplate( const U8* buffer, S32 buffer_size, LLMessageTemplate** msg_template );
|
BOOL decodeTemplate( const U8* buffer, S32 buffer_size, LLMessageTemplate** msg_template );
|
||||||
|
// <edit>
|
||||||
|
private:
|
||||||
|
// </edit>
|
||||||
|
|
||||||
void logMsgFromInvalidCircuit( const LLHost& sender, BOOL recv_reliable );
|
void logMsgFromInvalidCircuit( const LLHost& sender, BOOL recv_reliable );
|
||||||
void logTrustedMsgFromUntrustedCircuit( const LLHost& sender );
|
void logTrustedMsgFromUntrustedCircuit( const LLHost& sender );
|
||||||
|
|||||||
@@ -784,6 +784,28 @@
|
|||||||
<string>S32</string>
|
<string>S32</string>
|
||||||
<key>Value</key>
|
<key>Value</key>
|
||||||
<integer>5</integer>
|
<integer>5</integer>
|
||||||
|
</map>
|
||||||
|
<key>SpoofProtectionAlerts</key>
|
||||||
|
<map>
|
||||||
|
<key>Comment</key>
|
||||||
|
<string>Enables IP Spoofing protection alerts</string>
|
||||||
|
<key>Persist</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>Type</key>
|
||||||
|
<string>Boolean</string>
|
||||||
|
<key>Value</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</map>
|
||||||
|
<key>SpoofProtectionLevel</key>
|
||||||
|
<map>
|
||||||
|
<key>Comment</key>
|
||||||
|
<string>IP Spoofing protection level</string>
|
||||||
|
<key>Persist</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>Type</key>
|
||||||
|
<string>U32</string>
|
||||||
|
<key>Value</key>
|
||||||
|
<integer>0</integer>
|
||||||
</map>
|
</map>
|
||||||
<key>Socks5ProxyEnabled</key>
|
<key>Socks5ProxyEnabled</key>
|
||||||
<map>
|
<map>
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ private:
|
|||||||
U32 mLinksForChattingObjects;
|
U32 mLinksForChattingObjects;
|
||||||
U32 mTimeFormat;
|
U32 mTimeFormat;
|
||||||
U32 mDateFormat;
|
U32 mDateFormat;
|
||||||
|
U32 mSpoofProtectionAtOpen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -180,6 +181,7 @@ void LLPrefsInertImpl::refresh()
|
|||||||
{
|
{
|
||||||
combo->setCurrentByIndex(mDateFormat);
|
combo->setCurrentByIndex(mDateFormat);
|
||||||
}
|
}
|
||||||
|
mSpoofProtectionAtOpen = gSavedSettings.getU32("SpoofProtectionLevel");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLPrefsInertImpl::cancel()
|
void LLPrefsInertImpl::cancel()
|
||||||
@@ -199,6 +201,7 @@ void LLPrefsInertImpl::cancel()
|
|||||||
gSavedSettings.setBOOL("RevokePermsOnStandUp", mRevokePermsOnStandUp);
|
gSavedSettings.setBOOL("RevokePermsOnStandUp", mRevokePermsOnStandUp);
|
||||||
gSavedSettings.setBOOL("WindEnabled", mEnableLLWind);
|
gSavedSettings.setBOOL("WindEnabled", mEnableLLWind);
|
||||||
gSavedSettings.setBOOL("BroadcastViewerEffects", mBroadcastViewerEffects);
|
gSavedSettings.setBOOL("BroadcastViewerEffects", mBroadcastViewerEffects);
|
||||||
|
gSavedSettings.setU32("SpoofProtectionLevel", mSpoofProtectionAtOpen);
|
||||||
|
|
||||||
gLLWindEnabled = mEnableLLWind;
|
gLLWindEnabled = mEnableLLWind;
|
||||||
|
|
||||||
@@ -261,7 +264,16 @@ void LLPrefsInertImpl::apply()
|
|||||||
gSavedSettings.setString("ShortTimeFormat", short_time);
|
gSavedSettings.setString("ShortTimeFormat", short_time);
|
||||||
gSavedSettings.setString("LongTimeFormat", long_time);
|
gSavedSettings.setString("LongTimeFormat", long_time);
|
||||||
gSavedSettings.setString("TimestampFormat", timestamp);
|
gSavedSettings.setString("TimestampFormat", timestamp);
|
||||||
|
if(gMessageSystem)
|
||||||
|
{
|
||||||
|
U32 new_spoof_protection = gSavedSettings.getU32("SpoofProtectionLevel");
|
||||||
|
if(new_spoof_protection != mSpoofProtectionAtOpen)
|
||||||
|
{
|
||||||
|
mSpoofProtectionAtOpen = new_spoof_protection;
|
||||||
|
gMessageSystem->stopSpoofProtection();
|
||||||
|
gMessageSystem->startSpoofProtection(new_spoof_protection);
|
||||||
|
}
|
||||||
|
}
|
||||||
refreshValues();
|
refreshValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -926,6 +926,14 @@ bool idle_startup()
|
|||||||
LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().insert("DIAGNOSTIC", diagnostic));
|
LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().insert("DIAGNOSTIC", diagnostic));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// <edit>
|
||||||
|
if(gMessageSystem)
|
||||||
|
{
|
||||||
|
gMessageSystem->startSpoofProtection(gSavedSettings.getU32("SpoofProtectionLevel"));
|
||||||
|
gMessageSystem->setSpoofDroppedCallback(spoof_dropped_callback);
|
||||||
|
}
|
||||||
|
// </edit>
|
||||||
|
|
||||||
#if LL_WINDOWS
|
#if LL_WINDOWS
|
||||||
// On the windows dev builds, unpackaged, the message.xml file will
|
// On the windows dev builds, unpackaged, the message.xml file will
|
||||||
// be located in indra/build-vc**/newview/<config>/app_settings.
|
// be located in indra/build-vc**/newview/<config>/app_settings.
|
||||||
|
|||||||
@@ -5915,3 +5915,15 @@ void LLOfferInfo::forceResponse(InventoryOfferResponse response)
|
|||||||
LLNotifications::instance().forceResponse(params, response);
|
LLNotifications::instance().forceResponse(params, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// <edit> lol
|
||||||
|
void spoof_dropped_callback(LLNetCanary::entry entry)
|
||||||
|
{
|
||||||
|
if(gSavedSettings.getBOOL("SpoofProtectionAlerts"))
|
||||||
|
{
|
||||||
|
LLSD args;
|
||||||
|
args["[MESSAGE]"] = llformat("A suspicious %s packet was dropped based on your IP Spoofing Protection settings.", entry.name.c_str());
|
||||||
|
LLNotifications::instance().add("SystemMessageTip",args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// </edit>
|
||||||
|
|
||||||
|
|||||||
@@ -197,6 +197,10 @@ void process_decline_callingcard(LLMessageSystem* msg, void**);
|
|||||||
// Message system exception prototypes
|
// Message system exception prototypes
|
||||||
void invalid_message_callback(LLMessageSystem*, void*, EMessageException);
|
void invalid_message_callback(LLMessageSystem*, void*, EMessageException);
|
||||||
|
|
||||||
|
// <edit>
|
||||||
|
void spoof_dropped_callback(LLNetCanary::entry entry);
|
||||||
|
// </edit>
|
||||||
|
|
||||||
void process_initiate_download(LLMessageSystem* msg, void**);
|
void process_initiate_download(LLMessageSystem* msg, void**);
|
||||||
void start_new_inventory_observer();
|
void start_new_inventory_observer();
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,25 @@
|
|||||||
mouse_opaque="true" name="enable_clouds" radio_style="false"
|
mouse_opaque="true" name="enable_clouds" radio_style="false"
|
||||||
width="400" />
|
width="400" />
|
||||||
</panel>
|
</panel>
|
||||||
|
<panel border="true" left="1" bottom="-408" height="408" width="500" mouse_opaque="true"
|
||||||
|
follows="left|top|right|bottom" label="Security" name="Security">
|
||||||
|
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
|
||||||
|
bottom="-20" drop_shadow_visible="true" enabled="true" follows="left|top"
|
||||||
|
font="SansSerifSmall" h_pad="0" halign="left" height="10" left="12"
|
||||||
|
mouse_opaque="false" name="text_box" v_pad="0" width="500">
|
||||||
|
IP Spoofing Protection (0 being off, 3 being highest)
|
||||||
|
</text>
|
||||||
|
<slider bottom_delta="-25" can_edit_text="false"
|
||||||
|
decimal_digits="0" enabled="true" follows="left|top" height="15"
|
||||||
|
increment="1" initial_val="0" left_delta="0" max_val="3" min_val="0"
|
||||||
|
mouse_opaque="true" control_name="SpoofProtectionLevel" name="ip_spoof_slider" show_text="true"
|
||||||
|
width="180" />
|
||||||
|
<check_box bottom_delta="-25" control_name="SpoofProtectionAlerts" enabled="true"
|
||||||
|
follows="left|top" font="SansSerifSmall" height="16" initial_value="true"
|
||||||
|
label="Enable Alerts" left="10"
|
||||||
|
mouse_opaque="true" name="enable_alerts" radio_style="false"
|
||||||
|
width="400" />
|
||||||
|
</panel>
|
||||||
<panel border="true" left="1" bottom="-408" height="408" width="500" mouse_opaque="true"
|
<panel border="true" left="1" bottom="-408" height="408" width="500" mouse_opaque="true"
|
||||||
follows="left|top|right|bottom" label="Miscellaneous" name="Miscellaneous">
|
follows="left|top|right|bottom" label="Miscellaneous" name="Miscellaneous">
|
||||||
<check_box bottom_delta="-30" control_name="DoubleClickTeleport" enabled="true"
|
<check_box bottom_delta="-30" control_name="DoubleClickTeleport" enabled="true"
|
||||||
|
|||||||
Reference in New Issue
Block a user