mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 15:48:19 +00:00
Fix buffer overlows in IP address masking logic.
That could occur either in taking a zero-length mask on an IPv6 address (e.g. [fe80::]/0) or a reverse mask of length 128 on any address (e.g. via the remask_addr BuiltIn Function).
This commit is contained in:
parent
713fd2fbaf
commit
965e4d421d
1 changed files with 28 additions and 30 deletions
|
@ -1,5 +1,6 @@
|
||||||
// See the file "COPYING" in the main distribution directory for copyright.
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "IPAddr.h"
|
#include "IPAddr.h"
|
||||||
|
@ -45,6 +46,14 @@ HashKey* BuildConnIDHashKey(const ConnID& id)
|
||||||
return new HashKey(&key, sizeof(key));
|
return new HashKey(&key, sizeof(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint32_t bit_mask32(int bottom_bits)
|
||||||
|
{
|
||||||
|
if ( bottom_bits >= 32 )
|
||||||
|
return 0xffffffff;
|
||||||
|
|
||||||
|
return (((uint32_t) 1) << bottom_bits) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
void IPAddr::Mask(int top_bits_to_keep)
|
void IPAddr::Mask(int top_bits_to_keep)
|
||||||
{
|
{
|
||||||
if ( top_bits_to_keep < 0 || top_bits_to_keep > 128 )
|
if ( top_bits_to_keep < 0 || top_bits_to_keep > 128 )
|
||||||
|
@ -53,25 +62,20 @@ void IPAddr::Mask(int top_bits_to_keep)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t tmp[4];
|
uint32_t mask_bits[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
|
||||||
memcpy(tmp, in6.s6_addr, sizeof(in6.s6_addr));
|
std::ldiv_t res = std::ldiv(top_bits_to_keep, 32);
|
||||||
|
|
||||||
int word = 3;
|
if ( res.quot < 4 )
|
||||||
int bits_to_chop = 128 - top_bits_to_keep;
|
mask_bits[res.quot] =
|
||||||
|
htonl(mask_bits[res.quot] & ~bit_mask32(32 - res.rem));
|
||||||
|
|
||||||
while ( bits_to_chop >= 32 )
|
for ( unsigned int i = res.quot + 1; i < 4; ++i )
|
||||||
{
|
mask_bits[i] = 0;
|
||||||
tmp[word] = 0;
|
|
||||||
--word;
|
|
||||||
bits_to_chop -= 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t w = ntohl(tmp[word]);
|
uint32_t* p = reinterpret_cast<uint32_t*>(in6.s6_addr);
|
||||||
w >>= bits_to_chop;
|
|
||||||
w <<= bits_to_chop;
|
|
||||||
tmp[word] = htonl(w);
|
|
||||||
|
|
||||||
memcpy(in6.s6_addr, tmp, sizeof(in6.s6_addr));
|
for ( unsigned int i = 0; i < 4; ++i )
|
||||||
|
p[i] &= mask_bits[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPAddr::ReverseMask(int top_bits_to_chop)
|
void IPAddr::ReverseMask(int top_bits_to_chop)
|
||||||
|
@ -82,25 +86,19 @@ void IPAddr::ReverseMask(int top_bits_to_chop)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t tmp[4];
|
uint32_t mask_bits[4] = { 0, 0, 0, 0 };
|
||||||
memcpy(tmp, in6.s6_addr, sizeof(in6.s6_addr));
|
std::ldiv_t res = std::ldiv(top_bits_to_chop, 32);
|
||||||
|
|
||||||
int word = 0;
|
if ( res.quot < 4 )
|
||||||
int bits_to_chop = top_bits_to_chop;
|
mask_bits[res.quot] = htonl(bit_mask32(32 - res.rem));
|
||||||
|
|
||||||
while ( bits_to_chop >= 32 )
|
for ( unsigned int i = res.quot + 1; i < 4; ++i )
|
||||||
{
|
mask_bits[i] = 0xffffffff;
|
||||||
tmp[word] = 0;
|
|
||||||
++word;
|
|
||||||
bits_to_chop -= 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t w = ntohl(tmp[word]);
|
uint32_t* p = reinterpret_cast<uint32_t*>(in6.s6_addr);
|
||||||
w <<= bits_to_chop;
|
|
||||||
w >>= bits_to_chop;
|
|
||||||
tmp[word] = htonl(w);
|
|
||||||
|
|
||||||
memcpy(in6.s6_addr, tmp, sizeof(in6.s6_addr));
|
for ( unsigned int i = 0; i < 4; ++i )
|
||||||
|
p[i] &= mask_bits[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPAddr::Init(const std::string& s)
|
void IPAddr::Init(const std::string& s)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue