minissdpc.c: Fix buffer overrun in SSDP packet parsing

fixes #267

there were several errors in ProcessSSDPData()
in the parsing of ST: MX: and MAN: headers
so a few bytes could be read after the end of the buffer.
This commit is contained in:
Thomas Bernard 2017-12-12 10:42:54 +01:00
parent 256b93e5d3
commit 9fcc0a72f0
1 changed files with 20 additions and 11 deletions

View File

@ -40,6 +40,10 @@
#include "codelength.h"
#include "macros.h"
#ifndef MIN
#define MIN(x,y) (((x)<(y))?(x):(y))
#endif /* MIN */
/* SSDP ip/port */
#define SSDP_PORT (1900)
#define SSDP_MCAST_ADDR ("239.255.255.250")
@ -989,6 +993,7 @@ ProcessSSDPData(int s, const char *bufr, int n,
* a multiple part response from the device, those multiple part
* responses SHOULD be spread at random intervals through the time period
* from 0 to the number of seconds specified in the MX header field. */
char atoi_buffer[8];
/* get the string representation of the sender address */
sockaddr_to_string(sender, sender_str, sizeof(sender_str));
@ -1040,13 +1045,15 @@ ProcessSSDPData(int s, const char *bufr, int n,
st_len = 0;
while((*st == ' ' || *st == '\t') && (st < bufr + n))
st++;
while(st[st_len]!='\r' && st[st_len]!='\n'
&& (st + st_len < bufr + n))
while((st + st_len < bufr + n)
&& (st[st_len]!='\r' && st[st_len]!='\n'))
st_len++;
l = st_len;
while(l > 0 && st[l-1] != ':')
l--;
st_ver = atoi(st+l);
memset(atoi_buffer, 0, sizeof(atoi_buffer));
memcpy(atoi_buffer, st + l, MIN((int)(sizeof(atoi_buffer) - 1), st_len - l));
st_ver = atoi(atoi_buffer);
syslog(LOG_DEBUG, "ST: %.*s (ver=%d)", st_len, st, st_ver);
/*j = 0;*/
/*while(bufr[i+j]!='\r') j++;*/
@ -1059,12 +1066,14 @@ ProcessSSDPData(int s, const char *bufr, int n,
int mx_len;
mx = bufr+i+3;
mx_len = 0;
while((*mx == ' ' || *mx == '\t') && (mx < bufr + n))
while((mx < bufr + n) && (*mx == ' ' || *mx == '\t'))
mx++;
while(mx[mx_len]!='\r' && mx[mx_len]!='\n'
&& (mx + mx_len < bufr + n))
while((mx + mx_len < bufr + n)
&& (mx[mx_len]!='\r' && mx[mx_len]!='\n'))
mx_len++;
mx_value = atoi(mx);
memset(atoi_buffer, 0, sizeof(atoi_buffer));
memcpy(atoi_buffer, mx, MIN((int)(sizeof(atoi_buffer) - 1), mx_len));
mx_value = atoi(atoi_buffer);
syslog(LOG_DEBUG, "MX: %.*s (value=%d)", mx_len, mx, mx_value);
}
#endif /* defined(UPNP_STRICT) || defined(DELAY_MSEARCH_RESPONSE) */
@ -1076,12 +1085,12 @@ ProcessSSDPData(int s, const char *bufr, int n,
int man_len;
man = bufr+i+4;
man_len = 0;
while((*man == ' ' || *man == '\t') && (man < bufr + n))
while((man < bufr + n) && (*man == ' ' || *man == '\t'))
man++;
while(man[man_len]!='\r' && man[man_len]!='\n'
&& (man + man_len < bufr + n))
while((man + man_len < bufr + n)
&& (man[man_len]!='\r' && man[man_len]!='\n'))
man_len++;
if(strncmp(man, "\"ssdp:discover\"", 15) != 0) {
if((man_len < 15) || (strncmp(man, "\"ssdp:discover\"", 15) != 0)) {
syslog(LOG_INFO, "ignoring SSDP packet MAN empty or invalid header");
return;
}