2007-11-16 04:45:00 +00:00
/*
* libretroshare / src / serialiser : rstlvbase . cc
*
* RetroShare Serialiser .
*
* Copyright 2007 - 2008 by Robert Fernie , Horatio , Chris Parker
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Library General Public License for more details .
*
* You should have received a copy of the GNU Library General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307
* USA .
*
* Please report all bugs and problems to " retroshare@lunamutt.com " .
*
*/
# include <iostream>
# include "serialiser/rstlvbase.h"
# include "serialiser/rsbaseserial.h"
//*********************
// A facility func
inline void * right_shift_void_pointer ( void * p , uint32_t len ) {
return ( void * ) ( ( uint8_t * ) p + len ) ;
}
//*********************
2013-09-18 19:32:04 +00:00
//#define TLV_BASE_DEBUG 1
2007-11-16 04:45:00 +00:00
/**** Basic TLV Functions ****/
2010-05-09 20:06:19 +00:00
uint32_t GetTlvSize ( void * data ) {
2007-11-16 04:45:00 +00:00
if ( ! data )
return 0 ;
2009-09-08 20:18:43 +00:00
uint32_t len ;
2007-11-16 04:45:00 +00:00
2009-09-08 20:18:43 +00:00
void * from = right_shift_void_pointer ( data , TLV_HEADER_TYPE_SIZE ) ;
2007-11-16 04:45:00 +00:00
2009-09-08 20:18:43 +00:00
memcpy ( ( void * ) & len , from , TLV_HEADER_LEN_SIZE ) ;
2007-11-16 04:45:00 +00:00
2009-09-08 20:18:43 +00:00
len = ntohl ( len ) ;
2007-11-16 04:45:00 +00:00
return len ;
}
uint16_t GetTlvType ( void * data ) {
if ( ! data )
return 0 ;
uint16_t type ;
2009-09-08 20:18:43 +00:00
memcpy ( ( void * ) & type , data , TLV_HEADER_TYPE_SIZE ) ;
2007-11-16 04:45:00 +00:00
type = ntohs ( type ) ;
return type ;
}
//tested
bool SetTlvBase ( void * data , uint32_t size , uint32_t * offset , uint16_t type ,
2009-09-08 20:18:43 +00:00
uint32_t len ) {
2007-11-16 04:45:00 +00:00
if ( ! data )
return false ;
if ( ! offset )
return false ;
2009-09-08 20:18:43 +00:00
if ( size < * offset + TLV_HEADER_SIZE )
2007-11-16 04:45:00 +00:00
return false ;
uint16_t type_n = htons ( type ) ;
//copy type_n to (data+*offset)
void * to = right_shift_void_pointer ( data , * offset ) ;
2009-09-08 20:18:43 +00:00
memcpy ( to , ( void * ) & type_n , TLV_HEADER_TYPE_SIZE ) ;
2007-11-16 04:45:00 +00:00
2009-09-08 20:18:43 +00:00
uint32_t len_n = htonl ( len ) ;
2007-11-16 04:45:00 +00:00
//copy len_n to (data + *offset +2)
2009-09-08 20:18:43 +00:00
to = right_shift_void_pointer ( to , TLV_HEADER_TYPE_SIZE ) ;
memcpy ( ( void * ) to , ( void * ) & len_n , TLV_HEADER_LEN_SIZE ) ;
2007-11-16 04:45:00 +00:00
2009-09-08 20:18:43 +00:00
* offset + = TLV_HEADER_SIZE ;
2007-11-16 04:45:00 +00:00
return true ;
}
2009-09-08 20:18:43 +00:00
bool SetTlvType ( void * data , uint32_t size , uint16_t type )
{
if ( ! data )
return false ;
if ( size < TLV_HEADER_SIZE )
return false ;
uint16_t type_n = htons ( type ) ;
memcpy ( data , ( void * ) & type_n , TLV_HEADER_TYPE_SIZE ) ;
return true ;
}
2007-11-16 04:45:00 +00:00
//tested
2009-09-08 20:18:43 +00:00
bool SetTlvSize ( void * data , uint32_t size , uint32_t len ) {
2007-11-16 04:45:00 +00:00
if ( ! data )
return false ;
2009-09-08 20:18:43 +00:00
if ( size < TLV_HEADER_SIZE )
2007-11-16 04:45:00 +00:00
return false ;
2009-09-08 20:18:43 +00:00
uint32_t len_n = htonl ( len ) ;
2007-11-16 04:45:00 +00:00
2009-09-08 20:18:43 +00:00
void * to = ( void * ) ( ( uint8_t * ) data + TLV_HEADER_TYPE_SIZE ) ;
2007-11-16 04:45:00 +00:00
2009-09-08 20:18:43 +00:00
memcpy ( to , ( void * ) & len_n , TLV_HEADER_LEN_SIZE ) ;
2007-11-16 04:45:00 +00:00
return true ;
}
2009-09-08 20:18:43 +00:00
/* Step past unknown TLV TYPE */
bool SkipUnknownTlv ( void * data , uint32_t size , uint32_t * offset )
{
if ( ! data )
return false ;
if ( size < * offset + TLV_HEADER_SIZE )
return false ;
/* extract the type and size */
void * tlvstart = right_shift_void_pointer ( data , * offset ) ;
2010-04-23 13:42:01 +00:00
//uint16_t tlvtype = GetTlvType(tlvstart);
2009-09-08 20:18:43 +00:00
uint32_t tlvsize = GetTlvSize ( tlvstart ) ;
/* check that there is size */
uint32_t tlvend = * offset + tlvsize ;
if ( size < tlvend )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " SkipUnknownTlv() FAILED - not enough space. " < < std : : endl ;
std : : cerr < < " SkipUnknownTlv() size: " < < size < < std : : endl ;
std : : cerr < < " SkipUnknownTlv() tlvsize: " < < tlvsize < < std : : endl ;
std : : cerr < < " SkipUnknownTlv() tlvend: " < < tlvend < < std : : endl ;
# endif
return false ;
}
bool ok = true ;
/* step past this tlv item */
* offset = tlvend ;
return ok ;
}
2007-11-16 04:45:00 +00:00
/**** Generic TLV Functions ****
* This have the same data ( int or string for example ) ,
* but they can have different types eg . a string could represent a name or a path ,
* so we include a type parameter in the arguments
*/
//tested
bool SetTlvUInt32 ( void * data , uint32_t size , uint32_t * offset , uint16_t type ,
uint32_t out )
{
if ( ! data )
return false ;
2009-09-08 20:18:43 +00:00
uint32_t tlvsize = GetTlvUInt32Size ( ) ; /* this will always be 8 bytes */
2007-11-16 04:45:00 +00:00
uint32_t tlvend = * offset + tlvsize ; /* where the data will extend to */
if ( size < tlvend )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " SetTlvUInt32() FAILED - not enough space. (or earlier) " < < std : : endl ;
std : : cerr < < " SetTlvUInt32() size: " < < size < < std : : endl ;
std : : cerr < < " SetTlvUInt32() tlvsize: " < < tlvsize < < std : : endl ;
std : : cerr < < " SetTlvUInt32() tlvend: " < < tlvend < < std : : endl ;
# endif
return false ;
}
bool ok = true ;
/* Now use the function we got to set the TlvHeader */
/* function shifts offset to the new start for the next data */
ok & = SetTlvBase ( data , tlvend , offset , type , tlvsize ) ;
# ifdef TLV_BASE_DEBUG
if ( ! ok )
{
std : : cerr < < " SetTlvUInt32() SetTlvBase FAILED (or earlier) " < < std : : endl ;
}
# endif
/* now set the UInt32 ( in rsbaseserial.h???) */
ok & = setRawUInt32 ( data , tlvend , offset , out ) ;
# ifdef TLV_BASE_DEBUG
if ( ! ok )
{
std : : cerr < < " SetTlvUInt32() setRawUInt32 FAILED (or earlier) " < < std : : endl ;
}
# endif
return ok ;
}
//tested
bool GetTlvUInt32 ( void * data , uint32_t size , uint32_t * offset ,
uint16_t type , uint32_t * in )
{
if ( ! data )
return false ;
2009-09-08 20:18:43 +00:00
if ( size < * offset + TLV_HEADER_SIZE )
2007-11-16 04:45:00 +00:00
return false ;
/* extract the type and size */
void * tlvstart = right_shift_void_pointer ( data , * offset ) ;
uint16_t tlvtype = GetTlvType ( tlvstart ) ;
2009-09-08 20:18:43 +00:00
uint32_t tlvsize = GetTlvSize ( tlvstart ) ;
2007-11-16 04:45:00 +00:00
/* check that there is size */
uint32_t tlvend = * offset + tlvsize ;
if ( size < tlvend )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " GetTlvUInt32() FAILED - not enough space. " < < std : : endl ;
std : : cerr < < " GetTlvUInt32() size: " < < size < < std : : endl ;
std : : cerr < < " GetTlvUInt32() tlvsize: " < < tlvsize < < std : : endl ;
std : : cerr < < " GetTlvUInt32() tlvend: " < < tlvend < < std : : endl ;
# endif
return false ;
}
if ( type ! = tlvtype )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " GetTlvUInt32() FAILED - Type mismatch " < < std : : endl ;
std : : cerr < < " GetTlvUInt32() type: " < < type < < std : : endl ;
std : : cerr < < " GetTlvUInt32() tlvtype: " < < tlvtype < < std : : endl ;
# endif
return false ;
}
2009-09-08 20:18:43 +00:00
* offset + = TLV_HEADER_SIZE ; /* step past header */
2007-11-16 04:45:00 +00:00
2007-12-12 00:54:42 +00:00
bool ok = true ;
ok & = getRawUInt32 ( data , tlvend , offset , in ) ;
return ok ;
}
2014-03-22 03:53:44 +00:00
// UInt16
bool SetTlvUInt16 ( void * data , uint32_t size , uint32_t * offset , uint16_t type ,
uint16_t out )
{
if ( ! data )
return false ;
uint32_t tlvsize = GetTlvUInt16Size ( ) ; /* this will always be 8 bytes */
uint32_t tlvend = * offset + tlvsize ; /* where the data will extend to */
if ( size < tlvend )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " SetTlvUInt16() FAILED - not enough space. (or earlier) " < < std : : endl ;
std : : cerr < < " SetTlvUInt16() size: " < < size < < std : : endl ;
std : : cerr < < " SetTlvUInt16() tlvsize: " < < tlvsize < < std : : endl ;
std : : cerr < < " SetTlvUInt16() tlvend: " < < tlvend < < std : : endl ;
# endif
return false ;
}
bool ok = true ;
/* Now use the function we got to set the TlvHeader */
/* function shifts offset to the new start for the next data */
ok & = SetTlvBase ( data , tlvend , offset , type , tlvsize ) ;
# ifdef TLV_BASE_DEBUG
if ( ! ok )
{
std : : cerr < < " SetTlvUInt16() SetTlvBase FAILED (or earlier) " < < std : : endl ;
}
# endif
/* now set the UInt16 ( in rsbaseserial.h???) */
ok & = setRawUInt16 ( data , tlvend , offset , out ) ;
# ifdef TLV_BASE_DEBUG
if ( ! ok )
{
std : : cerr < < " SetTlvUInt16() setRawUInt16 FAILED (or earlier) " < < std : : endl ;
}
# endif
return ok ;
}
bool GetTlvUInt16 ( void * data , uint32_t size , uint32_t * offset ,
uint16_t type , uint16_t * in )
{
if ( ! data )
return false ;
if ( size < * offset + TLV_HEADER_SIZE )
return false ;
/* extract the type and size */
void * tlvstart = right_shift_void_pointer ( data , * offset ) ;
uint16_t tlvtype = GetTlvType ( tlvstart ) ;
uint32_t tlvsize = GetTlvSize ( tlvstart ) ;
/* check that there is size */
uint32_t tlvend = * offset + tlvsize ;
if ( size < tlvend )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " GetTlvUInt16() FAILED - not enough space. " < < std : : endl ;
std : : cerr < < " GetTlvUInt16() size: " < < size < < std : : endl ;
std : : cerr < < " GetTlvUInt16() tlvsize: " < < tlvsize < < std : : endl ;
std : : cerr < < " GetTlvUInt16() tlvend: " < < tlvend < < std : : endl ;
# endif
return false ;
}
if ( type ! = tlvtype )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " GetTlvUInt16() FAILED - Type mismatch " < < std : : endl ;
std : : cerr < < " GetTlvUInt16() type: " < < type < < std : : endl ;
std : : cerr < < " GetTlvUInt16() tlvtype: " < < tlvtype < < std : : endl ;
# endif
return false ;
}
* offset + = TLV_HEADER_SIZE ; /* step past header */
bool ok = true ;
ok & = getRawUInt16 ( data , tlvend , offset , in ) ;
return ok ;
}
2007-12-12 00:54:42 +00:00
uint32_t GetTlvUInt64Size ( ) {
2009-09-08 20:18:43 +00:00
return TLV_HEADER_SIZE + 8 ;
2007-11-16 04:45:00 +00:00
}
uint32_t GetTlvUInt32Size ( ) {
2009-09-08 20:18:43 +00:00
return TLV_HEADER_SIZE + 4 ;
2007-11-16 04:45:00 +00:00
}
uint32_t GetTlvUInt16Size ( ) {
2009-09-08 20:18:43 +00:00
return TLV_HEADER_SIZE + sizeof ( uint16_t ) ;
2007-11-16 04:45:00 +00:00
}
uint32_t GetTlvUInt8Size ( ) {
2009-09-08 20:18:43 +00:00
return TLV_HEADER_SIZE + sizeof ( uint8_t ) ;
2007-12-12 00:54:42 +00:00
}
bool SetTlvUInt64 ( void * data , uint32_t size , uint32_t * offset , uint16_t type ,
uint64_t out )
{
if ( ! data )
return false ;
2009-09-08 20:18:43 +00:00
uint32_t tlvsize = GetTlvUInt64Size ( ) ;
2007-12-12 00:54:42 +00:00
uint32_t tlvend = * offset + tlvsize ;
if ( size < tlvend )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " SetTlvUInt64() FAILED - not enough space. (or earlier) " < < std : : endl ;
std : : cerr < < " SetTlvUInt64() size: " < < size < < std : : endl ;
std : : cerr < < " SetTlvUInt64() tlvsize: " < < tlvsize < < std : : endl ;
std : : cerr < < " SetTlvUInt64() tlvend: " < < tlvend < < std : : endl ;
# endif
return false ;
}
bool ok = true ;
/* Now use the function we got to set the TlvHeader */
/* function shifts offset to the new start for the next data */
ok & = SetTlvBase ( data , tlvend , offset , type , tlvsize ) ;
# ifdef TLV_BASE_DEBUG
if ( ! ok )
{
std : : cerr < < " SetTlvUInt64() SetTlvBase FAILED (or earlier) " < < std : : endl ;
}
# endif
/* now set the UInt64 ( in rsbaseserial.h???) */
ok & = setRawUInt64 ( data , tlvend , offset , out ) ;
# ifdef TLV_BASE_DEBUG
if ( ! ok )
{
std : : cerr < < " SetTlvUInt64() setRawUInt64 FAILED (or earlier) " < < std : : endl ;
}
# endif
return ok ;
}
bool GetTlvUInt64 ( void * data , uint32_t size , uint32_t * offset ,
uint16_t type , uint64_t * in )
{
if ( ! data )
return false ;
2009-09-08 20:18:43 +00:00
if ( size < * offset + TLV_HEADER_SIZE )
2007-12-12 00:54:42 +00:00
return false ;
/* extract the type and size */
void * tlvstart = right_shift_void_pointer ( data , * offset ) ;
uint16_t tlvtype = GetTlvType ( tlvstart ) ;
2009-09-08 20:18:43 +00:00
uint32_t tlvsize = GetTlvSize ( tlvstart ) ;
2007-12-12 00:54:42 +00:00
/* check that there is size */
uint32_t tlvend = * offset + tlvsize ;
if ( size < tlvend )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " GetTlvUInt64() FAILED - not enough space. " < < std : : endl ;
std : : cerr < < " GetTlvUInt64() size: " < < size < < std : : endl ;
std : : cerr < < " GetTlvUInt64() tlvsize: " < < tlvsize < < std : : endl ;
std : : cerr < < " GetTlvUInt64() tlvend: " < < tlvend < < std : : endl ;
# endif
return false ;
}
if ( type ! = tlvtype )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " GetTlvUInt64() FAILED - Type mismatch " < < std : : endl ;
std : : cerr < < " GetTlvUInt64() type: " < < type < < std : : endl ;
std : : cerr < < " GetTlvUInt64() tlvtype: " < < tlvtype < < std : : endl ;
# endif
return false ;
}
2007-11-16 04:45:00 +00:00
2009-09-08 20:18:43 +00:00
* offset + = TLV_HEADER_SIZE ; /* step past header */
2007-12-12 00:54:42 +00:00
bool ok = true ;
ok & = getRawUInt64 ( data , tlvend , offset , in ) ;
return ok ;
2007-11-16 04:45:00 +00:00
}
2007-12-12 00:54:42 +00:00
2007-11-16 04:45:00 +00:00
bool SetTlvString ( void * data , uint32_t size , uint32_t * offset ,
uint16_t type , std : : string out )
{
if ( ! data )
return false ;
2009-09-08 20:18:43 +00:00
uint32_t tlvsize = GetTlvStringSize ( out ) ;
2007-11-16 04:45:00 +00:00
uint32_t tlvend = * offset + tlvsize ; /* where the data will extend to */
if ( size < tlvend )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " SetTlvString() FAILED - not enough space " < < std : : endl ;
std : : cerr < < " SetTlvString() size: " < < size < < std : : endl ;
std : : cerr < < " SetTlvString() tlvsize: " < < tlvsize < < std : : endl ;
std : : cerr < < " SetTlvString() tlvend: " < < tlvend < < std : : endl ;
# endif
return false ;
}
bool ok = true ;
ok & = SetTlvBase ( data , tlvend , offset , type , tlvsize ) ;
void * to = right_shift_void_pointer ( data , * offset ) ;
2010-05-09 20:06:19 +00:00
uint32_t strlen = tlvsize - TLV_HEADER_SIZE ;
2007-11-16 04:45:00 +00:00
memcpy ( to , out . c_str ( ) , strlen ) ;
* offset + = strlen ;
return ok ;
}
2015-07-30 20:17:10 +02:00
static bool readHex ( char s1 , char s2 , uint8_t & v )
{
v = 0 ;
if ( s1 > = ' a ' & & s1 < = ' f ' )
v + = ( s1 - ' a ' ) + 10 ;
else if ( s1 > = ' A ' & & s1 < = ' F ' )
v + = ( s1 - ' A ' ) + 10 ;
else if ( s1 > = ' 0 ' & & s1 < = ' 9 ' )
v + = s1 - ' 0 ' ;
else
return false ;
v = v < < 4 ;
if ( s2 > = ' a ' & & s2 < = ' f ' )
v + = ( s2 - ' a ' ) + 10 ;
else if ( s2 > = ' A ' & & s2 < = ' F ' )
v + = ( s2 - ' A ' ) + 10 ;
else if ( s2 > = ' 0 ' & & s2 < = ' 9 ' )
v + = s2 - ' 0 ' ;
else
return false ;
return true ;
}
static bool find_decoded_string ( const std : : string & in , const std : : string & suspicious_string )
{
2015-09-24 18:03:19 -04:00
uint32_t ss_pointer = 0 ;
2015-07-30 20:17:10 +02:00
2015-09-24 18:03:19 -04:00
for ( uint32_t i = 0 ; i < in . length ( ) ; + + i )
2015-07-30 20:17:10 +02:00
{
uint8_t hexv ;
char next_char ;
if ( in [ i ] = = ' % ' & & i + 2 < in . length ( ) & & readHex ( in [ i + 1 ] , in [ i + 2 ] , hexv ) )
{
next_char = hexv ;
i + = 2 ;
}
else
next_char = in [ i ] ;
if ( suspicious_string [ ss_pointer ] = = next_char )
ss_pointer + + ;
else
ss_pointer = 0 ;
if ( ss_pointer = = suspicious_string . length ( ) )
return true ;
}
return false ;
}
2007-11-16 04:45:00 +00:00
//tested
bool GetTlvString ( void * data , uint32_t size , uint32_t * offset ,
uint16_t type , std : : string & in )
{
2015-06-23 19:25:13 +00:00
if ( ! data )
return false ;
2007-11-16 04:45:00 +00:00
2015-06-23 19:25:13 +00:00
if ( size < * offset )
{
2007-11-16 04:45:00 +00:00
# ifdef TLV_BASE_DEBUG
2015-06-23 19:25:13 +00:00
std : : cerr < < " GetTlvString() FAILED - not enough space " < < std : : endl ;
std : : cerr < < " GetTlvString() size: " < < size < < std : : endl ;
std : : cerr < < " GetTlvString() *offset: " < < * offset < < std : : endl ;
2007-11-16 04:45:00 +00:00
# endif
2015-06-23 19:25:13 +00:00
return false ;
}
/* extract the type and size */
void * tlvstart = right_shift_void_pointer ( data , * offset ) ;
uint16_t tlvtype = GetTlvType ( tlvstart ) ;
uint32_t tlvsize = GetTlvSize ( tlvstart ) ;
/* check that there is size */
uint32_t tlvend = * offset + tlvsize ;
if ( size < tlvend )
{
2007-11-16 04:45:00 +00:00
# ifdef TLV_BASE_DEBUG
2015-06-23 19:25:13 +00:00
std : : cerr < < " GetTlvString() FAILED - not enough space " < < std : : endl ;
std : : cerr < < " GetTlvString() size: " < < size < < std : : endl ;
std : : cerr < < " GetTlvString() tlvsize: " < < tlvsize < < std : : endl ;
std : : cerr < < " GetTlvString() tlvend: " < < tlvend < < std : : endl ;
2007-11-16 04:45:00 +00:00
# endif
2015-06-23 19:25:13 +00:00
return false ;
}
2007-11-16 04:45:00 +00:00
2015-06-23 19:25:13 +00:00
if ( type ! = tlvtype )
{
2007-11-16 04:45:00 +00:00
# ifdef TLV_BASE_DEBUG
2015-06-23 19:25:13 +00:00
std : : cerr < < " GetTlvString() FAILED - invalid type " < < std : : endl ;
std : : cerr < < " GetTlvString() type: " < < type < < std : : endl ;
std : : cerr < < " GetTlvString() tlvtype: " < < tlvtype < < std : : endl ;
2007-11-16 04:45:00 +00:00
# endif
2015-06-23 19:25:13 +00:00
return false ;
}
2007-11-16 04:45:00 +00:00
2015-06-23 19:25:13 +00:00
char * strdata = ( char * ) right_shift_void_pointer ( tlvstart , TLV_HEADER_SIZE ) ;
uint32_t strsize = tlvsize - TLV_HEADER_SIZE ; /* remove the header */
if ( strsize < = 0 ) {
in = " " ;
} else {
in = std : : string ( strdata , strsize ) ;
}
2007-11-16 04:45:00 +00:00
2015-08-05 20:51:34 +02:00
# ifdef TLV_BASE_DEBUG
if ( type = = TLV_TYPE_STR_MSG )
std : : cerr < < " Checking string \" " < < in < < " \" " < < std : : endl ;
# endif
2015-01-31 12:30:31 +00:00
// Check for string content. We want to avoid possible lol bombs as soon as possible.
static const int number_of_suspiscious_strings = 4 ;
static const std : : string err_in = " **** String removed (SVG bomb?) **** " ;
static std : : string suspiscious_strings [ number_of_suspiscious_strings ] = { " <!e " , // base ingredient of xml bombs
" <!E " ,
2015-06-23 19:25:13 +00:00
" PD94bW " , // this is the base64 encoding of "<?xml*"
" PHN2Zy " // this is the base64 encoding of "<svg*"
} ;
2015-01-31 12:30:31 +00:00
# ifdef TLV_BASE_DEBUG
std : : cerr < < " Checking wide string \" " < < in < < std : : endl ;
# endif
// Drop any string with "<!" or "<!"...
// TODO: check what happens with partial messages
//
for ( int i = 0 ; i < number_of_suspiscious_strings ; + + i )
2015-07-30 20:17:10 +02:00
if ( find_decoded_string ( in , suspiscious_strings [ i ] ) )
2015-01-31 12:30:31 +00:00
{
std : : cerr < < " **** suspiscious wstring contains \" " < < suspiscious_strings [ i ] < < " \" (SVG bomb suspected). " ;
std : : cerr < < " ========== Original string ========= " < < std : : endl ;
std : : cerr < < in < < std : : endl ;
std : : cerr < < " =============== END ================ " < < std : : endl ;
for ( uint32_t k = 0 ; k < in . length ( ) ; + + k )
if ( k < err_in . length ( ) )
in [ k ] = err_in [ k ] ; // It's important to keep the same size for in than the size it should have,
else
in [ k ] = ' ' ; // otherwise the deserialization of derived items that use it might fail
break ;
}
2015-06-23 19:25:13 +00:00
// Also check that the string does not contain invalid characters.
// Every character less than 0x20 will be turned into a space (0x20).
// This is compatible with utf8, as all utf8 chars are > 0x7f.
// We do this for strings that should not contain some
// special characters by design.
if ( type = = 0 // this is used for mGroupName and mMsgName
| | type = = TLV_TYPE_STR_PEERID
| | type = = TLV_TYPE_STR_NAME
| | type = = TLV_TYPE_STR_PATH
| | type = = TLV_TYPE_STR_TITLE
| | type = = TLV_TYPE_STR_SUBJECT
| | type = = TLV_TYPE_STR_LOCATION
| | type = = TLV_TYPE_STR_VERSION )
{
bool modified = false ;
for ( uint32_t i = 0 ; i < in . length ( ) ; + + i )
if ( in [ i ] < 0x20 & & in [ i ] > 0 )
{
modified = true ;
in [ i ] = 0x20 ;
}
if ( modified )
std : : cerr < < " (WW) De-serialised string of type " < < type < < " contains forbidden characters. They have been replaced by spaces. New string: \" " < < in < < " \" " < < std : : endl ;
}
* offset + = tlvsize ; /* step along */
return true ;
2007-11-16 04:45:00 +00:00
}
2009-03-13 21:14:30 +00:00
uint32_t GetTlvStringSize ( const std : : string & in ) {
2009-09-08 20:18:43 +00:00
return TLV_HEADER_SIZE + in . size ( ) ;
2007-11-16 04:45:00 +00:00
}
2008-01-26 13:00:57 +00:00
2015-01-31 12:30:31 +00:00
# ifdef REMOVED_CODE
2008-01-26 13:00:57 +00:00
/* We must use a consistent wchar size for cross platform ness.
* As unix uses 4 bytes , and windows 2 bytes ? we ' ll go with 4 bytes for maximum flexibility
*/
const uint32_t RS_WCHAR_SIZE = 4 ;
bool SetTlvWideString ( void * data , uint32_t size , uint32_t * offset ,
uint16_t type , std : : wstring out )
{
if ( ! data )
return false ;
2009-09-08 20:18:43 +00:00
uint32_t tlvsize = GetTlvWideStringSize ( out ) ;
2008-01-26 13:00:57 +00:00
uint32_t tlvend = * offset + tlvsize ; /* where the data will extend to */
if ( size < tlvend )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " SetTlvWideString() FAILED - not enough space " < < std : : endl ;
std : : cerr < < " SetTlvWideString() size: " < < size < < std : : endl ;
std : : cerr < < " SetTlvWideString() tlvsize: " < < tlvsize < < std : : endl ;
std : : cerr < < " SetTlvWideString() tlvend: " < < tlvend < < std : : endl ;
# endif
return false ;
}
bool ok = true ;
ok & = SetTlvBase ( data , tlvend , offset , type , tlvsize ) ;
2009-09-08 20:18:43 +00:00
uint32_t strlen = out . length ( ) ;
2008-01-26 13:00:57 +00:00
/* Must convert manually to ensure its always the same! */
2009-09-08 20:18:43 +00:00
for ( uint32_t i = 0 ; i < strlen ; i + + )
2008-01-26 13:00:57 +00:00
{
uint32_t widechar = out [ i ] ;
ok & = setRawUInt32 ( data , tlvend , offset , widechar ) ;
}
return ok ;
}
//tested
bool GetTlvWideString ( void * data , uint32_t size , uint32_t * offset ,
uint16_t type , std : : wstring & in )
{
if ( ! data )
return false ;
2009-09-08 20:18:43 +00:00
if ( size < * offset + TLV_HEADER_SIZE )
2008-01-26 13:00:57 +00:00
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " GetTlvWideString() FAILED - not enough space " < < std : : endl ;
std : : cerr < < " GetTlvWideString() size: " < < size < < std : : endl ;
std : : cerr < < " GetTlvWideString() *offset: " < < * offset < < std : : endl ;
# endif
return false ;
}
/* extract the type and size */
void * tlvstart = right_shift_void_pointer ( data , * offset ) ;
uint16_t tlvtype = GetTlvType ( tlvstart ) ;
2009-09-08 20:18:43 +00:00
uint32_t tlvsize = GetTlvSize ( tlvstart ) ;
2008-01-26 13:00:57 +00:00
/* check that there is size */
uint32_t tlvend = * offset + tlvsize ;
if ( size < tlvend )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " GetTlvWideString() FAILED - not enough space " < < std : : endl ;
std : : cerr < < " GetTlvWideString() size: " < < size < < std : : endl ;
std : : cerr < < " GetTlvWideString() tlvsize: " < < tlvsize < < std : : endl ;
std : : cerr < < " GetTlvWideString() tlvend: " < < tlvend < < std : : endl ;
# endif
return false ;
}
if ( type ! = tlvtype )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " GetTlvWideString() FAILED - invalid type " < < std : : endl ;
std : : cerr < < " GetTlvWideString() type: " < < type < < std : : endl ;
std : : cerr < < " GetTlvWideString() tlvtype: " < < tlvtype < < std : : endl ;
# endif
return false ;
}
bool ok = true ;
/* remove the header, calc string length */
2009-09-08 20:18:43 +00:00
* offset + = TLV_HEADER_SIZE ;
2010-05-09 20:06:19 +00:00
uint32_t strlen = ( tlvsize - TLV_HEADER_SIZE ) / RS_WCHAR_SIZE ;
2008-01-26 13:00:57 +00:00
/* Must convert manually to ensure its always the same! */
2009-09-08 20:18:43 +00:00
for ( uint32_t i = 0 ; i < strlen ; i + + )
2008-01-26 13:00:57 +00:00
{
uint32_t widechar ;
ok & = getRawUInt32 ( data , tlvend , offset , & widechar ) ;
in + = widechar ;
}
2013-09-16 22:24:43 +00:00
// Check for message content. We want to avoid possible lol bombs as soon as possible.
2013-09-18 19:32:04 +00:00
static const int number_of_suspiscious_strings = 4 ;
static const std : : wstring err_in = L " **** String removed (SVG bomb?) **** " ;
2013-11-28 21:11:53 +00:00
static std : : wstring suspiscious_strings [ number_of_suspiscious_strings ] = { L " <!e " , // base ingredient of xml bombs
2013-09-18 19:32:04 +00:00
L " <!E " ,
2013-11-28 21:11:53 +00:00
L " PD94bW " , // this is the base64 encoding of <?xml*
L " PHN2Zy " // this is the base64 encoding of <svg*
2013-09-18 19:32:04 +00:00
} ;
2013-09-16 22:24:43 +00:00
2013-09-18 19:32:04 +00:00
# ifdef TLV_BASE_DEBUG
std : : wcerr < < L " Checking wide string \" " < < in < < std : : endl ;
# endif
2013-09-16 22:24:43 +00:00
// Drop any string with "<!" or "<!"...
// TODO: check what happens with partial messages
//
2013-09-18 19:32:04 +00:00
for ( int i = 0 ; i < number_of_suspiscious_strings ; + + i )
if ( in . find ( suspiscious_strings [ i ] ) ! = std : : string : : npos )
{
std : : wcerr < < L " **** suspiscious wstring contains \" " < < suspiscious_strings [ i ] < < L " \" (SVG bomb suspected). " ;
std : : cerr < < " ========== Original string ========= " < < std : : endl ;
std : : wcerr < < in < < std : : endl ;
std : : cerr < < " =============== END ================ " < < std : : endl ;
for ( uint32_t k = 0 ; k < in . length ( ) ; + + k )
if ( k < err_in . length ( ) )
in [ k ] = err_in [ k ] ; // It's important to keep the same size for in than the size it should have,
else
in [ k ] = L ' ' ; // otherwise the deserialization of derived items that use it might fail
break ;
}
2013-09-16 22:24:43 +00:00
2008-01-26 13:00:57 +00:00
return ok ;
}
uint32_t GetTlvWideStringSize ( std : : wstring & in ) {
2009-09-08 20:18:43 +00:00
return TLV_HEADER_SIZE + in . size ( ) * RS_WCHAR_SIZE ;
2008-01-26 13:00:57 +00:00
}
2015-01-31 12:30:31 +00:00
# endif
2008-01-26 13:00:57 +00:00
2007-11-16 04:45:00 +00:00
bool SetTlvIpAddrPortV4 ( void * data , uint32_t size , uint32_t * offset ,
uint16_t type , struct sockaddr_in * out ) {
if ( ! data )
return false ;
2009-09-08 20:18:43 +00:00
uint32_t tlvsize = GetTlvIpAddrPortV4Size ( ) ;
2007-12-12 00:54:42 +00:00
uint32_t tlvend = * offset + tlvsize ; /* where the data will extend to */
2007-11-16 04:45:00 +00:00
2007-12-12 00:54:42 +00:00
if ( size < tlvend )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " SetTlvIpAddrPortV4() FAILED - not enough space " < < std : : endl ;
std : : cerr < < " SetTlvIpAddrPortV4() size: " < < size < < std : : endl ;
std : : cerr < < " SetTlvIpAddrPortV4() tlvsize: " < < tlvsize < < std : : endl ;
std : : cerr < < " SetTlvIpAddrPortV4() tlvend: " < < tlvend < < std : : endl ;
# endif
return false ;
}
2007-11-16 04:45:00 +00:00
2007-12-12 00:54:42 +00:00
bool ok = true ;
ok & = SetTlvBase ( data , tlvend , offset , type , tlvsize ) ;
2007-11-16 04:45:00 +00:00
2009-12-18 17:51:56 +00:00
sockaddr_in addr = * out ;
2011-06-24 15:10:52 +00:00
2013-09-11 07:09:30 +00:00
/* now add the data .... (keep in network order) */
2009-12-18 17:51:56 +00:00
uint32_t ipaddr = addr . sin_addr . s_addr ;
2013-09-11 07:09:30 +00:00
ok & = setRawUInt32 ( data , tlvend , offset , ipaddr ) ;
2007-11-16 04:45:00 +00:00
2009-12-18 17:51:56 +00:00
uint16_t port = addr . sin_port ;
2013-09-11 07:09:30 +00:00
ok & = setRawUInt16 ( data , tlvend , offset , port ) ;
2007-11-16 04:45:00 +00:00
2007-12-12 00:54:42 +00:00
return ok ;
2007-11-16 04:45:00 +00:00
}
bool GetTlvIpAddrPortV4 ( void * data , uint32_t size , uint32_t * offset ,
uint16_t type , struct sockaddr_in * in ) {
if ( ! data )
return false ;
2009-09-08 20:18:43 +00:00
if ( size < * offset + TLV_HEADER_SIZE )
2007-12-12 00:54:42 +00:00
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " GetIpAddrPortV4() FAILED - not enough space " < < std : : endl ;
std : : cerr < < " GetIpAddrPortV4() size: " < < size < < std : : endl ;
std : : cerr < < " GetIpAddrPortV4() *offset: " < < * offset < < std : : endl ;
# endif
2007-11-16 04:45:00 +00:00
return false ;
2007-12-12 00:54:42 +00:00
}
2007-11-16 04:45:00 +00:00
2007-12-12 00:54:42 +00:00
/* extract the type and size */
void * tlvstart = right_shift_void_pointer ( data , * offset ) ;
uint16_t tlvtype = GetTlvType ( tlvstart ) ;
2009-09-08 20:18:43 +00:00
uint32_t tlvsize = GetTlvSize ( tlvstart ) ;
2007-11-16 04:45:00 +00:00
2007-12-12 00:54:42 +00:00
/* check that there is size */
uint32_t tlvend = * offset + tlvsize ;
if ( size < tlvend )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " GetIpAddrPortV4() FAILED - not enough space " < < std : : endl ;
std : : cerr < < " GetIpAddrPortV4() size: " < < size < < std : : endl ;
std : : cerr < < " GetIpAddrPortV4() tlvsize: " < < tlvsize < < std : : endl ;
std : : cerr < < " GetIpAddrPortV4() tlvend: " < < tlvend < < std : : endl ;
# endif
2007-11-16 04:45:00 +00:00
return false ;
2007-12-12 00:54:42 +00:00
}
2007-11-16 04:45:00 +00:00
2007-12-12 00:54:42 +00:00
if ( type ! = tlvtype )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " GetIpAddrPortV4() FAILED - invalid type " < < std : : endl ;
std : : cerr < < " GetIpAddrPortV4() type: " < < type < < std : : endl ;
std : : cerr < < " GetIpAddrPortV4() tlvtype: " < < tlvtype < < std : : endl ;
# endif
2007-11-16 04:45:00 +00:00
return false ;
2007-12-12 00:54:42 +00:00
}
2007-11-16 04:45:00 +00:00
2009-09-08 20:18:43 +00:00
* offset + = TLV_HEADER_SIZE ; /* skip header */
2007-11-16 04:45:00 +00:00
2007-12-12 00:54:42 +00:00
bool ok = true ;
2007-11-16 04:45:00 +00:00
2013-09-11 07:09:30 +00:00
/* now get the data .... (keep in network order) */
2007-11-16 04:45:00 +00:00
2007-12-12 00:54:42 +00:00
uint32_t ipaddr ;
ok & = getRawUInt32 ( data , tlvend , offset , & ipaddr ) ;
in - > sin_family = AF_INET ; /* set FAMILY */
2013-09-11 07:09:30 +00:00
in - > sin_addr . s_addr = ipaddr ;
2007-11-16 04:45:00 +00:00
2007-12-12 00:54:42 +00:00
uint16_t port ;
ok & = getRawUInt16 ( data , tlvend , offset , & port ) ;
2013-09-11 07:09:30 +00:00
in - > sin_port = port ;
2007-11-16 04:45:00 +00:00
2007-12-12 00:54:42 +00:00
return ok ;
2007-11-16 04:45:00 +00:00
}
2007-12-12 00:54:42 +00:00
uint32_t GetTlvIpAddrPortV4Size ( ) {
2009-09-08 20:18:43 +00:00
return TLV_HEADER_SIZE + 4 + 2 ; /* header + 4 (IP) + 2 (Port) */
2007-12-12 00:54:42 +00:00
}
2007-11-16 04:45:00 +00:00
2013-09-11 07:09:30 +00:00
bool SetTlvIpAddrPortV6 ( void * data , uint32_t size , uint32_t * offset ,
uint16_t type , struct sockaddr_in6 * out ) {
if ( ! data )
return false ;
2015-03-16 21:27:35 +00:00
uint32_t tlvsize = GetTlvIpAddrPortV6Size ( ) ;
2013-09-11 07:09:30 +00:00
uint32_t tlvend = * offset + tlvsize ; /* where the data will extend to */
if ( size < tlvend )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " SetTlvIpAddrPortV6() FAILED - not enough space " < < std : : endl ;
std : : cerr < < " SetTlvIpAddrPortV6() size: " < < size < < std : : endl ;
std : : cerr < < " SetTlvIpAddrPortV6() tlvsize: " < < tlvsize < < std : : endl ;
std : : cerr < < " SetTlvIpAddrPortV6() tlvend: " < < tlvend < < std : : endl ;
# endif
return false ;
}
bool ok = true ;
ok & = SetTlvBase ( data , tlvend , offset , type , tlvsize ) ;
/* now add the data (keep in network order) */
uint32_t * ip6addr = ( uint32_t * ) out - > sin6_addr . s6_addr ;
for ( int i = 0 ; i < 4 ; i + + )
{
ok & = setRawUInt32 ( data , tlvend , offset , ip6addr [ i ] ) ;
}
2013-09-13 14:35:19 +00:00
ok & = setRawUInt16 ( data , tlvend , offset , out - > sin6_port ) ;
2013-09-11 07:09:30 +00:00
return ok ;
}
bool GetTlvIpAddrPortV6 ( void * data , uint32_t size , uint32_t * offset ,
uint16_t type , struct sockaddr_in6 * in ) {
if ( ! data )
return false ;
if ( size < * offset + TLV_HEADER_SIZE )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " GetIpAddrPortV6() FAILED - not enough space " < < std : : endl ;
std : : cerr < < " GetIpAddrPortV6() size: " < < size < < std : : endl ;
std : : cerr < < " GetIpAddrPortV6() *offset: " < < * offset < < std : : endl ;
# endif
return false ;
}
/* extract the type and size */
void * tlvstart = right_shift_void_pointer ( data , * offset ) ;
uint16_t tlvtype = GetTlvType ( tlvstart ) ;
uint32_t tlvsize = GetTlvSize ( tlvstart ) ;
/* check that there is size */
uint32_t tlvend = * offset + tlvsize ;
if ( size < tlvend )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " GetIpAddrPortV6() FAILED - not enough space " < < std : : endl ;
std : : cerr < < " GetIpAddrPortV6() size: " < < size < < std : : endl ;
std : : cerr < < " GetIpAddrPortV6() tlvsize: " < < tlvsize < < std : : endl ;
std : : cerr < < " GetIpAddrPortV6() tlvend: " < < tlvend < < std : : endl ;
# endif
return false ;
}
if ( type ! = tlvtype )
{
# ifdef TLV_BASE_DEBUG
std : : cerr < < " GetIpAddrPortV6() FAILED - invalid type " < < std : : endl ;
std : : cerr < < " GetIpAddrPortV6() type: " < < type < < std : : endl ;
std : : cerr < < " GetIpAddrPortV6() tlvtype: " < < tlvtype < < std : : endl ;
# endif
return false ;
}
* offset + = TLV_HEADER_SIZE ; /* skip header */
bool ok = true ;
/* now get the data (keep in network order) */
uint32_t * ip6addr = ( uint32_t * ) in - > sin6_addr . s6_addr ;
for ( int i = 0 ; i < 4 ; i + + )
{
2013-09-13 14:35:19 +00:00
ok & = getRawUInt32 ( data , tlvend , offset , & ( ip6addr [ i ] ) ) ;
2013-09-11 07:09:30 +00:00
}
in - > sin6_family = AF_INET6 ; /* set FAMILY */
ok & = getRawUInt16 ( data , tlvend , offset , & ( in - > sin6_port ) ) ;
return ok ;
}
uint32_t GetTlvIpAddrPortV6Size ( ) {
return TLV_HEADER_SIZE + 16 + 2 ; /* header + 16 (IP) + 2 (Port) */
}