summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenri Herscher <henri@oreka.org>2007-07-03 16:42:00 +0000
committerHenri Herscher <henri@oreka.org>2007-07-03 16:42:00 +0000
commited63e37f8466f27a990f7310bbcf1faf86697e9a (patch)
treef41023ee2eb219ed5eeaa836515da8dd7a1c594c
parent1b42814d7ab545334fa97982b1b3023731a0cd64 (diff)
Fixed rare but potential crashes by making sure orkaudio cannot read memory beyond the end of any captured packet data.
git-svn-id: https://oreka.svn.sourceforge.net/svnroot/oreka/trunk@452 09dcff7a-b715-0410-9601-b79a96267cd0
-rw-r--r--orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.cpp57
-rw-r--r--orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h23
-rw-r--r--orkaudio/audiocaptureplugins/voip/VoIp.cpp84
3 files changed, 111 insertions, 53 deletions
diff --git a/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.cpp b/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.cpp
index 500f740..660fd08 100644
--- a/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.cpp
+++ b/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.cpp
@@ -74,10 +74,24 @@ CStdString SkinnyMessageToString(int msgEnum)
}
-bool SkinnyValidateStartMediaTransmission(SkStartMediaTransmissionStruct* smt)
+bool SkinnyValidateStartMediaTransmission(SkStartMediaTransmissionStruct* smt, u_char* packetEnd)
{
bool valid = true;
- if (smt->remoteTcpPort > 65535)
+ if(((u_char*)smt + sizeof(SkStartMediaTransmissionStruct)) > packetEnd)
+ {
+ valid = false;
+ }
+ else if (smt->remoteTcpPort > 65535)
+ {
+ valid = false;
+ }
+ return valid;
+}
+
+bool SkinnyValidateStopMediaTransmission(SkStopMediaTransmissionStruct* smt, u_char* packetEnd)
+{
+ bool valid = true;
+ if(((u_char*)smt + sizeof(SkStopMediaTransmissionStruct)) > packetEnd)
{
valid = false;
}
@@ -107,10 +121,14 @@ bool checkPartyString(char* string, int size)
return valid;
}
-bool SkinnyValidateCallInfo(SkCallInfoStruct* sci)
+bool SkinnyValidateCallInfo(SkCallInfoStruct* sci, u_char* packetEnd)
{
bool valid = true;
- if (sci->callType > SKINNY_CALL_TYPE_FORWARD)
+ if(((u_char*)sci + sizeof(SkCallInfoStruct)) > packetEnd)
+ {
+ valid = false;
+ }
+ else if (sci->callType > SKINNY_CALL_TYPE_FORWARD)
{
valid = false;
}
@@ -134,10 +152,14 @@ bool SkinnyValidateCallInfo(SkCallInfoStruct* sci)
}
-bool SkinnyValidateCcm5CallInfo(SkCcm5CallInfoStruct *sci)
+bool SkinnyValidateCcm5CallInfo(SkCcm5CallInfoStruct *sci, u_char* packetEnd)
{
bool valid = true;
- if (sci->callType > SKINNY_CALL_TYPE_FORWARD)
+ if(((u_char*)sci + sizeof(SkCcm5CallInfoStruct)) > packetEnd)
+ {
+ valid = false;
+ }
+ else if (sci->callType > SKINNY_CALL_TYPE_FORWARD)
{
valid = false;
}
@@ -159,19 +181,27 @@ bool SkinnyValidateCcm5CallInfo(SkCcm5CallInfoStruct *sci)
}
-bool SkinnyValidateOpenReceiveChannelAck(SkOpenReceiveChannelAckStruct* orca)
+bool SkinnyValidateOpenReceiveChannelAck(SkOpenReceiveChannelAckStruct* orca, u_char* packetEnd)
{
bool valid = true;
- if (orca->endpointTcpPort > 65535)
+ if(((u_char*)orca + sizeof(SkOpenReceiveChannelAckStruct)) > packetEnd)
+ {
+ valid = false;
+ }
+ else if (orca->endpointTcpPort > 65535)
{
valid = false;
}
return valid;
}
-bool SkinnyValidateLineStat(SkLineStatStruct* lineStat)
+bool SkinnyValidateLineStat(SkLineStatStruct* lineStat, u_char* packetEnd)
{
bool valid = true;
+ if(((u_char*)lineStat + sizeof(SkLineStatStruct)) > packetEnd)
+ {
+ valid = false;
+ }
if(valid)
{
valid = checkPartyString(lineStat->displayName, SKINNY_DISPLAY_NAME_SIZE);
@@ -183,11 +213,14 @@ bool SkinnyValidateLineStat(SkLineStatStruct* lineStat)
return valid;
}
-bool SkinnyValidateSoftKeyEvent(SkSoftKeyEventMessageStruct* softKeyEvent)
+bool SkinnyValidateSoftKeyEvent(SkSoftKeyEventMessageStruct* softKeyEvent, u_char* packetEnd)
{
bool valid = true;
-
- if(softKeyEvent->softKeyEvent > SKINNY_SOFTKEY_MAX_EVENT ||
+ if(((u_char*)softKeyEvent + sizeof(SkSoftKeyEventMessageStruct)) > packetEnd)
+ {
+ valid = false;
+ }
+ else if(softKeyEvent->softKeyEvent > SKINNY_SOFTKEY_MAX_EVENT ||
softKeyEvent->softKeyEvent < SKINNY_SOFTKEY_MIN_EVENT)
{
valid = false;
diff --git a/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h b/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h
index c01303a..f054c43 100644
--- a/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h
+++ b/orkaudio/audiocaptureplugins/voip/PacketHeaderDefs.h
@@ -111,7 +111,7 @@ typedef struct
// and some more fields
} SkStartMediaTransmissionStruct;
-bool SkinnyValidateStartMediaTransmission(SkStartMediaTransmissionStruct *);
+bool SkinnyValidateStartMediaTransmission(SkStartMediaTransmissionStruct *, u_char* packetEnd);
typedef struct
@@ -121,6 +121,7 @@ typedef struct
unsigned long passThruPartyId;
} SkStopMediaTransmissionStruct;
+bool SkinnyValidateStopMediaTransmission(SkStopMediaTransmissionStruct*, u_char* packetEnd);
typedef struct
{
@@ -145,7 +146,7 @@ typedef struct
unsigned long callType;
} SkCallInfoStruct;
-bool SkinnyValidateCallInfo(SkCallInfoStruct *);
+bool SkinnyValidateCallInfo(SkCallInfoStruct *, u_char* packetEnd);
#define SKINNY_CCM5_PARTIES_BLOCK_SIZE 76
@@ -159,7 +160,7 @@ typedef struct
char parties[SKINNY_CCM5_PARTIES_BLOCK_SIZE];
} SkCcm5CallInfoStruct;
-bool SkinnyValidateCcm5CallInfo(SkCcm5CallInfoStruct *);
+bool SkinnyValidateCcm5CallInfo(SkCcm5CallInfoStruct *, u_char* packetEnd);
#define SKINNY_LINE_DIR_NUMBER_SIZE 24
#define SKINNY_DISPLAY_NAME_SIZE 40
@@ -171,7 +172,7 @@ typedef struct
char displayName[SKINNY_DISPLAY_NAME_SIZE];
} SkLineStatStruct;
-bool SkinnyValidateLineStat(SkLineStatStruct*);
+bool SkinnyValidateLineStat(SkLineStatStruct*, u_char* packetEnd);
// Endpoint -> Cisco Callmanager messages
typedef struct
@@ -183,7 +184,7 @@ typedef struct
unsigned long passThruPartyId;
} SkOpenReceiveChannelAckStruct;
-bool SkinnyValidateOpenReceiveChannelAck(SkOpenReceiveChannelAckStruct *);
+bool SkinnyValidateOpenReceiveChannelAck(SkOpenReceiveChannelAckStruct *, u_char* packetEnd);
typedef struct
{
@@ -193,7 +194,7 @@ typedef struct
unsigned long callIdentifier;
} SkSoftKeyEventMessageStruct;
-bool SkinnyValidateSoftKeyEvent(SkSoftKeyEventMessageStruct *);
+bool SkinnyValidateSoftKeyEvent(SkSoftKeyEventMessageStruct *, u_char* packetEnd);
#define SKINNY_CTRL_PORT 2000
#define SKINNY_MIN_MESSAGE_SIZE 12
@@ -331,5 +332,15 @@ struct Iax2MetaTrunkEntryTs {
struct Iax2MiniHeader mini;
};
+//==============================================
+// SIP
+
+#define SIP_METHOD_INVITE_SIZE 6
+#define SIP_METHOD_BYE_SIZE 3
+#define SIP_METHOD_INVITE "INVITE"
+#define SIP_METHOD_BYE "BYE"
+
#endif
+
+
diff --git a/orkaudio/audiocaptureplugins/voip/VoIp.cpp b/orkaudio/audiocaptureplugins/voip/VoIp.cpp
index c41d477..5569688 100644
--- a/orkaudio/audiocaptureplugins/voip/VoIp.cpp
+++ b/orkaudio/audiocaptureplugins/voip/VoIp.cpp
@@ -1047,17 +1047,18 @@ bool TryRtp(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, UdpH
}
-bool TrySipBye(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, UdpHeaderStruct* udpHeader, u_char* udpPayload)
+bool TrySipBye(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, UdpHeaderStruct* udpHeader, u_char* udpPayload, u_char* packetEnd)
{
bool result = false;
- int udp_act_payload_len = (ntohs(udpHeader->len)-sizeof(UdpHeaderStruct));
- if(udp_act_payload_len < 3)
+ int sipLength = ntohs(udpHeader->len) - sizeof(UdpHeaderStruct);
+ char* sipEnd = (char*)udpPayload + sipLength;
+ if(sipLength < sizeof(SIP_METHOD_BYE) || sipEnd > (char*)packetEnd)
{
- return false; // Frame too small
+ return false;
}
- if (memcmp("BYE", (void*)udpPayload, 3) == 0)
+ if (memcmp(SIP_METHOD_BYE, (void*)udpPayload, SIP_METHOD_BYE_SIZE) == 0)
{
result = true;
int sipLength = ntohs(udpHeader->len);
@@ -1077,8 +1078,8 @@ bool TrySipBye(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, U
return result;
}
-bool TrySipInvite(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, UdpHeaderStruct* udpHeader, u_char* udpPayload);
-bool TrySipBye(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, UdpHeaderStruct* udpHeader, u_char* udpPayload);
+bool TrySipInvite(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, UdpHeaderStruct* udpHeader, u_char* udpPayload, u_char* packetEnd);
+bool TrySipBye(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, UdpHeaderStruct* udpHeader, u_char* udpPayload, u_char* packetEnd);
static bool SipByeTcpToUdp(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader,TcpHeaderStruct* tcpHeader, u_char *pBuffer, int bLength)
{
@@ -1088,7 +1089,7 @@ static bool SipByeTcpToUdp(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct*
udpHeader.dest = tcpHeader->dest;
udpHeader.len = htons(bLength+sizeof(UdpHeaderStruct));
- return TrySipBye(ethernetHeader, ipHeader, &udpHeader, pBuffer);
+ return TrySipBye(ethernetHeader, ipHeader, &udpHeader, pBuffer, pBuffer+bLength);
}
static bool SipInviteTcpToUdp(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, TcpHeaderStruct* tcpHeader, u_char *pBuffer, int bLength)
@@ -1099,7 +1100,7 @@ static bool SipInviteTcpToUdp(EthernetHeaderStruct* ethernetHeader, IpHeaderStru
udpHeader.dest = tcpHeader->dest;
udpHeader.len = htons(bLength+sizeof(UdpHeaderStruct));
- return TrySipInvite(ethernetHeader, ipHeader, &udpHeader, pBuffer);
+ return TrySipInvite(ethernetHeader, ipHeader, &udpHeader, pBuffer, pBuffer+bLength);
}
bool TrySipTcp(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, TcpHeaderStruct* tcpHeader)
@@ -1114,13 +1115,13 @@ bool TrySipTcp(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, T
u_char* startTcpPayload = (u_char*)tcpHeader + TCP_HEADER_LENGTH;
tcpLengthPayloadLength = ((u_char*)ipHeader+ntohs(ipHeader->ip_len)) - startTcpPayload;
- if(tcpLengthPayloadLength < 6)
+ if(tcpLengthPayloadLength < SIP_METHOD_INVITE_SIZE)
{
return false;
}
- if((memcmp("INVITE", (void*)startTcpPayload, 6) == 0) ||
- (memcmp("BYE", (void*)startTcpPayload, 3) == 0))
+ if((memcmp(SIP_METHOD_INVITE, (void*)startTcpPayload, SIP_METHOD_INVITE_SIZE) == 0) ||
+ (memcmp(SIP_METHOD_BYE, (void*)startTcpPayload, SIP_METHOD_BYE_SIZE) == 0))
{
SipTcpStreamRef tcpstream(new SipTcpStream());
int exists = 0;
@@ -1166,7 +1167,7 @@ bool TrySipTcp(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, T
tcpstream->ToString(tcpStream);
LOG4CXX_INFO(s_sipTcpPacketLog, "Obtained complete TCP Stream: " + tcpStream);
- if(memcmp("INVITE", (void*)buffer->GetBuffer(), 6) == 0)
+ if(memcmp(SIP_METHOD_INVITE, (void*)buffer->GetBuffer(), SIP_METHOD_INVITE_SIZE) == 0)
return SipInviteTcpToUdp(ethernetHeader, ipHeader, tcpHeader, buffer->GetBuffer(), buffer->Size());
return SipByeTcpToUdp(ethernetHeader, ipHeader, tcpHeader, buffer->GetBuffer(), buffer->Size());
@@ -1205,7 +1206,7 @@ bool TrySipTcp(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, T
tcpstream->ToString(tcpStream);
LOG4CXX_INFO(s_sipTcpPacketLog, "TCP Stream updated to completion: " + tcpStream);
- if(memcmp("INVITE", (void*)buffer->GetBuffer(), 6) == 0) {
+ if(memcmp(SIP_METHOD_INVITE, (void*)buffer->GetBuffer(), SIP_METHOD_INVITE_SIZE) == 0) {
SipInviteTcpToUdp(ethernetHeader, ipHeader, tcpHeader, buffer->GetBuffer(), buffer->Size());
} else {
SipByeTcpToUdp(ethernetHeader, ipHeader, tcpHeader, buffer->GetBuffer(), buffer->Size());
@@ -1229,23 +1230,22 @@ bool TrySipTcp(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, T
return result;
}
-bool TrySipInvite(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, UdpHeaderStruct* udpHeader, u_char* udpPayload)
+bool TrySipInvite(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader, UdpHeaderStruct* udpHeader, u_char* udpPayload, u_char* packetEnd)
{
bool result = false;
bool drop = false;
- int udp_act_payload_len = (ntohs(udpHeader->len)-sizeof(UdpHeaderStruct));
- if(udp_act_payload_len < 6)
+ int sipLength = ntohs(udpHeader->len) - sizeof(UdpHeaderStruct);
+ char* sipEnd = (char*)udpPayload + sipLength;
+ if(sipLength < sizeof(SIP_METHOD_INVITE) || sipEnd > (char*)packetEnd)
{
- return false; // Frame too small
+ return false;
}
- if (memcmp("INVITE", (void*)udpPayload, 6) == 0)
+
+ if (memcmp(SIP_METHOD_INVITE, (void*)udpPayload, SIP_METHOD_INVITE_SIZE) == 0)
{
result = true;
- int sipLength = ntohs(udpHeader->len);
- char* sipEnd = (char*)udpPayload + sipLength;
-
SipInviteInfoRef info(new SipInviteInfo());
char* fromField = memFindAfter("From:", (char*)udpPayload, sipEnd);
@@ -1369,7 +1369,7 @@ bool TrySipInvite(EthernetHeaderStruct* ethernetHeader, IpHeaderStruct* ipHeader
return result;
}
-void HandleSkinnyMessage(SkinnyHeaderStruct* skinnyHeader, IpHeaderStruct* ipHeader)
+void HandleSkinnyMessage(SkinnyHeaderStruct* skinnyHeader, IpHeaderStruct* ipHeader, u_char* packetEnd)
{
bool useful = true;
CStdString logMsg;
@@ -1389,7 +1389,7 @@ void HandleSkinnyMessage(SkinnyHeaderStruct* skinnyHeader, IpHeaderStruct* ipHea
{
case SkStartMediaTransmission:
startMedia = (SkStartMediaTransmissionStruct*)skinnyHeader;
- if(SkinnyValidateStartMediaTransmission(startMedia))
+ if(SkinnyValidateStartMediaTransmission(startMedia, packetEnd))
{
if(s_skinnyPacketLog->isInfoEnabled())
{
@@ -1409,15 +1409,23 @@ void HandleSkinnyMessage(SkinnyHeaderStruct* skinnyHeader, IpHeaderStruct* ipHea
case SkCloseReceiveChannel:
// StopMediaTransmission and CloseReceiveChannel have the same definition, treat them the same for now.
stopMedia = (SkStopMediaTransmissionStruct*)skinnyHeader;
- if(s_skinnyPacketLog->isInfoEnabled())
+ if(SkinnyValidateStopMediaTransmission(stopMedia, packetEnd))
+ {
+ if(s_skinnyPacketLog->isInfoEnabled())
+ {
+ logMsg.Format(" ConferenceId:%u PassThruPartyId:%u", stopMedia->conferenceId, stopMedia->passThruPartyId);
+ }
+ RtpSessionsSingleton::instance()->ReportSkinnyStopMediaTransmission(stopMedia, ipHeader);
+ }
+ else
{
- logMsg.Format(" ConferenceId:%u PassThruPartyId:%u", stopMedia->conferenceId, stopMedia->passThruPartyId);
+ useful = false;
+ LOG4CXX_WARN(s_skinnyPacketLog, "Invalid StopMediaTransmission or CloseReceiveChannel.");
}
- RtpSessionsSingleton::instance()->ReportSkinnyStopMediaTransmission(stopMedia, ipHeader);
break;
case SkCallInfoMessage:
callInfo = (SkCallInfoStruct*)skinnyHeader;
- if(SkinnyValidateCallInfo(callInfo))
+ if(SkinnyValidateCallInfo(callInfo, packetEnd))
{
if(s_skinnyPacketLog->isInfoEnabled())
{
@@ -1433,7 +1441,7 @@ void HandleSkinnyMessage(SkinnyHeaderStruct* skinnyHeader, IpHeaderStruct* ipHea
break;
case SkCcm5CallInfoMessage:
ccm5CallInfo = (SkCcm5CallInfoStruct*)skinnyHeader;
- if(SkinnyValidateCcm5CallInfo(ccm5CallInfo))
+ if(SkinnyValidateCcm5CallInfo(ccm5CallInfo, packetEnd))
{
// Extract Calling and Called number.
CStdString callingParty;
@@ -1460,7 +1468,7 @@ void HandleSkinnyMessage(SkinnyHeaderStruct* skinnyHeader, IpHeaderStruct* ipHea
break;
case SkOpenReceiveChannelAck:
openReceiveAck = (SkOpenReceiveChannelAckStruct*)skinnyHeader;
- if(SkinnyValidateOpenReceiveChannelAck(openReceiveAck))
+ if(SkinnyValidateOpenReceiveChannelAck(openReceiveAck, packetEnd))
{
if(s_skinnyPacketLog->isInfoEnabled())
{
@@ -1479,7 +1487,7 @@ void HandleSkinnyMessage(SkinnyHeaderStruct* skinnyHeader, IpHeaderStruct* ipHea
break;
case SkLineStatMessage:
lineStat = (SkLineStatStruct*)skinnyHeader;
- if(SkinnyValidateLineStat(lineStat))
+ if(SkinnyValidateLineStat(lineStat, packetEnd))
{
if(s_skinnyPacketLog->isInfoEnabled())
{
@@ -1497,7 +1505,7 @@ void HandleSkinnyMessage(SkinnyHeaderStruct* skinnyHeader, IpHeaderStruct* ipHea
break;
case SkSoftKeyEventMessage:
softKeyEvent = (SkSoftKeyEventMessageStruct*)skinnyHeader;
- if(SkinnyValidateSoftKeyEvent(softKeyEvent))
+ if(SkinnyValidateSoftKeyEvent(softKeyEvent, packetEnd))
{
useful = true;
logMsg.Format(" eventString:%s eventNum:%d lineInstance:%lu callId:%lu",
@@ -1610,6 +1618,12 @@ void HandlePacket(u_char *param, const struct pcap_pkthdr *header, const u_char
}
int ipHeaderLength = ipHeader->ip_hl*4;
u_char* ipPacketEnd = (u_char*)ipHeader + ntohs(ipHeader->ip_len);
+ u_char* captureEnd = (u_char*)pkt_data + header->caplen;
+ if( captureEnd < (u_char*)ipPacketEnd || (u_char*)ipPacketEnd <= ((u_char*)ipHeader + ipHeaderLength + TCP_HEADER_LENGTH))
+ {
+ // The packet has been snipped or has not enough payload, drop it,
+ return;
+ }
#ifdef WIN32
if(!s_liveCapture)
@@ -1675,12 +1689,12 @@ void HandlePacket(u_char *param, const struct pcap_pkthdr *header, const u_char
if(!detectedUsefulPacket) {
detectedUsefulPacket= TrySipInvite(ethernetHeader, ipHeader, udpHeader,
- udpPayload);
+ udpPayload, ipPacketEnd);
}
if(!detectedUsefulPacket) {
detectedUsefulPacket = TrySipBye(ethernetHeader, ipHeader, udpHeader,
- udpPayload);
+ udpPayload, ipPacketEnd);
}
if(DLLCONFIG.m_iax2Support == false)
{
@@ -1757,7 +1771,7 @@ void HandlePacket(u_char *param, const struct pcap_pkthdr *header, const u_char
}
MutexSentinel mutexSentinel(s_mutex); // serialize access for competing pcap threads
- HandleSkinnyMessage(skinnyHeader, ipHeader);
+ HandleSkinnyMessage(skinnyHeader, ipHeader, ipPacketEnd);
// Point to next skinny message within this TCP packet
skinnyHeader = (SkinnyHeaderStruct*)((u_char*)skinnyHeader + SKINNY_HEADER_LENGTH + skinnyHeader->len);