Commit f30d703a authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Fix various problems with the SDP parser:

- the reserved bit must be ignored
- off-by-one in decompression
- decompression did not *read* realloc() result
etc
parent c32f5ca0
...@@ -255,7 +255,7 @@ struct demux_sys_t ...@@ -255,7 +255,7 @@ struct demux_sys_t
/* Main parsing functions */ /* Main parsing functions */
static int ParseConnection( vlc_object_t *p_obj, sdp_t *p_sdp ); static int ParseConnection( vlc_object_t *p_obj, sdp_t *p_sdp );
static int ParseSAP( services_discovery_t *p_sd, uint8_t *p_buffer, int i_read ); static int ParseSAP( services_discovery_t *p_sd, const uint8_t *p_buffer, size_t i_read );
static sdp_t * ParseSDP( vlc_object_t *p_sd, char* psz_sdp ); static sdp_t * ParseSDP( vlc_object_t *p_sd, char* psz_sdp );
static sap_announce_t *CreateAnnounce( services_discovery_t *, uint16_t, sdp_t * ); static sap_announce_t *CreateAnnounce( services_discovery_t *, uint16_t, sdp_t * );
static int RemoveAnnounce( services_discovery_t *p_sd, sap_announce_t *p_announce ); static int RemoveAnnounce( services_discovery_t *p_sd, sap_announce_t *p_announce );
...@@ -264,9 +264,7 @@ struct demux_sys_t ...@@ -264,9 +264,7 @@ struct demux_sys_t
static char *GetAttribute( sdp_t *p_sdp, const char *psz_search ); static char *GetAttribute( sdp_t *p_sdp, const char *psz_search );
static vlc_bool_t IsSameSession( sdp_t *p_sdp1, sdp_t *p_sdp2 ); static vlc_bool_t IsSameSession( sdp_t *p_sdp1, sdp_t *p_sdp2 );
static int InitSocket( services_discovery_t *p_sd, const char *psz_address, int i_port ); static int InitSocket( services_discovery_t *p_sd, const char *psz_address, int i_port );
#ifdef HAVE_ZLIB_H static int Decompress( const unsigned char *psz_src, unsigned char **_dst, int i_len );
static int Decompress( unsigned char *psz_src, unsigned char **_dst, int i_len );
#endif
static void FreeSDP( sdp_t *p_sdp ); static void FreeSDP( sdp_t *p_sdp );
/***************************************************************************** /*****************************************************************************
...@@ -600,45 +598,37 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) ...@@ -600,45 +598,37 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
**************************************************************/ **************************************************************/
/* i_read is at least > 6 */ /* i_read is at least > 6 */
static int ParseSAP( services_discovery_t *p_sd, uint8_t *p_buffer, int i_read ) static int ParseSAP( services_discovery_t *p_sd, const uint8_t *buf,
size_t len )
{ {
int i_version, i_address_type, i_hash, i; int i;
char *psz_sdp, *psz_foo, *psz_initial_sdp; const char *psz_sdp;
uint8_t *p_decompressed_buffer = NULL; const uint8_t *end = buf + len;
sdp_t *p_sdp; sdp_t *p_sdp;
vlc_bool_t b_compressed;
vlc_bool_t b_need_delete = VLC_FALSE;
/* First, check the sap announce is correct */ assert (buf[len] == '\0');
i_version = p_buffer[0] >> 5;
if( i_version != 1 ) if (len < 4)
{ return VLC_EGENERIC;
msg_Dbg( p_sd, "strange sap version %d found", i_version );
}
i_address_type = p_buffer[0] & 0x10; uint8_t flags = buf[0];
if( (p_buffer[0] & 0x08) != 0 ) /* First, check the sap announce is correct */
{ if ((flags >> 5) != 1)
msg_Dbg( p_sd, "reserved bit incorrectly set" );
return VLC_EGENERIC; return VLC_EGENERIC;
}
if( (p_buffer[0] & 0x04) != 0 ) vlc_bool_t b_ipv6 = (flags & 0x10) != 0;
{ vlc_bool_t b_need_delete = (flags & 0x04) != 0;
msg_Dbg( p_sd, "session deletion packet" );
b_need_delete = VLC_TRUE;
}
if( p_buffer[0] & 0x02 ) if (flags & 0x02)
{ {
msg_Dbg( p_sd, "encrypted packet, unsupported" ); msg_Dbg( p_sd, "encrypted packet, unsupported" );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
b_compressed = p_buffer[0] & 0x01; vlc_bool_t b_compressed = (flags & 0x01) != 0;
i_hash = ( p_buffer[2] << 8 ) + p_buffer[3]; uint16_t i_hash = U16_AT (buf + 2);
if( p_sd->p_sys->b_strict && i_hash == 0 ) if( p_sd->p_sys->b_strict && i_hash == 0 )
{ {
...@@ -646,84 +636,55 @@ static int ParseSAP( services_discovery_t *p_sd, uint8_t *p_buffer, int i_read ) ...@@ -646,84 +636,55 @@ static int ParseSAP( services_discovery_t *p_sd, uint8_t *p_buffer, int i_read )
return VLC_EGENERIC; return VLC_EGENERIC;
} }
psz_sdp = (char *)p_buffer + 4; // Skips source address and auth data
psz_initial_sdp = psz_sdp; buf += 4 + (b_ipv6 ? 16 : 4) + buf[1];
if (buf > end)
if( i_address_type == 0 ) /* ipv4 source address */
{
psz_sdp += 4;
if( i_read <= 9 )
{
msg_Warn( p_sd, "too short SAP packet" );
return VLC_EGENERIC; return VLC_EGENERIC;
}
} uint8_t *decomp = NULL;
else /* ipv6 source address */ if (b_compressed)
{ {
psz_sdp += 16; int newsize = Decompress (buf, &decomp, end - buf);
if( i_read <= 21 ) if (newsize < 0)
{ {
msg_Warn( p_sd, "too short SAP packet" ); msg_Warn( p_sd, "decompression of sap packet failed" );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
}
if( b_compressed ) decomp = realloc (decomp, newsize + 1);
{ decomp[newsize++] = '\0';
#ifdef HAVE_ZLIB_H
int i_decompressed_size;
i_decompressed_size = Decompress( (uint8_t *)psz_sdp, psz_sdp = (const char *)decomp;
&p_decompressed_buffer, i_read - ( psz_sdp - (char *)p_buffer ) ); len = newsize;
if( i_decompressed_size > 0 )
{
psz_sdp = (char *)p_decompressed_buffer;
realloc( p_decompressed_buffer, i_decompressed_size++ );
psz_sdp[i_decompressed_size] = '\0';
} }
else else
{ {
msg_Warn( p_sd, "decompression of sap packet failed" ); psz_sdp = (const char *)buf;
return VLC_EGENERIC; len = end - buf;
}
#else
msg_Warn( p_sd, "ignoring compressed sap packet" );
return VLC_EGENERIC;
#endif
} }
/* Add the size of authentification info */ assert (buf[len] == '\0');
if( i_read < p_buffer[1] + (psz_sdp - psz_initial_sdp ) )
{ msg_Dbg( p_sd, "SDP:\n%s", psz_sdp );
msg_Warn( p_sd, "too short SAP packet\n");
return VLC_EGENERIC;
}
psz_sdp += p_buffer[1];
psz_foo = psz_sdp;
/* Skip payload type */ /* Skip payload type */
/* Handle announces without \0 between SAP and SDP */ /* SAPv1 has implicit "application/sdp" payload type: first line is v=0 */
while( *psz_sdp != '\0' && ( psz_sdp[0] != 'v' && psz_sdp[1] != '=' ) ) if (strncmp (psz_sdp, "v=0", 3))
{
if( psz_sdp - psz_initial_sdp >= i_read - 5 )
{ {
msg_Warn( p_sd, "empty SDP ?"); size_t clen = strlen (psz_sdp) + 1;
}
psz_sdp++;
}
if( *psz_sdp == '\0' ) if (strcmp (psz_sdp, "application/sdp"))
{ {
psz_sdp++; msg_Dbg (p_sd, "unsupported content type: %s", psz_sdp);
} return VLC_EGENERIC;
if( ( psz_sdp != psz_foo ) && strcasecmp( psz_foo, "application/sdp" ) )
{
msg_Dbg( p_sd, "unhandled content type: %s", psz_foo );
} }
if( ( psz_sdp - (char *)p_buffer ) >= i_read )
{ // skips content type
msg_Warn( p_sd, "package without content" ); if (len <= clen)
return VLC_EGENERIC; return VLC_EGENERIC;
len -= clen;
psz_sdp += clen;
} }
/* Parse SDP info */ /* Parse SDP info */
...@@ -779,7 +740,7 @@ static int ParseSAP( services_discovery_t *p_sd, uint8_t *p_buffer, int i_read ) ...@@ -779,7 +740,7 @@ static int ParseSAP( services_discovery_t *p_sd, uint8_t *p_buffer, int i_read )
CreateAnnounce( p_sd, i_hash, p_sdp ); CreateAnnounce( p_sd, i_hash, p_sdp );
FREENULL( p_decompressed_buffer ); FREENULL (decomp);
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -1280,9 +1241,9 @@ static int InitSocket( services_discovery_t *p_sd, const char *psz_address, ...@@ -1280,9 +1241,9 @@ static int InitSocket( services_discovery_t *p_sd, const char *psz_address,
return VLC_EGENERIC; return VLC_EGENERIC;
} }
#ifdef HAVE_ZLIB_H static int Decompress( const unsigned char *psz_src, unsigned char **_dst, int i_len )
static int Decompress( unsigned char *psz_src, unsigned char **_dst, int i_len )
{ {
#ifdef HAVE_ZLIB_H
int i_result, i_dstsize, n; int i_result, i_dstsize, n;
unsigned char *psz_dst; unsigned char *psz_dst;
z_stream d_stream; z_stream d_stream;
...@@ -1293,10 +1254,8 @@ static int Decompress( unsigned char *psz_src, unsigned char **_dst, int i_len ) ...@@ -1293,10 +1254,8 @@ static int Decompress( unsigned char *psz_src, unsigned char **_dst, int i_len )
i_result = inflateInit(&d_stream); i_result = inflateInit(&d_stream);
if( i_result != Z_OK ) if( i_result != Z_OK )
{
printf( "inflateInit() failed. Result: %d\n", i_result );
return( -1 ); return( -1 );
}
d_stream.next_in = (Bytef *)psz_src; d_stream.next_in = (Bytef *)psz_src;
d_stream.avail_in = i_len; d_stream.avail_in = i_len;
n = 0; n = 0;
...@@ -1312,11 +1271,8 @@ static int Decompress( unsigned char *psz_src, unsigned char **_dst, int i_len ) ...@@ -1312,11 +1271,8 @@ static int Decompress( unsigned char *psz_src, unsigned char **_dst, int i_len )
i_result = inflate(&d_stream, Z_NO_FLUSH); i_result = inflate(&d_stream, Z_NO_FLUSH);
if( ( i_result != Z_OK ) && ( i_result != Z_STREAM_END ) ) if( ( i_result != Z_OK ) && ( i_result != Z_STREAM_END ) )
{
printf( "Zlib decompression failed. Result: %d\n", i_result );
return( -1 ); return( -1 );
} }
}
while( ( d_stream.avail_out == 0 ) && ( d_stream.avail_in != 0 ) && while( ( d_stream.avail_out == 0 ) && ( d_stream.avail_in != 0 ) &&
( i_result != Z_STREAM_END ) ); ( i_result != Z_STREAM_END ) );
...@@ -1326,8 +1282,13 @@ static int Decompress( unsigned char *psz_src, unsigned char **_dst, int i_len ) ...@@ -1326,8 +1282,13 @@ static int Decompress( unsigned char *psz_src, unsigned char **_dst, int i_len )
*_dst = (unsigned char *)realloc( psz_dst, i_dstsize ); *_dst = (unsigned char *)realloc( psz_dst, i_dstsize );
return i_dstsize; return i_dstsize;
} #else
(void)psz_src;
(void)_dst;
(void)i_len;
return -1;
#endif #endif
}
static void FreeSDP( sdp_t *p_sdp ) static void FreeSDP( sdp_t *p_sdp )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment