Merge pull request #887 from hardening/hardening1

Adding security checks
This commit is contained in:
Marc-André Moreau 2013-01-10 16:47:56 -08:00
commit 40f44281a1
18 changed files with 330 additions and 158 deletions

View File

@ -88,10 +88,13 @@ void rail_string_to_unicode_string(rdpRailOrder* rail_order, char* string, RAIL_
unicode_string->length = (UINT16) length;
}
void rail_read_pdu_header(STREAM* s, UINT16* orderType, UINT16* orderLength)
BOOL rail_read_pdu_header(STREAM* s, UINT16* orderType, UINT16* orderLength)
{
if(stream_get_left(s) < 4)
return FALSE;
stream_read_UINT16(s, *orderType); /* orderType (2 bytes) */
stream_read_UINT16(s, *orderLength); /* orderLength (2 bytes) */
return TRUE;
}
void rail_write_pdu_header(STREAM* s, UINT16 orderType, UINT16 orderLength)
@ -133,23 +136,31 @@ void rail_write_high_contrast(STREAM* s, HIGH_CONTRAST* high_contrast)
rail_write_unicode_string(s, &high_contrast->colorScheme); /* colorScheme */
}
void rail_read_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake)
BOOL rail_read_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake)
{
if(stream_get_left(s) < 4)
return FALSE;
stream_read_UINT32(s, handshake->buildNumber); /* buildNumber (4 bytes) */
return TRUE;
}
void rail_read_server_exec_result_order(STREAM* s, RAIL_EXEC_RESULT_ORDER* exec_result)
BOOL rail_read_server_exec_result_order(STREAM* s, RAIL_EXEC_RESULT_ORDER* exec_result)
{
if(stream_get_left(s) < 8)
return FALSE;
stream_read_UINT16(s, exec_result->flags); /* flags (2 bytes) */
stream_read_UINT16(s, exec_result->execResult); /* execResult (2 bytes) */
stream_read_UINT32(s, exec_result->rawResult); /* rawResult (4 bytes) */
stream_seek_UINT16(s); /* padding (2 bytes) */
rail_read_unicode_string(s, &exec_result->exeOrFile); /* exeOrFile */
return rail_read_unicode_string(s, &exec_result->exeOrFile); /* exeOrFile */
}
void rail_read_server_sysparam_order(STREAM* s, RAIL_SYSPARAM_ORDER* sysparam)
BOOL rail_read_server_sysparam_order(STREAM* s, RAIL_SYSPARAM_ORDER* sysparam)
{
BYTE body;
if(stream_get_left(s) < 5)
return FALSE;
stream_read_UINT32(s, sysparam->param); /* systemParam (4 bytes) */
stream_read_BYTE(s, body); /* body (1 byte) */
@ -166,10 +177,13 @@ void rail_read_server_sysparam_order(STREAM* s, RAIL_SYSPARAM_ORDER* sysparam)
default:
break;
}
return TRUE;
}
void rail_read_server_minmaxinfo_order(STREAM* s, RAIL_MINMAXINFO_ORDER* minmaxinfo)
BOOL rail_read_server_minmaxinfo_order(STREAM* s, RAIL_MINMAXINFO_ORDER* minmaxinfo)
{
if(stream_get_left(s) < 20)
return FALSE;
stream_read_UINT32(s, minmaxinfo->windowId); /* windowId (4 bytes) */
stream_read_UINT16(s, minmaxinfo->maxWidth); /* maxWidth (2 bytes) */
stream_read_UINT16(s, minmaxinfo->maxHeight); /* maxHeight (2 bytes) */
@ -179,11 +193,14 @@ void rail_read_server_minmaxinfo_order(STREAM* s, RAIL_MINMAXINFO_ORDER* minmaxi
stream_read_UINT16(s, minmaxinfo->minTrackHeight); /* minTrackHeight (2 bytes) */
stream_read_UINT16(s, minmaxinfo->maxTrackWidth); /* maxTrackWidth (2 bytes) */
stream_read_UINT16(s, minmaxinfo->maxTrackHeight); /* maxTrackHeight (2 bytes) */
return TRUE;
}
void rail_read_server_localmovesize_order(STREAM* s, RAIL_LOCALMOVESIZE_ORDER* localmovesize)
BOOL rail_read_server_localmovesize_order(STREAM* s, RAIL_LOCALMOVESIZE_ORDER* localmovesize)
{
UINT16 isMoveSizeStart;
if(stream_get_left(s) < 12)
return FALSE;
stream_read_UINT32(s, localmovesize->windowId); /* windowId (4 bytes) */
stream_read_UINT16(s, isMoveSizeStart); /* isMoveSizeStart (2 bytes) */
@ -192,20 +209,27 @@ void rail_read_server_localmovesize_order(STREAM* s, RAIL_LOCALMOVESIZE_ORDER* l
stream_read_UINT16(s, localmovesize->moveSizeType); /* moveSizeType (2 bytes) */
stream_read_UINT16(s, localmovesize->posX); /* posX (2 bytes) */
stream_read_UINT16(s, localmovesize->posY); /* posY (2 bytes) */
return TRUE;
}
void rail_read_server_get_appid_resp_order(STREAM* s, RAIL_GET_APPID_RESP_ORDER* get_appid_resp)
BOOL rail_read_server_get_appid_resp_order(STREAM* s, RAIL_GET_APPID_RESP_ORDER* get_appid_resp)
{
if(stream_get_left(s) < 516)
return FALSE;
stream_read_UINT32(s, get_appid_resp->windowId); /* windowId (4 bytes) */
stream_read(s, &get_appid_resp->applicationIdBuffer[0], 512); /* applicationId (256 UNICODE chars) */
get_appid_resp->applicationId.length = 512;
get_appid_resp->applicationId.string = &get_appid_resp->applicationIdBuffer[0];
return TRUE;
}
void rail_read_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_info)
BOOL rail_read_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_info)
{
if(stream_get_left(s) < 4)
return FALSE;
stream_read_UINT32(s, langbar_info->languageBarStatus); /* languageBarStatus (4 bytes) */
return TRUE;
}
void rail_write_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake)
@ -332,9 +356,10 @@ void rail_write_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_i
stream_write_UINT32(s, langbar_info->languageBarStatus); /* languageBarStatus (4 bytes) */
}
void rail_recv_handshake_order(rdpRailOrder* rail_order, STREAM* s)
BOOL rail_recv_handshake_order(rdpRailOrder* rail_order, STREAM* s)
{
rail_read_handshake_order(s, &rail_order->handshake);
if(!rail_read_handshake_order(s, &rail_order->handshake))
return FALSE;
rail_order->handshake.buildNumber = 0x00001DB0;
rail_send_handshake_order(rail_order);
@ -371,56 +396,70 @@ void rail_recv_handshake_order(rdpRailOrder* rail_order, STREAM* s)
rail_send_channel_event(rail_order->plugin,
RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS, &rail_order->sysparam);
return TRUE;
}
void rail_recv_exec_result_order(rdpRailOrder* rail_order, STREAM* s)
BOOL rail_recv_exec_result_order(rdpRailOrder* rail_order, STREAM* s)
{
rail_read_server_exec_result_order(s, &rail_order->exec_result);
if(!rail_read_server_exec_result_order(s, &rail_order->exec_result))
return FALSE;
rail_send_channel_event(rail_order->plugin,
RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS, &rail_order->exec_result);
return TRUE;
}
void rail_recv_server_sysparam_order(rdpRailOrder* rail_order, STREAM* s)
BOOL rail_recv_server_sysparam_order(rdpRailOrder* rail_order, STREAM* s)
{
rail_read_server_sysparam_order(s, &rail_order->sysparam);
if(!rail_read_server_sysparam_order(s, &rail_order->sysparam))
return FALSE;
rail_send_channel_event(rail_order->plugin,
RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM, &rail_order->sysparam);
return TRUE;
}
void rail_recv_server_minmaxinfo_order(rdpRailOrder* rail_order, STREAM* s)
BOOL rail_recv_server_minmaxinfo_order(rdpRailOrder* rail_order, STREAM* s)
{
rail_read_server_minmaxinfo_order(s, &rail_order->minmaxinfo);
if(!rail_read_server_minmaxinfo_order(s, &rail_order->minmaxinfo))
return FALSE;
rail_send_channel_event(rail_order->plugin,
RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_MINMAXINFO, &rail_order->minmaxinfo);
return TRUE;
}
void rail_recv_server_localmovesize_order(rdpRailOrder* rail_order, STREAM* s)
BOOL rail_recv_server_localmovesize_order(rdpRailOrder* rail_order, STREAM* s)
{
rail_read_server_localmovesize_order(s, &rail_order->localmovesize);
if(!rail_read_server_localmovesize_order(s, &rail_order->localmovesize))
return FALSE;
rail_send_channel_event(rail_order->plugin,
RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_LOCALMOVESIZE, &rail_order->localmovesize);
return TRUE;
}
void rail_recv_server_get_appid_resp_order(rdpRailOrder* rail_order, STREAM* s)
BOOL rail_recv_server_get_appid_resp_order(rdpRailOrder* rail_order, STREAM* s)
{
rail_read_server_get_appid_resp_order(s, &rail_order->get_appid_resp);
if(!rail_read_server_get_appid_resp_order(s, &rail_order->get_appid_resp))
return FALSE;
rail_send_channel_event(rail_order->plugin,
RDP_EVENT_TYPE_RAIL_CHANNEL_APPID_RESP, &rail_order->get_appid_resp);
return TRUE;
}
void rail_recv_langbar_info_order(rdpRailOrder* rail_order, STREAM* s)
BOOL rail_recv_langbar_info_order(rdpRailOrder* rail_order, STREAM* s)
{
rail_read_langbar_info_order(s, &rail_order->langbar_info);
if(!rail_read_langbar_info_order(s, &rail_order->langbar_info))
return FALSE;
rail_send_channel_event(rail_order->plugin,
RDP_EVENT_TYPE_RAIL_CHANNEL_LANGBARINFO, &rail_order->langbar_info);
return TRUE;
}
void rail_order_recv(rdpRailOrder* rail_order, STREAM* s)
BOOL rail_order_recv(rdpRailOrder* rail_order, STREAM* s)
{
UINT16 orderType;
UINT16 orderLength;
rail_read_pdu_header(s, &orderType, &orderLength);
if(!rail_read_pdu_header(s, &orderType, &orderLength))
return FALSE;
DEBUG_RAIL("Received %s PDU, length:%d",
RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], orderLength);
@ -428,37 +467,31 @@ void rail_order_recv(rdpRailOrder* rail_order, STREAM* s)
switch (orderType)
{
case RDP_RAIL_ORDER_HANDSHAKE:
rail_recv_handshake_order(rail_order, s);
break;
return rail_recv_handshake_order(rail_order, s);
case RDP_RAIL_ORDER_EXEC_RESULT:
rail_recv_exec_result_order(rail_order, s);
break;
return rail_recv_exec_result_order(rail_order, s);
case RDP_RAIL_ORDER_SYSPARAM:
rail_recv_server_sysparam_order(rail_order, s);
break;
return rail_recv_server_sysparam_order(rail_order, s);
case RDP_RAIL_ORDER_MINMAXINFO:
rail_recv_server_minmaxinfo_order(rail_order, s);
break;
return rail_recv_server_minmaxinfo_order(rail_order, s);
case RDP_RAIL_ORDER_LOCALMOVESIZE:
rail_recv_server_localmovesize_order(rail_order, s);
break;
return rail_recv_server_localmovesize_order(rail_order, s);
case RDP_RAIL_ORDER_GET_APPID_RESP:
rail_recv_server_get_appid_resp_order(rail_order, s);
break;
return rail_recv_server_get_appid_resp_order(rail_order, s);
case RDP_RAIL_ORDER_LANGBARINFO:
rail_recv_langbar_info_order(rail_order, s);
break;
return rail_recv_langbar_info_order(rail_order, s);
default:
printf("Unknown RAIL PDU order reveived.");
break;
}
return TRUE;
}
void rail_send_handshake_order(rdpRailOrder* rail_order)

View File

@ -56,13 +56,13 @@
void rail_string_to_unicode_string(rdpRailOrder* rail_order, char* string, RAIL_UNICODE_STRING* unicode_string);
void rail_read_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake);
void rail_read_server_exec_result_order(STREAM* s, RAIL_EXEC_RESULT_ORDER* exec_result);
void rail_read_server_sysparam_order(STREAM* s, RAIL_SYSPARAM_ORDER* sysparam);
void rail_read_server_minmaxinfo_order(STREAM* s, RAIL_MINMAXINFO_ORDER* minmaxinfo);
void rail_read_server_localmovesize_order(STREAM* s, RAIL_LOCALMOVESIZE_ORDER* localmovesize);
void rail_read_server_get_appid_resp_order(STREAM* s, RAIL_GET_APPID_RESP_ORDER* get_appid_resp);
void rail_read_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_info);
BOOL rail_read_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake);
BOOL rail_read_server_exec_result_order(STREAM* s, RAIL_EXEC_RESULT_ORDER* exec_result);
BOOL rail_read_server_sysparam_order(STREAM* s, RAIL_SYSPARAM_ORDER* sysparam);
BOOL rail_read_server_minmaxinfo_order(STREAM* s, RAIL_MINMAXINFO_ORDER* minmaxinfo);
BOOL rail_read_server_localmovesize_order(STREAM* s, RAIL_LOCALMOVESIZE_ORDER* localmovesize);
BOOL rail_read_server_get_appid_resp_order(STREAM* s, RAIL_GET_APPID_RESP_ORDER* get_appid_resp);
BOOL rail_read_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_info);
void rail_write_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake);
void rail_write_client_status_order(STREAM* s, RAIL_CLIENT_STATUS_ORDER* client_status);
@ -76,7 +76,7 @@ void rail_write_client_window_move_order(STREAM* s, RAIL_WINDOW_MOVE_ORDER* wind
void rail_write_client_get_appid_req_order(STREAM* s, RAIL_GET_APPID_REQ_ORDER* get_appid_req);
void rail_write_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_info);
void rail_order_recv(rdpRailOrder* rail_order, STREAM* s);
BOOL rail_order_recv(rdpRailOrder* rail_order, STREAM* s);
void rail_send_handshake_order(rdpRailOrder* rail_order);
void rail_send_client_status_order(rdpRailOrder* rail_order);

View File

@ -51,7 +51,7 @@
#define BER_PC(_pc) (_pc ? BER_CONSTRUCT : BER_PRIMITIVE)
FREERDP_API void ber_read_length(STREAM* s, int* length);
FREERDP_API BOOL ber_read_length(STREAM* s, int* length);
FREERDP_API int ber_write_length(STREAM* s, int length);
FREERDP_API int _ber_skip_length(int length);
FREERDP_API int ber_get_content_length(int length);

View File

@ -26,7 +26,7 @@
FREERDP_API void rail_unicode_string_alloc(RAIL_UNICODE_STRING* unicode_string, UINT16 cbString);
FREERDP_API void rail_unicode_string_free(RAIL_UNICODE_STRING* unicode_string);
FREERDP_API void rail_read_unicode_string(STREAM* s, RAIL_UNICODE_STRING* unicode_string);
FREERDP_API BOOL rail_read_unicode_string(STREAM* s, RAIL_UNICODE_STRING* unicode_string);
FREERDP_API void rail_write_unicode_string(STREAM* s, RAIL_UNICODE_STRING* unicode_string);
FREERDP_API void rail_write_unicode_string_value(STREAM* s, RAIL_UNICODE_STRING* unicode_string);
FREERDP_API void* rail_clone_order(UINT32 event_type, void* order);

View 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 */

View 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 */

View File

@ -91,30 +91,36 @@ BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channel_id, BYTE* data, int size)
return TRUE;
}
void freerdp_channel_process(freerdp* instance, STREAM* s, UINT16 channel_id)
BOOL freerdp_channel_process(freerdp* instance, STREAM* s, UINT16 channel_id)
{
UINT32 length;
UINT32 flags;
int chunk_length;
if(stream_get_left(s) < 4)
return FALSE;
stream_read_UINT32(s, length);
stream_read_UINT32(s, flags);
chunk_length = stream_get_left(s);
IFCALL(instance->ReceiveChannelData, instance,
channel_id, stream_get_tail(s), chunk_length, flags, length);
return TRUE;
}
void freerdp_channel_peer_process(freerdp_peer* client, STREAM* s, UINT16 channel_id)
BOOL freerdp_channel_peer_process(freerdp_peer* client, STREAM* s, UINT16 channel_id)
{
UINT32 length;
UINT32 flags;
int chunk_length;
if(stream_get_left(s) < 8)
return FALSE;
stream_read_UINT32(s, length);
stream_read_UINT32(s, flags);
chunk_length = stream_get_left(s);
IFCALL(client->ReceiveChannelData, client,
channel_id, stream_get_tail(s), chunk_length, flags, length);
return TRUE;
}

View File

@ -21,7 +21,7 @@
#define __CHANNEL_H
BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channel_id, BYTE* data, int size);
void freerdp_channel_process(freerdp* instance, STREAM* s, UINT16 channel_id);
void freerdp_channel_peer_process(freerdp_peer* client, STREAM* s, UINT16 channel_id);
BOOL freerdp_channel_process(freerdp* instance, STREAM* s, UINT16 channel_id);
BOOL freerdp_channel_peer_process(freerdp_peer* client, STREAM* s, UINT16 channel_id);
#endif /* __CHANNEL_H */

View File

@ -314,7 +314,8 @@ BOOL gcc_read_client_data_blocks(STREAM* s, rdpSettings* settings, int length)
while (length > 0)
{
pos = stream_get_pos(s);
gcc_read_user_data_header(s, &type, &blockLength);
if(!gcc_read_user_data_header(s, &type, &blockLength))
return FALSE;
switch (type)
{
@ -452,12 +453,12 @@ void gcc_write_server_data_blocks(STREAM* s, rdpSettings* settings)
BOOL gcc_read_user_data_header(STREAM* s, UINT16* type, UINT16* length)
{
if (stream_get_left(s) < 4)
return FALSE;
stream_read_UINT16(s, *type); /* type */
stream_read_UINT16(s, *length); /* length */
if (*length < 4)
return FALSE;
if (stream_get_left(s) < *length - 4)
return FALSE;
@ -749,6 +750,8 @@ BOOL gcc_read_server_core_data(STREAM* s, rdpSettings* settings)
UINT32 version;
UINT32 clientRequestedProtocols;
if(stream_get_left(s) < 8)
return FALSE;
stream_read_UINT32(s, version); /* version */
stream_read_UINT32(s, clientRequestedProtocols); /* clientRequestedProtocols */
@ -822,6 +825,8 @@ BOOL gcc_read_server_security_data(STREAM* s, rdpSettings* settings)
BYTE* data;
UINT32 length;
if (stream_get_left(s) < 8)
return FALSE;
stream_read_UINT32(s, settings->EncryptionMethods); /* encryptionMethod */
stream_read_UINT32(s, settings->EncryptionLevel); /* encryptionLevel */
@ -834,9 +839,14 @@ BOOL gcc_read_server_security_data(STREAM* s, rdpSettings* settings)
return TRUE;
}
if (stream_get_left(s) < 8)
return FALSE;
stream_read_UINT32(s, settings->ServerRandomLength); /* serverRandomLen */
stream_read_UINT32(s, settings->ServerCertificateLength); /* serverCertLen */
if (stream_get_left(s) < settings->ServerRandomLength + settings->ServerCertificateLength)
return FALSE;
if (settings->ServerRandomLength > 0)
{
/* serverRandom */
@ -1106,6 +1116,8 @@ BOOL gcc_read_server_network_data(STREAM* s, rdpSettings* settings)
UINT16 channelCount;
UINT16 channelId;
if(stream_get_left(s) < 4)
return FALSE;
stream_read_UINT16(s, MCSChannelId); /* MCSChannelId */
stream_read_UINT16(s, channelCount); /* channelCount */
@ -1115,6 +1127,9 @@ BOOL gcc_read_server_network_data(STREAM* s, rdpSettings* settings)
settings->ChannelCount, channelCount);
}
if(stream_get_left(s) < channelCount * 2)
return FALSE;
for (i = 0; i < channelCount; i++)
{
stream_read_UINT16(s, channelId); /* channelId */
@ -1122,7 +1137,7 @@ BOOL gcc_read_server_network_data(STREAM* s, rdpSettings* settings)
}
if (channelCount % 2 == 1)
stream_seek(s, 2); /* padding */
return stream_skip(s, 2); /* padding */
return TRUE;
}
@ -1156,13 +1171,17 @@ BOOL gcc_read_client_cluster_data(STREAM* s, rdpSettings* settings, UINT16 block
{
UINT32 flags;
if (blockLength < 8)
if (blockLength < 4)
return FALSE;
stream_read_UINT32(s, flags); /* flags */
if ((flags & REDIRECTED_SESSIONID_FIELD_VALID))
{
if(blockLength < 8)
return FALSE;
stream_read_UINT32(s, settings->RedirectedSessionId); /* redirectedSessionID */
}
return TRUE;
}

View 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;

View 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);

View File

@ -1158,17 +1158,20 @@ int credssp_recv(rdpCredssp* credssp)
}
/* TSRequest */
ber_read_sequence_tag(s, &length);
ber_read_contextual_tag(s, 0, &length, TRUE);
ber_read_integer(s, &version);
if(!ber_read_sequence_tag(s, &length) ||
!ber_read_contextual_tag(s, 0, &length, TRUE) ||
!ber_read_integer(s, &version))
return -1;
/* [1] negoTokens (NegoData) */
if (ber_read_contextual_tag(s, 1, &length, TRUE) != FALSE)
{
ber_read_sequence_tag(s, &length); /* SEQUENCE OF NegoDataItem */
ber_read_sequence_tag(s, &length); /* NegoDataItem */
ber_read_contextual_tag(s, 0, &length, TRUE); /* [0] negoToken */
ber_read_octet_string_tag(s, &length); /* OCTET STRING */
if (!ber_read_sequence_tag(s, &length) || /* SEQUENCE OF NegoDataItem */
!ber_read_sequence_tag(s, &length) || /* NegoDataItem */
!ber_read_contextual_tag(s, 0, &length, TRUE) || /* [0] negoToken */
!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
stream_get_left(s) < length)
return -1;
sspi_SecBufferAlloc(&credssp->negoToken, length);
stream_read(s, credssp->negoToken.pvBuffer, length);
credssp->negoToken.cbBuffer = length;
@ -1177,7 +1180,9 @@ int credssp_recv(rdpCredssp* credssp)
/* [2] authInfo (OCTET STRING) */
if (ber_read_contextual_tag(s, 2, &length, TRUE) != FALSE)
{
ber_read_octet_string_tag(s, &length); /* OCTET STRING */
if(!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
stream_get_left(s) < length)
return -1;
sspi_SecBufferAlloc(&credssp->authInfo, length);
stream_read(s, credssp->authInfo.pvBuffer, length);
credssp->authInfo.cbBuffer = length;
@ -1186,7 +1191,9 @@ int credssp_recv(rdpCredssp* credssp)
/* [3] pubKeyAuth (OCTET STRING) */
if (ber_read_contextual_tag(s, 3, &length, TRUE) != FALSE)
{
ber_read_octet_string_tag(s, &length); /* OCTET STRING */
if(!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
stream_get_left(s) < length)
return -1;
sspi_SecBufferAlloc(&credssp->pubKeyAuth, length);
stream_read(s, credssp->pubKeyAuth.pvBuffer, length);
credssp->pubKeyAuth.cbBuffer = length;

View 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()

View File

@ -118,7 +118,8 @@ fips_oddparity_table[256] =
0xf8, 0xf8, 0xfb, 0xfb, 0xfd, 0xfd, 0xfe, 0xfe
};
static void security_salted_hash(BYTE* salt, BYTE* input, int length, BYTE* salt1, BYTE* salt2, BYTE* output)
static void security_salted_hash(const BYTE* salt, const BYTE* input, int length,
const BYTE* salt1, const BYTE* salt2, BYTE* output)
{
CryptoMd5 md5;
CryptoSha1 sha1;
@ -141,13 +142,14 @@ static void security_salted_hash(BYTE* salt, BYTE* input, int length, BYTE* salt
crypto_md5_final(md5, output);
}
static void security_premaster_hash(char* input, int length, BYTE* premaster_secret, BYTE* client_random, BYTE* server_random, BYTE* output)
static void security_premaster_hash(const char* input, int length, const BYTE* premaster_secret, const BYTE* client_random, const BYTE* server_random, BYTE* output)
{
/* PremasterHash(Input) = SaltedHash(PremasterSecret, Input, ClientRandom, ServerRandom) */
security_salted_hash(premaster_secret, (BYTE*)input, length, client_random, server_random, output);
}
void security_master_secret(BYTE* premaster_secret, BYTE* client_random, BYTE* server_random, BYTE* output)
void security_master_secret(const BYTE* premaster_secret, const BYTE* client_random,
const BYTE* server_random, BYTE* output)
{
/* MasterSecret = PremasterHash('A') + PremasterHash('BB') + PremasterHash('CCC') */
security_premaster_hash("A", 1, premaster_secret, client_random, server_random, &output[0]);
@ -155,13 +157,15 @@ void security_master_secret(BYTE* premaster_secret, BYTE* client_random, BYTE* s
security_premaster_hash("CCC", 3, premaster_secret, client_random, server_random, &output[32]);
}
static void security_master_hash(char* input, int length, BYTE* master_secret, BYTE* client_random, BYTE* server_random, BYTE* output)
static void security_master_hash(const char* input, int length, const BYTE* master_secret,
const BYTE* client_random, const BYTE* server_random, BYTE* output)
{
/* MasterHash(Input) = SaltedHash(MasterSecret, Input, ServerRandom, ClientRandom) */
security_salted_hash(master_secret, (BYTE*)input, length, server_random, client_random, output);
security_salted_hash(master_secret, (const BYTE*)input, length, server_random, client_random, output);
}
void security_session_key_blob(BYTE* master_secret, BYTE* client_random, BYTE* server_random, BYTE* output)
void security_session_key_blob(const BYTE* master_secret, const BYTE* client_random,
const BYTE* server_random, BYTE* output)
{
/* MasterHash = MasterHash('A') + MasterHash('BB') + MasterHash('CCC') */
security_master_hash("A", 1, master_secret, client_random, server_random, &output[0]);
@ -169,13 +173,14 @@ void security_session_key_blob(BYTE* master_secret, BYTE* client_random, BYTE* s
security_master_hash("CCC", 3, master_secret, client_random, server_random, &output[32]);
}
void security_mac_salt_key(BYTE* session_key_blob, BYTE* client_random, BYTE* server_random, BYTE* output)
void security_mac_salt_key(const BYTE* session_key_blob, const BYTE* client_random,
const BYTE* server_random, BYTE* output)
{
/* MacSaltKey = First128Bits(SessionKeyBlob) */
memcpy(output, session_key_blob, 16);
}
void security_md5_16_32_32(BYTE* in0, BYTE* in1, BYTE* in2, BYTE* output)
void security_md5_16_32_32(const BYTE* in0, const BYTE* in1, const BYTE* in2, BYTE* output)
{
CryptoMd5 md5;
@ -186,7 +191,8 @@ void security_md5_16_32_32(BYTE* in0, BYTE* in1, BYTE* in2, BYTE* output)
crypto_md5_final(md5, output);
}
void security_licensing_encryption_key(BYTE* session_key_blob, BYTE* client_random, BYTE* server_random, BYTE* output)
void security_licensing_encryption_key(const BYTE* session_key_blob, const BYTE* client_random,
const BYTE* server_random, BYTE* output)
{
/* LicensingEncryptionKey = MD5(Second128Bits(SessionKeyBlob) + ClientRandom + ServerRandom)) */
security_md5_16_32_32(&session_key_blob[16], client_random, server_random, output);
@ -200,7 +206,8 @@ void security_UINT32_le(BYTE* output, UINT32 value)
output[3] = (value >> 24) & 0xFF;
}
void security_mac_data(BYTE* mac_salt_key, BYTE* data, UINT32 length, BYTE* output)
void security_mac_data(const BYTE* mac_salt_key, const BYTE* data, UINT32 length,
BYTE* output)
{
CryptoMd5 md5;
CryptoSha1 sha1;
@ -227,7 +234,7 @@ void security_mac_data(BYTE* mac_salt_key, BYTE* data, UINT32 length, BYTE* outp
crypto_md5_final(md5, output);
}
void security_mac_signature(rdpRdp *rdp, BYTE* data, UINT32 length, BYTE* output)
void security_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BYTE* output)
{
CryptoMd5 md5;
CryptoSha1 sha1;
@ -255,7 +262,8 @@ void security_mac_signature(rdpRdp *rdp, BYTE* data, UINT32 length, BYTE* output
memcpy(output, md5_digest, 8);
}
void security_salted_mac_signature(rdpRdp *rdp, BYTE* data, UINT32 length, BOOL encryption, BYTE* output)
void security_salted_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length,
BOOL encryption, BYTE* output)
{
CryptoMd5 md5;
CryptoSha1 sha1;
@ -298,14 +306,16 @@ void security_salted_mac_signature(rdpRdp *rdp, BYTE* data, UINT32 length, BOOL
memcpy(output, md5_digest, 8);
}
static void security_A(BYTE* master_secret, BYTE* client_random, BYTE* server_random, BYTE* output)
static void security_A(BYTE* master_secret, const BYTE* client_random, BYTE* server_random,
BYTE* output)
{
security_premaster_hash("A", 1, master_secret, client_random, server_random, &output[0]);
security_premaster_hash("BB", 2, master_secret, client_random, server_random, &output[16]);
security_premaster_hash("CCC", 3, master_secret, client_random, server_random, &output[32]);
}
static void security_X(BYTE* master_secret, BYTE* client_random, BYTE* server_random, BYTE* output)
static void security_X(BYTE* master_secret, const BYTE* client_random, BYTE* server_random,
BYTE* output)
{
security_premaster_hash("X", 1, master_secret, client_random, server_random, &output[0]);
security_premaster_hash("YY", 2, master_secret, client_random, server_random, &output[16]);
@ -345,7 +355,7 @@ static void fips_expand_key_bits(BYTE* in, BYTE* out)
out[i] = fips_oddparity_table[fips_reverse_table[out[i]]];
}
BOOL security_establish_keys(BYTE* client_random, rdpRdp* rdp)
BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp)
{
BYTE pre_master_secret[48];
BYTE master_secret[48];
@ -495,7 +505,7 @@ BOOL security_decrypt(BYTE* data, int length, rdpRdp* rdp)
return TRUE;
}
void security_hmac_signature(BYTE* data, int length, BYTE* output, rdpRdp* rdp)
void security_hmac_signature(const BYTE* data, int length, BYTE* output, rdpRdp* rdp)
{
BYTE buf[20];
BYTE use_count_le[4];
@ -523,7 +533,7 @@ BOOL security_fips_decrypt(BYTE* data, int length, rdpRdp* rdp)
return TRUE;
}
BOOL security_fips_check_signature(BYTE* data, int length, BYTE* sig, rdpRdp* rdp)
BOOL security_fips_check_signature(const BYTE* data, int length, const BYTE* sig, rdpRdp* rdp)
{
BYTE buf[20];
BYTE use_count_le[4];

View File

@ -26,22 +26,22 @@
#include <freerdp/freerdp.h>
#include <freerdp/utils/stream.h>
void security_master_secret(BYTE* premaster_secret, BYTE* client_random, BYTE* server_random, BYTE* output);
void security_session_key_blob(BYTE* master_secret, BYTE* client_random, BYTE* server_random, BYTE* output);
void security_mac_salt_key(BYTE* session_key_blob, BYTE* client_random, BYTE* server_random, BYTE* output);
void security_licensing_encryption_key(BYTE* session_key_blob, BYTE* client_random, BYTE* server_random, BYTE* output);
void security_mac_data(BYTE* mac_salt_key, BYTE* data, UINT32 length, BYTE* output);
void security_master_secret(const BYTE* premaster_secret, const BYTE* client_random, const BYTE* server_random, BYTE* output);
void security_session_key_blob(const BYTE* master_secret, const BYTE* client_random, const BYTE* server_random, BYTE* output);
void security_mac_salt_key(const BYTE* session_key_blob, const BYTE* client_random, const BYTE* server_random, BYTE* output);
void security_licensing_encryption_key(const BYTE* session_key_blob, const BYTE* client_random, const BYTE* server_random, BYTE* output);
void security_mac_data(const BYTE* mac_salt_key, const BYTE* data, UINT32 length, BYTE* output);
void security_mac_signature(rdpRdp *rdp, BYTE* data, UINT32 length, BYTE* output);
void security_salted_mac_signature(rdpRdp *rdp, BYTE* data, UINT32 length, BOOL encryption, BYTE* output);
BOOL security_establish_keys(BYTE* client_random, rdpRdp* rdp);
void security_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BYTE* output);
void security_salted_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BOOL encryption, BYTE* output);
BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp);
BOOL security_encrypt(BYTE* data, int length, rdpRdp* rdp);
BOOL security_decrypt(BYTE* data, int length, rdpRdp* rdp);
void security_hmac_signature(BYTE* data, int length, BYTE* output, rdpRdp* rdp);
void security_hmac_signature(const BYTE* data, int length, BYTE* output, rdpRdp* rdp);
BOOL security_fips_encrypt(BYTE* data, int length, rdpRdp* rdp);
BOOL security_fips_decrypt(BYTE* data, int length, rdpRdp* rdp);
BOOL security_fips_check_signature(BYTE* data, int length, BYTE* sig, rdpRdp* rdp);
BOOL security_fips_check_signature(const BYTE* data, int length, const BYTE* sig, rdpRdp* rdp);
#endif /* __SECURITY_H */

View File

@ -23,25 +23,33 @@
#include <freerdp/crypto/ber.h>
void ber_read_length(STREAM* s, int* length)
BOOL ber_read_length(STREAM* s, int* length)
{
BYTE byte;
if(stream_get_left(s) < 1)
return FALSE;
stream_read_BYTE(s, byte);
if (byte & 0x80)
{
byte &= ~(0x80);
if(stream_get_left(s) < byte)
return FALSE;
if (byte == 1)
stream_read_BYTE(s, *length);
if (byte == 2)
stream_read_UINT16_be(s, *length);
else
return FALSE;
}
else
{
*length = byte;
}
return TRUE;
}
/**
@ -92,6 +100,8 @@ BOOL ber_read_universal_tag(STREAM* s, BYTE tag, BOOL pc)
{
BYTE byte;
if(stream_get_left(s) < 1)
return FALSE;
stream_read_BYTE(s, byte);
if (byte != (BER_CLASS_UNIV | BER_PC(pc) | (BER_TAG_MASK & tag)))
@ -125,26 +135,32 @@ BOOL ber_read_application_tag(STREAM* s, BYTE tag, int* length)
if (tag > 30)
{
if(stream_get_left(s) < 1)
return FALSE;
stream_read_BYTE(s, byte);
if (byte != ((BER_CLASS_APPL | BER_CONSTRUCT) | BER_TAG_MASK))
return FALSE;
if(stream_get_left(s) < 1)
return FALSE;
stream_read_BYTE(s, byte);
if (byte != tag)
return FALSE;
ber_read_length(s, length);
return ber_read_length(s, length);
}
else
{
if(stream_get_left(s) < 1)
return FALSE;
stream_read_BYTE(s, byte);
if (byte != ((BER_CLASS_APPL | BER_CONSTRUCT) | (BER_TAG_MASK & tag)))
return FALSE;
ber_read_length(s, length);
return ber_read_length(s, length);
}
return TRUE;
@ -176,6 +192,8 @@ BOOL ber_read_contextual_tag(STREAM* s, BYTE tag, int* length, BOOL pc)
{
BYTE byte;
if(stream_get_left(s) < 1)
return FALSE;
stream_read_BYTE(s, byte);
if (byte != ((BER_CLASS_CTXT | BER_PC(pc)) | (BER_TAG_MASK & tag)))
@ -184,9 +202,7 @@ BOOL ber_read_contextual_tag(STREAM* s, BYTE tag, int* length, BOOL pc)
return FALSE;
}
ber_read_length(s, length);
return TRUE;
return ber_read_length(s, length);
}
int ber_write_contextual_tag(STREAM* s, BYTE tag, int length, BOOL pc)
@ -204,14 +220,14 @@ BOOL ber_read_sequence_tag(STREAM* s, int* length)
{
BYTE byte;
if(stream_get_left(s) < 1)
return FALSE;
stream_read_BYTE(s, byte);
if (byte != ((BER_CLASS_UNIV | BER_CONSTRUCT) | (BER_TAG_SEQUENCE_OF)))
return FALSE;
ber_read_length(s, length);
return TRUE;
return ber_read_length(s, length);
}
/**
@ -240,14 +256,15 @@ BOOL ber_read_enumerated(STREAM* s, BYTE* enumerated, BYTE count)
{
int length;
ber_read_universal_tag(s, BER_TAG_ENUMERATED, FALSE);
ber_read_length(s, &length);
if (length == 1)
stream_read_BYTE(s, *enumerated);
else
if(!ber_read_universal_tag(s, BER_TAG_ENUMERATED, FALSE) ||
!ber_read_length(s, &length))
return FALSE;
if (length != 1 || stream_get_left(s) < 1)
return FALSE;
stream_read_BYTE(s, *enumerated);
/* check that enumerated value falls within expected range */
if (*enumerated + 1 > count)
return FALSE;
@ -264,10 +281,13 @@ void ber_write_enumerated(STREAM* s, BYTE enumerated, BYTE count)
BOOL ber_read_bit_string(STREAM* s, int* length, BYTE* padding)
{
ber_read_universal_tag(s, BER_TAG_BIT_STRING, FALSE);
ber_read_length(s, length);
stream_read_BYTE(s, *padding);
if(!ber_read_universal_tag(s, BER_TAG_BIT_STRING, FALSE) ||
!ber_read_length(s, length))
return FALSE;
if(stream_get_left(s) < 1)
return FALSE;
stream_read_BYTE(s, *padding);
return TRUE;
}
@ -287,9 +307,9 @@ void ber_write_octet_string(STREAM* s, const BYTE* oct_str, int length)
BOOL ber_read_octet_string_tag(STREAM* s, int* length)
{
ber_read_universal_tag(s, BER_TAG_OCTET_STRING, FALSE);
ber_read_length(s, length);
return TRUE;
return
ber_read_universal_tag(s, BER_TAG_OCTET_STRING, FALSE) &&
ber_read_length(s, length);
}
int ber_write_octet_string_tag(STREAM* s, int length)
@ -315,11 +335,13 @@ BOOL ber_read_BOOL(STREAM* s, BOOL* value)
int length;
BYTE v;
if (!ber_read_universal_tag(s, BER_TAG_BOOLEAN, FALSE))
if (!ber_read_universal_tag(s, BER_TAG_BOOLEAN, FALSE) ||
!ber_read_length(s, &length))
return FALSE;
ber_read_length(s, &length);
if (length != 1)
if (length != 1 || stream_get_left(s) < 1)
return FALSE;
stream_read_BYTE(s, v);
*value = (v ? TRUE : FALSE);
return TRUE;
@ -342,11 +364,16 @@ BOOL ber_read_integer(STREAM* s, UINT32* value)
{
int length;
ber_read_universal_tag(s, BER_TAG_INTEGER, FALSE);
ber_read_length(s, &length);
if(!ber_read_universal_tag(s, BER_TAG_INTEGER, FALSE) ||
!ber_read_length(s, &length) ||
stream_get_left(s) < length)
return FALSE;
if (value == NULL)
{
// even if we don't care the integer value, check the announced size
if(length < 1 || length > 4)
return FALSE;
stream_seek(s, length);
return TRUE;
}
@ -429,7 +456,7 @@ int ber_skip_integer(UINT32 value)
BOOL ber_read_integer_length(STREAM* s, int* length)
{
ber_read_universal_tag(s, BER_TAG_INTEGER, FALSE);
ber_read_length(s, length);
return TRUE;
return
ber_read_universal_tag(s, BER_TAG_INTEGER, FALSE) &&
ber_read_length(s, length);
}

View File

@ -46,9 +46,13 @@ void rail_unicode_string_free(RAIL_UNICODE_STRING* unicode_string)
free(unicode_string->string);
}
void rail_read_unicode_string(STREAM* s, RAIL_UNICODE_STRING* unicode_string)
BOOL rail_read_unicode_string(STREAM* s, RAIL_UNICODE_STRING* unicode_string)
{
if(stream_get_left(s) < 2)
return FALSE;
stream_read_UINT16(s, unicode_string->length); /* cbString (2 bytes) */
if(stream_get_left(s) < unicode_string->length)
return FALSE;
if (unicode_string->string == NULL)
unicode_string->string = (BYTE*) malloc(unicode_string->length);
@ -56,6 +60,7 @@ void rail_read_unicode_string(STREAM* s, RAIL_UNICODE_STRING* unicode_string)
unicode_string->string = (BYTE*) realloc(unicode_string->string, unicode_string->length);
stream_read(s, unicode_string->string, unicode_string->length);
return TRUE;
}
void rail_write_unicode_string(STREAM* s, RAIL_UNICODE_STRING* unicode_string)

View File

@ -29,13 +29,18 @@
#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)