Detect overflow in CreateClientRequestPacket(UlaGua).

Pass output buffer size to CreateClientRequestPacket(UlaGua)
from SearchByTarget and detect overflow.
Handle SearchByTarget error in UpnpSearchAsync.
(cherry picked from commit ff635f92c08cf8f7ebca973450bd79feacb2e0b1)
This commit is contained in:
Yoichi NAKAYAMA 2012-03-11 02:47:58 +09:00 committed by Marcelo Roberto Jimenez
parent 1ed33f3c5b
commit 6ba4181fe6
3 changed files with 89 additions and 21 deletions

View File

@ -322,6 +322,9 @@ Version 1.6.16
Further measures against buffer overflows. Further measures against buffer overflows.
Pass output buffer size to CreateClientRequestPacket(UlaGua)
from SearchByTarget and detect overflow.
Handle SearchByTarget error in UpnpSearchAsync.
Treat large argument as error in UpnpAddVirtualDir. Treat large argument as error in UpnpAddVirtualDir.
Do not clear buffer before snprintf. Do not clear buffer before snprintf.
Clarify the last argument of GetDescDocumentAndURL has size LINE_SIZE. Clarify the last argument of GetDescDocumentAndURL has size LINE_SIZE.

View File

@ -1770,6 +1770,7 @@ int UpnpSearchAsync(
{ {
struct Handle_Info *SInfo = NULL; struct Handle_Info *SInfo = NULL;
char *Target = ( char * )Target_const; char *Target = ( char * )Target_const;
int retVal;
if( UpnpSdkInit != 1 ) { if( UpnpSdkInit != 1 ) {
return UPNP_E_FINISH; return UPNP_E_FINISH;
@ -1792,7 +1793,9 @@ int UpnpSearchAsync(
} }
HandleUnlock(); HandleUnlock();
SearchByTarget( Mx, Target, ( void * )Cookie_const ); retVal = SearchByTarget( Mx, Target, ( void * )Cookie_const );
if (retVal != 1)
return retVal;
UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__, UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__,
"Exiting UpnpSearchAsync \n" ); "Exiting UpnpSearchAsync \n" );

View File

@ -316,9 +316,11 @@ end_ssdp_handle_ctrlpt_msg:
* \brief Creates a HTTP search request packet depending on the input * \brief Creates a HTTP search request packet depending on the input
* parameter. * parameter.
*/ */
static void CreateClientRequestPacket( static int CreateClientRequestPacket(
/*! [in] Output string in HTTP format. */ /*! [in,out] Output string in HTTP format. */
IN char *RqstBuf, INOUT char *RqstBuf,
/*! [in] RqstBuf size. */
IN size_t RqstBufSize,
/*! [in] Search Target. */ /*! [in] Search Target. */
IN int Mx, IN int Mx,
/*! [in] Number of seconds to wait to collect all the responses. */ /*! [in] Number of seconds to wait to collect all the responses. */
@ -326,68 +328,121 @@ static void CreateClientRequestPacket(
/*! [in] search address family. */ /*! [in] search address family. */
IN int AddressFamily) IN int AddressFamily)
{ {
int rc;
char TempBuf[COMMAND_LEN]; char TempBuf[COMMAND_LEN];
const char *command = "M-SEARCH * HTTP/1.1\r\n";
const char *man = "MAN: \"ssdp:discover\"\r\n";
memset(TempBuf, 0, sizeof(TempBuf)); memset(TempBuf, 0, sizeof(TempBuf));
strcpy(RqstBuf, "M-SEARCH * HTTP/1.1\r\n"); if (RqstBufSize <= strlen(command))
return UPNP_E_INTERNAL_ERROR;
strcpy(RqstBuf, command);
if (AddressFamily == AF_INET) { if (AddressFamily == AF_INET) {
snprintf(TempBuf, sizeof(TempBuf), "HOST: %s:%d\r\n", SSDP_IP, rc = snprintf(TempBuf, sizeof(TempBuf), "HOST: %s:%d\r\n", SSDP_IP,
SSDP_PORT); SSDP_PORT);
} else if (AddressFamily == AF_INET6) { } else if (AddressFamily == AF_INET6) {
snprintf(TempBuf, sizeof(TempBuf), "HOST: [%s]:%d\r\n", rc = snprintf(TempBuf, sizeof(TempBuf), "HOST: [%s]:%d\r\n",
SSDP_IPV6_LINKLOCAL, SSDP_PORT); SSDP_IPV6_LINKLOCAL, SSDP_PORT);
} }
if (rc < 0 || (unsigned int) rc >= sizeof(TempBuf))
return UPNP_E_INTERNAL_ERROR;
if (RqstBufSize <= strlen(RqstBuf) + strlen(TempBuf))
return UPNP_E_BUFFER_TOO_SMALL;
strcat(RqstBuf, TempBuf); strcat(RqstBuf, TempBuf);
strcat(RqstBuf, "MAN: \"ssdp:discover\"\r\n");
if (RqstBufSize <= strlen(RqstBuf) + strlen(man))
return UPNP_E_BUFFER_TOO_SMALL;
strcat(RqstBuf, man);
if (Mx > 0) { if (Mx > 0) {
snprintf(TempBuf, sizeof(TempBuf), "MX: %d\r\n", Mx); rc = snprintf(TempBuf, sizeof(TempBuf), "MX: %d\r\n", Mx);
if (rc < 0 || (unsigned int) rc >= sizeof(TempBuf))
return UPNP_E_INTERNAL_ERROR;
if (RqstBufSize <= strlen(RqstBuf) + strlen(TempBuf))
return UPNP_E_BUFFER_TOO_SMALL;
strcat(RqstBuf, TempBuf); strcat(RqstBuf, TempBuf);
} }
if (SearchTarget != NULL) { if (SearchTarget != NULL) {
snprintf(TempBuf, sizeof(TempBuf), "ST: %s\r\n", SearchTarget); rc = snprintf(TempBuf, sizeof(TempBuf), "ST: %s\r\n", SearchTarget);
if (rc < 0 || (unsigned int) rc >= sizeof(TempBuf))
return UPNP_E_INTERNAL_ERROR;
if (RqstBufSize <= strlen(RqstBuf) + strlen(TempBuf))
return UPNP_E_BUFFER_TOO_SMALL;
strcat(RqstBuf, TempBuf); strcat(RqstBuf, TempBuf);
} }
if (RqstBufSize <= strlen(RqstBuf) + strlen("\r\n"))
return UPNP_E_BUFFER_TOO_SMALL;
strcat(RqstBuf, "\r\n"); strcat(RqstBuf, "\r\n");
return UPNP_E_SUCCESS;
} }
/*! /*!
* \brief * \brief
*/ */
static void CreateClientRequestPacketUlaGua( static int CreateClientRequestPacketUlaGua(
/*! [in] . */ /*! [in,out] . */
char *RqstBuf, char *RqstBuf,
/*! [in] . */ /*! [in] . */
size_t RqstBufSize,
/*! [in] . */
int Mx, int Mx,
/*! [in] . */ /*! [in] . */
char *SearchTarget, char *SearchTarget,
/*! [in] . */ /*! [in] . */
int AddressFamily) int AddressFamily)
{ {
int rc;
char TempBuf[COMMAND_LEN]; char TempBuf[COMMAND_LEN];
const char *command = "M-SEARCH * HTTP/1.1\r\n";
const char *man = "MAN: \"ssdp:discover\"\r\n";
memset(TempBuf, 0, sizeof(TempBuf)); memset(TempBuf, 0, sizeof(TempBuf));
strcpy(RqstBuf, "M-SEARCH * HTTP/1.1\r\n"); if (RqstBufSize <= strlen(command))
return UPNP_E_INTERNAL_ERROR;
strcpy(RqstBuf, command);
if (AddressFamily == AF_INET) { if (AddressFamily == AF_INET) {
snprintf(TempBuf, sizeof(TempBuf), "HOST: %s:%d\r\n", SSDP_IP, rc = snprintf(TempBuf, sizeof(TempBuf), "HOST: %s:%d\r\n", SSDP_IP,
SSDP_PORT); SSDP_PORT);
} else if (AddressFamily == AF_INET6) { } else if (AddressFamily == AF_INET6) {
snprintf(TempBuf, sizeof(TempBuf), "HOST: [%s]:%d\r\n", rc = snprintf(TempBuf, sizeof(TempBuf), "HOST: [%s]:%d\r\n",
SSDP_IPV6_SITELOCAL, SSDP_PORT); SSDP_IPV6_SITELOCAL, SSDP_PORT);
} }
if (rc < 0 || (unsigned int) rc >= sizeof(TempBuf))
return UPNP_E_INTERNAL_ERROR;
if (RqstBufSize <= strlen(RqstBuf) + strlen(TempBuf))
return UPNP_E_BUFFER_TOO_SMALL;
strcat(RqstBuf, TempBuf); strcat(RqstBuf, TempBuf);
strcat(RqstBuf, "MAN: \"ssdp:discover\"\r\n");
if (RqstBufSize <= strlen(RqstBuf) + strlen(man))
return UPNP_E_BUFFER_TOO_SMALL;
strcat(RqstBuf, man);
if (Mx > 0) { if (Mx > 0) {
snprintf(TempBuf, sizeof(TempBuf), "MX: %d\r\n", Mx); rc = snprintf(TempBuf, sizeof(TempBuf), "MX: %d\r\n", Mx);
if (rc < 0 || (unsigned int) rc >= sizeof(TempBuf))
return UPNP_E_INTERNAL_ERROR;
if (RqstBufSize <= strlen(RqstBuf) + strlen(TempBuf))
return UPNP_E_BUFFER_TOO_SMALL;
strcat(RqstBuf, TempBuf); strcat(RqstBuf, TempBuf);
} }
if (SearchTarget) { if (SearchTarget) {
snprintf(TempBuf, sizeof(TempBuf), "ST: %s\r\n", SearchTarget); rc = snprintf(TempBuf, sizeof(TempBuf), "ST: %s\r\n", SearchTarget);
if (rc < 0 || (unsigned int) rc >= sizeof(TempBuf))
return UPNP_E_INTERNAL_ERROR;
if (RqstBufSize <= strlen(RqstBuf) + strlen(TempBuf))
return UPNP_E_BUFFER_TOO_SMALL;
strcat(RqstBuf, TempBuf); strcat(RqstBuf, TempBuf);
} }
if (RqstBufSize <= strlen(RqstBuf) + strlen("\r\n"))
return UPNP_E_BUFFER_TOO_SMALL;
strcat(RqstBuf, "\r\n"); strcat(RqstBuf, "\r\n");
return UPNP_E_SUCCESS;
} }
/*! /*!
@ -460,6 +515,7 @@ int SearchByTarget(int Mx, char *St, void *Cookie)
enum SsdpSearchType requestType; enum SsdpSearchType requestType;
unsigned long addrv4 = inet_addr(gIF_IPV4); unsigned long addrv4 = inet_addr(gIF_IPV4);
SOCKET max_fd = 0; SOCKET max_fd = 0;
int retVal;
/*ThreadData *ThData; */ /*ThreadData *ThData; */
ThreadPoolJob job; ThreadPoolJob job;
@ -476,9 +532,15 @@ int SearchByTarget(int Mx, char *St, void *Cookie)
timeTillRead = MIN_SEARCH_TIME; timeTillRead = MIN_SEARCH_TIME;
else if (timeTillRead > MAX_SEARCH_TIME) else if (timeTillRead > MAX_SEARCH_TIME)
timeTillRead = MAX_SEARCH_TIME; timeTillRead = MAX_SEARCH_TIME;
CreateClientRequestPacket(ReqBufv4, timeTillRead, St, AF_INET); retVal = CreateClientRequestPacket(ReqBufv4, sizeof(ReqBufv4), timeTillRead, St, AF_INET);
CreateClientRequestPacket(ReqBufv6, timeTillRead, St, AF_INET6); if (retVal != UPNP_E_SUCCESS)
CreateClientRequestPacketUlaGua(ReqBufv6UlaGua, timeTillRead, St, AF_INET6); return retVal;
retVal = CreateClientRequestPacket(ReqBufv6, sizeof(ReqBufv6), timeTillRead, St, AF_INET6);
if (retVal != UPNP_E_SUCCESS)
return retVal;
retVal = CreateClientRequestPacketUlaGua(ReqBufv6UlaGua, sizeof(ReqBufv6UlaGua), timeTillRead, St, AF_INET6);
if (retVal != UPNP_E_SUCCESS)
return retVal;
memset(&__ss_v4, 0, sizeof(__ss_v4)); memset(&__ss_v4, 0, sizeof(__ss_v4));
destAddr4->sin_family = AF_INET; destAddr4->sin_family = AF_INET;