/* ConnectData */
if (!per_read_choice(s, &choice))
return FALSE;
+
if (!per_read_object_identifier(s, t124_02_98_oid))
return FALSE;
/* ConnectGCCPDU */
if (!per_read_choice(s, &choice))
return FALSE;
+
if (!per_read_selection(s, &selection))
return FALSE;
/* ConferenceCreateRequest::conferenceName */
if (!per_read_numeric_string(s, 1)) /* ConferenceName::numeric */
return FALSE;
+
if (!per_read_padding(s, 1)) /* padding */
return FALSE;
/* UserData (SET OF SEQUENCE) */
- if (!per_read_number_of_sets(s, &number) || number != 1) /* one set of UserData */
+ if (!per_read_number_of_sets(s, &number)
+ || number != 1) /* one set of UserData */
return FALSE;
- if (!per_read_choice(s, &choice) || choice != 0xC0) /* UserData::value present + select h221NonStandard (1) */
+
+ if (!per_read_choice(s, &choice)
+ || choice != 0xC0) /* UserData::value present + select h221NonStandard (1) */
return FALSE;
/* h221NonStandard */
- if (!per_read_octet_string(s, h221_cs_key, 4, 4)) /* h221NonStandard, client-to-server H.221 key, "Duca" */
+ if (!per_read_octet_string(s, h221_cs_key, 4,
+ 4)) /* h221NonStandard, client-to-server H.221 key, "Duca" */
return FALSE;
/* userData::value (OCTET_STRING) */
if (!per_read_length(s, &length))
return FALSE;
+
if (Stream_GetRemainingLength(s) < length)
return FALSE;
+
if (!gcc_read_client_data_blocks(s, mcs, length))
return FALSE;
void gcc_write_conference_create_request(wStream* s, wStream* userData)
{
/* ConnectData */
- per_write_choice(s, 0); /* From Key select object (0) of type OBJECT_IDENTIFIER */
- per_write_object_identifier(s, t124_02_98_oid); /* ITU-T T.124 (02/98) OBJECT_IDENTIFIER */
-
+ per_write_choice(s,
+ 0); /* From Key select object (0) of type OBJECT_IDENTIFIER */
+ per_write_object_identifier(s,
+ t124_02_98_oid); /* ITU-T T.124 (02/98) OBJECT_IDENTIFIER */
/* ConnectData::connectPDU (OCTET_STRING) */
per_write_length(s, Stream_GetPosition(userData) + 14); /* connectPDU length */
-
/* ConnectGCCPDU */
- per_write_choice(s, 0); /* From ConnectGCCPDU select conferenceCreateRequest (0) of type ConferenceCreateRequest */
- per_write_selection(s, 0x08); /* select optional userData from ConferenceCreateRequest */
-
+ per_write_choice(s,
+ 0); /* From ConnectGCCPDU select conferenceCreateRequest (0) of type ConferenceCreateRequest */
+ per_write_selection(s,
+ 0x08); /* select optional userData from ConferenceCreateRequest */
/* ConferenceCreateRequest::conferenceName */
per_write_numeric_string(s, (BYTE*)"1", 1, 1); /* ConferenceName::numeric */
per_write_padding(s, 1); /* padding */
-
/* UserData (SET OF SEQUENCE) */
per_write_number_of_sets(s, 1); /* one set of UserData */
- per_write_choice(s, 0xC0); /* UserData::value present + select h221NonStandard (1) */
-
+ per_write_choice(s,
+ 0xC0); /* UserData::value present + select h221NonStandard (1) */
/* h221NonStandard */
- per_write_octet_string(s, h221_cs_key, 4, 4); /* h221NonStandard, client-to-server H.221 key, "Duca" */
-
+ per_write_octet_string(s, h221_cs_key, 4,
+ 4); /* h221NonStandard, client-to-server H.221 key, "Duca" */
/* userData::value (OCTET_STRING) */
- per_write_octet_string(s, Stream_Buffer(userData), Stream_GetPosition(userData), 0); /* array of client data blocks */
+ per_write_octet_string(s, Stream_Buffer(userData), Stream_GetPosition(userData),
+ 0); /* array of client data blocks */
}
BOOL gcc_read_conference_create_response(wStream* s, rdpMcs* mcs)
/* ConnectData */
if (!per_read_choice(s, &choice) ||
- !per_read_object_identifier(s, t124_02_98_oid))
+ !per_read_object_identifier(s, t124_02_98_oid))
return FALSE;
/* ConnectData::connectPDU (OCTET_STRING) */
return FALSE;
/* h221NonStandard */
- if (!per_read_octet_string(s, h221_sc_key, 4, 4)) /* h221NonStandard, server-to-client H.221 key, "McDn" */
+ if (!per_read_octet_string(s, h221_sc_key, 4,
+ 4)) /* h221NonStandard, server-to-client H.221 key, "McDn" */
return FALSE;
/* userData (OCTET_STRING) */
if (!gcc_read_server_data_blocks(s, mcs, length))
{
- WLog_ERR(TAG, "gcc_read_conference_create_response: gcc_read_server_data_blocks failed");
+ WLog_ERR(TAG,
+ "gcc_read_conference_create_response: gcc_read_server_data_blocks failed");
return FALSE;
}
/* ConnectData */
per_write_choice(s, 0);
per_write_object_identifier(s, t124_02_98_oid);
-
/* ConnectData::connectPDU (OCTET_STRING) */
/* This length MUST be ignored by the client according to [MS-RDPBCGR] */
per_write_length(s, 0x2A);
-
/* ConnectGCCPDU */
per_write_choice(s, 0x14);
-
/* ConferenceCreateResponse::nodeID (UserID) */
per_write_integer16(s, 0x79F3, 1001);
-
/* ConferenceCreateResponse::tag (INTEGER) */
per_write_integer(s, 1);
-
/* ConferenceCreateResponse::result (ENUMERATED) */
per_write_enumerated(s, 0, MCS_Result_enum_length);
-
/* number of UserData sets */
per_write_number_of_sets(s, 1);
-
/* UserData::value present + select h221NonStandard (1) */
per_write_choice(s, 0xC0);
-
/* h221NonStandard */
- per_write_octet_string(s, h221_sc_key, 4, 4); /* h221NonStandard, server-to-client H.221 key, "McDn" */
-
+ per_write_octet_string(s, h221_sc_key, 4,
+ 4); /* h221NonStandard, server-to-client H.221 key, "McDn" */
/* userData (OCTET_STRING) */
- per_write_octet_string(s, Stream_Buffer(userData), Stream_GetPosition(userData), 0); /* array of server data blocks */
+ per_write_octet_string(s, Stream_Buffer(userData), Stream_GetPosition(userData),
+ 0); /* array of server data blocks */
}
BOOL gcc_read_client_data_blocks(wStream* s, rdpMcs* mcs, int length)
if (!gcc_read_user_data_header(s, &type, &blockLength))
return FALSE;
- if (Stream_GetRemainingLength(s) < (size_t) (blockLength - 4))
+ if (Stream_GetRemainingLength(s) < (size_t)(blockLength - 4))
return FALSE;
switch (type)
case CS_CORE:
if (!gcc_read_client_core_data(s, mcs, blockLength - 4))
return FALSE;
+
break;
case CS_SECURITY:
if (!gcc_read_client_security_data(s, mcs, blockLength - 4))
return FALSE;
+
break;
case CS_NET:
if (!gcc_read_client_network_data(s, mcs, blockLength - 4))
return FALSE;
+
break;
case CS_CLUSTER:
if (!gcc_read_client_cluster_data(s, mcs, blockLength - 4))
return FALSE;
+
break;
case CS_MONITOR:
if (!gcc_read_client_monitor_data(s, mcs, blockLength - 4))
return FALSE;
+
break;
case CS_MCS_MSGCHANNEL:
if (!gcc_read_client_message_channel_data(s, mcs, blockLength - 4))
return FALSE;
+
break;
case CS_MONITOR_EX:
if (!gcc_read_client_monitor_extended_data(s, mcs, blockLength - 4))
return FALSE;
+
break;
case 0xC009:
case CS_MULTITRANSPORT:
if (!gcc_read_client_multitransport_channel_data(s, mcs, blockLength - 4))
return FALSE;
+
break;
default:
if (endPos != (begPos + blockLength))
{
- WLog_ERR(TAG, "Error parsing GCC client data block 0x%04X: Actual Offset: %d Expected Offset: %d",
- type, endPos, begPos + blockLength);
+ WLog_ERR(TAG,
+ "Error parsing GCC client data block 0x%04X: Actual Offset: %d Expected Offset: %d",
+ type, endPos, begPos + blockLength);
}
length -= blockLength;
void gcc_write_client_data_blocks(wStream* s, rdpMcs* mcs)
{
rdpSettings* settings = mcs->settings;
-
gcc_write_client_core_data(s, mcs);
gcc_write_client_cluster_data(s, mcs);
gcc_write_client_security_data(s, mcs);
{
if (settings->UseMultimon && !settings->SpanMonitors)
{
- WLog_ERR(TAG, "WARNING: true multi monitor support was not advertised by server!");
+ WLog_ERR(TAG,
+ "WARNING: true multi monitor support was not advertised by server!");
if (settings->ForceMultimon)
{
- WLog_ERR(TAG, "Sending multi monitor information anyway (may break connectivity!)");
+ WLog_ERR(TAG,
+ "Sending multi monitor information anyway (may break connectivity!)");
gcc_write_client_monitor_data(s, mcs);
gcc_write_client_monitor_extended_data(s, mcs);
}
else
{
- WLog_ERR(TAG, "Use /multimon:force to force sending multi monitor information");
+ WLog_ERR(TAG,
+ "Use /multimon:force to force sending multi monitor information");
}
}
}
WLog_ERR(TAG, "gcc_read_server_data_blocks: gcc_read_server_core_data failed");
return FALSE;
}
+
break;
case SC_SECURITY:
if (!gcc_read_server_security_data(s, mcs))
{
- WLog_ERR(TAG, "gcc_read_server_data_blocks: gcc_read_server_security_data failed");
+ WLog_ERR(TAG,
+ "gcc_read_server_data_blocks: gcc_read_server_security_data failed");
return FALSE;
}
+
break;
case SC_NET:
if (!gcc_read_server_network_data(s, mcs))
{
- WLog_ERR(TAG, "gcc_read_server_data_blocks: gcc_read_server_network_data failed");
+ WLog_ERR(TAG,
+ "gcc_read_server_data_blocks: gcc_read_server_network_data failed");
return FALSE;
}
+
break;
case SC_MCS_MSGCHANNEL:
if (!gcc_read_server_message_channel_data(s, mcs))
{
- WLog_ERR(TAG, "gcc_read_server_data_blocks: gcc_read_server_message_channel_data failed");
+ WLog_ERR(TAG,
+ "gcc_read_server_data_blocks: gcc_read_server_message_channel_data failed");
return FALSE;
}
+
break;
case SC_MULTITRANSPORT:
if (!gcc_read_server_multitransport_channel_data(s, mcs))
{
- WLog_ERR(TAG, "gcc_read_server_data_blocks: gcc_read_server_multitransport_channel_data failed");
+ WLog_ERR(TAG,
+ "gcc_read_server_data_blocks: gcc_read_server_multitransport_channel_data failed");
return FALSE;
}
+
break;
default:
WLog_ERR(TAG, "gcc_read_server_data_blocks: ignoring type=%hu", type);
break;
}
+
offset += blockLength;
Stream_SetPointer(s, holdp + blockLength);
}
BOOL gcc_write_server_data_blocks(wStream* s, rdpMcs* mcs)
{
return gcc_write_server_core_data(s, mcs) && /* serverCoreData */
- gcc_write_server_network_data(s, mcs) && /* serverNetworkData */
- gcc_write_server_security_data(s, mcs) && /* serverSecurityData */
- gcc_write_server_message_channel_data(s, mcs); /* serverMessageChannelData */
-
+ gcc_write_server_network_data(s, mcs) && /* serverNetworkData */
+ gcc_write_server_security_data(s, mcs) && /* serverSecurityData */
+ gcc_write_server_message_channel_data(s, mcs); /* serverMessageChannelData */
/* TODO: Send these GCC data blocks only when the client sent them */
//gcc_write_server_multitransport_channel_data(s, settings); /* serverMultitransportChannelData */
}
Stream_Read_UINT16(s, *type); /* type */
Stream_Read_UINT16(s, *length); /* length */
- if (Stream_GetRemainingLength(s) < (size_t) (*length - 4))
+ if (Stream_GetRemainingLength(s) < (size_t)(*length - 4))
return FALSE;
return TRUE;
Stream_Read_UINT32(s, version); /* version (4 bytes) */
settings->RdpVersion = (version == RDP_VERSION_4 ? 4 : 7);
-
Stream_Read_UINT16(s, settings->DesktopWidth); /* DesktopWidth (2 bytes) */
Stream_Read_UINT16(s, settings->DesktopHeight); /* DesktopHeight (2 bytes) */
Stream_Read_UINT16(s, colorDepth); /* ColorDepth (2 bytes) */
/* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 32 / 2,
- &str, 0, NULL, NULL) < 1)
+ &str, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert client host name");
return FALSE;
}
+
Stream_Seek(s, 32);
free(settings->ClientHostname);
settings->ClientHostname = str;
str = NULL;
-
Stream_Read_UINT32(s, settings->KeyboardType); /* KeyboardType (4 bytes) */
- Stream_Read_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType (4 bytes) */
- Stream_Read_UINT32(s, settings->KeyboardFunctionKey); /* KeyboardFunctionKey (4 bytes) */
-
+ Stream_Read_UINT32(s,
+ settings->KeyboardSubType); /* KeyboardSubType (4 bytes) */
+ Stream_Read_UINT32(s,
+ settings->KeyboardFunctionKey); /* KeyboardFunctionKey (4 bytes) */
Stream_Seek(s, 64); /* imeFileName (64 bytes) */
-
blockLength -= 128;
/**
{
if (blockLength < 2)
break;
+
Stream_Read_UINT16(s, postBeta2ColorDepth); /* postBeta2ColorDepth (2 bytes) */
blockLength -= 2;
if (blockLength < 2)
break;
+
Stream_Seek_UINT16(s); /* clientProductID (2 bytes) */
blockLength -= 2;
if (blockLength < 4)
break;
+
Stream_Seek_UINT32(s); /* serialNumber (4 bytes) */
blockLength -= 4;
if (blockLength < 2)
break;
+
Stream_Read_UINT16(s, highColorDepth); /* highColorDepth (2 bytes) */
blockLength -= 2;
if (blockLength < 2)
break;
- Stream_Read_UINT16(s, supportedColorDepths); /* supportedColorDepths (2 bytes) */
+
+ Stream_Read_UINT16(s,
+ supportedColorDepths); /* supportedColorDepths (2 bytes) */
blockLength -= 2;
if (blockLength < 2)
break;
- Stream_Read_UINT16(s, earlyCapabilityFlags); /* earlyCapabilityFlags (2 bytes) */
+
+ Stream_Read_UINT16(s,
+ earlyCapabilityFlags); /* earlyCapabilityFlags (2 bytes) */
settings->EarlyCapabilityFlags = (UINT32) earlyCapabilityFlags;
blockLength -= 2;
break;
if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2,
- &str, 0, NULL, NULL) < 1)
+ &str, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert the client product identifier");
return FALSE;
}
+
Stream_Seek(s, 64); /* clientDigProductId (64 bytes) */
free(settings->ClientProductId);
settings->ClientProductId = str;
if (blockLength < 1)
break;
+
Stream_Read_UINT8(s, connectionType); /* connectionType (1 byte) */
blockLength -= 1;
if (blockLength < 1)
break;
+
Stream_Seek_UINT8(s); /* pad1octet (1 byte) */
blockLength -= 1;
if (blockLength < 4)
break;
- Stream_Read_UINT32(s, serverSelectedProtocol); /* serverSelectedProtocol (4 bytes) */
+
+ Stream_Read_UINT32(s,
+ serverSelectedProtocol); /* serverSelectedProtocol (4 bytes) */
blockLength -= 4;
if (blockLength < 4)
break;
- Stream_Read_UINT32(s, settings->DesktopPhysicalWidth); /* desktopPhysicalWidth (4 bytes) */
+
+ Stream_Read_UINT32(s,
+ settings->DesktopPhysicalWidth); /* desktopPhysicalWidth (4 bytes) */
blockLength -= 4;
if (blockLength < 4)
break;
- Stream_Read_UINT32(s, settings->DesktopPhysicalHeight); /* desktopPhysicalHeight (4 bytes) */
+
+ Stream_Read_UINT32(s,
+ settings->DesktopPhysicalHeight); /* desktopPhysicalHeight (4 bytes) */
blockLength -= 4;
if (blockLength < 2)
break;
- Stream_Read_UINT16(s, settings->DesktopOrientation); /* desktopOrientation (2 bytes) */
+
+ Stream_Read_UINT16(s,
+ settings->DesktopOrientation); /* desktopOrientation (2 bytes) */
blockLength -= 2;
if (blockLength < 4)
break;
- Stream_Read_UINT32(s, settings->DesktopScaleFactor); /* desktopScaleFactor (4 bytes) */
+
+ Stream_Read_UINT32(s,
+ settings->DesktopScaleFactor); /* desktopScaleFactor (4 bytes) */
blockLength -= 4;
if (blockLength < 4)
break;
- Stream_Read_UINT32(s, settings->DeviceScaleFactor); /* deviceScaleFactor (4 bytes) */
+
+ Stream_Read_UINT32(s,
+ settings->DeviceScaleFactor); /* deviceScaleFactor (4 bytes) */
blockLength -= 4;
if (settings->SelectedProtocol != serverSelectedProtocol)
return FALSE;
- } while (0);
+ }
+ while (0);
if (highColorDepth > 0)
{
case RNS_UD_COLOR_4BPP:
clientColorDepth = 4;
break;
+
case RNS_UD_COLOR_8BPP:
clientColorDepth = 8;
break;
+
case RNS_UD_COLOR_16BPP_555:
clientColorDepth = 15;
break;
+
case RNS_UD_COLOR_16BPP_565:
clientColorDepth = 16;
break;
+
case RNS_UD_COLOR_24BPP:
clientColorDepth = 24;
break;
+
default:
return FALSE;
}
case RNS_UD_COLOR_4BPP:
clientColorDepth = 4;
break;
+
case RNS_UD_COLOR_8BPP:
clientColorDepth = 8;
break;
+
default:
return FALSE;
}
settings->ColorDepth = clientColorDepth;
if (settings->NetworkAutoDetect)
- settings->NetworkAutoDetect = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_NETWORK_AUTODETECT) ? TRUE : FALSE;
+ settings->NetworkAutoDetect = (earlyCapabilityFlags &
+ RNS_UD_CS_SUPPORT_NETWORK_AUTODETECT) ? TRUE : FALSE;
if (settings->SupportHeartbeatPdu)
- settings->SupportHeartbeatPdu = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_HEARTBEAT_PDU) ? TRUE : FALSE;
+ settings->SupportHeartbeatPdu = (earlyCapabilityFlags &
+ RNS_UD_CS_SUPPORT_HEARTBEAT_PDU) ? TRUE : FALSE;
if (settings->SupportGraphicsPipeline)
- settings->SupportGraphicsPipeline = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL) ? TRUE : FALSE;
+ settings->SupportGraphicsPipeline = (earlyCapabilityFlags &
+ RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL) ? TRUE : FALSE;
if (settings->SupportDynamicTimeZone)
- settings->SupportDynamicTimeZone = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE) ? TRUE : FALSE;
+ settings->SupportDynamicTimeZone = (earlyCapabilityFlags &
+ RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE) ? TRUE : FALSE;
if (settings->SupportMonitorLayoutPdu)
- settings->SupportMonitorLayoutPdu = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU) ? TRUE : FALSE;
+ settings->SupportMonitorLayoutPdu = (earlyCapabilityFlags &
+ RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU) ? TRUE : FALSE;
if (!(earlyCapabilityFlags & RNS_UD_CS_VALID_CONNECTION_TYPE))
connectionType = 0;
- settings->SupportErrorInfoPdu = earlyCapabilityFlags & RNS_UD_CS_SUPPORT_ERRINFO_PDU;
-
+ settings->SupportErrorInfoPdu = earlyCapabilityFlags &
+ RNS_UD_CS_SUPPORT_ERRINFO_PDU;
settings->ConnectionType = connectionType;
-
return TRUE;
}
WCHAR* clientDigProductId = NULL;
int clientDigProductIdLength;
rdpSettings* settings = mcs->settings;
-
gcc_write_user_data_header(s, CS_CORE, 234);
-
version = settings->RdpVersion >= 5 ? RDP_VERSION_5_PLUS : RDP_VERSION_4;
-
- clientNameLength = ConvertToUnicode(CP_UTF8, 0, settings->ClientHostname, -1, &clientName, 0);
- clientDigProductIdLength = ConvertToUnicode(CP_UTF8, 0, settings->ClientProductId, -1, &clientDigProductId, 0);
-
+ clientNameLength = ConvertToUnicode(CP_UTF8, 0, settings->ClientHostname, -1,
+ &clientName, 0);
+ clientDigProductIdLength = ConvertToUnicode(CP_UTF8, 0,
+ settings->ClientProductId, -1, &clientDigProductId, 0);
Stream_Write_UINT32(s, version); /* Version */
Stream_Write_UINT16(s, settings->DesktopWidth); /* DesktopWidth */
Stream_Write_UINT16(s, settings->DesktopHeight); /* DesktopHeight */
- Stream_Write_UINT16(s, RNS_UD_COLOR_8BPP); /* ColorDepth, ignored because of postBeta2ColorDepth */
- Stream_Write_UINT16(s, RNS_UD_SAS_DEL); /* SASSequence (Secure Access Sequence) */
+ Stream_Write_UINT16(s,
+ RNS_UD_COLOR_8BPP); /* ColorDepth, ignored because of postBeta2ColorDepth */
+ Stream_Write_UINT16(s,
+ RNS_UD_SAS_DEL); /* SASSequence (Secure Access Sequence) */
Stream_Write_UINT32(s, settings->KeyboardLayout); /* KeyboardLayout */
Stream_Write_UINT32(s, settings->ClientBuild); /* ClientBuild */
Stream_Write(s, clientName, (clientNameLength * 2));
Stream_Zero(s, 32 - (clientNameLength * 2));
free(clientName);
-
Stream_Write_UINT32(s, settings->KeyboardType); /* KeyboardType */
Stream_Write_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType */
Stream_Write_UINT32(s, settings->KeyboardFunctionKey); /* KeyboardFunctionKey */
-
Stream_Zero(s, 64); /* imeFileName */
-
Stream_Write_UINT16(s, RNS_UD_COLOR_8BPP); /* postBeta2ColorDepth */
Stream_Write_UINT16(s, 1); /* clientProductID */
Stream_Write_UINT32(s, 0); /* serialNumber (should be initialized to 0) */
-
highColorDepth = MIN(settings->ColorDepth, 24);
-
supportedColorDepths =
- RNS_UD_24BPP_SUPPORT |
- RNS_UD_16BPP_SUPPORT |
- RNS_UD_15BPP_SUPPORT;
-
+ RNS_UD_24BPP_SUPPORT |
+ RNS_UD_16BPP_SUPPORT |
+ RNS_UD_15BPP_SUPPORT;
earlyCapabilityFlags = RNS_UD_CS_SUPPORT_ERRINFO_PDU;
if (settings->NetworkAutoDetect)
Stream_Write_UINT16(s, highColorDepth); /* highColorDepth */
Stream_Write_UINT16(s, supportedColorDepths); /* supportedColorDepths */
-
Stream_Write_UINT16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */
/* clientDigProductId (64 bytes, null-terminated unicode, truncated to 31 characters) */
clientDigProductIdLength = 32;
clientDigProductId[clientDigProductIdLength - 1] = 0;
}
- Stream_Write(s, clientDigProductId, (clientDigProductIdLength * 2) );
- Stream_Zero(s, 64 - (clientDigProductIdLength * 2) );
- free(clientDigProductId);
+ Stream_Write(s, clientDigProductId, (clientDigProductIdLength * 2));
+ Stream_Zero(s, 64 - (clientDigProductIdLength * 2));
+ free(clientDigProductId);
Stream_Write_UINT8(s, connectionType); /* connectionType */
Stream_Write_UINT8(s, 0); /* pad1octet */
-
Stream_Write_UINT32(s, settings->SelectedProtocol); /* serverSelectedProtocol */
-
- Stream_Write_UINT32(s, settings->DesktopPhysicalWidth); /* desktopPhysicalWidth */
- Stream_Write_UINT32(s, settings->DesktopPhysicalHeight); /* desktopPhysicalHeight */
+ Stream_Write_UINT32(s,
+ settings->DesktopPhysicalWidth); /* desktopPhysicalWidth */
+ Stream_Write_UINT32(s,
+ settings->DesktopPhysicalHeight); /* desktopPhysicalHeight */
Stream_Write_UINT16(s, settings->DesktopOrientation); /* desktopOrientation */
Stream_Write_UINT32(s, settings->DesktopScaleFactor); /* desktopScaleFactor */
Stream_Write_UINT32(s, settings->DeviceScaleFactor); /* deviceScaleFactor */
return FALSE;
gcc_write_user_data_header(s, SC_CORE, 16);
-
version = settings->RdpVersion == 4 ? RDP_VERSION_4 : RDP_VERSION_5_PLUS;
if (settings->SupportDynamicTimeZone)
earlyCapabilityFlags |= RNS_UD_SC_DYNAMIC_DST_SUPPORTED;
Stream_Write_UINT32(s, version); /* version (4 bytes) */
- Stream_Write_UINT32(s, settings->RequestedProtocols); /* clientRequestedProtocols (4 bytes) */
- Stream_Write_UINT32(s, earlyCapabilityFlags); /* earlyCapabilityFlags (4 bytes) */
+ Stream_Write_UINT32(s,
+ settings->RequestedProtocols); /* clientRequestedProtocols (4 bytes) */
+ Stream_Write_UINT32(s,
+ earlyCapabilityFlags); /* earlyCapabilityFlags (4 bytes) */
return TRUE;
}
if (settings->UseRdpSecurityLayer)
{
Stream_Read_UINT32(s, settings->EncryptionMethods); /* encryptionMethods */
+
if (settings->EncryptionMethods == 0)
Stream_Read_UINT32(s, settings->EncryptionMethods); /* extEncryptionMethods */
else
{
Stream_Seek(s, 8);
}
+
return TRUE;
}
void gcc_write_client_security_data(wStream* s, rdpMcs* mcs)
{
rdpSettings* settings = mcs->settings;
-
gcc_write_user_data_header(s, CS_SECURITY, 12);
if (settings->UseRdpSecurityLayer)
case ENCRYPTION_METHOD_NONE:
WLog_DBG(TAG, "Server rdp encryption method: NONE");
break;
+
case ENCRYPTION_METHOD_40BIT:
WLog_DBG(TAG, "Server rdp encryption method: 40BIT");
break;
+
case ENCRYPTION_METHOD_56BIT:
WLog_DBG(TAG, "Server rdp encryption method: 56BIT");
break;
+
case ENCRYPTION_METHOD_128BIT:
WLog_DBG(TAG, "Server rdp encryption method: 128BIT");
break;
+
case ENCRYPTION_METHOD_FIPS:
WLog_DBG(TAG, "Server rdp encryption method: FIPS");
break;
+
default:
- WLog_ERR(TAG, "Received unknown encryption method %08X", serverEncryptionMethod);
+ WLog_ERR(TAG, "Received unknown encryption method %08X",
+ serverEncryptionMethod);
return FALSE;
}
- if (settings->UseRdpSecurityLayer && !(settings->EncryptionMethods & serverEncryptionMethod))
+ if (settings->UseRdpSecurityLayer
+ && !(settings->EncryptionMethods & serverEncryptionMethod))
{
- WLog_WARN(TAG, "Server uses non-advertised encryption method 0x%08X", serverEncryptionMethod);
+ WLog_WARN(TAG, "Server uses non-advertised encryption method 0x%08X",
+ serverEncryptionMethod);
/* FIXME: Should we return FALSE; in this case ?? */
}
{
validCryptoConfig = TRUE;
}
+
break;
+
case ENCRYPTION_LEVEL_FIPS:
if (settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
{
validCryptoConfig = TRUE;
}
+
break;
+
case ENCRYPTION_LEVEL_LOW:
case ENCRYPTION_LEVEL_HIGH:
case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE:
{
validCryptoConfig = TRUE;
}
+
break;
+
default:
- WLog_ERR(TAG, "Received unknown encryption level %08X", settings->EncryptionLevel);
+ WLog_ERR(TAG, "Received unknown encryption level %08X",
+ settings->EncryptionLevel);
}
if (!validCryptoConfig)
{
- WLog_ERR(TAG, "Received invalid cryptographic configuration (level=0x%08X method=0x%08X)",
- settings->EncryptionLevel, settings->EncryptionMethods);
+ WLog_ERR(TAG,
+ "Received invalid cryptographic configuration (level=0x%08X method=0x%08X)",
+ settings->EncryptionLevel, settings->EncryptionMethods);
return FALSE;
}
Stream_Read_UINT32(s, settings->ServerRandomLength); /* serverRandomLen */
Stream_Read_UINT32(s, settings->ServerCertificateLength); /* serverCertLen */
- if (Stream_GetRemainingLength(s) < settings->ServerRandomLength + settings->ServerCertificateLength)
+ if (Stream_GetRemainingLength(s) < settings->ServerRandomLength +
+ settings->ServerCertificateLength)
return FALSE;
- if ((settings->ServerRandomLength <= 0) || (settings->ServerCertificateLength <= 0))
+ if ((settings->ServerRandomLength <= 0)
+ || (settings->ServerCertificateLength <= 0))
return FALSE;
/* serverRandom */
settings->ServerRandom = (BYTE*) malloc(settings->ServerRandomLength);
+
if (!settings->ServerRandom)
return FALSE;
- Stream_Read(s, settings->ServerRandom, settings->ServerRandomLength);
-
+ Stream_Read(s, settings->ServerRandom, settings->ServerRandomLength);
/* serverCertificate */
settings->ServerCertificate = (BYTE*) malloc(settings->ServerCertificateLength);
+
if (!settings->ServerCertificate)
return FALSE;
- Stream_Read(s, settings->ServerCertificate, settings->ServerCertificateLength);
+ Stream_Read(s, settings->ServerCertificate, settings->ServerCertificateLength);
certificate_free(settings->RdpServerCertificate);
settings->RdpServerCertificate = certificate_new();
+
if (!settings->RdpServerCertificate)
return FALSE;
data = settings->ServerCertificate;
length = settings->ServerCertificateLength;
-
- return certificate_read_server_certificate(settings->RdpServerCertificate, data, length);
+ return certificate_read_server_certificate(settings->RdpServerCertificate, data,
+ length);
}
static const BYTE initial_signature[] =
case ENCRYPTION_LEVEL_NONE:
WLog_INFO(TAG, "Active rdp encryption level: NONE");
break;
+
case ENCRYPTION_LEVEL_FIPS:
WLog_INFO(TAG, "Active rdp encryption level: FIPS Compliant");
break;
+
case ENCRYPTION_LEVEL_HIGH:
WLog_INFO(TAG, "Active rdp encryption level: HIGH");
break;
+
case ENCRYPTION_LEVEL_LOW:
WLog_INFO(TAG, "Active rdp encryption level: LOW");
break;
+
case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE:
WLog_INFO(TAG, "Active rdp encryption level: CLIENT-COMPATIBLE");
break;
+
default:
- WLog_ERR(TAG, "Invalid server encryption level 0x%08X", settings->EncryptionLevel);
+ WLog_ERR(TAG, "Invalid server encryption level 0x%08X",
+ settings->EncryptionLevel);
WLog_ERR(TAG, "Switching to encryption level CLIENT-COMPATIBLE");
settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
}
/* The only valid method is NONE in this case */
settings->EncryptionMethods = ENCRYPTION_METHOD_NONE;
break;
+
case ENCRYPTION_LEVEL_FIPS:
+
/* The only valid method is FIPS in this case */
if (!(settings->EncryptionMethods & ENCRYPTION_METHOD_FIPS))
{
- WLog_WARN(TAG, "client does not support FIPS as required by server configuration");
+ WLog_WARN(TAG,
+ "client does not support FIPS as required by server configuration");
}
+
settings->EncryptionMethods = ENCRYPTION_METHOD_FIPS;
break;
+
case ENCRYPTION_LEVEL_HIGH:
+
/* Maximum key strength supported by the server must be used (128 bit)*/
if (!(settings->EncryptionMethods & ENCRYPTION_METHOD_128BIT))
{
- WLog_WARN(TAG, "client does not support 128 bit encryption method as required by server configuration");
+ WLog_WARN(TAG,
+ "client does not support 128 bit encryption method as required by server configuration");
}
+
settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT;
break;
+
case ENCRYPTION_LEVEL_LOW:
case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE:
+
/* Maximum key strength supported by the client must be used */
if (settings->EncryptionMethods & ENCRYPTION_METHOD_128BIT)
settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT;
WLog_WARN(TAG, "client has not announced any supported encryption methods");
settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT;
}
+
break;
+
default:
WLog_ERR(TAG, "internal error: unknown encryption level");
return FALSE;
case ENCRYPTION_METHOD_NONE:
WLog_INFO(TAG, "Selected rdp encryption method: NONE");
break;
+
case ENCRYPTION_METHOD_40BIT:
WLog_INFO(TAG, "Selected rdp encryption method: 40BIT");
break;
+
case ENCRYPTION_METHOD_56BIT:
WLog_INFO(TAG, "Selected rdp encryption method: 56BIT");
break;
+
case ENCRYPTION_METHOD_128BIT:
WLog_INFO(TAG, "Selected rdp encryption method: 128BIT");
break;
+
case ENCRYPTION_METHOD_FIPS:
WLog_INFO(TAG, "Selected rdp encryption method: FIPS");
break;
+
default:
WLog_ERR(TAG, "internal error: unknown encryption method");
return FALSE;
if (settings->EncryptionMethods != ENCRYPTION_METHOD_NONE)
{
serverRandomLen = 32;
-
keyLen = settings->RdpServerRsaKey->ModulusLength;
expLen = sizeof(settings->RdpServerRsaKey->exponent);
wPublicKeyBlobLen = 4; /* magic (RSA1) */
wPublicKeyBlobLen += expLen;
wPublicKeyBlobLen += keyLen;
wPublicKeyBlobLen += 8; /* 8 bytes of zero padding */
-
serverCertLen = 4; /* dwVersion */
serverCertLen += 4; /* dwSigAlgId */
serverCertLen += 4; /* dwKeyAlgId */
serverCertLen += 2; /* wSignatureBlobLen */
serverCertLen += sizeof(encryptedSignature); /* SignatureBlob */
serverCertLen += 8; /* 8 bytes of zero padding */
-
headerLen += sizeof(serverRandomLen);
headerLen += sizeof(serverCertLen);
headerLen += serverRandomLen;
if (!Stream_EnsureRemainingCapacity(s, headerLen + 4))
return FALSE;
- gcc_write_user_data_header(s, SC_SECURITY, headerLen);
+ gcc_write_user_data_header(s, SC_SECURITY, headerLen);
Stream_Write_UINT32(s, settings->EncryptionMethods); /* encryptionMethod */
Stream_Write_UINT32(s, settings->EncryptionLevel); /* encryptionLevel */
Stream_Write_UINT32(s, serverRandomLen); /* serverRandomLen */
Stream_Write_UINT32(s, serverCertLen); /* serverCertLen */
-
settings->ServerRandomLength = serverRandomLen;
settings->ServerRandom = (BYTE*) malloc(serverRandomLen);
winpr_RAND(settings->ServerRandom, serverRandomLen);
Stream_Write(s, settings->ServerRandom, serverRandomLen);
-
sigData = Stream_Pointer(s);
-
Stream_Write_UINT32(s, CERT_CHAIN_VERSION_1); /* dwVersion (4 bytes) */
Stream_Write_UINT32(s, SIGNATURE_ALG_RSA); /* dwSigAlgId */
Stream_Write_UINT32(s, KEY_EXCHANGE_ALG_RSA); /* dwKeyAlgId */
Stream_Write_UINT16(s, BB_RSA_KEY_BLOB); /* wPublicKeyBlobType */
-
Stream_Write_UINT16(s, wPublicKeyBlobLen); /* wPublicKeyBlobLen */
Stream_Write(s, "RSA1", 4); /* magic */
Stream_Write_UINT32(s, keyLen + 8); /* keylen */
Stream_Write_UINT32(s, keyLen * 8); /* bitlen */
Stream_Write_UINT32(s, keyLen - 1); /* datalen */
-
Stream_Write(s, settings->RdpServerRsaKey->exponent, expLen);
Stream_Write(s, settings->RdpServerRsaKey->Modulus, keyLen);
Stream_Zero(s, 8);
-
sigDataLen = Stream_Pointer(s) - sigData;
-
Stream_Write_UINT16(s, BB_RSA_SIGNATURE_BLOB); /* wSignatureBlobType */
Stream_Write_UINT16(s, sizeof(encryptedSignature) + 8); /* wSignatureBlobLen */
-
memcpy(signature, initial_signature, sizeof(initial_signature));
if (!winpr_MD5_Init(&md5))
return FALSE;
+
if (!winpr_MD5_Update(&md5, sigData, sigDataLen))
return FALSE;
+
if (!winpr_MD5_Final(&md5, signature, sizeof(signature)))
return FALSE;
crypto_rsa_private_encrypt(signature, sizeof(signature), TSSK_KEY_LENGTH,
- tssk_modulus, tssk_privateExponent, encryptedSignature);
-
+ tssk_modulus, tssk_privateExponent, encryptedSignature);
Stream_Write(s, encryptedSignature, sizeof(encryptedSignature));
Stream_Zero(s, 8);
return TRUE;
* - options: a 32-bit, unsigned integer. Channel option flags
*/
Stream_Read(s, mcs->channels[i].Name, 8); /* name (8 bytes) */
+
if (!memchr(mcs->channels[i].Name, 0, 8))
{
- WLog_ERR(TAG, "protocol violation: received a static channel name with missing null-termination");
+ WLog_ERR(TAG,
+ "protocol violation: received a static channel name with missing null-termination");
return FALSE;
}
+
Stream_Read_UINT32(s, mcs->channels[i].options); /* options (4 bytes) */
mcs->channels[i].ChannelId = mcs->baseChannelId++;
}
{
length = mcs->channelCount * 12 + 8;
gcc_write_user_data_header(s, CS_NET, length);
-
Stream_Write_UINT32(s, mcs->channelCount); /* channelCount */
/* channelDefArray */
Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */
Stream_Read_UINT16(s, channelCount); /* channelCount */
-
parsedChannelCount = channelCount;
if (channelCount != mcs->channelCount)
{
WLog_ERR(TAG, "requested %d channels, got %d instead",
- mcs->channelCount, channelCount);
+ mcs->channelCount, channelCount);
/* we ensure that the response is not bigger than the request */
BOOL gcc_write_server_network_data(wStream* s, rdpMcs* mcs)
{
UINT32 i;
- int payloadLen = 8 + mcs->channelCount * 2 + (mcs->channelCount % 2 == 1 ? 2 : 0);
+ int payloadLen = 8 + mcs->channelCount * 2 + (mcs->channelCount % 2 == 1 ? 2 :
+ 0);
if (!Stream_EnsureRemainingCapacity(s, payloadLen + 4))
return FALSE;
gcc_write_user_data_header(s, SC_NET, payloadLen);
-
Stream_Write_UINT16(s, MCS_GLOBAL_CHANNEL_ID); /* MCSChannelId */
Stream_Write_UINT16(s, mcs->channelCount); /* channelCount */
if (mcs->channelCount % 2 == 1)
Stream_Write_UINT16(s, 0);
+
return TRUE;
}
{
UINT32 flags;
rdpSettings* settings = mcs->settings;
-
gcc_write_user_data_header(s, CS_CLUSTER, 12);
-
flags = REDIRECTION_SUPPORTED | (REDIRECTION_VERSION4 << 2);
if (settings->ConsoleSession || settings->RedirectedSessionId)
if (monitorCount > settings->MonitorDefArraySize)
{
- WLog_ERR(TAG, "too many announced monitors(%d), clamping to %d", monitorCount, settings->MonitorDefArraySize);
+ WLog_ERR(TAG, "too many announced monitors(%d), clamping to %d", monitorCount,
+ settings->MonitorDefArraySize);
monitorCount = settings->MonitorDefArraySize;
}
Stream_Read_UINT32(s, right); /* right */
Stream_Read_UINT32(s, bottom); /* bottom */
Stream_Read_UINT32(s, flags); /* flags */
-
settings->MonitorDefArray[index].x = left;
settings->MonitorDefArray[index].y = top;
settings->MonitorDefArray[index].width = right - left + 1;
{
length = (20 * settings->MonitorCount) + 12;
gcc_write_user_data_header(s, CS_MONITOR, length);
-
Stream_Write_UINT32(s, 0); /* flags */
Stream_Write_UINT32(s, settings->MonitorCount); /* monitorCount */
left = settings->MonitorDefArray[i].x;
top = settings->MonitorDefArray[i].y;
right = settings->MonitorDefArray[i].x + settings->MonitorDefArray[i].width - 1;
- bottom = settings->MonitorDefArray[i].y + settings->MonitorDefArray[i].height - 1;
+ bottom = settings->MonitorDefArray[i].y + settings->MonitorDefArray[i].height -
+ 1;
flags = settings->MonitorDefArray[i].is_primary ? MONITOR_PRIMARY : 0;
-
Stream_Write_UINT32(s, left); /* left */
Stream_Write_UINT32(s, top); /* top */
Stream_Write_UINT32(s, right); /* right */
}
}
-BOOL gcc_read_client_monitor_extended_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
+BOOL gcc_read_client_monitor_extended_data(wStream* s, rdpMcs* mcs,
+ UINT16 blockLength)
{
UINT32 index;
UINT32 flags;
for (index = 0; index < monitorCount; index++)
{
- Stream_Read_UINT32(s, settings->MonitorDefArray[index].attributes.physicalWidth); /* physicalWidth */
- Stream_Read_UINT32(s, settings->MonitorDefArray[index].attributes.physicalHeight); /* physicalHeight */
- Stream_Read_UINT32(s, settings->MonitorDefArray[index].attributes.orientation); /* orientation */
- Stream_Read_UINT32(s, settings->MonitorDefArray[index].attributes.desktopScaleFactor); /* desktopScaleFactor */
- Stream_Read_UINT32(s, settings->MonitorDefArray[index].attributes.deviceScaleFactor); /* deviceScaleFactor */
+ Stream_Read_UINT32(s,
+ settings->MonitorDefArray[index].attributes.physicalWidth); /* physicalWidth */
+ Stream_Read_UINT32(s,
+ settings->MonitorDefArray[index].attributes.physicalHeight); /* physicalHeight */
+ Stream_Read_UINT32(s,
+ settings->MonitorDefArray[index].attributes.orientation); /* orientation */
+ Stream_Read_UINT32(s,
+ settings->MonitorDefArray[index].attributes.desktopScaleFactor); /* desktopScaleFactor */
+ Stream_Read_UINT32(s,
+ settings->MonitorDefArray[index].attributes.deviceScaleFactor); /* deviceScaleFactor */
}
return TRUE;
{
length = (20 * settings->MonitorCount) + 16;
gcc_write_user_data_header(s, CS_MONITOR_EX, length);
-
Stream_Write_UINT32(s, 0); /* flags */
Stream_Write_UINT32(s, 20); /* monitorAttributeSize */
Stream_Write_UINT32(s, settings->MonitorCount); /* monitorCount */
for (i = 0; i < settings->MonitorCount; i++)
{
- Stream_Write_UINT32(s, settings->MonitorDefArray[i].attributes.physicalWidth); /* physicalWidth */
- Stream_Write_UINT32(s, settings->MonitorDefArray[i].attributes.physicalHeight); /* physicalHeight */
- Stream_Write_UINT32(s, settings->MonitorDefArray[i].attributes.orientation); /* orientation */
- Stream_Write_UINT32(s, settings->MonitorDefArray[i].attributes.desktopScaleFactor); /* desktopScaleFactor */
- Stream_Write_UINT32(s, settings->MonitorDefArray[i].attributes.deviceScaleFactor); /* deviceScaleFactor */
+ Stream_Write_UINT32(s,
+ settings->MonitorDefArray[i].attributes.physicalWidth); /* physicalWidth */
+ Stream_Write_UINT32(s,
+ settings->MonitorDefArray[i].attributes.physicalHeight); /* physicalHeight */
+ Stream_Write_UINT32(s,
+ settings->MonitorDefArray[i].attributes.orientation); /* orientation */
+ Stream_Write_UINT32(s,
+ settings->MonitorDefArray[i].attributes.desktopScaleFactor); /* desktopScaleFactor */
+ Stream_Write_UINT32(s,
+ settings->MonitorDefArray[i].attributes.deviceScaleFactor); /* deviceScaleFactor */
}
}
}
* @param settings rdp settings
*/
-BOOL gcc_read_client_message_channel_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
+BOOL gcc_read_client_message_channel_data(wStream* s, rdpMcs* mcs,
+ UINT16 blockLength)
{
UINT32 flags;
return FALSE;
Stream_Read_UINT32(s, flags);
-
mcs->messageChannelId = mcs->baseChannelId++;
-
return TRUE;
}
rdpSettings* settings = mcs->settings;
if (settings->NetworkAutoDetect ||
- settings->SupportHeartbeatPdu ||
- settings->SupportMultitransport)
+ settings->SupportHeartbeatPdu ||
+ settings->SupportMultitransport)
{
gcc_write_user_data_header(s, CS_MCS_MSGCHANNEL, 8);
-
Stream_Write_UINT32(s, 0); /* flags */
}
}
return FALSE;
Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */
-
/* Save the MCS message channel id */
mcs->messageChannelId = MCSChannelId;
-
return TRUE;
}
return FALSE;
gcc_write_user_data_header(s, SC_MCS_MSGCHANNEL, 6);
-
Stream_Write_UINT16(s, mcs->messageChannelId); /* mcsChannelId (2 bytes) */
return TRUE;
}
* @param settings rdp settings
*/
-BOOL gcc_read_client_multitransport_channel_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
+BOOL gcc_read_client_multitransport_channel_data(wStream* s, rdpMcs* mcs,
+ UINT16 blockLength)
{
UINT32 flags;
return FALSE;
Stream_Read_UINT32(s, flags);
-
return TRUE;
}
if (settings->MultitransportFlags != 0)
{
gcc_write_user_data_header(s, CS_MULTITRANSPORT, 8);
-
Stream_Write_UINT32(s, settings->MultitransportFlags); /* flags */
}
}
return FALSE;
Stream_Read_UINT32(s, flags); /* flags */
-
return TRUE;
}
void gcc_write_server_multitransport_channel_data(wStream* s, rdpMcs* mcs)
{
UINT32 flags = 0;
-
gcc_write_user_data_header(s, SC_MULTITRANSPORT, 8);
-
Stream_Write_UINT32(s, flags); /* flags (4 bytes) */
}
static void transport_ssl_cb(SSL* ssl, int where, int ret)
{
- rdpTransport *transport;
+ rdpTransport* transport;
+
if ((where | SSL_CB_ALERT) && (ret == 561))
{
- transport = (rdpTransport *) SSL_get_app_data(ssl);
+ transport = (rdpTransport*) SSL_get_app_data(ssl);
+
if (!freerdp_get_last_error(transport->context))
freerdp_set_last_error(transport->context, FREERDP_ERROR_AUTHENTICATION_FAILED);
}
wStream* transport_send_stream_init(rdpTransport* transport, int size)
{
wStream* s;
+
if (!(s = StreamPool_Take(transport->ReceivePool, size)))
return NULL;
+
if (!Stream_EnsureCapacity(s, size))
{
Stream_Release(s);
return NULL;
}
+
Stream_SetPosition(s, 0);
return s;
}
{
BIO* socketBio;
BIO* bufferedBio;
-
socketBio = BIO_new(BIO_s_simple_socket());
if (!socketBio)
return FALSE;
BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
-
bufferedBio = BIO_new(BIO_s_buffered_socket());
if (!bufferedBio)
return FALSE;
bufferedBio = BIO_push(bufferedBio, socketBio);
-
transport->frontBio = bufferedBio;
-
return TRUE;
}
}
transport->frontBio = tls->bio;
-
- BIO_callback_ctrl(tls->bio, BIO_CTRL_SET_CALLBACK, (bio_info_cb*) transport_ssl_cb);
+ BIO_callback_ctrl(tls->bio, BIO_CTRL_SET_CALLBACK,
+ (bio_info_cb*) transport_ssl_cb);
SSL_set_app_data(tls->ssl, transport);
if (!transport->frontBio)
if (settings->AuthenticationServiceClass)
{
rdp->nla->ServicePrincipalName =
- nla_make_spn(settings->AuthenticationServiceClass, settings->ServerHostname);
+ nla_make_spn(settings->AuthenticationServiceClass, settings->ServerHostname);
if (!rdp->nla->ServicePrincipalName)
return FALSE;
freerdp_set_last_error(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
transport_set_nla_mode(transport, FALSE);
-
return FALSE;
}
rdp_client_transition_to_state(rdp, CONNECTION_STATE_NLA);
-
return TRUE;
}
-BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port, int timeout)
+BOOL transport_connect(rdpTransport* transport, const char* hostname,
+ UINT16 port, int timeout)
{
int sockfd;
BOOL status = FALSE;
rdpSettings* settings = transport->settings;
rdpContext* context = transport->context;
-
transport->async = settings->AsyncTransport;
if (transport->GatewayEnabled)
}
if (!(transport->thread = CreateThread(NULL, 0,
- (LPTHREAD_START_ROUTINE) transport_client_thread, transport, 0, NULL)))
+ (LPTHREAD_START_ROUTINE) transport_client_thread, transport, 0, NULL)))
{
WLog_ERR(TAG, "Failed to create transport client thread");
CloseHandle(transport->stopEvent);
return FALSE;
transport->frontBio = transport->tls->bio;
-
return TRUE;
}
transport_set_nla_mode(transport, FALSE);
nla_free(transport->nla);
transport->nla = NULL;
- tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
+ tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
tls_send_alert(transport->tls);
return FALSE;
}
transport_bio_error_log(tag, biofunc, bio, __FILE__, __FUNCTION__, __LINE__)
static void transport_bio_error_log(LPCSTR tag, LPCSTR biofunc, BIO* bio,
- LPCSTR file, LPCSTR func, DWORD line)
+ LPCSTR file, LPCSTR func, DWORD line)
{
unsigned long sslerr;
- char *buf;
+ char* buf;
wLog* log;
wLogMessage log_message;
int saveerrno;
-
saveerrno = errno;
-
log = WLog_Get(tag);
+
if (!log)
return;
log_message.Level = WLOG_ERROR;
+
if (log_message.Level < WLog_GetLogLevel(log))
return;
}
buf = malloc(120);
+
if (buf)
{
- while((sslerr = ERR_get_error()))
+ while ((sslerr = ERR_get_error()))
{
ERR_error_string_n(sslerr, buf, 120);
log_message.FormatString = "%s returned an error: %s";
WLog_PrintMessage(log, &log_message, biofunc, buf);
}
+
free(buf);
}
}
WLog_ERR(TAG, "BIO_read: transport->frontBio null");
return -1;
}
+
WLog_ERR_BIO(TAG, "BIO_read", transport->frontBio);
transport->layer = TRANSPORT_LAYER_CLOSED;
return -1;
* @param[in] toRead number of bytes to read
* @return < 0 on error; 0 if not enough data is available (non blocking mode); 1 toRead bytes read
*/
-static int transport_read_layer_bytes(rdpTransport* transport, wStream* s, unsigned int toRead)
+static int transport_read_layer_bytes(rdpTransport* transport, wStream* s,
+ unsigned int toRead)
{
int status;
status = transport_read_layer(transport, Stream_Pointer(s), toRead);
int position;
int pduLength;
BYTE* header;
-
position = 0;
pduLength = 0;
return -1;
position = Stream_GetPosition(s);
+
/* Make sure there is enough space for the longest header within the stream */
if (!Stream_EnsureCapacity(s, 4))
return -1;
/* Make sure at least two bytes are read for further processing */
- if (position < 2 && (status = transport_read_layer_bytes(transport, s, 2 - position)) != 1)
+ if (position < 2
+ && (status = transport_read_layer_bytes(transport, s, 2 - position)) != 1)
{
/* No data available at the moment */
return status;
{
/* check for header bytes already was readed in previous calls */
if (position < 3
- && (status = transport_read_layer_bytes(transport, s, 3 - position)) != 1)
+ && (status = transport_read_layer_bytes(transport, s, 3 - position)) != 1)
return status;
pduLength = header[2];
{
/* check for header bytes already was readed in previous calls */
if (position < 4
- && (status = transport_read_layer_bytes(transport, s, 4 - position)) != 1)
+ && (status = transport_read_layer_bytes(transport, s, 4 - position)) != 1)
return status;
pduLength = (header[2] << 8) | header[3];
/* TPKT header */
/* check for header bytes already was readed in previous calls */
if (position < 4
- && (status = transport_read_layer_bytes(transport, s, 4 - position)) != 1)
+ && (status = transport_read_layer_bytes(transport, s, 4 - position)) != 1)
return status;
pduLength = (header[2] << 8) | header[3];
{
/* check for header bytes already was readed in previous calls */
if (position < 3
- && (status = transport_read_layer_bytes(transport, s, 3 - position)) != 1)
+ && (status = transport_read_layer_bytes(transport, s, 3 - position)) != 1)
return status;
pduLength = ((header[1] & 0x7F) << 8) | header[2];
if (!Stream_EnsureCapacity(s, Stream_GetPosition(s) + pduLength))
return -1;
- status = transport_read_layer_bytes(transport, s, pduLength - Stream_GetPosition(s));
+
+ status = transport_read_layer_bytes(transport, s,
+ pduLength - Stream_GetPosition(s));
if (status != 1)
return status;
if (Stream_GetPosition(s) >= pduLength)
- WLog_Packet(WLog_Get(TAG), WLOG_TRACE, Stream_Buffer(s), pduLength, WLOG_PACKET_INBOUND);
+ WLog_Packet(WLog_Get(TAG), WLOG_TRACE, Stream_Buffer(s), pduLength,
+ WLOG_PACKET_INBOUND);
Stream_SealLength(s);
Stream_SetPosition(s, 0);
}
EnterCriticalSection(&(transport->WriteLock));
-
length = Stream_GetPosition(s);
writtenlength = length;
Stream_SetPosition(s, 0);
if (length > 0)
{
- WLog_Packet(WLog_Get(TAG), WLOG_TRACE, Stream_Buffer(s), length, WLOG_PACKET_OUTBOUND);
+ WLog_Packet(WLog_Get(TAG), WLOG_TRACE, Stream_Buffer(s), length,
+ WLOG_PACKET_OUTBOUND);
}
while (length > 0)
length -= status;
Stream_Seek(s, status);
}
- transport->written += writtenlength;
+ transport->written += writtenlength;
out_cleanup:
if (status < 0)
}
Stream_Release(s);
-
LeaveCriticalSection(&(transport->WriteLock));
return status;
}
-DWORD transport_get_event_handles(rdpTransport* transport, HANDLE* events, DWORD count)
+DWORD transport_get_event_handles(rdpTransport* transport, HANDLE* events,
+ DWORD count)
{
DWORD nCount = 0;
DWORD tmp;
{
if (BIO_get_event(transport->frontBio, &events[nCount]) != 1)
return 0;
+
nCount++;
}
}
DWORD index;
DWORD nCount;
HANDLE events[64];
-
nCount = transport_get_event_handles(transport, events, 64);
-
*rcount = nCount;
for (index = 0; index < nCount; index++)
if (!transport)
return -1;
- while(!freerdp_shall_disconnect(transport->context->instance))
+ while (!freerdp_shall_disconnect(transport->context->instance))
{
/**
* Note: transport_read_pdu tries to read one PDU from
{
if (status < 0)
WLog_DBG(TAG, "transport_check_fds: transport_read_pdu() - %i", status);
+
return status;
}
received = transport->ReceiveBuffer;
+
if (!(transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0)))
return -1;
+
/**
* status:
* -1: error
* 0: success
* 1: redirection
*/
- recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra);
+ recv_status = transport->ReceiveCallback(transport, received,
+ transport->ReceiveExtra);
Stream_Release(received);
/* session redirection or activation */
if (recv_status < 0)
{
- WLog_ERR(TAG, "transport_check_fds: transport->ReceiveCallback() - %i", recv_status);
+ WLog_ERR(TAG, "transport_check_fds: transport->ReceiveCallback() - %i",
+ recv_status);
return -1;
}
}
}
transport->frontBio = NULL;
-
transport->layer = TRANSPORT_LAYER_TCP;
-
return status;
}
rdpTransport* transport = (rdpTransport*) arg;
rdpContext* context = transport->context;
rdpRdp* rdp = context->rdp;
-
WLog_DBG(TAG, "Asynchronous transport thread started");
-
nCount = 0;
handles[nCount++] = transport->stopEvent;
handles[nCount++] = transport->connectedEvent;
-
status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
switch (status)
{
nCount = 1; /* transport->stopEvent */
- if (!(nCountTmp = freerdp_get_event_handles(context, &handles[nCount], 64 - nCount)))
+ if (!(nCountTmp = freerdp_get_event_handles(context, &handles[nCount],
+ 64 - nCount)))
{
WLog_ERR(TAG, "freerdp_get_event_handles failed");
break;
}
- nCount += nCountTmp;
+ nCount += nCountTmp;
status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
if (transport->layer == TRANSPORT_LAYER_CLOSED)
WLog_ERR(TAG, "WaitForMultipleObjects returned WAIT_TIMEOUT");
else
WLog_ERR(TAG, "WaitForMultipleObjects returned 0x%08X", status);
+
dwExitCode = 1;
break;
}
rdpTransport* transport_new(rdpContext* context)
{
rdpTransport* transport;
-
transport = (rdpTransport*) calloc(1, sizeof(rdpTransport));
if (!transport)
transport->context = context;
transport->settings = context->settings;
-
transport->ReceivePool = StreamPool_New(TRUE, BUFFER_SIZE);
if (!transport->ReceivePool)
transport->connectedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (!transport->connectedEvent || transport->connectedEvent == INVALID_HANDLE_VALUE)
+ if (!transport->connectedEvent
+ || transport->connectedEvent == INVALID_HANDLE_VALUE)
goto out_free_receivebuffer;
transport->blocking = TRUE;
CloseHandle(transport->connectedEvent);
DeleteCriticalSection(&(transport->ReadLock));
DeleteCriticalSection(&(transport->WriteLock));
-
free(transport);
}
};
typedef struct _BIO_RDP_TLS BIO_RDP_TLS;
-long bio_rdp_tls_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
+long bio_rdp_tls_callback(BIO* bio, int mode, const char* argp, int argi,
+ long argl, long ret)
{
return 1;
}
return 0;
BIO_clear_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_READ | BIO_FLAGS_IO_SPECIAL);
-
EnterCriticalSection(&tls->lock);
-
status = SSL_write(tls->ssl, buf, size);
error = SSL_get_error(tls->ssl, status);
-
LeaveCriticalSection(&tls->lock);
if (status <= 0)
return 0;
BIO_clear_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_READ | BIO_FLAGS_IO_SPECIAL);
-
EnterCriticalSection(&tls->lock);
-
status = SSL_read(tls->ssl, buf, size);
error = SSL_get_error(tls->ssl, status);
-
LeaveCriticalSection(&tls->lock);
if (status <= 0)
}
#ifdef HAVE_VALGRIND_MEMCHECK_H
+
if (status > 0)
{
VALGRIND_MAKE_MEM_DEFINED(buf, status);
}
-#endif
+#endif
return status;
}
size = strlen(str);
status = BIO_write(bio, str, size);
-
return status;
}
status = BIO_ctrl(tls->ssl->rbio, cmd, num, ptr);
else
status = 1;
+
break;
case BIO_C_GET_FD:
SSL_set_connect_state(tls->ssl);
else
SSL_set_accept_state(tls->ssl);
+
status = 1;
break;
case BIO_CTRL_PENDING:
status = SSL_pending(tls->ssl);
+
if (status == 0)
status = BIO_pending(tls->ssl->rbio);
+
break;
case BIO_CTRL_FLUSH:
SSL_set_bio(tls->ssl, bio->next_bio, bio->next_bio);
CRYPTO_add(&(bio->next_bio->references), 1, CRYPTO_LOCK_BIO);
}
+
status = 1;
break;
tls->ssl->wbio = tls->ssl->rbio = NULL;
}
+
status = 1;
break;
*((SSL**) ptr) = tls->ssl;
status = 1;
}
+
break;
case BIO_C_SET_SSL:
case BIO_C_DO_STATE_MACHINE:
BIO_clear_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_WRITE | BIO_FLAGS_IO_SPECIAL);
bio->retry_reason = 0;
-
status = SSL_do_handshake(tls->ssl);
if (status <= 0)
break;
}
}
+
break;
default:
static int bio_rdp_tls_new(BIO* bio)
{
BIO_RDP_TLS* tls;
-
bio->init = 0;
bio->num = 0;
bio->flags = BIO_FLAGS_SHOULD_RETRY;
bio->next_bio = NULL;
-
tls = calloc(1, sizeof(BIO_RDP_TLS));
if (!tls)
return 0;
bio->ptr = (void*) tls;
-
InitializeCriticalSectionAndSpinCount(&tls->lock, 4000);
-
return 1;
}
}
DeleteCriticalSection(&tls->lock);
-
free(tls);
-
return 1;
}
switch (cmd)
{
case BIO_CTRL_SET_CALLBACK:
- SSL_set_info_callback(tls->ssl, (void (*)(const SSL *, int, int)) fp);
+ SSL_set_info_callback(tls->ssl, (void (*)(const SSL*, int, int)) fp);
status = 1;
break;
{
BIO* bio;
SSL* ssl;
-
bio = BIO_new(BIO_s_rdp_tls());
if (!bio)
SSL_set_accept_state(ssl);
BIO_set_ssl(bio, ssl, BIO_CLOSE);
-
return bio;
}
if (peer)
remote_cert = SSL_get_peer_certificate(tls->ssl);
else
- remote_cert = X509_dup( SSL_get_certificate(tls->ssl) );
+ remote_cert = X509_dup(SSL_get_certificate(tls->ssl));
if (!remote_cert)
{
}
cert = malloc(sizeof(*cert));
+
if (!cert)
{
X509_free(remote_cert);
}
cert->px509 = remote_cert;
-
/* Get the peer's chain. If it does not exist, we're setting NULL (clean data either way) */
chain = SSL_get_peer_cert_chain(tls->ssl);
cert->px509chain = chain;
-
return cert;
}
UINT32 ChannelBindingTokenLength;
SEC_CHANNEL_BINDINGS* ChannelBindings;
SecPkgContext_Bindings* ContextBindings;
-
ZeroMemory(CertificateHash, sizeof(CertificateHash));
X509_digest(cert, EVP_sha256(), CertificateHash, &CertificateHashLength);
-
PrefixLength = strlen(TLS_SERVER_END_POINT);
ChannelBindingTokenLength = PrefixLength + CertificateHashLength;
+ ContextBindings = (SecPkgContext_Bindings*) calloc(1,
+ sizeof(SecPkgContext_Bindings));
- ContextBindings = (SecPkgContext_Bindings*) calloc(1, sizeof(SecPkgContext_Bindings));
if (!ContextBindings)
return NULL;
- ContextBindings->BindingsLength = sizeof(SEC_CHANNEL_BINDINGS) + ChannelBindingTokenLength;
- ChannelBindings = (SEC_CHANNEL_BINDINGS*) calloc(1, ContextBindings->BindingsLength);
+ ContextBindings->BindingsLength = sizeof(SEC_CHANNEL_BINDINGS) +
+ ChannelBindingTokenLength;
+ ChannelBindings = (SEC_CHANNEL_BINDINGS*) calloc(1,
+ ContextBindings->BindingsLength);
+
if (!ChannelBindings)
goto out_free;
- ContextBindings->Bindings = ChannelBindings;
+ ContextBindings->Bindings = ChannelBindings;
ChannelBindings->cbApplicationDataLength = ChannelBindingTokenLength;
ChannelBindings->dwApplicationDataOffset = sizeof(SEC_CHANNEL_BINDINGS);
- ChannelBindingToken = &((BYTE*) ChannelBindings)[ChannelBindings->dwApplicationDataOffset];
-
+ ChannelBindingToken = &((BYTE*)
+ ChannelBindings)[ChannelBindings->dwApplicationDataOffset];
strcpy((char*) ChannelBindingToken, TLS_SERVER_END_POINT);
- CopyMemory(&ChannelBindingToken[PrefixLength], CertificateHash, CertificateHashLength);
-
+ CopyMemory(&ChannelBindingToken[PrefixLength], CertificateHash,
+ CertificateHashLength);
return ContextBindings;
-
out_free:
free(ContextBindings);
return NULL;
}
#if OPENSSL_VERSION_NUMBER >= 0x010000000L
-static BOOL tls_prepare(rdpTls* tls, BIO* underlying, const SSL_METHOD* method, int options, BOOL clientMode)
+static BOOL tls_prepare(rdpTls* tls, BIO* underlying, const SSL_METHOD* method,
+ int options, BOOL clientMode)
#else
-static BOOL tls_prepare(rdpTls* tls, BIO* underlying, SSL_METHOD* method, int options, BOOL clientMode)
+static BOOL tls_prepare(rdpTls* tls, BIO* underlying, SSL_METHOD* method,
+ int options, BOOL clientMode)
#endif
{
rdpSettings* settings = tls->settings;
-
tls->ctx = SSL_CTX_new(method);
if (!tls->ctx)
return FALSE;
}
- SSL_CTX_set_mode(tls->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);
-
+ SSL_CTX_set_mode(tls->ctx,
+ SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);
SSL_CTX_set_options(tls->ctx, options);
SSL_CTX_set_read_ahead(tls->ctx, 1);
BIO_push(tls->bio, underlying);
tls->underlying = underlying;
-
return TRUE;
}
HANDLE event;
DWORD status;
#endif
-
status = BIO_do_handshake(tls->bio);
if (status == 1)
WLog_ERR(TAG, "unable to retrieve BIO fd");
return -1;
}
+
#else
BIO_get_event(tls->bio, &event);
WLog_ERR(TAG, "unable to retrieve BIO event");
return -1;
}
-#endif
+#endif
#ifdef HAVE_POLL_H
pollfds.fd = fd;
pollfds.events = POLLIN;
status = poll(&pollfds, 1, 10 * 1000);
}
while ((status < 0) && (errno == EINTR));
+
#elif !defined(_WIN32)
FD_ZERO(&rset);
FD_SET(fd, &rset);
tv.tv_sec = 0;
tv.tv_usec = 10 * 1000; /* 10ms */
-
status = _select(fd + 1, &rset, NULL, NULL, &tv);
#else
status = WaitForSingleObject(event, 10);
#endif
-
#ifndef _WIN32
+
if (status < 0)
{
WLog_ERR(TAG, "error during select()");
return -1;
}
+
#else
+
if ((status != WAIT_OBJECT_0) && (status != WAIT_TIMEOUT))
{
WLog_ERR(TAG, "error during WaitForSingleObject(): 0x%04X", status);
return -1;
}
+
#endif
}
while (TRUE);
if (!crypto_cert_get_public_key(cert, &tls->PublicKey, &tls->PublicKeyLength))
{
- WLog_ERR(TAG, "crypto_cert_get_public_key failed to return the server public key.");
+ WLog_ERR(TAG,
+ "crypto_cert_get_public_key failed to return the server public key.");
verify_status = -1;
goto out;
}
out:
tls_free_certificate(cert);
-
return verify_status;
}
int tls_connect(rdpTls* tls, BIO* underlying)
{
int options = 0;
-
/**
* SSL_OP_NO_COMPRESSION:
*
#ifdef SSL_OP_NO_COMPRESSION
options |= SSL_OP_NO_COMPRESSION;
#endif
-
/**
* SSL_OP_TLS_BLOCK_PADDING_BUG:
*
* It absolutely needs to be disabled otherwise it won't work.
*/
options |= SSL_OP_TLS_BLOCK_PADDING_BUG;
-
/**
* SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS:
*
* support empty fragments. This needs to be disabled.
*/
options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
-
/**
* disable SSLv2 and SSLv3
*/
#ifndef OPENSSL_NO_TLSEXT
SSL_set_tlsext_host_name(tls->ssl, tls->hostname);
#endif
-
return tls_do_handshake(tls, TRUE);
}
#ifndef OPENSSL_NO_TLSEXT
-static void tls_openssl_tlsext_debug_callback(SSL *s, int client_server,
- int type, unsigned char *data, int len, void *arg)
+static void tls_openssl_tlsext_debug_callback(SSL* s, int client_server,
+ int type, unsigned char* data, int len, void* arg)
{
/* see code comment in tls_accept() below */
-
- if (type == TLSEXT_TYPE_server_name) {
+ if (type == TLSEXT_TYPE_server_name)
+ {
WLog_DBG(TAG, "Client uses SNI (extension disabled)");
s->servername_done = 2;
}
}
#endif
-BOOL tls_accept(rdpTls* tls, BIO* underlying, rdpSettings *settings)
+BOOL tls_accept(rdpTls* tls, BIO* underlying, rdpSettings* settings)
{
long options = 0;
- BIO *bio;
- RSA *rsa;
- X509 *x509;
-
+ BIO* bio;
+ RSA* rsa;
+ X509* x509;
/**
* SSL_OP_NO_SSLv2:
*
* SSLv3 is used by, eg. Microsoft RDC for Mac OS X.
*/
options |= SSL_OP_NO_SSLv2;
-
/**
* SSL_OP_NO_COMPRESSION:
*
#ifdef SSL_OP_NO_COMPRESSION
options |= SSL_OP_NO_COMPRESSION;
#endif
-
/**
* SSL_OP_TLS_BLOCK_PADDING_BUG:
*
* It absolutely needs to be disabled otherwise it won't work.
*/
options |= SSL_OP_TLS_BLOCK_PADDING_BUG;
-
/**
* SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS:
*
if (settings->PrivateKeyFile)
{
bio = BIO_new_file(settings->PrivateKeyFile, "rb+");
+
if (!bio)
{
- WLog_ERR(TAG, "BIO_new_file failed for private key %s", settings->PrivateKeyFile);
+ WLog_ERR(TAG, "BIO_new_file failed for private key %s",
+ settings->PrivateKeyFile);
return FALSE;
}
}
else if (settings->PrivateKeyContent)
{
- bio = BIO_new_mem_buf(settings->PrivateKeyContent, strlen(settings->PrivateKeyContent));
+ bio = BIO_new_mem_buf(settings->PrivateKeyContent,
+ strlen(settings->PrivateKeyContent));
+
if (!bio)
{
WLog_ERR(TAG, "BIO_new_mem_buf failed for private key");
return FALSE;
}
-
if (settings->CertificateFile)
{
bio = BIO_new_file(settings->CertificateFile, "rb+");
+
if (!bio)
{
- WLog_ERR(TAG, "BIO_new_file failed for certificate %s", settings->CertificateFile);
+ WLog_ERR(TAG, "BIO_new_file failed for certificate %s",
+ settings->CertificateFile);
return FALSE;
}
}
else if (settings->CertificateContent)
{
- bio = BIO_new_mem_buf(settings->CertificateContent, strlen(settings->CertificateContent));
+ bio = BIO_new_mem_buf(settings->CertificateContent,
+ strlen(settings->CertificateContent));
+
if (!bio)
{
WLog_ERR(TAG, "BIO_new_mem_buf failed for certificate");
return FALSE;
}
-
if (SSL_use_certificate(tls->ssl, x509) <= 0)
{
WLog_ERR(TAG, "SSL_use_certificate_file failed");
* extension debug callback that sets the SSL context's servername_done
* to 1 which effectively disables the parsing of that extension type.
*/
-
SSL_set_tlsext_debug_callback(tls->ssl, tls_openssl_tlsext_debug_callback);
#endif
-
return tls_do_handshake(tls, FALSE) > 0;
}
* Manually sending a TLS alert is necessary in certain cases,
* like when server-side NLA results in an authentication failure.
*/
-
SSL_set_quiet_shutdown(tls->ssl, 1);
if ((tls->alertLevel == TLS_ALERT_LEVEL_FATAL) && (tls->ssl->session))
return TRUE;
}
-BIO *findBufferedBio(BIO *front)
+BIO* findBufferedBio(BIO* front)
{
- BIO *ret = front;
+ BIO* ret = front;
while (ret)
{
if (BIO_method_type(ret) == BIO_TYPE_BUFFERED)
return ret;
+
ret = ret->next_bio;
}
return 0;
}
-BOOL tls_match_hostname(char *pattern, int pattern_length, char *hostname)
+BOOL tls_match_hostname(char* pattern, int pattern_length, char* hostname)
{
if (strlen(hostname) == pattern_length)
{
- if (_strnicmp( hostname, pattern, pattern_length) == 0)
+ if (_strnicmp(hostname, pattern, pattern_length) == 0)
return TRUE;
}
- if ((pattern_length > 2) && (pattern[0] == '*') && (pattern[1] == '.') && (((int) strlen(hostname)) >= pattern_length))
+ if ((pattern_length > 2) && (pattern[0] == '*') && (pattern[1] == '.')
+ && (((int) strlen(hostname)) >= pattern_length))
{
char* check_hostname = &hostname[strlen(hostname) - pattern_length + 1];
- if (_strnicmp( check_hostname, &pattern[1], pattern_length - 1) == 0)
+ if (_strnicmp(check_hostname, &pattern[1], pattern_length - 1) == 0)
{
return TRUE;
}
return FALSE;
}
-int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int port)
+int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname,
+ int port)
{
int match;
int index;
int offset;
BYTE* pemCert;
freerdp* instance = (freerdp*) tls->settings->instance;
-
/**
* Don't manage certificates internally, leave it up entirely to the external client implementation
*/
-
bio = BIO_new(BIO_s_mem());
if (!bio)
offset = 0;
length = 2048;
pemCert = (BYTE*) malloc(length + 1);
+
if (!pemCert)
{
WLog_ERR(TAG, "error allocating pemCert");
while (offset >= length)
{
int new_len;
- BYTE *new_cert;
-
+ BYTE* new_cert;
new_len = length * 2;
new_cert = (BYTE*) realloc(pemCert, new_len + 1);
+
if (!new_cert)
return -1;
+
length = new_len;
pemCert = new_cert;
-
status = BIO_read(bio, &pemCert[offset], length);
if (status < 0)
length = offset;
pemCert[length] = '\0';
-
status = -1;
if (instance->VerifyX509Certificate)
- status = instance->VerifyX509Certificate(instance, pemCert, length, hostname, port, tls->isGatewayTransport);
+ status = instance->VerifyX509Certificate(instance, pemCert, length, hostname,
+ port, tls->isGatewayTransport);
else
WLog_ERR(TAG, "No VerifyX509Certificate callback registered!");
if (status < 0)
{
WLog_ERR(TAG, "VerifyX509Certificate failed: (length = %d) status: [%d] %s",
- length, status, pemCert);
+ length, status, pemCert);
return -1;
}
hostname = tls->settings->CertificateName;
/* attempt verification using OpenSSL and the ~/.freerdp/certs certificate store */
- certificate_status = x509_verify_certificate(cert, tls->certificate_store->path);
-
+ certificate_status = x509_verify_certificate(cert,
+ tls->certificate_store->path);
/* verify certificate name match */
certificate_data = crypto_get_certificate_data(cert->px509, hostname, port);
-
-
/* extra common name and alternative names */
common_name = crypto_cert_subject_common_name(cert->px509, &common_name_length);
- alt_names = crypto_cert_subject_alt_name(cert->px509, &alt_names_count, &alt_names_lengths);
+ alt_names = crypto_cert_subject_alt_name(cert->px509, &alt_names_count,
+ &alt_names_lengths);
/* compare against common name */
char* fingerprint;
freerdp* instance = (freerdp*) tls->settings->instance;
DWORD accept_certificate = 0;
-
issuer = crypto_cert_issuer(cert->px509);
subject = crypto_cert_subject(cert->px509);
fingerprint = crypto_cert_fingerprint(cert->px509);
-
/* search for matching entry in known_hosts file */
match = certificate_data_match(tls->certificate_store, certificate_data);
/* no entry was found in known_hosts file, prompt user for manual verification */
if (!hostname_match)
tls_print_certificate_name_mismatch_error(
- hostname, port,
- common_name, alt_names,
- alt_names_count);
+ hostname, port,
+ common_name, alt_names,
+ alt_names_count);
/* Automatically accept certificate on first use */
if (tls->settings->AutoAcceptCertificate)
else if (instance->VerifyCertificate)
{
accept_certificate = instance->VerifyCertificate(
- instance, common_name,
- subject, issuer,
- fingerprint, !hostname_match);
+ instance, common_name,
+ subject, issuer,
+ fingerprint, !hostname_match);
}
- switch(accept_certificate)
+ switch (accept_certificate)
{
case 1:
/* user accepted certificate, add entry in known_hosts file */
- verification_status = certificate_data_print(tls->certificate_store, certificate_data);
+ verification_status = certificate_data_print(tls->certificate_store,
+ certificate_data);
break;
+
case 2:
/* user did accept temporaty, do not add to known hosts file */
verification_status = TRUE;
break;
+
default:
/* user did not accept, abort and do not add entry in known_hosts file */
verification_status = FALSE; /* failure! */
char* old_subject = NULL;
char* old_issuer = NULL;
char* old_fingerprint = NULL;
-
/* entry was found in known_hosts file, but fingerprint does not match. ask user to use it */
tls_print_certificate_error(hostname, port, fingerprint,
- tls->certificate_store->file);
+ tls->certificate_store->file);
if (!certificate_get_stored_data(tls->certificate_store,
- certificate_data, &old_subject,
- &old_issuer, &old_fingerprint))
+ certificate_data, &old_subject,
+ &old_issuer, &old_fingerprint))
WLog_WARN(TAG, "Failed to get certificate entry for %s:hu",
- hostname, port);
+ hostname, port);
if (instance->VerifyChangedCertificate)
{
accept_certificate = instance->VerifyChangedCertificate(
- instance, common_name, subject, issuer,
- fingerprint, old_subject, old_issuer,
- old_fingerprint);
+ instance, common_name, subject, issuer,
+ fingerprint, old_subject, old_issuer,
+ old_fingerprint);
}
free(old_fingerprint);
- switch(accept_certificate)
+ switch (accept_certificate)
{
case 1:
/* user accepted certificate, add entry in known_hosts file */
- verification_status = certificate_data_replace(tls->certificate_store, certificate_data);
+ verification_status = certificate_data_replace(tls->certificate_store,
+ certificate_data);
break;
+
case 2:
/* user did accept temporaty, do not add to known hosts file */
verification_status = TRUE;
break;
+
default:
/* user did not accept, abort and do not add entry in known_hosts file */
verification_status = FALSE; /* failure! */
}
certificate_data_free(certificate_data);
-
free(common_name);
if (alt_names)
crypto_cert_subject_alt_name_free(alt_names_count, alt_names_lengths,
- alt_names);
+ alt_names);
return (verification_status == 0) ? 0 : 1;
}
void tls_print_certificate_error(char* hostname, UINT16 port, char* fingerprint,
- char *hosts_file)
+ char* hosts_file)
{
WLog_ERR(TAG, "The host key for %s:%hu has changed", hostname, port);
WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
WLog_ERR(TAG, "@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
WLog_ERR(TAG, "IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
- WLog_ERR(TAG, "Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
+ WLog_ERR(TAG,
+ "Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
WLog_ERR(TAG, "It is also possible that a host key has just been changed.");
- WLog_ERR(TAG, "The fingerprint for the host key sent by the remote host is%s", fingerprint);
+ WLog_ERR(TAG, "The fingerprint for the host key sent by the remote host is%s",
+ fingerprint);
WLog_ERR(TAG, "Please contact your system administrator.");
- WLog_ERR(TAG, "Add correct host key in %s to get rid of this message.", hosts_file);
- WLog_ERR(TAG, "Host key for %s has changed and you have requested strict checking.", hostname);
+ WLog_ERR(TAG, "Add correct host key in %s to get rid of this message.",
+ hosts_file);
+ WLog_ERR(TAG,
+ "Host key for %s has changed and you have requested strict checking.",
+ hostname);
WLog_ERR(TAG, "Host key verification failed.");
}
void tls_print_certificate_name_mismatch_error(char* hostname, UINT16 port,
- char* common_name, char** alt_names,
- int alt_names_count)
+ char* common_name, char** alt_names,
+ int alt_names_count)
{
int index;
-
assert(NULL != hostname);
WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
WLog_ERR(TAG, "@ WARNING: CERTIFICATE NAME MISMATCH! @");
WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
WLog_ERR(TAG, "The hostname used for this connection (%s:%hu) ",
- hostname, port);
+ hostname, port);
WLog_ERR(TAG, "does not match %s given in the certificate:",
- alt_names_count < 1 ? "the name" : "any of the names");
+ alt_names_count < 1 ? "the name" : "any of the names");
WLog_ERR(TAG, "Common Name (CN):");
WLog_ERR(TAG, "\t%s", common_name ? common_name : "no CN found in certificate");
+
if (alt_names_count > 0)
{
assert(NULL != alt_names);
WLog_ERR(TAG, "Alternative names:");
+
for (index = 0; index < alt_names_count; index++)
{
assert(alt_names[index]);
WLog_ERR(TAG, "\t %s", alt_names[index]);
}
}
+
WLog_ERR(TAG, "A valid certificate for the wrong name should NOT be trusted!");
}
rdpTls* tls_new(rdpSettings* settings)
{
rdpTls* tls;
-
tls = (rdpTls*) calloc(1, sizeof(rdpTls));
if (!tls)
return NULL;
winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
-
tls->settings = settings;
if (!settings->ServerMode)
tls->alertLevel = TLS_ALERT_LEVEL_WARNING;
tls->alertDescription = TLS_ALERT_DESCRIPTION_CLOSE_NOTIFY;
-
return tls;
-
out_free:
free(tls);
return NULL;