check stream sizes when reading ClientInfoPDU
authorrdp.effort <rdp.effort@gmail.com>
Fri, 11 Jan 2013 00:18:11 +0000 (01:18 +0100)
committerrdp.effort <rdp.effort@gmail.com>
Fri, 11 Jan 2013 00:18:11 +0000 (01:18 +0100)
libfreerdp/core/info.c
libfreerdp/core/info.h

index 4c95894..40e1aa4 100644 (file)
@@ -49,15 +49,18 @@ static const char* const INFO_TYPE_LOGON_STRINGS[] =
  * @param settings settings
  */
 
-void rdp_read_server_auto_reconnect_cookie(STREAM* s, rdpSettings* settings)
+BOOL rdp_read_server_auto_reconnect_cookie(STREAM* s, rdpSettings* settings)
 {
        ARC_SC_PRIVATE_PACKET* autoReconnectCookie;
        autoReconnectCookie = settings->ServerAutoReconnectCookie;
 
+       if(stream_get_left(s) < 4+4+4+16)
+               return FALSE;
        stream_read_UINT32(s, autoReconnectCookie->cbLen); /* cbLen (4 bytes) */
        stream_read_UINT32(s, autoReconnectCookie->version); /* version (4 bytes) */
        stream_read_UINT32(s, autoReconnectCookie->logonId); /* LogonId (4 bytes) */
        stream_read(s, autoReconnectCookie->arcRandomBits, 16); /* arcRandomBits (16 bytes) */
+       return TRUE;
 }
 
 /**
@@ -115,6 +118,8 @@ BOOL rdp_read_extended_info_packet(STREAM* s, rdpSettings* settings)
        UINT16 cbClientDir;
        UINT16 cbAutoReconnectLen;
 
+       if(stream_get_left(s) < 4)
+               return FALSE;
        stream_read_UINT16(s, clientAddressFamily); /* clientAddressFamily */
        stream_read_UINT16(s, cbClientAddress); /* cbClientAddress */
 
@@ -126,6 +131,8 @@ BOOL rdp_read_extended_info_packet(STREAM* s, rdpSettings* settings)
        ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) stream_get_tail(s), cbClientAddress / 2, &settings->ClientAddress, 0, NULL, NULL);
        stream_seek(s, cbClientAddress);
 
+       if(stream_get_left(s) < 2)
+               return FALSE;
        stream_read_UINT16(s, cbClientDir); /* cbClientDir */
 
        if (stream_get_left(s) < cbClientDir)
@@ -140,6 +147,8 @@ BOOL rdp_read_extended_info_packet(STREAM* s, rdpSettings* settings)
        if (!rdp_read_client_time_zone(s, settings))
                return FALSE;
 
+       if(stream_get_left(s) < 10)
+               return FALSE;
        stream_seek_UINT32(s); /* clientSessionId, should be set to 0 */
        stream_read_UINT32(s, settings->PerformanceFlags); /* performanceFlags */
 
@@ -225,6 +234,9 @@ BOOL rdp_read_info_packet(STREAM* s, rdpSettings* settings)
        UINT16 cbAlternateShell;
        UINT16 cbWorkingDir;
 
+       if(stream_get_left(s) < 18) // invalid packet
+               return FALSE;
+
        stream_seek_UINT32(s); /* CodePage */
        stream_read_UINT32(s, flags); /* flags */
 
@@ -468,53 +480,71 @@ BOOL rdp_send_client_info(rdpRdp* rdp)
        return rdp_send(rdp, s, MCS_GLOBAL_CHANNEL_ID);
 }
 
-void rdp_recv_logon_info_v1(rdpRdp* rdp, STREAM* s)
+BOOL rdp_recv_logon_info_v1(rdpRdp* rdp, STREAM* s)
 {
        UINT32 cbDomain;
        UINT32 cbUserName;
 
+       if(stream_get_left(s) < 4+52+4+512+4)
+               return FALSE;
        stream_read_UINT32(s, cbDomain); /* cbDomain (4 bytes) */
        stream_seek(s, 52); /* domain (52 bytes) */
        stream_read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */
        stream_seek(s, 512); /* userName (512 bytes) */
        stream_seek_UINT32(s); /* sessionId (4 bytes) */
+       return TRUE;
 }
 
-void rdp_recv_logon_info_v2(rdpRdp* rdp, STREAM* s)
+BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, STREAM* s)
 {
        UINT32 cbDomain;
        UINT32 cbUserName;
 
+       if(stream_get_left(s) < 2+4+4+4+4+558)
+               return FALSE;
        stream_seek_UINT16(s); /* version (2 bytes) */
        stream_seek_UINT32(s); /* size (4 bytes) */
        stream_seek_UINT32(s); /* sessionId (4 bytes) */
        stream_read_UINT32(s, cbDomain); /* cbDomain (4 bytes) */
        stream_read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */
        stream_seek(s, 558); /* pad */
+
+       if(stream_get_left(s) < cbDomain+cbUserName)
+               return FALSE;
        stream_seek(s, cbDomain); /* domain */
        stream_seek(s, cbUserName); /* userName */
+       return TRUE;
 }
 
-void rdp_recv_logon_plain_notify(rdpRdp* rdp, STREAM* s)
+BOOL rdp_recv_logon_plain_notify(rdpRdp* rdp, STREAM* s)
 {
+       if(stream_get_left(s) < 576)
+               return FALSE;
        stream_seek(s, 576); /* pad */
+       return TRUE;
 }
 
-void rdp_recv_logon_error_info(rdpRdp* rdp, STREAM* s)
+BOOL rdp_recv_logon_error_info(rdpRdp* rdp, STREAM* s)
 {
        UINT32 errorNotificationType;
        UINT32 errorNotificationData;
 
+       if(stream_get_left(s) < 4)
+               return FALSE;
        stream_read_UINT32(s, errorNotificationType); /* errorNotificationType (4 bytes) */
        stream_read_UINT32(s, errorNotificationData); /* errorNotificationData (4 bytes) */
+       return TRUE;
 }
 
-void rdp_recv_logon_info_extended(rdpRdp* rdp, STREAM* s)
+BOOL rdp_recv_logon_info_extended(rdpRdp* rdp, STREAM* s)
 {
        UINT32 cbFieldData;
        UINT32 fieldsPresent;
        UINT16 Length;
 
+       if(stream_get_left(s) < 6)
+               return FALSE;
+
        stream_read_UINT16(s, Length); /* The total size in bytes of this structure */
        stream_read_UINT32(s, fieldsPresent); /* fieldsPresent (4 bytes) */
 
@@ -522,23 +552,34 @@ void rdp_recv_logon_info_extended(rdpRdp* rdp, STREAM* s)
 
        if (fieldsPresent & LOGON_EX_AUTORECONNECTCOOKIE)
        {
+               if(stream_get_left(s) < 4)
+                       return FALSE;
                stream_read_UINT32(s, cbFieldData); /* cbFieldData (4 bytes) */
-               rdp_read_server_auto_reconnect_cookie(s, rdp->settings);
+               if(rdp_read_server_auto_reconnect_cookie(s, rdp->settings) == FALSE)
+                       return FALSE;
        }
 
        if (fieldsPresent & LOGON_EX_LOGONERRORS)
        {
+               if(stream_get_left(s) < 4)
+                       return FALSE;
                stream_read_UINT32(s, cbFieldData); /* cbFieldData (4 bytes) */
-               rdp_recv_logon_error_info(rdp, s);
+               if(rdp_recv_logon_error_info(rdp, s) == FALSE)
+                       return FALSE;
        }
 
+       if(stream_get_left(s) < 570)
+               return FALSE;
        stream_seek(s, 570); /* pad */
+       return TRUE;
 }
 
 BOOL rdp_recv_save_session_info(rdpRdp* rdp, STREAM* s)
 {
        UINT32 infoType;
 
+       if(stream_get_left(s) < 4)
+               return FALSE;
        stream_read_UINT32(s, infoType); /* infoType (4 bytes) */
 
        //printf("%s\n", INFO_TYPE_LOGON_STRINGS[infoType]);
@@ -546,20 +587,16 @@ BOOL rdp_recv_save_session_info(rdpRdp* rdp, STREAM* s)
        switch (infoType)
        {
                case INFO_TYPE_LOGON:
-                       rdp_recv_logon_info_v1(rdp, s);
-                       break;
+                       return rdp_recv_logon_info_v1(rdp, s);
 
                case INFO_TYPE_LOGON_LONG:
-                       rdp_recv_logon_info_v2(rdp, s);
-                       break;
+                       return rdp_recv_logon_info_v2(rdp, s);
 
                case INFO_TYPE_LOGON_PLAIN_NOTIFY:
-                       rdp_recv_logon_plain_notify(rdp, s);
-                       break;
+                       return rdp_recv_logon_plain_notify(rdp, s);
 
                case INFO_TYPE_LOGON_EXTENDED_INF:
-                       rdp_recv_logon_info_extended(rdp, s);
-                       break;
+                       return rdp_recv_logon_info_extended(rdp, s);
 
                default:
                        break;
index fa3d0f1..e6598b4 100644 (file)
@@ -75,7 +75,7 @@ void rdp_write_system_time(STREAM* s, SYSTEM_TIME* system_time);
 void rdp_get_client_time_zone(STREAM* s, rdpSettings* settings);
 BOOL rdp_read_client_time_zone(STREAM* s, rdpSettings* settings);
 void rdp_write_client_time_zone(STREAM* s, rdpSettings* settings);
-void rdp_read_server_auto_reconnect_cookie(STREAM* s, rdpSettings* settings);
+BOOL rdp_read_server_auto_reconnect_cookie(STREAM* s, rdpSettings* settings);
 BOOL rdp_read_client_auto_reconnect_cookie(STREAM* s, rdpSettings* settings);
 void rdp_write_client_auto_reconnect_cookie(STREAM* s, rdpSettings* settings);
 void rdp_write_auto_reconnect_cookie(STREAM* s, rdpSettings* settings);