diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c index 4c958946c..40e1aa48a 100644 --- a/libfreerdp/core/info.c +++ b/libfreerdp/core/info.c @@ -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; diff --git a/libfreerdp/core/info.h b/libfreerdp/core/info.h index fa3d0f1a1..e6598b47b 100644 --- a/libfreerdp/core/info.h +++ b/libfreerdp/core/info.h @@ -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);