File cve-fixes-bnc828028.diff of Package libzrtpcpp
commit c8617100f359b217a974938c5539a1dd8a120b0e
Author: Werner Dittmann <Werner.Dittmann@t-online.de>
Date: Tue Jun 25 10:22:06 2013 +0200
Fix vulnerabilities found and reported by Mark Dowd
- limit length of memcpy
- limit number of offered algorithms in Hello packet
- length check in PING packet
- fix a small coding error
[Backport to 2.x attempted by Jan Engelhardt <jengelh@inai.de>]
References: https://bugzilla.novell.com/show_bug.cgi?id=828028
References: CVE-2013-2221, CVE-2013-2222, CVE-2013-2223
---
src/ZRtp.cpp | 8 +++++---
src/ZrtpPacketHello.cpp | 5 +++++
src/ZrtpQueue.cpp | 4 ++++
src/ZrtpStateClass.cpp | 4 +++-
4 files changed, 17 insertions(+), 4 deletions(-)
Index: libzrtpcpp-2.3.3/src/ZRtp.cpp
===================================================================
--- libzrtpcpp-2.3.3.orig/src/ZRtp.cpp
+++ libzrtpcpp-2.3.3/src/ZRtp.cpp
@@ -1189,7 +1189,8 @@ ZrtpPacketError* ZRtp::prepareError(uint
}
ZrtpPacketPingAck* ZRtp::preparePingAck(ZrtpPacketPing* ppkt) {
-
+ if (ppkt->getLength() != 6) // A PING packet must have a length of 6 words
+ return NULL;
// Because we do not support ZRTP proxy mode use the truncated ZID.
// If this code shall be used in ZRTP proxy implementation the computation
// of the endpoint hash must be enhanced (see chaps 5.15ff and 5.16)
@@ -1511,7 +1512,7 @@ AlgorithmEnum* ZRtp::findBestSASType(Zrt
// Build list of offered known algos in Hello, append mandatory algos if necessary
for (numAlgosOffered = 0, i = 0; i < num; i++) {
- algosOffered[numAlgosOffered] = &zrtpSasTypes.getByName((const char*)hello->getSasType(i++));
+ algosOffered[numAlgosOffered] = &zrtpSasTypes.getByName((const char*)hello->getSasType(i));
if (!algosOffered[numAlgosOffered]->isValid())
continue;
if (*(int32_t*)(algosOffered[numAlgosOffered++]->getName()) == *(int32_t*)mandatorySasType) {
@@ -2296,7 +2297,8 @@ void ZRtp::setClientId(std::string id) {
}
void ZRtp::storeMsgTemp(ZrtpPacketBase* pkt) {
- int32_t length = pkt->getLength() * ZRTP_WORD_SIZE;
+ uint32_t length = pkt->getLength() * ZRTP_WORD_SIZE;
+ length = (length > sizeof(tempMsgBuffer)) ? sizeof(tempMsgBuffer) : length;
memset(tempMsgBuffer, 0, sizeof(tempMsgBuffer));
memcpy(tempMsgBuffer, (uint8_t*)pkt->getHeaderBase(), length);
lengthOfMsgData = length;
Index: libzrtpcpp-2.3.3/src/ZrtpPacketHello.cpp
===================================================================
--- libzrtpcpp-2.3.3.orig/src/ZrtpPacketHello.cpp
+++ libzrtpcpp-2.3.3/src/ZrtpPacketHello.cpp
@@ -106,10 +106,15 @@ ZrtpPacketHello::ZrtpPacketHello(uint8_t
uint32_t temp = ntohl(t);
nHash = (temp & (0xf << 16)) >> 16;
+ nHash &= 0x7; // restrict to max 7 algorithms
nCipher = (temp & (0xf << 12)) >> 12;
+ nCipher &= 0x7;
nAuth = (temp & (0xf << 8)) >> 8;
+ nAuth &= 0x7;
nPubkey = (temp & (0xf << 4)) >> 4;
+ nPubkey &= 0x7;
nSas = temp & 0xf;
+ nSas &= 0x7;
oHash = sizeof(Hello_t);
oCipher = oHash + (nHash * ZRTP_WORD_SIZE);
Index: libzrtpcpp-2.3.3/src/ZrtpQueue.cpp
===================================================================
--- libzrtpcpp-2.3.3.orig/src/ZrtpQueue.cpp
+++ libzrtpcpp-2.3.3/src/ZrtpQueue.cpp
@@ -158,6 +158,10 @@ ZrtpQueue::takeInDataPacket(void)
// if ZRTP processing is enabled. Because valid RTP packets are
// already handled we delete any packets here after processing.
if (enableZrtp && zrtpEngine != NULL) {
+ // Fixed header length + smallest ZRTP packet (includes CRC)
+ if (rtn < (12 + sizeof(HelloAckPacket_t))) // data too small, dismiss
+ return 0;
+
// Get CRC value into crc (see above how to compute the offset)
uint16_t temp = rtn - CRC_SIZE;
uint32_t crc = *(uint32_t*)(buffer + temp);
Index: libzrtpcpp-2.3.3/src/ZrtpStateClass.cpp
===================================================================
--- libzrtpcpp-2.3.3.orig/src/ZrtpStateClass.cpp
+++ libzrtpcpp-2.3.3/src/ZrtpStateClass.cpp
@@ -114,7 +114,9 @@ void ZrtpStateClass::processEvent(Event_
else if (first == 'p' && middle == ' ' && last == ' ') {
ZrtpPacketPing ppkt(pkt);
ZrtpPacketPingAck* ppktAck = parent->preparePingAck(&ppkt);
- parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(ppktAck));
+ if (ppktAck != NULL) { // ACK only to valid PING packet, otherwise ignore it
+ parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(ppktAck));
+ }
parent->synchLeave();
return;
}