Beispiel #1
0
/* Receive a vector of pending packets from the UDP socket.
   The returned packets contain the source address and the channel they arrived
   on.  If they did not arrive on a bound channel, the the channel will be set
   to -1.
   This function returns the number of packets read from the network, or -1
   on error.  This function does not block, so can return 0 packets pending.
*/
extern int SDLNet_UDP_RecvV(UDPsocket sock, UDPpacket **packets)
{
    int numrecv, i, j;
    struct UDP_channel *binding;
    socklen_t sock_len;
    struct sockaddr_in sock_addr;

    if ( sock == NULL ) {
        return(0);
    }

    numrecv = 0;
    while ( packets[numrecv] && SocketReady(sock->channel) )
    {
        UDPpacket *packet;

        packet = packets[numrecv];

        sock_len = sizeof(sock_addr);
        packet->status = recvfrom(sock->channel,
                packet->data, packet->maxlen, 0,
                (struct sockaddr *)&sock_addr,
                        &sock_len);
        if ( packet->status >= 0 ) {
            packet->len = packet->status;
            packet->address.host = sock_addr.sin_addr.s_addr;
            packet->address.port = sock_addr.sin_port;
            packet->channel = -1;

            for (i=(SDLNET_MAX_UDPCHANNELS-1); i>=0; --i )
            {
                binding = &sock->binding[i];

                for ( j=binding->numbound-1; j>=0; --j )
                {
                    if ( (packet->address.host == binding->address[j].host) &&
                         (packet->address.port == binding->address[j].port) )
                    {
                        packet->channel = i;
                        goto foundit; /* break twice */
                    }
                }
            }
foundit:
            ++numrecv;
        }

        else
        {
            packet->len = 0;
        }
    }

    sock->ready = 0;

    return(numrecv);
}
bool Connection::DoClientKeyExchange()
{
	// Generate RC4 key
	unsigned int i = 0;
	unsigned char rc4key[RC4_KEY_SIZE];
	unsigned char buffer[128];

	memset(rc4key, 0, sizeof(rc4key));
	SetRC4Key(rc4key);

	// Receive the pubic key packet
	Sleep(20);
	memset(buffer, 0, sizeof(buffer));

	if ( !SocketReady() || (recv(m_Socket, (char *) buffer, 74, 0) != 74) )
	{
		LogMessage("[%d] ERROR: DoClientKeyExchange recv\n", m_RecvThreadHandle);
		return false;
	}

	// Clear the buffer
	memset(buffer, 0, WWRSA_BLOCK_SIZE - RC4_KEY_SIZE + sizeof(long));

	// Put the length in front of the buffer
	unsigned char *key = buffer + sizeof(long);
	*((unsigned long *) buffer) = ntohl(WWRSA_BLOCK_SIZE);

	// Copy the RC4 key to the bottom of the buffer
	unsigned char *dest = &key[WWRSA_BLOCK_SIZE - 1];
	unsigned char *src = rc4key;
	for (i = 0; i < RC4_KEY_SIZE; i++) *dest-- = *src++;

	// Encrypt the RC4 key
	m_WestwoodRSA.Encrypt(key, WWRSA_BLOCK_SIZE, key);

	// Send the encrypted RC4 key to the server
	int length = WWRSA_BLOCK_SIZE + sizeof(long);

	// Returns true if not socket error or timeout and buffer was completely sent
	return bool( SocketReady() && (send(m_Socket, (char *) buffer, length, 0) == length) );
}
Beispiel #3
0
/* Receive a vector of pending packets from the UDP socket.
   The returned packets contain the source address and the channel they arrived
   on.  If they did not arrive on a bound channel, the the channel will be set
   to -1.
   This function returns the number of packets read from the network, or -1
   on error.  This function does not block, so can return 0 packets pending.
*/
extern int SDLNet_UDP_RecvV(UDPsocket sock, UDPpacket **packets)
{
	int numrecv, i, j;
	struct UDP_channel *binding;
#ifdef MACOS_OPENTRANSPORT
	TUnitData OTpacket;
	OTFlags flags;
	InetAddress address;
#else
	int sock_len;
	struct sockaddr_in sock_addr;
#endif

	numrecv = 0;
	while ( packets[numrecv] && SocketReady(sock->channel) ) 
	{
	UDPpacket *packet;

		packet = packets[numrecv];
		
#ifdef MACOS_OPENTRANSPORT
		memset(&OTpacket, 0, sizeof(OTpacket));
		OTpacket.addr.buf = (Uint8 *)&address;
		OTpacket.addr.maxlen = (sizeof address);
		OTpacket.udata.buf = packet->data;
		OTpacket.udata.maxlen = packet->maxlen;
		
		packet->status = OTRcvUData(sock->channel, &OTpacket, &flags);
#ifdef DEBUG_NET
		printf("Packet status: %d\n", packet->status);
#endif
		AsyncUDPPopEvent(sock);
		if (packet->status == noErr)
		{
			packet->len = OTpacket.udata.len;
			packet->address.host = address.fHost;
			packet->address.port = address.fPort;
#ifdef DEBUG_NET
			printf("Packet address: 0x%8.8x:%d, length = %d\n", packet->address.host, packet->address.port, packet->len);
#endif
		}
#else
		sock_len = sizeof(sock_addr);
		packet->status = recvfrom(sock->channel,
				packet->data, packet->maxlen, 0,
				(struct sockaddr *)&sock_addr,
#ifdef USE_GUSI_SOCKETS
				(unsigned int *)&sock_len);
#else
						&sock_len);
#endif
		if ( packet->status >= 0 ) {
			packet->len = packet->status;
			packet->address.host = sock_addr.sin_addr.s_addr;
			packet->address.port = sock_addr.sin_port;
		}
#endif
		if (packet->status >= 0)
		{
			packet->channel = -1;
			
			for (i=(SDLNET_MAX_UDPCHANNELS-1); i>=0; --i ) 
			{
				binding = &sock->binding[i];
				
				for ( j=binding->numbound-1; j>=0; --j ) 
				{
					if ( (packet->address.host == binding->address[j].host) &&
					     (packet->address.port == binding->address[j].port) ) 
					{
						packet->channel = i;
						goto foundit; /* break twice */
					}
				}
			}
foundit:
			++numrecv;
		} 
		
		else 
		{
			packet->len = 0;
		}
	}
	
	sock->ready = 0;
	
	return(numrecv);
}
void Connection::RunRecvThread()
{
	bool isSocketReady	= false;		// Used for checking Socket state
	int numretries		= 0;

	int received;
	unsigned short bytes;
	short opcode;

	EnbTcpHeader header;
	char *ptr_hdr = (char*)&header;

	memset(&header, 0, sizeof(header));

	while (!g_ServerShutdown && !m_TcpThreadTerminated)
	{
		while (m_TcpThreadRunning)
		{
			// Do the key exchange if it hasn't been done yet
			if (!m_KeysExchanged)
			{
				if (!RunKeyExchange())
				{
					// Key Exchange failed.
					KillConnection();
					break;
				}
				else
				{
					m_KeysExchanged = true;
				}
			}

			// Main Loop

			isSocketReady = SocketReady(1);		// One Second Timeout

			if ( isSocketReady && (recv(m_Socket, ptr_hdr, 4, 0) == 4) )
			{
				m_InactivityTimer = 0;				

				if (m_PacketLoggingEnabled)
				{
					LogMessage("[%d] Received 4 byte header (encrypted):\n", m_RecvThreadHandle);
					DumpBuffer((unsigned char *) &header, 4);
				}

				if (m_ServerType != CONNECTION_TYPE_SECTOR_SERVER_TO_PROXY && m_ServerType != CONNECTION_TYPE_GLOBAL_PROXY_TO_SERVER)
				{
					m_CryptIn.RC4((unsigned char *) &header, 4);
				}

				if (m_PacketLoggingEnabled)
				{
					LogMessage("[%d] Received 4 byte header (decrypted):\n", m_RecvThreadHandle);
					DumpBuffer((unsigned char *) &header, 4);
				}

				bytes	= header.size - sizeof(EnbTcpHeader);	// Bytes to fetch
				opcode	= header.opcode;			// Opcode for this packet

				// This buffer check MUST be in place
				if ( (bytes > MAX_BUFFER) )
				{
					LogMessage("[%d] Received packet with incorrect payload length: opcode = 0x%02x, length = %d. Aborting.\n", m_RecvThreadHandle, opcode, bytes);
					
					KillConnection();			// We're not permitting a 2nd chance.
					break;
				}

				//LogMessage("Received packet: opcode = 0x%02x, length = %d\n", opcode, bytes);
				
				received = recv(m_Socket, (char *) m_RecvBuffer, bytes, 0);
				numretries = 0;

				while ( received != bytes && 			// Did we fetch everything?
					SocketReady() && 			// Can we still get more?
					numretries < MAX_RETRIES &&		// Can we still retry to get more?
					m_TcpThreadRunning )			// And we haven't been told to stop?
				{
					int rcv = recv(m_Socket, (char *) (m_RecvBuffer + received), bytes - received, 0);
					if (rcv > 0)
					{
						received += rcv;
					}
					else break;

					numretries++;				// Prevent an infinite loop
				}

				if ( received == bytes && m_TcpThreadRunning )	// We got the whole package and we haven't been told top stop
				{
					if (m_ServerType != CONNECTION_TYPE_SECTOR_SERVER_TO_PROXY && m_ServerType != CONNECTION_TYPE_GLOBAL_PROXY_TO_SERVER)
					{
						m_CryptIn.RC4(m_RecvBuffer, bytes);
					}

					if (m_PacketLoggingEnabled)
					{
						LogMessage("[%d] Received %d byte packet\n", m_RecvThreadHandle, received);
						DumpBuffer(m_RecvBuffer,bytes);
					}

					switch (m_ServerType)
					{
						case CONNECTION_TYPE_CLIENT_TO_GLOBAL_SERVER :
							ProcessGlobalServerOpcode(opcode, bytes);
							break;

						case CONNECTION_TYPE_CLIENT_TO_MASTER_SERVER :
							ProcessMasterServerOpcode(opcode, bytes);
							break;

						case CONNECTION_TYPE_CLIENT_TO_SECTOR_SERVER :
							//ProcessSectorServerOpcode(opcode, bytes);
							LogMessage("[%d] ERROR!!: Sector Server opcode received!\n", m_RecvThreadHandle);
							break;

						case CONNECTION_TYPE_MASTER_SERVER_TO_SECTOR_SERVER :
							ProcessMasterServerToSectorServerOpcode(opcode, bytes);
							break;

						case CONNECTION_TYPE_SECTOR_SERVER_TO_SECTOR_SERVER :
							ProcessSectorServerToSectorServerOpcode(opcode, bytes);
							break;

						case CONNECTION_TYPE_SECTOR_SERVER_TO_PROXY:
							ProcessProxyClientOpcode(opcode, bytes);
							break;

						case CONNECTION_TYPE_GLOBAL_PROXY_TO_SERVER:
							ProcessProxyGlobalOpcode(opcode, bytes);
							break;

						default:
							LogMessage("[%d] ERROR: Unknown type of connection.\n", m_RecvThreadHandle);
							m_TcpThreadRunning = false; // Shouldn't happen (but was able to with a buffer overflow).
							break;
					}
				}
				else
				{
					// Error Stage

					if (m_TcpThreadRunning) // We weren't told to stop, but never got our whole packet
					{
						LogMessage("[%d] Error receiving TCP packet on port %d, got %d bytes, expecting %d -- aborting!\n", m_RecvThreadHandle,m_TcpPort, received, bytes);
						if (received > 0 && g_Debug && received < 10000) DumpBuffer(m_RecvBuffer, received);
					}

					m_TcpThreadRunning = false;
				}
			}
			else
			{
				// Check Connection Status

				DWORD error = WSAGetLastError();
				if ( !isSocketReady && error == 0 )
				{
					m_InactivityTimer++;

					if ( (m_MaxInactivityTime > 0) && (m_InactivityTimer > m_MaxInactivityTime) )
					{
						LogMessage("[%d] TCP connection on port %d exceeded maximum inactivity. Aborting.\n", m_RecvThreadHandle, m_TcpPort);

						m_TcpThreadRunning = false;
					}
				}
				else
				{
					switch (error)
					{
						case 0:
							LogMessage("[%d] TCP connection on port %d gracefully closed\n", m_RecvThreadHandle, m_TcpPort);
							break;
						case WSAECONNRESET:
							LogMessage("[%d] TCP connection on port %d was reset\n", m_RecvThreadHandle, m_TcpPort);
							break;
						default:
							LogMessage("[%d] TCP error on port %d (Error %d). Aborting.\n", m_RecvThreadHandle, m_TcpPort, error);
							break;
					}
					
					m_TcpThreadRunning = false;
				}
			}
		}

		KillConnection();		

		// m_TcpThreadRunning was set to false. Go to sleep...		
#ifdef WIN32
		SuspendThread(m_RecvThreadHandle);
#else
		pthread_cond_wait(&m_RecvThreadCond, &m_RecvThreadMtx);
#endif
	}

	m_TcpThreadTerminated = true;
}
bool Connection::DoKeyExchange()
{
	unsigned char buffer[128];
	unsigned char *p = buffer;
	int length;

	// Send the RSA Public Key to the client
	length = m_WestwoodRSA.GetModulus(&p);
	length += m_WestwoodRSA.GetPublicExponent(&p);

	if ( (send(m_Socket, (char *) buffer, length, 0) != length) ||		// Did send fail?
	     !SocketReady() || 							// Did the socket timeout?
	     (recv(m_Socket, (char *) buffer, 4, 0) != 4) )			// Never got a 4-byte header?
	{
		return false;		
	}

	long key_length = (long) ntohl((*((unsigned long *) buffer)));
	if ( (key_length <  WWRSA_BLOCK_SIZE) || (key_length > (WWRSA_BLOCK_SIZE + 1)) )
	{
		LogMessage("[%d] ERROR: DoKeyExchange key_length = %d\n", m_RecvThreadHandle, key_length);
		return false;
	}

	// Get the encrypted RC4 Session Key response from the client
	length = recv(m_Socket, (char *) buffer, key_length, 0);
	if (length != key_length)
	{
		LogMessage("[%d] ERROR: DoKeyExchange key_length = %d, recv_length = %d\n", m_RecvThreadHandle, key_length, length);
		return false;
	}

	// Ignore leading 0 if present
	p = buffer;
	if ( (key_length == WWRSA_BLOCK_SIZE + 1) && (*p == 0) )
	{
		key_length--;
		p++;
	}

	// Decrypt the RC4 Session Key
	unsigned char rc4key[WWRSA_BLOCK_SIZE];
	if (!m_WestwoodRSA.Decrypt(p, WWRSA_BLOCK_SIZE, rc4key))
	{
		LogMessage("[%d] ERROR: DoKeyExchange m_WestwoodRSA.Decrypt failed\n", m_RecvThreadHandle);
	        return false;
	}

	unsigned char rc4_key_buffer[RC4_KEY_SIZE];
	// Reverse the order of the decrypted RC4 Session Key
	rc4_key_buffer[0] = rc4key[0x3f];
	rc4_key_buffer[1] = rc4key[0x3e];
	rc4_key_buffer[2] = rc4key[0x3d];
	rc4_key_buffer[3] = rc4key[0x3c];
	rc4_key_buffer[4] = rc4key[0x3b];
	rc4_key_buffer[5] = rc4key[0x3a];
	rc4_key_buffer[6] = rc4key[0x39];
	rc4_key_buffer[7] = rc4key[0x38];

	SetRC4Key(rc4_key_buffer);

	return true;
}