Browse Source

Avoid aliasing problems by using special buf endian handling functions wrapping memcpy

pull/122/head
Francisco Blas (klondike) Izquierdo Riera 10 years ago
parent
commit
1636187e26
  1. 2
      Destination.cpp
  2. 8
      Garlic.cpp
  3. 2
      I2PEndian.cpp
  4. 25
      I2PEndian.h
  5. 4
      Identity.cpp
  6. 4
      NTCPSession.cpp
  7. 6
      NetDb.cpp
  8. 8
      SSUData.cpp
  9. 23
      SSUSession.cpp
  10. 2
      Streaming.cpp
  11. 14
      Streaming.h
  12. 2
      Tunnel.cpp
  13. 8
      TunnelEndpoint.cpp

2
Destination.cpp

@ -357,7 +357,7 @@ namespace client
void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len) void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len)
{ {
uint32_t length = be32toh (*(uint32_t *)buf); uint32_t length = bufbe32toh (buf);
buf += 4; buf += 4;
// we assume I2CP payload // we assume I2CP payload
switch (buf[9]) switch (buf[9])

8
Garlic.cpp

@ -331,7 +331,7 @@ namespace garlic
void GarlicDestination::HandleGarlicMessage (I2NPMessage * msg) void GarlicDestination::HandleGarlicMessage (I2NPMessage * msg)
{ {
uint8_t * buf = msg->GetPayload (); uint8_t * buf = msg->GetPayload ();
uint32_t length = be32toh (*(uint32_t *)buf); uint32_t length = bufbe32toh (buf);
buf += 4; // length buf += 4; // length
auto it = m_Tags.find (SessionTag(buf)); auto it = m_Tags.find (SessionTag(buf));
if (it != m_Tags.end ()) if (it != m_Tags.end ())
@ -389,7 +389,7 @@ namespace garlic
void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<i2p::crypto::CBCDecryption> decryption, void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<i2p::crypto::CBCDecryption> decryption,
i2p::tunnel::InboundTunnel * from) i2p::tunnel::InboundTunnel * from)
{ {
uint16_t tagCount = be16toh (*(uint16_t *)buf); uint16_t tagCount = bufbe16toh (buf);
buf += 2; len -= 2; buf += 2; len -= 2;
if (tagCount > 0) if (tagCount > 0)
{ {
@ -404,7 +404,7 @@ namespace garlic
} }
buf += tagCount*32; buf += tagCount*32;
len -= tagCount*32; len -= tagCount*32;
uint32_t payloadSize = be32toh (*(uint32_t *)buf); uint32_t payloadSize = bufbe32toh (buf);
if (payloadSize > len) if (payloadSize > len)
{ {
LogPrint (eLogError, "Unexpected payload size ", payloadSize); LogPrint (eLogError, "Unexpected payload size ", payloadSize);
@ -460,7 +460,7 @@ namespace garlic
// gwHash and gwTunnel sequence is reverted // gwHash and gwTunnel sequence is reverted
uint8_t * gwHash = buf; uint8_t * gwHash = buf;
buf += 32; buf += 32;
uint32_t gwTunnel = be32toh (*(uint32_t *)buf); uint32_t gwTunnel = bufbe32toh (buf);
buf += 4; buf += 4;
i2p::tunnel::OutboundTunnel * tunnel = nullptr; i2p::tunnel::OutboundTunnel * tunnel = nullptr;
if (from && from->GetTunnelPool ()) if (from && from->GetTunnelPool ())

2
I2PEndian.cpp

@ -5,6 +5,7 @@
#include "LittleBigEndian.h" #include "LittleBigEndian.h"
#ifdef NEEDS_LOCAL_ENDIAN
uint16_t htobe16(uint16_t int16) uint16_t htobe16(uint16_t int16)
{ {
BigEndian<uint16_t> u16(int16); BigEndian<uint16_t> u16(int16);
@ -40,6 +41,7 @@ uint64_t be64toh(uint64_t big64)
LittleEndian<uint64_t> u64(big64); LittleEndian<uint64_t> u64(big64);
return u64.raw_value; return u64.raw_value;
} }
#endif
/* it can be used in Windows 8 /* it can be used in Windows 8
#include <Winsock2.h> #include <Winsock2.h>

25
I2PEndian.h

@ -1,5 +1,7 @@
#ifndef I2PENDIAN_H__ #ifndef I2PENDIAN_H__
#define I2PENDIAN_H__ #define I2PENDIAN_H__
#include <inttypes.h>
#include <cstring>
#if defined(__linux__) || defined(__FreeBSD_kernel__) #if defined(__linux__) || defined(__FreeBSD_kernel__)
#include <endian.h> #include <endian.h>
@ -25,6 +27,7 @@
#define le64toh(x) OSSwapLittleToHostInt64(x) #define le64toh(x) OSSwapLittleToHostInt64(x)
#else #else
#define NEEDS_LOCAL_ENDIAN
#include <cstdint> #include <cstdint>
uint16_t htobe16(uint16_t int16); uint16_t htobe16(uint16_t int16);
uint32_t htobe32(uint32_t int32); uint32_t htobe32(uint32_t int32);
@ -44,5 +47,27 @@ uint64_t be64toh(uint64_t big64);
#endif #endif
inline uint16_t bufbe16toh(const uint8_t *buf)
{
uint16_t big16;
memcpy(&big16, buf, sizeof(uint16_t));
return be16toh(big16);
}
inline uint32_t bufbe32toh(const uint8_t *buf)
{
uint32_t big32;
memcpy(&big32, buf, sizeof(uint32_t));
return be32toh(big32);
}
inline uint64_t bufbe64toh(const uint8_t *buf)
{
uint64_t big64;
memcpy(&big64, buf, sizeof(uint64_t));
return be64toh(big64);
}
#endif // I2PENDIAN_H__ #endif // I2PENDIAN_H__

4
Identity.cpp

@ -275,14 +275,14 @@ namespace data
SigningKeyType IdentityEx::GetSigningKeyType () const SigningKeyType IdentityEx::GetSigningKeyType () const
{ {
if (m_StandardIdentity.certificate.type == CERTIFICATE_TYPE_KEY && m_ExtendedBuffer) if (m_StandardIdentity.certificate.type == CERTIFICATE_TYPE_KEY && m_ExtendedBuffer)
return be16toh (*(const uint16_t *)m_ExtendedBuffer); // signing key return bufbe16toh (m_ExtendedBuffer); // signing key
return SIGNING_KEY_TYPE_DSA_SHA1; return SIGNING_KEY_TYPE_DSA_SHA1;
} }
CryptoKeyType IdentityEx::GetCryptoKeyType () const CryptoKeyType IdentityEx::GetCryptoKeyType () const
{ {
if (m_StandardIdentity.certificate.type == CERTIFICATE_TYPE_KEY && m_ExtendedBuffer) if (m_StandardIdentity.certificate.type == CERTIFICATE_TYPE_KEY && m_ExtendedBuffer)
return be16toh (*(const uint16_t *)(m_ExtendedBuffer + 2)); // crypto key return bufbe16toh (m_ExtendedBuffer + 2); // crypto key
return CRYPTO_KEY_TYPE_ELGAMAL; return CRYPTO_KEY_TYPE_ELGAMAL;
} }

4
NTCPSession.cpp

@ -338,7 +338,7 @@ namespace transport
LogPrint (eLogDebug, "Phase 3 received: ", bytes_transferred); LogPrint (eLogDebug, "Phase 3 received: ", bytes_transferred);
m_Decryption.Decrypt (m_ReceiveBuffer, bytes_transferred, m_ReceiveBuffer); m_Decryption.Decrypt (m_ReceiveBuffer, bytes_transferred, m_ReceiveBuffer);
uint8_t * buf = m_ReceiveBuffer; uint8_t * buf = m_ReceiveBuffer;
uint16_t size = be16toh (*(uint16_t *)buf); uint16_t size = bufbe16toh (buf);
m_RemoteIdentity.FromBuffer (buf + 2, size); m_RemoteIdentity.FromBuffer (buf + 2, size);
size_t expectedSize = size + 2/*size*/ + 4/*timestamp*/ + m_RemoteIdentity.GetSignatureLen (); size_t expectedSize = size + 2/*size*/ + 4/*timestamp*/ + m_RemoteIdentity.GetSignatureLen ();
size_t paddingLen = expectedSize & 0x0F; size_t paddingLen = expectedSize & 0x0F;
@ -526,7 +526,7 @@ namespace transport
m_NextMessageOffset = 0; m_NextMessageOffset = 0;
m_Decryption.Decrypt (encrypted, m_NextMessage->buf); m_Decryption.Decrypt (encrypted, m_NextMessage->buf);
uint16_t dataSize = be16toh (*(uint16_t *)m_NextMessage->buf); uint16_t dataSize = bufbe16toh (m_NextMessage->buf);
if (dataSize) if (dataSize)
{ {
// new message // new message

6
NetDb.cpp

@ -436,7 +436,7 @@ namespace data
else else
{ {
LogPrint ("RouterInfo"); LogPrint ("RouterInfo");
size_t size = be16toh (*(uint16_t *)(buf + offset)); size_t size = bufbe16toh (buf + offset);
if (size > 2048) if (size > 2048)
{ {
LogPrint ("Invalid RouterInfo length ", (int)size); LogPrint ("Invalid RouterInfo length ", (int)size);
@ -597,10 +597,10 @@ namespace data
uint32_t replyTunnelID = 0; uint32_t replyTunnelID = 0;
if (flag & 0x01) //reply to tunnel if (flag & 0x01) //reply to tunnel
{ {
replyTunnelID = be32toh (*(uint32_t *)(buf + 64)); replyTunnelID = bufbe32toh (buf + 64);
excluded += 4; excluded += 4;
} }
uint16_t numExcluded = be16toh (*(uint16_t *)excluded); uint16_t numExcluded = bufbe16toh (excluded);
excluded += 2; excluded += 2;
if (numExcluded > 512) if (numExcluded > 512)
{ {

8
SSUData.cpp

@ -84,7 +84,7 @@ namespace transport
uint8_t numAcks =*buf; uint8_t numAcks =*buf;
buf++; buf++;
for (int i = 0; i < numAcks; i++) for (int i = 0; i < numAcks; i++)
ProcessSentMessageAck (be32toh (((uint32_t *)buf)[i])); ProcessSentMessageAck (bufbe32toh (buf+i*4));
buf += numAcks*4; buf += numAcks*4;
} }
if (flag & DATA_FLAG_ACK_BITFIELDS_INCLUDED) if (flag & DATA_FLAG_ACK_BITFIELDS_INCLUDED)
@ -94,7 +94,7 @@ namespace transport
buf++; buf++;
for (int i = 0; i < numBitfields; i++) for (int i = 0; i < numBitfields; i++)
{ {
uint32_t msgID = be32toh (*(uint32_t *)buf); uint32_t msgID = bufbe32toh (buf);
buf += 4; // msgID buf += 4; // msgID
auto it = m_SentMessages.find (msgID); auto it = m_SentMessages.find (msgID);
// process individual Ack bitfields // process individual Ack bitfields
@ -137,13 +137,13 @@ namespace transport
buf++; buf++;
for (int i = 0; i < numFragments; i++) for (int i = 0; i < numFragments; i++)
{ {
uint32_t msgID = be32toh (*(uint32_t *)buf); // message ID uint32_t msgID = bufbe32toh (buf); // message ID
buf += 4; buf += 4;
uint8_t frag[4]; uint8_t frag[4];
frag[0] = 0; frag[0] = 0;
memcpy (frag + 1, buf, 3); memcpy (frag + 1, buf, 3);
buf += 3; buf += 3;
uint32_t fragmentInfo = be32toh (*(uint32_t *)frag); // fragment info uint32_t fragmentInfo = bufbe32toh (frag); // fragment info
uint16_t fragmentSize = fragmentInfo & 0x1FFF; // bits 0 - 13 uint16_t fragmentSize = fragmentInfo & 0x1FFF; // bits 0 - 13
bool isLast = fragmentInfo & 0x010000; // bit 16 bool isLast = fragmentInfo & 0x010000; // bit 16
uint8_t fragmentNum = fragmentInfo >> 17; // bits 23 - 17 uint8_t fragmentNum = fragmentInfo >> 17; // bits 23 - 17

23
SSUSession.cpp

@ -210,7 +210,7 @@ namespace transport
} }
s.Insert (ourAddress, addressSize); // our IP s.Insert (ourAddress, addressSize); // our IP
payload += addressSize; // address payload += addressSize; // address
uint16_t ourPort = be16toh (*(uint16_t *)payload); uint16_t ourPort = bufbe16toh (payload);
s.Insert (payload, 2); // our port s.Insert (payload, 2); // our port
payload += 2; // port payload += 2; // port
LogPrint ("Our external address is ", ourIP.to_string (), ":", ourPort); LogPrint ("Our external address is ", ourIP.to_string (), ":", ourPort);
@ -221,7 +221,7 @@ namespace transport
s.Insert (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), 16); // remote IP v6 s.Insert (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), 16); // remote IP v6
s.Insert (htobe16 (m_RemoteEndpoint.port ())); // remote port s.Insert (htobe16 (m_RemoteEndpoint.port ())); // remote port
s.Insert (payload, 8); // relayTag and signed on time s.Insert (payload, 8); // relayTag and signed on time
m_RelayTag = be32toh (*(uint32_t *)payload); m_RelayTag = bufbe32toh (payload);
payload += 4; // relayTag payload += 4; // relayTag
payload += 4; // signed on time payload += 4; // signed on time
// decrypt signature // decrypt signature
@ -242,7 +242,7 @@ namespace transport
LogPrint (eLogDebug, "Session confirmed received"); LogPrint (eLogDebug, "Session confirmed received");
uint8_t * payload = buf + sizeof (SSUHeader); uint8_t * payload = buf + sizeof (SSUHeader);
payload++; // identity fragment info payload++; // identity fragment info
uint16_t identitySize = be16toh (*(uint16_t *)payload); uint16_t identitySize = bufbe16toh (payload);
payload += 2; // size of identity fragment payload += 2; // size of identity fragment
m_RemoteIdentity.FromBuffer (payload, identitySize); m_RemoteIdentity.FromBuffer (payload, identitySize);
m_Data.UpdatePacketSize (m_RemoteIdentity.GetIdentHash ()); m_Data.UpdatePacketSize (m_RemoteIdentity.GetIdentHash ());
@ -443,7 +443,7 @@ namespace transport
void SSUSession::ProcessRelayRequest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& from) void SSUSession::ProcessRelayRequest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& from)
{ {
uint32_t relayTag = be32toh (*(uint32_t *)buf); uint32_t relayTag = bufbe32toh (buf);
auto session = m_Server.FindRelaySession (relayTag); auto session = m_Server.FindRelaySession (relayTag);
if (session) if (session)
{ {
@ -457,7 +457,7 @@ namespace transport
buf += challengeSize; buf += challengeSize;
uint8_t * introKey = buf; uint8_t * introKey = buf;
buf += 32; // introkey buf += 32; // introkey
uint32_t nonce = be32toh (*(uint32_t *)buf); uint32_t nonce = bufbe32toh (buf);
SendRelayResponse (nonce, from, introKey, session->m_RemoteEndpoint); SendRelayResponse (nonce, from, introKey, session->m_RemoteEndpoint);
SendRelayIntro (session.get (), from); SendRelayIntro (session.get (), from);
} }
@ -550,9 +550,9 @@ namespace transport
uint8_t * payload = buf + sizeof (SSUHeader); uint8_t * payload = buf + sizeof (SSUHeader);
uint8_t remoteSize = *payload; uint8_t remoteSize = *payload;
payload++; // remote size payload++; // remote size
//boost::asio::ip::address_v4 remoteIP (be32toh (*(uint32_t* )(payload))); //boost::asio::ip::address_v4 remoteIP (bufbe32toh (payload));
payload += remoteSize; // remote address payload += remoteSize; // remote address
//uint16_t remotePort = be16toh (*(uint16_t *)(payload)); //uint16_t remotePort = bufbe16toh (payload);
payload += 2; // remote port payload += 2; // remote port
uint8_t ourSize = *payload; uint8_t ourSize = *payload;
payload++; // our size payload++; // our size
@ -570,7 +570,7 @@ namespace transport
ourIP = boost::asio::ip::address_v6 (bytes); ourIP = boost::asio::ip::address_v6 (bytes);
} }
payload += ourSize; // our address payload += ourSize; // our address
uint16_t ourPort = be16toh (*(uint16_t *)(payload)); uint16_t ourPort = bufbe16toh (payload);
payload += 2; // our port payload += 2; // our port
LogPrint ("Our external address is ", ourIP.to_string (), ":", ourPort); LogPrint ("Our external address is ", ourIP.to_string (), ":", ourPort);
i2p::context.UpdateAddress (ourIP); i2p::context.UpdateAddress (ourIP);
@ -582,9 +582,9 @@ namespace transport
if (size == 4) if (size == 4)
{ {
buf++; // size buf++; // size
boost::asio::ip::address_v4 address (be32toh (*(uint32_t* )buf)); boost::asio::ip::address_v4 address (bufbe32toh (buf));
buf += 4; // address buf += 4; // address
uint16_t port = be16toh (*(uint16_t *)buf); uint16_t port = bufbe16toh (buf);
// send hole punch of 1 byte // send hole punch of 1 byte
m_Server.Send (buf, 0, boost::asio::ip::udp::endpoint (address, port)); m_Server.Send (buf, 0, boost::asio::ip::udp::endpoint (address, port));
} }
@ -844,10 +844,11 @@ namespace transport
void SSUSession::ProcessPeerTest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint) void SSUSession::ProcessPeerTest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint)
{ {
uint8_t * buf1 = buf; uint8_t * buf1 = buf;
uint32_t nonce = be32toh (*(uint32_t *)buf); uint32_t nonce = bufbe32toh (buf);
buf += 4; // nonce buf += 4; // nonce
uint8_t size = *buf; uint8_t size = *buf;
buf++; // size buf++; // size
uint32_t address = (size == 4) ? *(uint32_t *)buf : 0; // use it as is uint32_t address = (size == 4) ? *(uint32_t *)buf : 0; // use it as is
buf += size; // address buf += size; // address
uint16_t port = *(uint16_t *)buf; // use it as is uint16_t port = *(uint16_t *)buf; // use it as is

2
Streaming.cpp

@ -167,7 +167,7 @@ namespace stream
if (flags & PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED) if (flags & PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED)
{ {
uint16_t maxPacketSize = be16toh (*(uint16_t *)optionData); uint16_t maxPacketSize = bufbe16toh (optionData);
LogPrint (eLogDebug, "Max packet size ", maxPacketSize); LogPrint (eLogDebug, "Max packet size ", maxPacketSize);
optionData += 2; optionData += 2;
} }

14
Streaming.h

@ -53,15 +53,15 @@ namespace stream
uint8_t * GetBuffer () { return buf + offset; }; uint8_t * GetBuffer () { return buf + offset; };
size_t GetLength () const { return len - offset; }; size_t GetLength () const { return len - offset; };
uint32_t GetSendStreamID () const { return be32toh (*(uint32_t *)buf); }; uint32_t GetSendStreamID () const { return bufbe32toh (buf); };
uint32_t GetReceiveStreamID () const { return be32toh (*(uint32_t *)(buf + 4)); }; uint32_t GetReceiveStreamID () const { return bufbe32toh (buf + 4); };
uint32_t GetSeqn () const { return be32toh (*(uint32_t *)(buf + 8)); }; uint32_t GetSeqn () const { return bufbe32toh (buf + 8); };
uint32_t GetAckThrough () const { return be32toh (*(uint32_t *)(buf + 12)); }; uint32_t GetAckThrough () const { return bufbe32toh (buf + 12); };
uint8_t GetNACKCount () const { return buf[16]; }; uint8_t GetNACKCount () const { return buf[16]; };
uint32_t GetNACK (int i) const { return be32toh (((uint32_t *)(buf + 17))[i]); }; uint32_t GetNACK (int i) const { return bufbe32toh (buf + 17 + 4 * i); };
const uint8_t * GetOption () const { return buf + 17 + GetNACKCount ()*4 + 3; }; // 3 = resendDelay + flags const uint8_t * GetOption () const { return buf + 17 + GetNACKCount ()*4 + 3; }; // 3 = resendDelay + flags
uint16_t GetFlags () const { return be16toh (*(uint16_t *)(GetOption () - 2)); }; uint16_t GetFlags () const { return bufbe16toh (GetOption () - 2); };
uint16_t GetOptionSize () const { return be16toh (*(uint16_t *)GetOption ()); }; uint16_t GetOptionSize () const { return bufbe16toh (GetOption ()); };
const uint8_t * GetOptionData () const { return GetOption () + 2; }; const uint8_t * GetOptionData () const { return GetOption () + 2; };
const uint8_t * GetPayload () const { return GetOptionData () + GetOptionSize (); }; const uint8_t * GetPayload () const { return GetOptionData () + GetOptionSize (); };

2
Tunnel.cpp

@ -356,7 +356,7 @@ namespace tunnel
I2NPMessage * msg = m_Queue.GetNextWithTimeout (1000); // 1 sec I2NPMessage * msg = m_Queue.GetNextWithTimeout (1000); // 1 sec
while (msg) while (msg)
{ {
uint32_t tunnelID = be32toh (*(uint32_t *)msg->GetPayload ()); uint32_t tunnelID = bufbe32toh (msg->GetPayload ());
InboundTunnel * tunnel = GetInboundTunnel (tunnelID); InboundTunnel * tunnel = GetInboundTunnel (tunnelID);
if (tunnel) if (tunnel)
tunnel->HandleTunnelDataMsg (msg); tunnel->HandleTunnelDataMsg (msg);

8
TunnelEndpoint.cpp

@ -61,7 +61,7 @@ namespace tunnel
break; break;
case eDeliveryTypeTunnel: // 1 case eDeliveryTypeTunnel: // 1
LogPrint ("Delivery type tunnel"); LogPrint ("Delivery type tunnel");
m.tunnelID = be32toh (*(uint32_t *)fragment); m.tunnelID = bufbe32toh (fragment);
fragment += 4; // tunnelID fragment += 4; // tunnelID
m.hash = i2p::data::IdentHash (fragment); m.hash = i2p::data::IdentHash (fragment);
fragment += 32; // hash fragment += 32; // hash
@ -79,7 +79,7 @@ namespace tunnel
if (isFragmented) if (isFragmented)
{ {
// Message ID // Message ID
msgID = be32toh (*(uint32_t *)fragment); msgID = bufbe32toh (fragment);
fragment += 4; fragment += 4;
LogPrint ("Fragmented message ", msgID); LogPrint ("Fragmented message ", msgID);
isLastFragment = false; isLastFragment = false;
@ -88,14 +88,14 @@ namespace tunnel
else else
{ {
// follow on // follow on
msgID = be32toh (*(uint32_t *)fragment); // MessageID msgID = bufbe32toh (fragment); // MessageID
fragment += 4; fragment += 4;
fragmentNum = (flag >> 1) & 0x3F; // 6 bits fragmentNum = (flag >> 1) & 0x3F; // 6 bits
isLastFragment = flag & 0x01; isLastFragment = flag & 0x01;
LogPrint ("Follow on fragment ", fragmentNum, " of message ", msgID, isLastFragment ? " last" : " non-last"); LogPrint ("Follow on fragment ", fragmentNum, " of message ", msgID, isLastFragment ? " last" : " non-last");
} }
uint16_t size = be16toh (*(uint16_t *)fragment); uint16_t size = bufbe16toh (fragment);
fragment += 2; fragment += 2;
LogPrint ("Fragment size=", (int)size); LogPrint ("Fragment size=", (int)size);

Loading…
Cancel
Save