checks stream sizes when reading redirection packets
authorrdp.effort <rdp.effort@gmail.com>
Fri, 11 Jan 2013 00:21:24 +0000 (01:21 +0100)
committerrdp.effort <rdp.effort@gmail.com>
Fri, 11 Jan 2013 00:21:24 +0000 (01:21 +0100)
include/freerdp/utils/stream.h
include/freerdp/utils/string.h
libfreerdp/core/redirection.c
libfreerdp/utils/string.c

index 9f4115b..c4b43ac 100644 (file)
@@ -172,5 +172,11 @@ FREERDP_API void stream_extend(STREAM* stream, int request_size);
        _src->p += _n; \
        } while (0)
 
+static INLINE BOOL stream_skip(STREAM* s, int sz) {
+       if (stream_get_left(s) < sz)
+               return FALSE;
+       stream_seek(s, sz);
+       return TRUE;
+}
 #endif /* FREERDP_UTILS_STREAM_H */
 
index faac240..68f805c 100644 (file)
@@ -32,7 +32,7 @@ struct rdp_string
 };
 typedef struct rdp_string rdpString;
 
-FREERDP_API void freerdp_string_read_length32(STREAM* s, rdpString* string);
+FREERDP_API BOOL freerdp_string_read_length32(STREAM* s, rdpString* string);
 FREERDP_API void freerdp_string_free(rdpString* string);
 
 #endif /* FREERDP_UTILS_STRING_H */
index ea6c607..095bcdf 100644 (file)
@@ -67,6 +67,8 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, STREAM* s)
        UINT16 length;
        rdpRedirection* redirection = rdp->redirection;
 
+       if(stream_get_left(s) < 12)
+               return FALSE;
        stream_read_UINT16(s, flags); /* flags (2 bytes) */
        stream_read_UINT16(s, length); /* length (2 bytes) */
        stream_read_UINT32(s, redirection->sessionID); /* sessionID (4 bytes) */
@@ -80,13 +82,19 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, STREAM* s)
 
        if (redirection->flags & LB_TARGET_NET_ADDRESS)
        {
-               freerdp_string_read_length32(s, &redirection->targetNetAddress);
+               if(!freerdp_string_read_length32(s, &redirection->targetNetAddress))
+                       return FALSE;
                DEBUG_REDIR("targetNetAddress: %s", redirection->targetNetAddress.ascii);
        }
 
        if (redirection->flags & LB_LOAD_BALANCE_INFO)
        {
+               if(stream_get_left(s) < 4)
+                       return FALSE;
                stream_read_UINT32(s, redirection->LoadBalanceInfoLength);
+               if(stream_get_left(s) < redirection->LoadBalanceInfoLength)
+                       return FALSE;
+
                redirection->LoadBalanceInfo = (BYTE*) malloc(redirection->LoadBalanceInfoLength);
                stream_read(s, redirection->LoadBalanceInfo, redirection->LoadBalanceInfoLength);
 #ifdef WITH_DEBUG_REDIR
@@ -97,19 +105,23 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, STREAM* s)
 
        if (redirection->flags & LB_USERNAME)
        {
-               freerdp_string_read_length32(s, &redirection->username);
+               if(!freerdp_string_read_length32(s, &redirection->username))
+                       return FALSE;
                DEBUG_REDIR("username: %s", redirection->username.ascii);
        }
 
        if (redirection->flags & LB_DOMAIN)
        {
-               freerdp_string_read_length32(s, &redirection->domain);
+               if(!freerdp_string_read_length32(s, &redirection->domain))
+                       return FALSE;
                DEBUG_REDIR("domain: %s", redirection->domain.ascii);
        }
 
        if (redirection->flags & LB_PASSWORD)
        {
                /* Note: length (hopefully) includes double zero termination */
+               if(stream_get_left(s) < 4)
+                       return FALSE;
                stream_read_UINT32(s, redirection->PasswordCookieLength);
                redirection->PasswordCookie = (BYTE*) malloc(redirection->PasswordCookieLength);
                stream_read(s, redirection->PasswordCookie, redirection->PasswordCookieLength);
@@ -122,19 +134,22 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, STREAM* s)
 
        if (redirection->flags & LB_TARGET_FQDN)
        {
-               freerdp_string_read_length32(s, &redirection->targetFQDN);
+               if(!freerdp_string_read_length32(s, &redirection->targetFQDN))
+                       return FALSE;
                DEBUG_REDIR("targetFQDN: %s", redirection->targetFQDN.ascii);
        }
 
        if (redirection->flags & LB_TARGET_NETBIOS_NAME)
        {
-               freerdp_string_read_length32(s, &redirection->targetNetBiosName);
+               if(!freerdp_string_read_length32(s, &redirection->targetNetBiosName))
+                       return FALSE;
                DEBUG_REDIR("targetNetBiosName: %s", redirection->targetNetBiosName.ascii);
        }
 
        if (redirection->flags & LB_CLIENT_TSV_URL)
        {
-               freerdp_string_read_length32(s, &redirection->tsvUrl);
+               if(!freerdp_string_read_length32(s, &redirection->tsvUrl))
+                       return FALSE;
                DEBUG_REDIR("tsvUrl: %s", redirection->tsvUrl.ascii);
        }
 
@@ -144,6 +159,8 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, STREAM* s)
                UINT32 count;
                UINT32 targetNetAddressesLength;
 
+               if(stream_get_left(s) < 8)
+                       return FALSE;
                stream_read_UINT32(s, targetNetAddressesLength);
 
                stream_read_UINT32(s, redirection->targetNetAddressesCount);
@@ -154,12 +171,14 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, STREAM* s)
 
                for (i = 0; i < (int) count; i++)
                {
-                       freerdp_string_read_length32(s, &redirection->targetNetAddresses[i]);
+                       if(!freerdp_string_read_length32(s, &redirection->targetNetAddresses[i]))
+                               return FALSE;
                        DEBUG_REDIR("targetNetAddresses: %s", (&redirection->targetNetAddresses[i])->ascii);
                }
        }
 
-       stream_seek(s, 8); /* pad (8 bytes) */
+       if (!stream_skip(s, 8)) /* pad (8 bytes) */
+               return FALSE;
 
        if (redirection->flags & LB_NOREDIRECT)
                return TRUE;
@@ -169,16 +188,14 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, STREAM* s)
 
 BOOL rdp_recv_redirection_packet(rdpRdp* rdp, STREAM* s)
 {
-       rdp_recv_server_redirection_pdu(rdp, s);
-       return TRUE;
+       return rdp_recv_server_redirection_pdu(rdp, s);
 }
 
 BOOL rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, STREAM* s)
 {
-       stream_seek_UINT16(s); /* pad2Octets (2 bytes) */
-       rdp_recv_server_redirection_pdu(rdp, s);
-       stream_seek_BYTE(s); /* pad2Octets (1 byte) */
-       return TRUE;
+       return stream_skip(s, 2) &&                                     /* pad2Octets (2 bytes) */
+               rdp_recv_server_redirection_pdu(rdp, s) &&
+               stream_skip(s, 1);                                                      /* pad2Octets (1 byte) */
 }
 
 rdpRedirection* redirection_new()
index 022fa0f..09d426f 100644 (file)
 
 #include <freerdp/utils/string.h>
 
-void freerdp_string_read_length32(STREAM* s, rdpString* string)
+BOOL freerdp_string_read_length32(STREAM* s, rdpString* string)
 {
+       if(stream_get_left(s) < 4)
+               return FALSE;
        stream_read_UINT32(s, string->length);
+       if(stream_get_left(s) < string->length)
+               return FALSE;
        string->unicode = (char*) malloc(string->length);
        stream_read(s, string->unicode, string->length);
 
        ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) string->unicode, string->length / 2, &string->ascii, 0, NULL, NULL);
+       return TRUE;
 }
 
 void freerdp_string_free(rdpString* string)