Procházet zdrojové kódy

low level network protection in TCP layer, fixed internal world address to properly accept local vs remote connections when set

Image před 3 roky
rodič
revize
ca26654639

+ 18 - 2
EQ2/source/WorldServer/LoginServer.cpp

@@ -33,6 +33,7 @@ using namespace std;
 #ifdef WIN32
 #include <process.h>
 #include <WinSock2.h>
+#include <Ws2tcpip.h>
 #include <windows.h>
 
 #define strncasecmp	_strnicmp
@@ -1012,11 +1013,26 @@ int32 LoginServer::DetermineCharacterLoginRequest ( UsertoWorldRequest_Struct* u
 	if(status == -2)
 	utwrs->response = -2;
 	*/
-	//printf("Response is %i for %i\n",utwrs->response,id);
-	if((strcmp(net.GetWorldAddress(), utwr->ip_address)==0) && (strlen(net.GetInternalWorldAddress())>0))
+	//printf("Response is %i for %i\n",utwrs->response,id);struct sockaddr_in sa;
+	int32 ipv4addr = 0;
+	int result = 0;
+	#ifdef WIN32
+		struct sockaddr_in myaddr;
+		ZeroMemory(&myaddr, sizeof(myaddr));
+		result = InetPton(AF_INET, utwr->ip_address, &(myaddr.sin_addr));
+		if(result)
+			ipv4addr = ntohl(myaddr.sin_addr.s_addr);
+
+	#else
+		inet_pton(AF_INET, utwr->ip_address, &ipv4addr);
+	#endif
+	if((result > 0 && (ipv4addr = ntohl(ipv4addr)) && IsPrivateAddress(ipv4addr)) || (strcmp(net.GetWorldAddress(), utwr->ip_address)==0) && (strlen(net.GetInternalWorldAddress())>0))
 		strcpy(utwrs->ip_address, net.GetInternalWorldAddress());
 	else
 		strcpy(utwrs->ip_address, net.GetWorldAddress());
+	
+	LogWrite(CCLIENT__INFO, 0, "World", "New client login attempt from %s, providing %s as the world server address.",utwr->ip_address, utwrs->ip_address );
+
 	utwrs->port = net.GetWorldPort();
 	utwrs->worldid = utwr->worldid;
 	SendPacket(outpack);

+ 8 - 1
EQ2/source/common/EQStream.cpp

@@ -251,6 +251,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p, EQProtocolPacket* lastp)
 				printf( "OP_Combined:\n");
 				DumpPacket(p);
 #endif
+				EQProtocolPacket* prevPacket = 0;
 				while(processed<p->size) {
 					if ((subpacket_length=(unsigned char)*(p->pBuffer+processed))==0xff) {
 						subpacket_length = ntohs(*(uint16*)(p->pBuffer + processed + 1));
@@ -268,6 +269,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p, EQProtocolPacket* lastp)
 						subp->copyInfo(p);
 						//I've seen some garbage packets get sent with wrong protocol opcodes but the rest of the combine is still correct
 						//So don't break if GetProtocolPacket fails
+						prevPacket = subp;
 #ifdef LE_DEBUG
 						printf( "Opcode %i:\n", subp->opcode);
 						DumpPacket(subp);
@@ -282,8 +284,13 @@ void EQStream::ProcessPacket(EQProtocolPacket *p, EQProtocolPacket* lastp)
 						//Garbage packet?
 						crypto->RC4Decrypt(p->pBuffer + processed + offset, subpacket_length);
 						LogWrite(PACKET__ERROR, 0, "Packet", "Garbage packet?!:");
-						printf("!!!!!!!!!Garbage Packet!!!!!!!!!!!!!:\n");
+						printf("!!!!!!!!!Garbage Packet!!!!!!!!!!!!! processed: %u, offset: %u, count: %i\n", processed, offset, count);
 						DumpPacket(p->pBuffer + processed + offset, subpacket_length);
+						if(prevPacket)
+						{
+							printf("prevPacketSize: %u\n", prevPacket->size);
+							DumpPacket(prevPacket);
+						}
 					}
 					processed+=subpacket_length+offset;
 				}

+ 23 - 0
EQ2/source/common/MiscFunctions.h

@@ -93,6 +93,29 @@ float as_float(const uint32 x);
 bool INIReadBool(FILE *f, const char *section, const char *property, bool *out);
 bool INIReadInt(FILE *f, const char *section, const char *property, int *out);
 
+static bool IsPrivateAddress(uint32_t ip)
+{
+    uint8_t b1, b2, b3, b4;
+    b1 = (uint8_t)(ip >> 24);
+    b2 = (uint8_t)((ip >> 16) & 0x0ff);
+    b3 = (uint8_t)((ip >> 8) & 0x0ff);
+    b4 = (uint8_t)(ip & 0x0ff);
+
+    // 10.x.y.z
+    if (b1 == 10)
+        return true;
+
+    // 172.16.0.0 - 172.31.255.255
+    if ((b1 == 172) && (b2 >= 16) && (b2 <= 31))
+        return true;
+
+    // 192.168.0.0 - 192.168.255.255
+    if ((b1 == 192) && (b2 == 168))
+        return true;
+
+    return false;
+}
+
 template<class Type> void AddData(Type input, string* datastring){
 	if(datastring)
 		datastring->append((char*)&input, sizeof(input));

+ 29 - 3
EQ2/source/common/TCPConnection.cpp

@@ -963,19 +963,21 @@ bool TCPConnection::ProcessReceivedDataAsPackets(char* errbuf) {
 	if (errbuf)
 		errbuf[0] = 0;
 	sint32 base = 0;
-	sint32 size = 7;
+	sint32 size = 0;
 	uchar* buffer;
+	sint32 sizeReq = sizeof(TCPNetPacket_Struct);
 	ServerPacket* pack = 0;
 	while ((recvbuf_used - base) >= size) {
 		TCPNetPacket_Struct* tnps = (TCPNetPacket_Struct*) &recvbuf[base];
 		buffer = tnps->buffer;
 		size = tnps->size;
-		if (size >= MaxTCPReceiveBufferSize) {
+
+		if (size < sizeReq || recvbuf_used < sizeReq || size >= MaxTCPReceiveBufferSize) {
 #if TCPN_DEBUG_Memory >= 1
 			cout << "TCPConnection[" << GetID() << "]::ProcessReceivedDataAsPackets(): size[" << size << "] >= MaxTCPReceiveBufferSize" << endl;
 #endif
 			if (errbuf)
-				snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::ProcessReceivedDataAsPackets(): size >= MaxTCPReceiveBufferSize");
+				snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::ProcessReceivedDataAsPackets(): size provided %i, recvbuf_used %i, checks failed: struct_size < %i || recvbuf_used < sizeReq || size >= MaxTCPReceiveBufferSize", size, recvbuf_used, sizeReq);
 			return false;
 		}
 		if ((recvbuf_used - base) >= size) {
@@ -986,12 +988,28 @@ bool TCPConnection::ProcessReceivedDataAsPackets(char* errbuf) {
 			// read headers
 			pack->opcode = tnps->opcode;
 			if (tnps->flags.compressed) {
+				sizeReq += 4;
+				if(size < sizeReq || recvbuf_used < sizeReq)
+				{		
+					if (errbuf)
+						snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::ProcessReceivedDataAsPackets(Flags.Compressed): size provided %i, recvbuf_used %i, checks failed: struct_size < %i || recvbuf_used < sizeReq", size, recvbuf_used, sizeReq);
+					safe_delete(pack);
+					return false;
+				}
 				pack->compressed = true;
 				pack->InflatedSize = *((sint32*)buffer);
 				pack->size -= 4;
 				buffer += 4;
 			}
 			if (tnps->flags.destination) {
+				sizeReq += 4;
+				if(size < sizeReq || recvbuf_used < sizeReq)
+				{		
+					if (errbuf)
+						snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::ProcessReceivedDataAsPackets(Flags.Destination): size provided %i, recvbuf_used %i, checks failed: struct_size < %i || recvbuf_used < sizeReq", size, recvbuf_used, sizeReq);
+					safe_delete(pack);
+					return false;
+				}
 				pack->destination = *((sint32*)buffer);
 				pack->size -= 4;
 				buffer += 4;
@@ -1005,6 +1023,14 @@ bool TCPConnection::ProcessReceivedDataAsPackets(char* errbuf) {
 					{
 						pack->pBuffer = new uchar[pack->InflatedSize];
 						pack->size = InflatePacket(buffer, pack->size, pack->pBuffer, pack->InflatedSize);
+						if(!pack->size)
+						{
+							if (errbuf)
+								snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::ProcessReceivedDataAsPackets(InflatePacket): size provided %i, recvbuf_used: %i, sizeReq: %i, could not inflate packet", size, recvbuf_used, sizeReq);
+
+							safe_delete(pack);
+							return false;
+						}
 					}
 					else
 					{